024 improvements
This commit is contained in:
+69
-40
@@ -6,6 +6,7 @@
|
||||
<cfparam name="ATTRIBUTES.output" type="string" default="report"/>
|
||||
<cfparam name="ATTRIBUTES.debug" type="boolean" default=false/>
|
||||
<cfparam name="ATTRIBUTES.tenant_wz_index" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.restrict_to_own_instances" type="boolean" default=true/>
|
||||
|
||||
|
||||
|
||||
@@ -102,7 +103,6 @@
|
||||
AND s.serviceType = 3
|
||||
</cfquery>
|
||||
|
||||
<!--- <cfdump var=#qSpec# abort=true/> --->
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qSpec (Left Outer Join with Free Tier)
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
@@ -110,9 +110,6 @@
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- <cfloop from=#attributes.dt_start# to=#attributes.dt_finish# step="#CreateTimeSpan( 1, 0, 0, 0 )#" index="local.dt">
|
||||
<cfdump var=#dateFormat(local.dt,"YYYY-MM-DD")#/>--->
|
||||
|
||||
<!--- *** Нужно еще реализовать в модели данных (каталоге) политики бесплатного минимума (free tier), сейчас прибито гвоздями --->
|
||||
<cfquery name="qComputing">
|
||||
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
|
||||
@@ -121,7 +118,7 @@
|
||||
WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
|
||||
WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
|
||||
WHEN vdc.name LIKE '%-v1cl5%' THEN 'iaas.ngc.a45'
|
||||
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28' -- *** смапить все кластера
|
||||
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
|
||||
WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40' -- *** смапить все кластера
|
||||
ELSE '['||vdc.name||']' end as code,
|
||||
sum(cpu_used/cpu_speed)/4. as core_h,
|
||||
@@ -146,6 +143,20 @@
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- если захочется сгенерить литерал таблицы соответствия
|
||||
with a as (
|
||||
select * from ngcloud_ru.storage_profile_types
|
||||
)
|
||||
select '('||id||', '''|| name||''', '''||
|
||||
|
||||
case
|
||||
when name ilike '%fastssd%' then 'fstssd'
|
||||
when name ilike '%ssd%' then 'ssd'
|
||||
when name ilike '%sata%' then 'sata'
|
||||
else '' end
|
||||
||''''||')'
|
||||
from a
|
||||
--->
|
||||
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
|
||||
<!--- очень долго исполняется --->
|
||||
<cfquery name="qStorage">
|
||||
@@ -159,9 +170,10 @@
|
||||
WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40'
|
||||
ELSE '['||vdc.name||']' END
|
||||
|| CASE
|
||||
WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-m'
|
||||
WHEN storage_profile_types.name ILIKE '%-SAS' THEN '.sas-m'
|
||||
WHEN storage_profile_types.name ILIKE '%-SATA' THEN '.sata-m'
|
||||
WHEN storage_profile_types.name ILIKE '%FASTSSD%' THEN '.fstssd-m'
|
||||
WHEN storage_profile_types.name ILIKE '%SSD%' THEN '.ssd-m'
|
||||
WHEN storage_profile_types.name ILIKE '%SAS%' THEN '.sas-m'
|
||||
WHEN storage_profile_types.name ILIKE '%SATA%' THEN '.sata-m'
|
||||
ELSE '.['|| storage_profile_types.name ||']' END
|
||||
as code,
|
||||
storage_profile_types.name, -- *** это не тип, а профайл
|
||||
@@ -201,8 +213,12 @@
|
||||
--,bucket_stat.placement_id
|
||||
,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
|
||||
,bucket_stat.timestamp_addition::date as dt
|
||||
,bucket_info.name as dimension_1,
|
||||
null as dimension_2
|
||||
,bucket_info.name || ' - ' || case
|
||||
when bucket_stat.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end
|
||||
as dimension_1
|
||||
,null as dimension_2
|
||||
from s3billing.bucket_stat
|
||||
join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id
|
||||
join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id
|
||||
@@ -285,7 +301,11 @@
|
||||
--category.name, bucket_info.name
|
||||
,'WZ'||lpad(user_info.name, 5, '0') as wz
|
||||
,usage_bucket_by_user.time::date as dt
|
||||
,bucket_info.name as dimension_1
|
||||
,bucket_info.name || ' - ' || case
|
||||
when bucket_info.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_info.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_info.placement_id,'FM9') ||']' end
|
||||
as dimension_1
|
||||
,null as dimension_2
|
||||
from s3billing.usage_bucket_by_user
|
||||
join s3billing.user_info on usage_bucket_by_user.user_id=user_info.id
|
||||
@@ -310,39 +330,40 @@
|
||||
</cfif>
|
||||
|
||||
<!--- собрали все метрики в один резалтсет --->
|
||||
<!--- Здесь мы знаем единицы измерения, причем надежнее, чем в спецификации --->
|
||||
<cfquery name="qUnifiedMetric" dbType="query">
|
||||
select dt, wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric,
|
||||
dimension_1, 'vdc' as dimension_1_name, dimension_2, NULL as dimension_2_name
|
||||
select dt, wz, code + '.vcpu-m' as code, core_h as raw_metric, core_h as metric,
|
||||
dimension_1, 'vdc' as dimension_1_name, dimension_2, NULL as dimension_2_name, 'ядро-ч' as unit
|
||||
from qComputing
|
||||
|
||||
union all
|
||||
select dt, wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric,
|
||||
dimension_1, 'vdc' as dimension_1_name, dimension_2, NULL as dimension_2_name
|
||||
select dt, wz, code + '.ram-m' as code, gb_h as raw_metric, gb_h as metric,
|
||||
dimension_1, 'vdc' as dimension_1_name, dimension_2, NULL as dimension_2_name, 'ГБайт-ч' as unit
|
||||
from qComputing
|
||||
|
||||
union all
|
||||
select dt, wz, code, gb_m_used as raw_metric, gb_m_used as metric,
|
||||
dimension_1, 'vdc' as dimension_1_name, dimension_2, 'storage policy' as dimension_2_name
|
||||
dimension_1, 'vdc' as dimension_1_name, dimension_2, 'storage policy' as dimension_2_name, 'ГБайт-м' as unit
|
||||
from qStorage
|
||||
|
||||
union all
|
||||
select dt, wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name
|
||||
select dt, wz, code + '.vol-m', vol_b as raw_metric, vol_gb as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name, 'ГБайт-м' as unit
|
||||
from qS3Vol
|
||||
|
||||
union all
|
||||
select dt, wz, code || '.get-m', get as raw_metric, get_10k as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name
|
||||
select dt, wz, code + '.get-m', get as raw_metric, get_10k as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name, '10тыс.шт.' as unit
|
||||
from qS3OpsTrf
|
||||
|
||||
union all
|
||||
select dt, wz, code || '.put-m', put as raw_metric, put_10k as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name
|
||||
select dt, wz, code + '.put-m', put as raw_metric, put_10k as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name, '10тыс.шт.' as unit
|
||||
from qS3OpsTrf
|
||||
|
||||
union all
|
||||
select dt, wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name
|
||||
select dt, wz, code + '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name, 'ГБайт' as unit
|
||||
from qS3OpsTrf
|
||||
|
||||
order by dt, code, dimension_1, dimension_2 <!--- /*dimension_*_name нужно только в качестве заголовка *** потом оптимизировать */ --->
|
||||
@@ -383,12 +404,12 @@
|
||||
<cfquery name="qChargeDaily" dbType="query">
|
||||
SELECT
|
||||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||
<d:field title="Код компонента">s.code</d:field>
|
||||
<d:field title="Код компонента">s.code as s_code</d:field>
|
||||
<d:field title="Код метрики">m.code as m_code</d:field>
|
||||
<d:field title="Код услуги">s.service_code as service_code</d:field>
|
||||
<d:field title="Услуга">s.svc</d:field>
|
||||
<d:field title="Компонент">s.component</d:field>
|
||||
<d:field title="Ед.изм.">s.unit</d:field>
|
||||
<d:field title="Ед.изм.">m.unit</d:field>
|
||||
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">
|
||||
s.price*(100-s.discount)/100 as discounted_price
|
||||
</d:field>
|
||||
@@ -408,22 +429,28 @@
|
||||
<d:field>m.dimension_2_name</d:field>
|
||||
</d:field_set>
|
||||
FROM qSpec as s, qUnifiedMetric as m
|
||||
WHERE m.wz=<cfqueryparam cfsqltype="cf_sql_varchar" value=#request.auth.wz#/>
|
||||
AND s.code=m.code
|
||||
WHERE s.code=m.code
|
||||
AND s.serviceStart <= m.dt
|
||||
AND (m.dt <= s.serviceEnd OR s.serviceEnd IS NULL)
|
||||
|
||||
<cfif #attributes.restrict_to_own_instances#>
|
||||
AND m.wz=<cfqueryparam cfsqltype="cf_sql_varchar" value=#request.auth.wz#/>
|
||||
</cfif>
|
||||
<!--- таким замысловатым способом мы реализуем FULL JOIN --->
|
||||
UNION ALL
|
||||
|
||||
SELECT NULL, m.code, NULL, NULL, NULL, NULL, 0,
|
||||
NULL, NULL, m.raw_metric, m.metric, NULL, NULL, NULL, NULL, m.dt, 0, m.dimension_1, m.dimension_1_name, m.dimension_2, m.dimension_2_name
|
||||
FROM qUnifiedMetric as m where m.code NOT IN (<cfqueryparam value="#ValueList(qSpec.code)#" cfsqltype="cf_sql_varchar" list="true">)
|
||||
FROM qUnifiedMetric as m
|
||||
WHERE m.code NOT IN (<cfqueryparam value="#ValueList(qSpec.code)#" cfsqltype="cf_sql_varchar" list="true">)
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT s.code, NULL, s.service_code, s.svc, s.component, s.unit, s.price*(100-s.discount)/100 as discounted_price,
|
||||
s.price, s.discount, NULL, NULL, s.serviceStart, s.serviceEnd, s.serviceHash, s.serviceCustomName, NULL, 0, NULL, NULL, NULL, NULL
|
||||
FROM qSpec as s where s.code NOT IN (<cfqueryparam value="#listRemoveDuplicates(ValueList(qUnifiedMetric.code))#" cfsqltype="cf_sql_varchar" list="true">)
|
||||
order by dt, code, dimension_1, dimension_2
|
||||
FROM qSpec as s
|
||||
WHERE s.code NOT IN (<cfqueryparam value="#listRemoveDuplicates(ValueList(qUnifiedMetric.code))#" cfsqltype="cf_sql_varchar" list="true">)
|
||||
|
||||
ORDER by dt, s_code, m_code, dimension_1, dimension_2
|
||||
</cfquery>
|
||||
<!--- диагностика ошибок в QoQ крайне невнятна и вводит в заблуждение --->
|
||||
|
||||
@@ -440,8 +467,9 @@
|
||||
<cfquery name="qChargeMonthly" dbType="query">
|
||||
SELECT
|
||||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||
<d:field title="Артикул по договору">code</d:field>
|
||||
<d:field title="Артикул по договору">s_code</d:field>
|
||||
<d:field title="Артикул по системам">m_code</d:field>
|
||||
<d:field title="Артикул">s_code as code</d:field>
|
||||
<d:field title="Код услуги">service_code</d:field>
|
||||
<d:field title="Услуга по каталогу">svc</d:field>
|
||||
<d:field title="serviceCustomName">serviceCustomName</d:field>
|
||||
@@ -464,15 +492,14 @@
|
||||
<d:field title="Месяц" cfSqlType="CF_SQL_INTEGER">month(dt) as month</d:field>
|
||||
</d:field_set>
|
||||
from qChargeDaily
|
||||
group by m_code, code, svc, service_code, serviceCustomName, component, unit, discounted_price, serviceStart, ServiceEnd, serviceHash, free_tier, year(dt), month(dt),
|
||||
group by s_code, m_code, svc, service_code, serviceCustomName, component, unit, discounted_price, serviceStart, ServiceEnd, serviceHash, free_tier, year(dt), month(dt),
|
||||
dimension_1_name, dimension_1, dimension_2_name, dimension_2
|
||||
order by year(dt), month(dt), m_code, code, serviceStart, dimension_1, dimension_2
|
||||
</cfquery>
|
||||
<!--- в связи с бедностью языка QoQ (нет CASE) грубо патчим резалтсет --->
|
||||
<!--- <cfloop query="qChargeMonthly">
|
||||
<cfset qChargeMonthly.chargeable_metric = (chargeable_metric GT 0) ? chargeable_metric : 0/> <!--- имя в левой части должно быть квалифицировано запросом (резалтсетом) --->
|
||||
<cfset qChargeMonthly.charge = (charge GT 0) ? charge : 0/>
|
||||
</cfloop> --->
|
||||
<cfloop query="qChargeMonthly">
|
||||
<cfset qChargeMonthly.code = (len(code) GT 0) ? code : m_code/><!--- имя в левой части должно быть квалифицировано запросом (резалтсетом) --->
|
||||
</cfloop>
|
||||
|
||||
|
||||
<!--- тут могут быть подводные камни с копированием и переиспользованием объектов --->
|
||||
@@ -491,6 +518,7 @@
|
||||
<!--- <cfdump var=#qChargeMonthly#/> --->
|
||||
<!--- *** проверить краевые даты --->
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qChargeMonthly
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qChargeMonthly#/>
|
||||
<cfflush/>
|
||||
@@ -507,10 +535,11 @@
|
||||
<cfset report.qStorageAge = qStorageAge/>
|
||||
<cfset report.qS3VolAge = qS3VolAge/>
|
||||
<cfset report.qS3OpsTrfAge = qS3OpsTrfAge/>
|
||||
<cfset report.qSpecification = qSpecification/>
|
||||
<cfset report.qCharge = qChargeMonthly/>
|
||||
<cfset report.qFreeTier = qFreeTier/><!--- мы не применяем скидку на уровне детализации, а только после агрегации. На самом деле правильно было бы агрегировать натуральные метрики, а умножать на цену уже агрегаты --->
|
||||
<cfset report.chargeTitleMap = titleMap/>
|
||||
<cfset report.chargeFieldCount = fieldCount/>
|
||||
<!--- <cfset report.chargeTitleMap = titleMap/>
|
||||
<cfset report.chargeFieldCount = fieldCount/> --->
|
||||
|
||||
<cfset "CALLER.#ATTRIBUTES.output#" = report/>
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<cfimport prefix="d" taglib="../lib/data"/>
|
||||
|
||||
<cfparam name="ATTRIBUTES.wz"/>
|
||||
<cfparam name="ATTRIBUTES.crm_cache_base" default="https://elma-cache.adl.nubes.ru/contract_ls.cfm"/>
|
||||
<!--- <cfparam name="ATTRIBUTES.crm_cache_base" default="https://elma-cache.adl.nubes.ru/contract_ls.cfm"/> --->
|
||||
<cfparam name="ATTRIBUTES.out" default="qComponent"/>
|
||||
|
||||
<cfhttp method="get"
|
||||
url="#ATTRIBUTES.crm_cache_base#?wz=#ATTRIBUTES.wz#"
|
||||
url="#request.crm_cache_base#?wz=#ATTRIBUTES.wz#"
|
||||
timeout=10
|
||||
charset="utf-8"
|
||||
result="res"
|
||||
|
||||
Reference in New Issue
Block a user