090 s3 from cmdb, inmem DECIMAL fix

This commit is contained in:
2026-10-01 16:59:49 +03:00
parent 669eaec34f
commit e645f0865d
4 changed files with 105 additions and 60 deletions
+2 -1
View File
@@ -24,6 +24,7 @@
<cfset this.datasources["#this.datasource#"]=getDS("#this.datasource#","ds_#this.datasource#")/>
<cfset this.datasources["billing-vc"]=getDS("billing-vc","ds_billing_vc")/>
<cfset this.datasources["billing-s3"]=getDS("billing-s3","ds_billing_s3")/>
<cfset this.datasources["cmdb"]=getDS("cmdb","ds_cmdb")/>
<!--- но датасорцы таинственно прочухались с прошлым пушем, без переноса инициализации в псевдоконструктор --->
<!--- а потом опять... --->
@@ -88,7 +89,7 @@
<!--- global settings --->
<!--- *************************************************************************************************** --->
<cfset request.APP_VERSION="0.00.089"/> <!--- *********************************************************** --->
<cfset request.APP_VERSION="0.00.090"/> <!--- *********************************************************** --->
<!--- *************************************************************************************************** --->
<cfset request.STAND=getStand()/>
<cfset request.RECORDS_PER_PAGE=500/>
+2 -1
View File
@@ -1,4 +1,5 @@
component {
/*0.04 precision fix DECIMAL(128,32) maybe too memory consumable*/
/*0.03 precision fix*/
/*0.02 timestamp support*/
/**
@@ -71,7 +72,7 @@ component {
case "BIGINT": return "BIGINT";
case "DOUBLE": case "FLOAT": case "REAL": return "DOUBLE";
case "BOOLEAN": case "BIT": return "BIT";
case "DECIMAL": case "NUMERIC": return "DECIMAL";
case "DECIMAL": case "NUMERIC": return "DECIMAL(128,32)";
case "TIMESTAMP": case "DATE": case "TIME": return "TIMESTAMP";
default: return "LONGVARCHAR"; // И тут тоже
}
+8
View File
@@ -1 +1,9 @@
Задача: S3 перепривязать через CMDB (по именованию аккаунта - не работает (суффиксы, вводимые руками, не гарантированы от ошибок, примеры есть)
Половинчатое решение: мы можем вытащить из CMDB контрагента для S3.
- Сделать источник данных к CMDB (сразу прод?)
- Сделать джойн и либо добавить найденные в CMDB связи с WZ, либо
На самом деле нужно сделать связь инстанса S3 со строкой спецификации.
Контракты и спецификации в CMDB сейчас пустышки, а надо вязать с настоящими контрактами и спецификациями, только тогда возможен правильный биллинг.
Затащить контракты и спецификации в CMDB из CRM? Какие записи отобрать?
12:58 09.10.2025 дополнительное соглашение к сделке. Шедевр
+48 -13
View File
@@ -238,7 +238,8 @@ HOT_FREE_LIMIT 1 10 1 100
when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code
,bucket_stat.placement_id
,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
--,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
,bucket_stat.owner as s3_user_name
,bucket_info.name as bucket
from s3billing.bucket_stat
join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id
@@ -246,7 +247,7 @@ HOT_FREE_LIMIT 1 10 1 100
where bucket_stat.placement_id in (1,2)
AND bucket_stat.timestamp_addition >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,dt_finish)#/>
<cfif len(wz)>
<cfif len(wz)><!--- *** --->
AND 'WZ'||lpad(bucket_stat.owner, 5, '0') like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#wz#%"/> /*выглядит очень неэффективным запросом*/
</cfif>
group by bucket_stat.owner, bucket_stat.placement_id, bucket_info.name
@@ -307,7 +308,8 @@ select
,bucket_info.placement_id
--category.name
,bucket_info.name as bucket
,'WZ'||lpad(user_info.name, 5, '0') as wz
,user_info.name as s3_user_name
--,'dummy' AS WZ
from s3billing.usage_bucket_by_user
join s3billing.user_info on usage_bucket_by_user.user_id=user_info.id
join s3billing.category on usage_bucket_by_user.category_id=category.id
@@ -336,7 +338,22 @@ select
<cfoutput>qS3OpsTrfAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfquery name="qS3User" datasource="cmdb" cachedWithin=#createTimeSpan(0, 0, 31, 0)#>
WITH current_state AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY instance_uid ORDER BY version DESC) as rn
FROM instance_state
)
SELECT s.instance_data->'job'->>'contragentCode' as wz, s.instance_data->'job'->>'userId' AS user_id, e.display_name
FROM current_state s
JOIN instance e on (s.instance_uid=e.instance_uid)
WHERE rn = 1 AND e.service_id=12
</cfquery>
<cfoutput>qS3User:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfif isDefined("DEBUG")>
<cfdump var=#qS3User#/>
<cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
</cfif>
<!--- выданы права на схему и таблицы, чтобы без толку не плодить источники данных --->
<!--- считаются часы работы ВМ с GPU --->
@@ -364,6 +381,9 @@ select
WHERE NOT vm.is_template
AND p.ts >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dt_start#/>
AND p.ts < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,dt_finish)#/>
<cfif len(wz)>
AND vm.client_id ilike <cfqueryparam cfsqltype="cf_sql_varchar" value="%#wz#%"/>
</cfif>
GROUP BY vm.client_id, item.key, c.code, vm.obj_id
ORDER BY vm.client_id, item.key, c.code, vm.obj_id;
</cfquery>
@@ -381,11 +401,15 @@ select
<cfoutput>qGpuAge:#getTickCount()-request.startTickCount#</cfoutput><cfif !isDefined("output_xls") AND !isDefined("output_json")><cfflush/></cfif>
<cfset db = new MemoryDbHelper()/>
<cfset db.register("qComputing", qComputing, "inmem")/>
<cfset db.register("qStorage", qStorage, "inmem")/>
<cfset db.register("qS3Vol", qS3Vol, "inmem")/>
<cfset db.register("qS3OpsTrf", qS3OpsTrf, "inmem")/>
<cfset db.register("qGpu", qGpu, "inmem")/>
<cfset db.register("qS3User", qS3User, "inmem")/>
<cfquery name="qUnifiedMetric" dbType="query">
<cfquery name="qUnifiedMetric" datasource="inmem">
select wz, code || '.vcpu' as code, core_h as raw_metric, core_h as metric, 'core-h' as unit, vdc as dimension1
from qComputing
<cfif len(code)>
@@ -408,28 +432,32 @@ from qStorage
union all
select wz, code || '.vol',vol_b as raw_metric, vol_gb as metric, 'GByte-m' as unit, bucket as dimension1
from qS3Vol
from qS3Vol s
left outer join qS3User u ON (s.s3_user_name = u.user_id)
<cfif len(code)>
where code || '.vol' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif>
union all
select wz, code || '.get', get as raw_metric, get_10k as metric, '10k' as unit, bucket as dimension1
from qS3OpsTrf
from qS3OpsTrf s
left outer join qS3User u ON (s.s3_user_name = u.user_id)
<cfif len(code)>
where code || '.get' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif>
union all
select wz, code || '.put', put as raw_metric, put_10k as metric, '10k' as unit, bucket as dimension1
from qS3OpsTrf
from qS3OpsTrf s
left outer join qS3User u ON (s.s3_user_name = u.user_id)
<cfif len(code)>
where code || '.put' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif>
union all
select wz, code || '.trf', bytes_sent as raw_metric, bytes_sent_gb as metric, 'GByte' as unit, bucket as dimension1
from qS3OpsTrf
from qS3OpsTrf s
left outer join qS3User u ON (s.s3_user_name = u.user_id)
<cfif len(code)>
where code || '.trf' like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#code#%"/>
</cfif>
@@ -455,7 +483,6 @@ order by wz, code
<!--- загружаем рекордсеты в inmemory db, вместо чтобы мучиться с QoQ --->
<cfset db = new MemoryDbHelper()/>
<cfset db.register("qUnifiedMetric", qUnifiedMetric, "inmem")/>
<cfset db.register("qContragent", qContragent, "inmem")/>
<cfset db.register("qSpec", qSpec, "inmem")/>
@@ -474,6 +501,11 @@ FULL JOIN, потому что нам нужны бесхозные записи
Группировка: по контрагенту,
--->
<!--- <cfquery name="qSpecTest" datasource="inmem">
select * from qSpec
</cfquery>
<cfdump var=#qSpecTest#/> --->
<cfquery name="qCharge" datasource="inmem">
/*EXPLAIN PLAN FOR*/
@@ -522,8 +554,10 @@ SELECT
<d:field title="Клиентс. назв.">s.user_description</d:field>
<d:field title="Pricing Model">CASE s.type WHEN 1 THEN 'install' WHEN 2 THEN 'fix' WHEN 3 THEN 'payg' ELSE NULL END as pricing_model</d:field>
</d:field_set>
,'***' as delim,s.*
FROM qUnifiedMetric m
<cfif local.inner_join>
INNER
<cfelse>
FULL
</cfif>
@@ -739,7 +773,7 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
<tr>
<td colspan="4"></td>
<td colspan="2" class="b r">Итого #code#:</td>
<td class="b r" style="font-size:110%; padding:0 1em;">#accum_metric_dimension_1#<cfif final_metric_dimension_1 NEQ 0 AND isNumeric(final_metric_dimension_1)>#round(final_metric_dimension_1,3)#</cfif></td>
<td class="b r" style="font-size:110%; padding:0 1em;"><!--- #accum_metric_dimension_1# ---><cfif final_metric_dimension_1 NEQ 0 AND isNumeric(final_metric_dimension_1)>#round(final_metric_dimension_1,3)#</cfif></td>
<td class="b r">#free_tier#</td>
<td class="b r" style="font-size:120%; padding:0 1em;"><cfif final_metric_dimension_1 NEQ 0 AND isNumeric(final_metric_dimension_1)>#max(ceiling(final_metric_dimension_1) - free_tier, 0)#</cfif></td>
<td class="b c">#unit# <cfif len(ed_izm)>[#ed_izm#]</cfif></td>
@@ -768,6 +802,7 @@ S3 операции и трафик: <b<cfif datediff("h",qS3OpsTrfAge.dt_load,
<cfdump var=#this.datasources[request.ds].connectionString#/>
<cfdump var=#this.datasources["billing-vc"].connectionString#/>
<cfdump var=#this.datasources["billing-s3"].connectionString#/>
<cfdump var=#this.datasources["cmdb"].connectionString#/>
<layout:page section="footer"/>