@electrolux-oss/plugin-infrawallet-backend 1.1.0-20251212102352-79a5aeb → 1.1.0-20251218080407-fbaf733

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -89,21 +89,22 @@ class DatadogClient extends InfraWalletClient.InfraWalletClient {
89
89
  }
90
90
  async fetchCosts(integrationConfig, client, query) {
91
91
  const costData = [];
92
- const startTime = moment__default.default(parseInt(query.startTime, 10));
93
- const endTime = moment__default.default(parseInt(query.endTime, 10));
94
- const firstDayOfLastMonth = moment__default.default().subtract(1, "M").startOf("M");
95
- if (startTime.isBefore(firstDayOfLastMonth)) {
96
- const historicalEndTime = moment__default.default.min(endTime, firstDayOfLastMonth.clone().subtract(1, "d"));
97
- const maxMonthRange = 2;
92
+ const startTime = moment__default.default.utc(parseInt(query.startTime, 10)).startOf("month");
93
+ const endTime = moment__default.default.utc(parseInt(query.endTime, 10)).startOf("month");
94
+ const historicalCutoff = moment__default.default.utc().startOf("month").subtract(2, "months");
95
+ if (startTime.isBefore(historicalCutoff)) {
96
+ const historicalEndTime = moment__default.default.min(endTime, historicalCutoff.clone().subtract(1, "month"));
97
+ const maxMonthRange = 3;
98
98
  let chunkStart = startTime.clone();
99
- while (chunkStart.isBefore(historicalEndTime)) {
100
- const chunkEnd = moment__default.default.min(
101
- chunkStart.clone().add(maxMonthRange, "months").subtract(1, "day"),
102
- historicalEndTime.clone()
103
- );
99
+ while (chunkStart.isSameOrBefore(historicalEndTime)) {
100
+ let chunkEnd = chunkStart.clone().add(maxMonthRange - 1, "months");
101
+ if (chunkEnd.isAfter(historicalEndTime)) {
102
+ chunkEnd = historicalEndTime.clone();
103
+ }
104
+ const apiEndMonth = chunkEnd.clone().add(1, "month");
104
105
  const historicalCost = await client.getHistoricalCostByOrg({
105
106
  startMonth: chunkStart,
106
- endMonth: chunkEnd,
107
+ endMonth: apiEndMonth,
107
108
  view: "sub-org"
108
109
  });
109
110
  try {
@@ -120,17 +121,15 @@ class DatadogClient extends InfraWalletClient.InfraWalletClient {
120
121
  if (historicalCost.data) {
121
122
  costData.push(...historicalCost.data);
122
123
  }
123
- chunkStart = chunkEnd.clone().add(1, "day").startOf("month");
124
+ chunkStart = chunkStart.clone().add(maxMonthRange, "months");
124
125
  }
125
126
  }
126
- if (endTime.isSameOrAfter(firstDayOfLastMonth)) {
127
- let estimatedCostStartTime = startTime;
128
- if (startTime.isBefore(firstDayOfLastMonth)) {
129
- estimatedCostStartTime = firstDayOfLastMonth;
130
- }
127
+ if (endTime.isSameOrAfter(historicalCutoff)) {
128
+ const estimatedStartTime = moment__default.default.max(startTime, historicalCutoff);
129
+ const apiEndTime = endTime.clone().add(1, "month");
131
130
  const estimatedCost = await client.getEstimatedCostByOrg({
132
- startMonth: estimatedCostStartTime,
133
- endMonth: endTime,
131
+ startMonth: estimatedStartTime,
132
+ endMonth: apiEndTime,
134
133
  view: "sub-org"
135
134
  });
136
135
  try {
@@ -152,12 +151,13 @@ class DatadogClient extends InfraWalletClient.InfraWalletClient {
152
151
  if (query.granularity === consts.GRANULARITY.MONTHLY) {
153
152
  costData.forEach((costByOrg) => {
154
153
  const orgName = costByOrg.attributes?.orgName;
155
- if (!this.evaluateIntegrationFilters(orgName, integrationConfig)) {
154
+ const date = costByOrg.attributes?.date;
155
+ if (!this.evaluateIntegrationFilters(orgName, integrationConfig) || !date) {
156
156
  return;
157
157
  }
158
158
  costs.push({
159
159
  orgName,
160
- date: costByOrg.attributes?.date,
160
+ date,
161
161
  // only keep cost breakdown
162
162
  charges: costByOrg.attributes?.charges?.filter((charge) => charge.chargeType !== "total")
163
163
  });
@@ -165,10 +165,12 @@ class DatadogClient extends InfraWalletClient.InfraWalletClient {
165
165
  } else {
166
166
  costData.forEach((costByOrg) => {
167
167
  const orgName = costByOrg.attributes?.orgName;
168
- if (!this.evaluateIntegrationFilters(orgName, integrationConfig)) {
168
+ const date = costByOrg.attributes?.date;
169
+ if (!this.evaluateIntegrationFilters(orgName, integrationConfig) || !date) {
169
170
  return;
170
171
  }
171
- const daysInMonth = moment__default.default(costByOrg.attributes?.date).daysInMonth();
172
+ const utcDate = moment__default.default.utc(date);
173
+ const daysInMonth = utcDate.daysInMonth();
172
174
  costByOrg.attributes?.charges?.forEach((charge) => {
173
175
  if (charge.chargeType === "total") {
174
176
  return;
@@ -176,7 +178,7 @@ class DatadogClient extends InfraWalletClient.InfraWalletClient {
176
178
  for (let i = 0; i < daysInMonth; i++) {
177
179
  const dailyCost = {
178
180
  orgName,
179
- date: moment__default.default(costByOrg.attributes?.date).add(i, "d"),
181
+ date: utcDate.clone().add(i, "d"),
180
182
  charges: [
181
183
  {
182
184
  productName: charge.productName,
@@ -219,7 +221,7 @@ class DatadogClient extends InfraWalletClient.InfraWalletClient {
219
221
  if (query.granularity === consts.GRANULARITY.DAILY) {
220
222
  periodFormat = "YYYY-MM-DD";
221
223
  }
222
- const dateObj = moment__default.default(costByOrg.date);
224
+ const dateObj = moment__default.default.utc(costByOrg.date);
223
225
  if (!dateObj.isValid()) {
224
226
  filteredOutInvalidDate++;
225
227
  return accumulator;
@@ -1 +1 @@
1
- {"version":3,"file":"DatadogClient.cjs.js","sources":["../../src/cost-clients/DatadogClient.ts"],"sourcesContent":["import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { v2 as datadogApiV2, client as datadogClient } from '@datadog/datadog-api-client';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { CLOUD_PROVIDER, GRANULARITY, PROVIDER_TYPE } from '../service/consts';\nimport { parseCost } from '../service/functions';\nimport { CostQuery, Report } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\nimport { DatadogCostByOrgResponseSchema } from '../schemas/DatadogBilling';\nimport { ZodError } from 'zod';\n\nexport class DatadogClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new DatadogClient(CLOUD_PROVIDER.DATADOG, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n // Datadog doesn't have this documented offically, raise a PR if any service is missed\n const aliases = new Map<string, string>([\n ['apm_host', 'APM Hosts'],\n ['apm_host_enterprise', 'APM Enterprise Hosts'],\n ['application_vulnerability_management_oss_host', 'Application Security - SCA Host'],\n ['application_security_host', 'ASM - Threat Management Hosts'],\n ['audit_trail', 'Audit Trail'],\n ['ci_pipeline', 'CI Visibility Committers'],\n ['ci_pipeline_indexed_spans', 'CI Visibility Spans'],\n ['cloud_cost_management', 'Cloud Cost Hosts'],\n ['cspm_container', 'Cloud Security Management Containers Pro'],\n ['cspm_host', 'Cloud Security Management Hosts Pro'],\n ['csm_host_pro', 'Cloud Security Management Hosts Pro'],\n ['cws_host', 'Cloud Workload Security Hosts'],\n ['infra_container', 'Containers'],\n ['infra_container_excl_agent', 'Containers'],\n ['timeseries', 'Custom Metrics'],\n ['error_tracking', 'Error Tracking'],\n ['incident_management', 'Incident Management'],\n ['logs_indexed_15day', 'Indexed Logs (15-day Retention)'],\n ['logs_indexed_180day', 'Indexed Logs (180-day Retention)'],\n ['logs_indexed_1day', 'Indexed Logs (1-day Retention)'],\n ['logs_indexed_30day', 'Indexed Logs (30-day Retention)'],\n ['logs_indexed_360day', 'Indexed Logs (360-day Retention)'],\n ['logs_indexed_3day', 'Indexed Logs (3-day Retention)'],\n ['logs_indexed_45day', 'Indexed Logs (45-day Retention)'],\n ['logs_indexed_60day', 'Indexed Logs (60-day Retention)'],\n ['logs_indexed_7day', 'Indexed Logs (7-day Retention)'],\n ['logs_indexed_90day', 'Indexed Logs (90-day Retention)'],\n ['apm_trace_search', 'Indexed Spans'],\n ['infra_host', 'Infra Hosts'],\n ['logs_ingested', 'Ingested Logs'],\n ['ingested_spans', 'Ingested Spans'],\n ['iot', 'IoT Devices'],\n ['npm_host', 'Network Hosts'],\n ['prof_container', 'Profiled Containers'],\n ['prof_host', 'Profiled Hosts'],\n ['rum_lite', 'RUM Sessions'],\n ['rum_replay', 'RUM with Session Replay Sessions'],\n ['siem_indexed', 'Security Analyzed and Indexed Logs'],\n ['sensitive_data_scanner', 'Sensitive Data Scanner'],\n ['serverless_apps', 'Serverless App Instances'],\n ['serverless_apm', 'Serverless Traced Invocations'],\n ['serverless_infra', 'Serverless Workload Functions'],\n ['siem', 'SIEM - Analyzed Logs'],\n ['synthetics_api_tests', 'Synthetics API Test Runs'],\n ['synthetics_browser_checks', 'Synthetics Browser Test Runs'],\n ['ci_testing', 'Test Visibility Committers'],\n ['ci_test_indexed_spans', 'Test Visibility Spans'],\n ]);\n\n if (aliases.has(convertedName)) {\n convertedName = aliases.get(convertedName) || convertedName;\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n protected async initCloudClient(integrationConfig: any): Promise<any> {\n const apiKey = integrationConfig.getString('apiKey');\n const applicationKey = integrationConfig.getString('applicationKey');\n const ddSite = integrationConfig.getString('ddSite');\n const configuration = datadogClient.createConfiguration({\n baseServer: new datadogClient.BaseServerConfiguration(ddSite, {}),\n authMethods: {\n apiKeyAuth: apiKey,\n appKeyAuth: applicationKey,\n },\n });\n const client = new datadogApiV2.UsageMeteringApi(configuration);\n return client;\n }\n\n protected async fetchCosts(integrationConfig: Config, client: any, query: CostQuery): Promise<any> {\n const costData: datadogApiV2.CostByOrg[] = [];\n const startTime = moment(parseInt(query.startTime, 10));\n const endTime = moment(parseInt(query.endTime, 10));\n const firstDayOfLastMonth = moment().subtract(1, 'M').startOf('M');\n\n // check if costs prior to 2 months ago are in query, if yes, use historical_cost API\n // https://docs.datadoghq.com/api/latest/usage-metering/#get-historical-cost-across-your-account\n if (startTime.isBefore(firstDayOfLastMonth)) {\n const historicalEndTime = moment.min(endTime, firstDayOfLastMonth.clone().subtract(1, 'd'));\n const maxMonthRange = 2;\n let chunkStart = startTime.clone();\n\n while (chunkStart.isBefore(historicalEndTime)) {\n const chunkEnd = moment.min(\n chunkStart.clone().add(maxMonthRange, 'months').subtract(1, 'day'),\n historicalEndTime.clone(),\n );\n\n const historicalCost: datadogApiV2.CostByOrgResponse = await client.getHistoricalCostByOrg({\n startMonth: chunkStart,\n endMonth: chunkEnd,\n view: 'sub-org',\n });\n\n try {\n DatadogCostByOrgResponseSchema.parse(historicalCost);\n this.logger.debug(`Datadog historical cost response validation passed`);\n } catch (error) {\n if (error instanceof ZodError) {\n this.logger.warn(`Datadog historical cost response validation failed: ${error.message}`);\n this.logger.debug(`Sample validation errors: ${JSON.stringify(error.errors.slice(0, 3))}`);\n } else {\n this.logger.warn(`Unexpected validation error: ${error.message}`);\n }\n }\n\n if (historicalCost.data) {\n costData.push(...historicalCost.data);\n }\n\n chunkStart = chunkEnd.clone().add(1, 'day').startOf('month');\n }\n }\n\n // check if current/last month costs are in query, if yes, use estimated_cost API\n // https://docs.datadoghq.com/api/latest/usage-metering/#get-estimated-cost-across-your-account\n if (endTime.isSameOrAfter(firstDayOfLastMonth)) {\n let estimatedCostStartTime = startTime;\n if (startTime.isBefore(firstDayOfLastMonth)) {\n estimatedCostStartTime = firstDayOfLastMonth;\n }\n\n const estimatedCost: datadogApiV2.CostByOrgResponse = await client.getEstimatedCostByOrg({\n startMonth: estimatedCostStartTime,\n endMonth: endTime,\n view: 'sub-org',\n });\n\n try {\n DatadogCostByOrgResponseSchema.parse(estimatedCost);\n this.logger.debug(`Datadog estimated cost response validation passed`);\n } catch (error) {\n if (error instanceof ZodError) {\n this.logger.warn(`Datadog estimated cost response validation failed: ${error.message}`);\n this.logger.debug(`Sample validation errors: ${JSON.stringify(error.errors.slice(0, 3))}`);\n } else {\n this.logger.warn(`Unexpected validation error: ${error.message}`);\n }\n }\n\n if (estimatedCost.data) {\n costData.push(...estimatedCost.data);\n }\n }\n\n const costs: any[] = [];\n\n if (query.granularity === GRANULARITY.MONTHLY) {\n costData.forEach(costByOrg => {\n const orgName = costByOrg.attributes?.orgName as string;\n if (!this.evaluateIntegrationFilters(orgName, integrationConfig)) {\n return;\n }\n\n costs.push({\n orgName: orgName,\n date: costByOrg.attributes?.date,\n // only keep cost breakdown\n charges: costByOrg.attributes?.charges?.filter(charge => charge.chargeType !== 'total'),\n });\n });\n } else {\n // Datadog doesn't provide daily costs based on usage, so we allocate monthly costs evenly by day\n costData.forEach(costByOrg => {\n const orgName = costByOrg.attributes?.orgName as string;\n if (!this.evaluateIntegrationFilters(orgName, integrationConfig)) {\n return;\n }\n\n const daysInMonth = moment(costByOrg.attributes?.date).daysInMonth();\n costByOrg.attributes?.charges?.forEach(charge => {\n if (charge.chargeType === 'total') {\n // only keep cost breakdown\n return;\n }\n\n for (let i = 0; i < daysInMonth; i++) {\n const dailyCost = {\n orgName: orgName,\n date: moment(costByOrg.attributes?.date).add(i, 'd'),\n charges: [\n {\n productName: charge.productName,\n cost: (charge.cost || 0) / daysInMonth,\n chargeType: charge.chargeType,\n },\n ],\n };\n costs.push(dailyCost);\n }\n });\n });\n }\n\n return costs;\n }\n\n protected async transformCostsData(subAccountConfig: Config, query: CostQuery, costResponse: any): Promise<Report[]> {\n const tags = subAccountConfig.getOptionalStringArray('tags');\n const tagKeyValues: { [key: string]: string } = {};\n tags?.forEach(tag => {\n const [k, v] = tag.split(':');\n tagKeyValues[k.trim()] = v.trim();\n });\n\n // Initialize tracking variables\n let processedRecords = 0;\n let filteredOutZeroAmount = 0;\n let filteredOutMissingFields = 0;\n let filteredOutInvalidDate = 0;\n const filteredOutTimeRange = 0;\n const uniqueKeys = new Set<string>();\n const totalRecords = costResponse?.length || 0;\n\n const transformedData = reduce(\n costResponse,\n (accumulator: { [key: string]: Report }, costByOrg) => {\n const account = costByOrg.orgName;\n const charges = costByOrg.charges;\n\n // Check for missing fields\n if (!account || !costByOrg.date) {\n filteredOutMissingFields++;\n return accumulator;\n }\n\n let periodFormat = 'YYYY-MM';\n if (query.granularity === GRANULARITY.DAILY) {\n periodFormat = 'YYYY-MM-DD';\n }\n\n const dateObj = moment(costByOrg.date);\n if (!dateObj.isValid()) {\n filteredOutInvalidDate++;\n return accumulator;\n }\n\n const period = dateObj.format(periodFormat);\n\n if (charges) {\n charges.forEach((charge: datadogApiV2.ChargebackBreakdown) => {\n const productName = charge.productName;\n const cost = charge.cost;\n\n // Check for missing fields\n if (!productName || cost === undefined || cost === null) {\n filteredOutMissingFields++;\n return;\n }\n\n const amount = parseCost(cost);\n\n // Check for zero amount\n if (amount === 0) {\n filteredOutZeroAmount++;\n return;\n }\n\n const keyName = `${account}->${productName} (${charge.chargeType})`;\n\n if (!accumulator[keyName]) {\n uniqueKeys.add(keyName);\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${account}`,\n service: `${this.convertServiceName(productName as string)} (${charge.chargeType})`,\n category: 'Observability',\n provider: this.provider,\n providerType: PROVIDER_TYPE.INTEGRATION,\n reports: {},\n ...tagKeyValues,\n };\n }\n\n accumulator[keyName].reports[period] = amount;\n processedRecords++;\n });\n }\n\n return accumulator;\n },\n {},\n );\n\n this.logTransformationSummary({\n processed: processedRecords,\n uniqueReports: uniqueKeys.size,\n zeroAmount: filteredOutZeroAmount,\n missingFields: filteredOutMissingFields,\n invalidDate: filteredOutInvalidDate,\n timeRange: filteredOutTimeRange,\n totalRecords,\n });\n\n return Object.values(transformedData);\n }\n}\n"],"names":["InfraWalletClient","CLOUD_PROVIDER","datadogClient","datadogApiV2","moment","DatadogCostByOrgResponseSchema","ZodError","GRANULARITY","reduce","parseCost","PROVIDER_TYPE"],"mappings":"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"}
1
+ {"version":3,"file":"DatadogClient.cjs.js","sources":["../../src/cost-clients/DatadogClient.ts"],"sourcesContent":["import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { v2 as datadogApiV2, client as datadogClient } from '@datadog/datadog-api-client';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { CLOUD_PROVIDER, GRANULARITY, PROVIDER_TYPE } from '../service/consts';\nimport { parseCost } from '../service/functions';\nimport { CostQuery, Report } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\nimport { DatadogCostByOrgResponseSchema } from '../schemas/DatadogBilling';\nimport { ZodError } from 'zod';\n\nexport class DatadogClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new DatadogClient(CLOUD_PROVIDER.DATADOG, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n // Datadog doesn't have this documented offically, raise a PR if any service is missed\n const aliases = new Map<string, string>([\n ['apm_host', 'APM Hosts'],\n ['apm_host_enterprise', 'APM Enterprise Hosts'],\n ['application_vulnerability_management_oss_host', 'Application Security - SCA Host'],\n ['application_security_host', 'ASM - Threat Management Hosts'],\n ['audit_trail', 'Audit Trail'],\n ['ci_pipeline', 'CI Visibility Committers'],\n ['ci_pipeline_indexed_spans', 'CI Visibility Spans'],\n ['cloud_cost_management', 'Cloud Cost Hosts'],\n ['cspm_container', 'Cloud Security Management Containers Pro'],\n ['cspm_host', 'Cloud Security Management Hosts Pro'],\n ['csm_host_pro', 'Cloud Security Management Hosts Pro'],\n ['cws_host', 'Cloud Workload Security Hosts'],\n ['infra_container', 'Containers'],\n ['infra_container_excl_agent', 'Containers'],\n ['timeseries', 'Custom Metrics'],\n ['error_tracking', 'Error Tracking'],\n ['incident_management', 'Incident Management'],\n ['logs_indexed_15day', 'Indexed Logs (15-day Retention)'],\n ['logs_indexed_180day', 'Indexed Logs (180-day Retention)'],\n ['logs_indexed_1day', 'Indexed Logs (1-day Retention)'],\n ['logs_indexed_30day', 'Indexed Logs (30-day Retention)'],\n ['logs_indexed_360day', 'Indexed Logs (360-day Retention)'],\n ['logs_indexed_3day', 'Indexed Logs (3-day Retention)'],\n ['logs_indexed_45day', 'Indexed Logs (45-day Retention)'],\n ['logs_indexed_60day', 'Indexed Logs (60-day Retention)'],\n ['logs_indexed_7day', 'Indexed Logs (7-day Retention)'],\n ['logs_indexed_90day', 'Indexed Logs (90-day Retention)'],\n ['apm_trace_search', 'Indexed Spans'],\n ['infra_host', 'Infra Hosts'],\n ['logs_ingested', 'Ingested Logs'],\n ['ingested_spans', 'Ingested Spans'],\n ['iot', 'IoT Devices'],\n ['npm_host', 'Network Hosts'],\n ['prof_container', 'Profiled Containers'],\n ['prof_host', 'Profiled Hosts'],\n ['rum_lite', 'RUM Sessions'],\n ['rum_replay', 'RUM with Session Replay Sessions'],\n ['siem_indexed', 'Security Analyzed and Indexed Logs'],\n ['sensitive_data_scanner', 'Sensitive Data Scanner'],\n ['serverless_apps', 'Serverless App Instances'],\n ['serverless_apm', 'Serverless Traced Invocations'],\n ['serverless_infra', 'Serverless Workload Functions'],\n ['siem', 'SIEM - Analyzed Logs'],\n ['synthetics_api_tests', 'Synthetics API Test Runs'],\n ['synthetics_browser_checks', 'Synthetics Browser Test Runs'],\n ['ci_testing', 'Test Visibility Committers'],\n ['ci_test_indexed_spans', 'Test Visibility Spans'],\n ]);\n\n if (aliases.has(convertedName)) {\n convertedName = aliases.get(convertedName) || convertedName;\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n protected async initCloudClient(integrationConfig: any): Promise<any> {\n const apiKey = integrationConfig.getString('apiKey');\n const applicationKey = integrationConfig.getString('applicationKey');\n const ddSite = integrationConfig.getString('ddSite');\n const configuration = datadogClient.createConfiguration({\n baseServer: new datadogClient.BaseServerConfiguration(ddSite, {}),\n authMethods: {\n apiKeyAuth: apiKey,\n appKeyAuth: applicationKey,\n },\n });\n const client = new datadogApiV2.UsageMeteringApi(configuration);\n return client;\n }\n\n protected async fetchCosts(integrationConfig: Config, client: any, query: CostQuery): Promise<any> {\n const costData: datadogApiV2.CostByOrg[] = [];\n // Strict UTC to prevent month boundary drift\n const startTime = moment.utc(parseInt(query.startTime, 10)).startOf('month');\n const endTime = moment.utc(parseInt(query.endTime, 10)).startOf('month');\n const historicalCutoff = moment.utc().startOf('month').subtract(2, 'months');\n\n // check if costs prior to 2 months ago are in query, if yes, use historical_cost API\n // https://docs.datadoghq.com/api/latest/usage-metering/#get-historical-cost-across-your-account\n if (startTime.isBefore(historicalCutoff)) {\n const historicalEndTime = moment.min(endTime, historicalCutoff.clone().subtract(1, 'month'));\n // Datadog API quirk: To get data FOR a specific end month, the API request must include the NEXT month.\n const maxMonthRange = 3;\n let chunkStart = startTime.clone();\n\n while (chunkStart.isSameOrBefore(historicalEndTime)) {\n let chunkEnd = chunkStart.clone().add(maxMonthRange - 1, 'months');\n if (chunkEnd.isAfter(historicalEndTime)) {\n chunkEnd = historicalEndTime.clone();\n }\n\n const apiEndMonth = chunkEnd.clone().add(1, 'month');\n\n const historicalCost: datadogApiV2.CostByOrgResponse = await client.getHistoricalCostByOrg({\n startMonth: chunkStart,\n endMonth: apiEndMonth,\n view: 'sub-org',\n });\n\n try {\n DatadogCostByOrgResponseSchema.parse(historicalCost);\n this.logger.debug(`Datadog historical cost response validation passed`);\n } catch (error) {\n if (error instanceof ZodError) {\n this.logger.warn(`Datadog historical cost response validation failed: ${error.message}`);\n this.logger.debug(`Sample validation errors: ${JSON.stringify(error.errors.slice(0, 3))}`);\n } else {\n this.logger.warn(`Unexpected validation error: ${error.message}`);\n }\n }\n\n if (historicalCost.data) {\n costData.push(...historicalCost.data);\n }\n\n chunkStart = chunkStart.clone().add(maxMonthRange, 'months');\n }\n }\n\n // check if current/last month costs are in query, if yes, use estimated_cost API\n // https://docs.datadoghq.com/api/latest/usage-metering/#get-estimated-cost-across-your-account\n if (endTime.isSameOrAfter(historicalCutoff)) {\n const estimatedStartTime = moment.max(startTime, historicalCutoff);\n const apiEndTime = endTime.clone().add(1, 'month');\n\n const estimatedCost: datadogApiV2.CostByOrgResponse = await client.getEstimatedCostByOrg({\n startMonth: estimatedStartTime,\n endMonth: apiEndTime,\n view: 'sub-org',\n });\n\n try {\n DatadogCostByOrgResponseSchema.parse(estimatedCost);\n this.logger.debug(`Datadog estimated cost response validation passed`);\n } catch (error) {\n if (error instanceof ZodError) {\n this.logger.warn(`Datadog estimated cost response validation failed: ${error.message}`);\n this.logger.debug(`Sample validation errors: ${JSON.stringify(error.errors.slice(0, 3))}`);\n } else {\n this.logger.warn(`Unexpected validation error: ${error.message}`);\n }\n }\n\n if (estimatedCost.data) {\n costData.push(...estimatedCost.data);\n }\n }\n\n const costs: any[] = [];\n\n if (query.granularity === GRANULARITY.MONTHLY) {\n costData.forEach(costByOrg => {\n const orgName = costByOrg.attributes?.orgName as string;\n const date = costByOrg.attributes?.date;\n\n if (!this.evaluateIntegrationFilters(orgName, integrationConfig) || !date) {\n return;\n }\n\n costs.push({\n orgName: orgName,\n date: date,\n // only keep cost breakdown\n charges: costByOrg.attributes?.charges?.filter(charge => charge.chargeType !== 'total'),\n });\n });\n } else {\n // Datadog doesn't provide daily costs based on usage, so we allocate monthly costs evenly by day\n costData.forEach(costByOrg => {\n const orgName = costByOrg.attributes?.orgName as string;\n const date = costByOrg.attributes?.date;\n\n if (!this.evaluateIntegrationFilters(orgName, integrationConfig) || !date) {\n return;\n }\n\n const utcDate = moment.utc(date);\n const daysInMonth = utcDate.daysInMonth();\n\n costByOrg.attributes?.charges?.forEach(charge => {\n if (charge.chargeType === 'total') {\n // only keep cost breakdown\n return;\n }\n\n for (let i = 0; i < daysInMonth; i++) {\n const dailyCost = {\n orgName: orgName,\n date: utcDate.clone().add(i, 'd'),\n charges: [\n {\n productName: charge.productName,\n cost: (charge.cost || 0) / daysInMonth,\n chargeType: charge.chargeType,\n },\n ],\n };\n costs.push(dailyCost);\n }\n });\n });\n }\n\n return costs;\n }\n\n protected async transformCostsData(subAccountConfig: Config, query: CostQuery, costResponse: any): Promise<Report[]> {\n const tags = subAccountConfig.getOptionalStringArray('tags');\n const tagKeyValues: { [key: string]: string } = {};\n tags?.forEach(tag => {\n const [k, v] = tag.split(':');\n tagKeyValues[k.trim()] = v.trim();\n });\n\n // Initialize tracking variables\n let processedRecords = 0;\n let filteredOutZeroAmount = 0;\n let filteredOutMissingFields = 0;\n let filteredOutInvalidDate = 0;\n const filteredOutTimeRange = 0;\n const uniqueKeys = new Set<string>();\n const totalRecords = costResponse?.length || 0;\n\n const transformedData = reduce(\n costResponse,\n (accumulator: { [key: string]: Report }, costByOrg) => {\n const account = costByOrg.orgName;\n const charges = costByOrg.charges;\n\n // Check for missing fields\n if (!account || !costByOrg.date) {\n filteredOutMissingFields++;\n return accumulator;\n }\n\n let periodFormat = 'YYYY-MM';\n if (query.granularity === GRANULARITY.DAILY) {\n periodFormat = 'YYYY-MM-DD';\n }\n\n const dateObj = moment.utc(costByOrg.date);\n if (!dateObj.isValid()) {\n filteredOutInvalidDate++;\n return accumulator;\n }\n\n const period = dateObj.format(periodFormat);\n\n if (charges) {\n charges.forEach((charge: datadogApiV2.ChargebackBreakdown) => {\n const productName = charge.productName;\n const cost = charge.cost;\n\n // Check for missing fields\n if (!productName || cost === undefined || cost === null) {\n filteredOutMissingFields++;\n return;\n }\n\n const amount = parseCost(cost);\n\n // Check for zero amount\n if (amount === 0) {\n filteredOutZeroAmount++;\n return;\n }\n\n const keyName = `${account}->${productName} (${charge.chargeType})`;\n\n if (!accumulator[keyName]) {\n uniqueKeys.add(keyName);\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${account}`,\n service: `${this.convertServiceName(productName as string)} (${charge.chargeType})`,\n category: 'Observability',\n provider: this.provider,\n providerType: PROVIDER_TYPE.INTEGRATION,\n reports: {},\n ...tagKeyValues,\n };\n }\n\n accumulator[keyName].reports[period] = amount;\n processedRecords++;\n });\n }\n\n return accumulator;\n },\n {},\n );\n\n this.logTransformationSummary({\n processed: processedRecords,\n uniqueReports: uniqueKeys.size,\n zeroAmount: filteredOutZeroAmount,\n missingFields: filteredOutMissingFields,\n invalidDate: filteredOutInvalidDate,\n timeRange: filteredOutTimeRange,\n totalRecords,\n });\n\n return Object.values(transformedData);\n }\n}\n"],"names":["InfraWalletClient","CLOUD_PROVIDER","datadogClient","datadogApiV2","moment","DatadogCostByOrgResponseSchema","ZodError","GRANULARITY","reduce","parseCost","PROVIDER_TYPE"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electrolux-oss/plugin-infrawallet-backend",
3
- "version": "1.1.0-20251212102352-79a5aeb",
3
+ "version": "1.1.0-20251218080407-fbaf733",
4
4
  "backstage": {
5
5
  "role": "backend-plugin",
6
6
  "pluginId": "infrawallet",