@electrolux-oss/plugin-infrawallet-backend 1.1.0-20260112100533-68a81f8 → 1.1.0-20260115072024-d6f33e2

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.
@@ -176,6 +176,66 @@ class InfraWalletClient {
176
176
  errors
177
177
  };
178
178
  }
179
+ // Helper method to check if database autoload should be used
180
+ shouldUseAutoloadFromDatabase(query, autoloadCostData) {
181
+ return query.tags === "()" && query.groups === "" && autoloadCostData && this.provider !== consts.CLOUD_PROVIDER.MOCK;
182
+ }
183
+ // Helper method to check if current month is included in the query
184
+ isCurrentMonthIncluded(query) {
185
+ const now = /* @__PURE__ */ new Date();
186
+ return query.granularity === consts.GRANULARITY.MONTHLY && parseInt(query.endTime, 10) >= new Date(now.getFullYear(), now.getMonth(), 1).getTime();
187
+ }
188
+ // Helper method to handle cached data retrieval
189
+ async handleCachedData(integrationName, query, results, forecasts) {
190
+ const cachedCosts = await functions.getReportsFromCache(this.cache, this.provider, integrationName, query);
191
+ if (!cachedCosts) {
192
+ return false;
193
+ }
194
+ this.logger.debug(`${this.provider}/${integrationName} costs from cache`);
195
+ cachedCosts.forEach((cost) => results.push(cost));
196
+ if (this.isCurrentMonthIncluded(query)) {
197
+ const cachedForecast = await functions.getForecastFromCache(this.cache, this.provider, integrationName, query);
198
+ if (cachedForecast !== void 0) {
199
+ this.logger.debug(`${this.provider}/${integrationName} forecast from cache: ${cachedForecast}`);
200
+ forecasts[this.provider] = cachedForecast;
201
+ }
202
+ }
203
+ return true;
204
+ }
205
+ // Helper method to process fresh data from API
206
+ async processFreshData(integrationConfig, integrationName, query, results, forecasts) {
207
+ const client = await this.initCloudClient(integrationConfig);
208
+ const costResponse = await this.fetchCosts(integrationConfig, client, query);
209
+ const transformedReports = await this.transformCostsData(integrationConfig, query, costResponse);
210
+ await functions.setReportsToCache(
211
+ this.cache,
212
+ transformedReports,
213
+ this.provider,
214
+ integrationName,
215
+ query,
216
+ functions.getDefaultCacheTTL(consts.CACHE_CATEGORY.COSTS, this.provider)
217
+ );
218
+ transformedReports.forEach((value) => results.push(value));
219
+ if (this.isCurrentMonthIncluded(query)) {
220
+ await this.handleForecastData(integrationConfig, integrationName, query, forecasts);
221
+ }
222
+ }
223
+ // Helper method to handle forecast data processing
224
+ async handleForecastData(integrationConfig, integrationName, query, forecasts) {
225
+ const integrationForecast = await this.fetchForecast(integrationConfig);
226
+ if (integrationForecast !== null && integrationForecast > 0) {
227
+ forecasts[this.provider] = integrationForecast;
228
+ await functions.setForecastToCache(
229
+ this.cache,
230
+ integrationForecast,
231
+ this.provider,
232
+ integrationName,
233
+ query,
234
+ functions.getDefaultCacheTTL(consts.CACHE_CATEGORY.COSTS, this.provider)
235
+ );
236
+ this.logger.debug(`${this.provider}/${integrationName} forecast cached: ${integrationForecast}`);
237
+ }
238
+ }
179
239
  async getCostReports(query) {
180
240
  const autoloadCostData = this.config.getOptionalBoolean("backend.infraWallet.autoload.enabled") ?? false;
181
241
  const integrationConfigs = this.config.getOptionalConfigArray(
@@ -187,47 +247,20 @@ class InfraWalletClient {
187
247
  const results = [];
188
248
  const forecasts = {};
189
249
  const errors = [];
190
- const now = /* @__PURE__ */ new Date();
191
- const isCurrentMonthIncluded = query.granularity === consts.GRANULARITY.MONTHLY && parseInt(query.endTime, 10) >= new Date(now.getFullYear(), now.getMonth(), 1).getTime();
192
- if (query.tags === "()" && query.groups === "" && autoloadCostData && this.provider !== consts.CLOUD_PROVIDER.MOCK) {
250
+ if (this.shouldUseAutoloadFromDatabase(query, autoloadCostData)) {
193
251
  const reportsFromDatabase = await this.getCostReportsFromDatabase(query);
194
- reportsFromDatabase.forEach((report) => {
195
- results.push(report);
196
- });
252
+ reportsFromDatabase.forEach((report) => results.push(report));
197
253
  } else {
198
254
  const promises = [];
199
255
  for (const integrationConfig of integrationConfigs) {
200
256
  const integrationName = integrationConfig.getString("name");
201
- const cachedCosts = await functions.getReportsFromCache(this.cache, this.provider, integrationName, query);
202
- if (cachedCosts) {
203
- this.logger.debug(`${this.provider}/${integrationName} costs from cache`);
204
- cachedCosts.forEach((cost) => {
205
- results.push(cost);
206
- });
257
+ const foundCachedData = await this.handleCachedData(integrationName, query, results, forecasts);
258
+ if (foundCachedData) {
207
259
  continue;
208
260
  }
209
261
  const promise = (async () => {
210
262
  try {
211
- const client = await this.initCloudClient(integrationConfig);
212
- const costResponse = await this.fetchCosts(integrationConfig, client, query);
213
- const transformedReports = await this.transformCostsData(integrationConfig, query, costResponse);
214
- await functions.setReportsToCache(
215
- this.cache,
216
- transformedReports,
217
- this.provider,
218
- integrationName,
219
- query,
220
- functions.getDefaultCacheTTL(consts.CACHE_CATEGORY.COSTS, this.provider)
221
- );
222
- transformedReports.forEach((value) => {
223
- results.push(value);
224
- });
225
- if (isCurrentMonthIncluded) {
226
- const integrationForecast = await this.fetchForecast(integrationConfig);
227
- if (integrationForecast !== null) {
228
- forecasts[this.provider] = integrationForecast;
229
- }
230
- }
263
+ await this.processFreshData(integrationConfig, integrationName, query, results, forecasts);
231
264
  } catch (e) {
232
265
  this.logger.error(e);
233
266
  errors.push({
@@ -1 +1 @@
1
- {"version":3,"file":"InfraWalletClient.cjs.js","sources":["../../src/cost-clients/InfraWalletClient.ts"],"sourcesContent":["import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { addMonths, endOfMonth, format, startOfMonth } from 'date-fns';\nimport { reduce } from 'lodash';\nimport { getWallet } from '../controllers/MetricSettingController';\nimport { CostItem, bulkInsertCostItems, countCostItems, getCostItems } from '../models/CostItem';\nimport {\n CACHE_CATEGORY,\n CLOUD_PROVIDER,\n GRANULARITY,\n NUMBER_OF_MONTHS_FETCHING_HISTORICAL_COSTS,\n PROVIDER_TYPE,\n} from '../service/consts';\nimport {\n getDefaultCacheTTL,\n getReportsFromCache,\n getTagKeysFromCache,\n getTagValuesFromCache,\n logTransformationSummary,\n setReportsToCache,\n setTagKeysToCache,\n setTagValuesToCache,\n tagExists,\n usageDateToPeriodString,\n} from '../service/functions';\nimport {\n ClientResponse,\n CloudProviderError,\n CostQuery,\n Filter,\n Report,\n Tag,\n TagsQuery,\n TagsResponse,\n TransformationSummary,\n Wallet,\n} from '../service/types';\n\nexport abstract class InfraWalletClient {\n constructor(\n protected readonly provider: CLOUD_PROVIDER,\n protected readonly config: Config,\n protected readonly database: DatabaseService,\n protected readonly cache: CacheService,\n protected readonly logger: LoggerService,\n ) {}\n\n protected convertServiceName(serviceName: string): string {\n return `${this.provider}/${serviceName}`;\n }\n\n protected evaluateIntegrationFilters(account: string, integrationConfig: Config): boolean {\n const filters: Filter[] = [];\n for (const filter of integrationConfig.getOptionalConfigArray('filters') || []) {\n filters.push({\n type: filter.getString('type'),\n attribute: filter.getString('attribute'),\n pattern: filter.getString('pattern'),\n });\n }\n return this.evaluateFilters(account, filters);\n }\n\n private evaluateFilters(account: string, filters: Filter[]): boolean {\n if (!filters || filters.length === 0) {\n // include if no filter\n return true;\n }\n\n let included = false;\n let hasIncludeFilter = false;\n\n for (const filter of filters) {\n const regex = new RegExp(filter.pattern);\n\n if (filter.type === 'exclude' && regex.test(account)) {\n // exclude immediately if an exclude filter matches\n return false;\n }\n\n if (filter.type === 'include') {\n hasIncludeFilter = true;\n\n if (regex.test(account)) {\n included = true;\n }\n }\n }\n\n if (hasIncludeFilter) {\n return included;\n }\n\n return true;\n }\n\n protected abstract initCloudClient(integrationConfig: Config): Promise<any>;\n\n // Get all cost allocation tag keys from one account\n protected async fetchTagKeys(\n _integrationConfig: Config,\n _client: any,\n _query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented by each provider client\n return { tagKeys: [], provider: this.provider };\n }\n\n // Get all tag values of the specified tag key from one account\n protected async fetchTagValues(\n _integrationConfig: Config,\n _client: any,\n _query: TagsQuery,\n _tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented by each provider client\n return { tagValues: [], provider: this.provider };\n }\n\n protected abstract fetchCosts(integrationConfig: Config, client: any, query: CostQuery): Promise<any>;\n protected async fetchForecast(_integrationConfig: Config): Promise<number | null> {\n return null;\n }\n\n protected abstract transformCostsData(\n integrationConfig: Config,\n query: CostQuery,\n costResponse: any,\n ): Promise<Report[]>;\n\n protected logTransformationSummary(summary: TransformationSummary): void {\n logTransformationSummary(this.logger, this.provider, summary);\n }\n\n // Get aggregated unique tag keys across all accounts of this cloud provider\n async getTagKeys(query: TagsQuery): Promise<TagsResponse> {\n const integrationConfigs = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n if (!integrationConfigs) {\n return { tags: [], errors: [] };\n }\n\n const promises = [];\n const aggregatedTags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n for (const integrationConfig of integrationConfigs) {\n const integrationName = integrationConfig.getString('name');\n\n const cachedTagKeys = await getTagKeysFromCache(this.cache, this.provider, integrationName, query);\n if (cachedTagKeys) {\n this.logger.info(`Reuse ${this.provider}/${integrationName} tag keys from cache`);\n\n for (const tag of cachedTagKeys) {\n if (!tagExists(aggregatedTags, tag)) {\n aggregatedTags.push(tag);\n }\n }\n\n continue;\n }\n\n const promise = (async () => {\n try {\n const client = await this.initCloudClient(integrationConfig);\n const response = await this.fetchTagKeys(integrationConfig, client, query);\n const tagKeysCache: Tag[] = [];\n\n for (const tagKey of response.tagKeys) {\n const tag = { key: tagKey, provider: response.provider };\n tagKeysCache.push(tag);\n\n if (!tagExists(aggregatedTags, tag)) {\n aggregatedTags.push(tag);\n }\n }\n await setTagKeysToCache(this.cache, tagKeysCache, this.provider, integrationName, query);\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: `${this.provider}/${integrationName}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n await Promise.all(promises);\n\n aggregatedTags.sort((a, b) => `${a.provider}/${a.key}`.localeCompare(`${b.provider}/${b.key}`));\n\n return {\n tags: aggregatedTags,\n errors: errors,\n };\n }\n\n // Get aggregated tag values of the specified tag key across all accounts of this cloud provider\n async getTagValues(query: TagsQuery, tagKey: string): Promise<TagsResponse> {\n const integrationConfigs = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n if (!integrationConfigs) {\n return { tags: [], errors: [] };\n }\n\n const promises = [];\n const aggregatedTags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n for (const integrationConfig of integrationConfigs) {\n const integrationName = integrationConfig.getString('name');\n\n const cachedTagValues = await getTagValuesFromCache(this.cache, this.provider, integrationName, tagKey, query);\n if (cachedTagValues) {\n this.logger.info(`Reuse ${this.provider}/${integrationName}/${tagKey} tag values from cache`);\n\n for (const tag of cachedTagValues) {\n if (!tagExists(aggregatedTags, tag)) {\n aggregatedTags.push(tag);\n }\n }\n\n continue;\n }\n\n const promise = (async () => {\n try {\n const client = await this.initCloudClient(integrationConfig);\n const response = await this.fetchTagValues(integrationConfig, client, query, tagKey);\n const tagValuesCache: Tag[] = [];\n\n for (const tagValue of response.tagValues) {\n const tag = { key: tagKey, value: tagValue, provider: response.provider };\n tagValuesCache.push(tag);\n\n if (!tagExists(aggregatedTags, tag)) {\n aggregatedTags.push(tag);\n }\n }\n await setTagValuesToCache(this.cache, tagValuesCache, this.provider, integrationName, tagKey, query);\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: `${this.provider}/${integrationName}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n await Promise.all(promises);\n\n aggregatedTags.sort((a, b) =>\n `${a.provider}/${a.key}=${a.value}`.localeCompare(`${b.provider}/${b.key}=${b.value}`),\n );\n\n return {\n tags: aggregatedTags,\n errors: errors,\n };\n }\n\n async getCostReports(query: CostQuery): Promise<ClientResponse> {\n const autoloadCostData = this.config.getOptionalBoolean('backend.infraWallet.autoload.enabled') ?? false;\n const integrationConfigs = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n if (!integrationConfigs) {\n return { reports: [], errors: [] };\n }\n\n const results: Report[] = [];\n const forecasts: Record<string, number> = {};\n const errors: CloudProviderError[] = [];\n\n const now = new Date();\n const isCurrentMonthIncluded =\n query.granularity === GRANULARITY.MONTHLY &&\n parseInt(query.endTime, 10) >= new Date(now.getFullYear(), now.getMonth(), 1).getTime();\n\n // if autoloadCostData enabled, for a query without any tags or groups, we get the results from the plugin database\n // skip Mock provider for autoloading data\n if (query.tags === '()' && query.groups === '' && autoloadCostData && this.provider !== CLOUD_PROVIDER.MOCK) {\n const reportsFromDatabase = await this.getCostReportsFromDatabase(query);\n reportsFromDatabase.forEach(report => {\n results.push(report);\n });\n } else {\n const promises = [];\n for (const integrationConfig of integrationConfigs) {\n const integrationName = integrationConfig.getString('name');\n\n // first check if there is any cached\n const cachedCosts = await getReportsFromCache(this.cache, this.provider, integrationName, query);\n if (cachedCosts) {\n this.logger.debug(`${this.provider}/${integrationName} costs from cache`);\n cachedCosts.forEach(cost => {\n results.push(cost);\n });\n continue;\n }\n\n const promise = (async () => {\n try {\n const client = await this.initCloudClient(integrationConfig);\n const costResponse = await this.fetchCosts(integrationConfig, client, query);\n\n const transformedReports = await this.transformCostsData(integrationConfig, query, costResponse);\n\n // cache the results\n await setReportsToCache(\n this.cache,\n transformedReports,\n this.provider,\n integrationName,\n query,\n getDefaultCacheTTL(CACHE_CATEGORY.COSTS, this.provider),\n );\n\n transformedReports.forEach((value: any) => {\n results.push(value);\n });\n if (isCurrentMonthIncluded) {\n const integrationForecast = await this.fetchForecast(integrationConfig);\n if (integrationForecast !== null) {\n forecasts[this.provider] = integrationForecast;\n }\n }\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: `${this.provider}/${integrationName}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n await Promise.all(promises);\n }\n\n return {\n reports: results,\n forecasts: forecasts,\n errors: errors,\n };\n }\n\n async saveCostReportsToDatabase(wallet: Wallet, granularity: GRANULARITY): Promise<void> {\n const count = await countCostItems(this.database, wallet.id, this.provider, granularity);\n\n const endTime = endOfMonth(new Date());\n let startTime = startOfMonth(addMonths(new Date(), -1));\n if (count === 0) {\n // if there is no record, the first call is going to fetch the last 364 days' cost data\n // it cannot be 365 day or 1 year because Azure API will responds with the following error\n // Invalid query definition: The time period for pulling the data cannot exceed 1 year(s)\n startTime = startOfMonth(\n addMonths(new Date(), -1 * NUMBER_OF_MONTHS_FETCHING_HISTORICAL_COSTS[this.provider] + 1),\n );\n }\n\n this.logger.debug(`Fetching ${granularity} costs from ${startTime} to ${endTime} for ${this.provider}`);\n\n const results: Report[] = [];\n const usageDateFormat = granularity === GRANULARITY.DAILY ? 'yyyyMMdd' : 'yyyyMM';\n try {\n const clientResponse = await this.getCostReports({\n filters: '',\n tags: '',\n groups: '',\n granularity: granularity,\n startTime: startTime.getTime().toString(),\n endTime: endTime.getTime().toString(),\n });\n clientResponse.reports.forEach((cost: Report) => {\n results.push(cost);\n });\n } catch (e) {\n this.logger.error(e);\n }\n\n await bulkInsertCostItems(\n this.database,\n wallet.id,\n this.provider,\n granularity,\n parseInt(format(startTime, usageDateFormat), 10),\n parseInt(format(endTime, usageDateFormat), 10),\n results,\n );\n }\n\n async getCostReportsFromDatabase(query: CostQuery): Promise<Report[]> {\n // TODO: support searching for different wallets in the future, for now it is always the default wallet\n const defaultWallet = await getWallet(this.database, 'default');\n if (defaultWallet !== undefined) {\n // query the database\n const usageDateFormat = query.granularity === 'daily' ? 'yyyyMMdd' : 'yyyyMM';\n const startUsageDate = parseInt(format(parseInt(query.startTime, 10), usageDateFormat), 10);\n const endUsageDate = parseInt(format(parseInt(query.endTime, 10), usageDateFormat), 10);\n const costItems = await getCostItems(\n this.database,\n defaultWallet.id,\n this.provider,\n query.granularity,\n startUsageDate,\n endUsageDate,\n );\n\n // transform the cost items into cost reports\n const transformedData = reduce(\n costItems,\n (accumulator: { [key: string]: Report }, row: CostItem) => {\n const key = row.key;\n const otherColumns =\n typeof row.other_columns === 'string' ? JSON.parse(row.other_columns) : row.other_columns;\n\n if (!accumulator[key]) {\n accumulator[key] = {\n id: key,\n account: row.account,\n service: row.service,\n category: row.category,\n provider: row.provider,\n providerType: PROVIDER_TYPE.INTEGRATION,\n reports: {},\n ...otherColumns,\n };\n }\n accumulator[key].reports[usageDateToPeriodString(row.usage_date)] = parseFloat(row.cost as string);\n\n return accumulator;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n\n return [];\n }\n}\n"],"names":["logTransformationSummary","getTagKeysFromCache","tagExists","setTagKeysToCache","getTagValuesFromCache","setTagValuesToCache","GRANULARITY","CLOUD_PROVIDER","getReportsFromCache","setReportsToCache","getDefaultCacheTTL","CACHE_CATEGORY","countCostItems","endOfMonth","startOfMonth","addMonths","NUMBER_OF_MONTHS_FETCHING_HISTORICAL_COSTS","bulkInsertCostItems","format","getWallet","getCostItems","reduce","PROVIDER_TYPE","usageDateToPeriodString"],"mappings":"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"}
1
+ {"version":3,"file":"InfraWalletClient.cjs.js","sources":["../../src/cost-clients/InfraWalletClient.ts"],"sourcesContent":["import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { addMonths, endOfMonth, format, startOfMonth } from 'date-fns';\nimport { reduce } from 'lodash';\nimport { getWallet } from '../controllers/MetricSettingController';\nimport { CostItem, bulkInsertCostItems, countCostItems, getCostItems } from '../models/CostItem';\nimport {\n CACHE_CATEGORY,\n CLOUD_PROVIDER,\n GRANULARITY,\n NUMBER_OF_MONTHS_FETCHING_HISTORICAL_COSTS,\n PROVIDER_TYPE,\n} from '../service/consts';\nimport {\n getDefaultCacheTTL,\n getForecastFromCache,\n getReportsFromCache,\n getTagKeysFromCache,\n getTagValuesFromCache,\n logTransformationSummary,\n setForecastToCache,\n setReportsToCache,\n setTagKeysToCache,\n setTagValuesToCache,\n tagExists,\n usageDateToPeriodString,\n} from '../service/functions';\nimport {\n ClientResponse,\n CloudProviderError,\n CostQuery,\n Filter,\n Report,\n Tag,\n TagsQuery,\n TagsResponse,\n TransformationSummary,\n Wallet,\n} from '../service/types';\n\nexport abstract class InfraWalletClient {\n constructor(\n protected readonly provider: CLOUD_PROVIDER,\n protected readonly config: Config,\n protected readonly database: DatabaseService,\n protected readonly cache: CacheService,\n protected readonly logger: LoggerService,\n ) {}\n\n protected convertServiceName(serviceName: string): string {\n return `${this.provider}/${serviceName}`;\n }\n\n protected evaluateIntegrationFilters(account: string, integrationConfig: Config): boolean {\n const filters: Filter[] = [];\n for (const filter of integrationConfig.getOptionalConfigArray('filters') || []) {\n filters.push({\n type: filter.getString('type'),\n attribute: filter.getString('attribute'),\n pattern: filter.getString('pattern'),\n });\n }\n return this.evaluateFilters(account, filters);\n }\n\n private evaluateFilters(account: string, filters: Filter[]): boolean {\n if (!filters || filters.length === 0) {\n // include if no filter\n return true;\n }\n\n let included = false;\n let hasIncludeFilter = false;\n\n for (const filter of filters) {\n const regex = new RegExp(filter.pattern);\n\n if (filter.type === 'exclude' && regex.test(account)) {\n // exclude immediately if an exclude filter matches\n return false;\n }\n\n if (filter.type === 'include') {\n hasIncludeFilter = true;\n\n if (regex.test(account)) {\n included = true;\n }\n }\n }\n\n if (hasIncludeFilter) {\n return included;\n }\n\n return true;\n }\n\n protected abstract initCloudClient(integrationConfig: Config): Promise<any>;\n\n // Get all cost allocation tag keys from one account\n protected async fetchTagKeys(\n _integrationConfig: Config,\n _client: any,\n _query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented by each provider client\n return { tagKeys: [], provider: this.provider };\n }\n\n // Get all tag values of the specified tag key from one account\n protected async fetchTagValues(\n _integrationConfig: Config,\n _client: any,\n _query: TagsQuery,\n _tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented by each provider client\n return { tagValues: [], provider: this.provider };\n }\n\n protected abstract fetchCosts(integrationConfig: Config, client: any, query: CostQuery): Promise<any>;\n protected async fetchForecast(_integrationConfig: Config): Promise<number | null> {\n return null;\n }\n\n protected abstract transformCostsData(\n integrationConfig: Config,\n query: CostQuery,\n costResponse: any,\n ): Promise<Report[]>;\n\n protected logTransformationSummary(summary: TransformationSummary): void {\n logTransformationSummary(this.logger, this.provider, summary);\n }\n\n // Get aggregated unique tag keys across all accounts of this cloud provider\n async getTagKeys(query: TagsQuery): Promise<TagsResponse> {\n const integrationConfigs = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n if (!integrationConfigs) {\n return { tags: [], errors: [] };\n }\n\n const promises = [];\n const aggregatedTags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n for (const integrationConfig of integrationConfigs) {\n const integrationName = integrationConfig.getString('name');\n\n const cachedTagKeys = await getTagKeysFromCache(this.cache, this.provider, integrationName, query);\n if (cachedTagKeys) {\n this.logger.info(`Reuse ${this.provider}/${integrationName} tag keys from cache`);\n\n for (const tag of cachedTagKeys) {\n if (!tagExists(aggregatedTags, tag)) {\n aggregatedTags.push(tag);\n }\n }\n\n continue;\n }\n\n const promise = (async () => {\n try {\n const client = await this.initCloudClient(integrationConfig);\n const response = await this.fetchTagKeys(integrationConfig, client, query);\n const tagKeysCache: Tag[] = [];\n\n for (const tagKey of response.tagKeys) {\n const tag = { key: tagKey, provider: response.provider };\n tagKeysCache.push(tag);\n\n if (!tagExists(aggregatedTags, tag)) {\n aggregatedTags.push(tag);\n }\n }\n await setTagKeysToCache(this.cache, tagKeysCache, this.provider, integrationName, query);\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: `${this.provider}/${integrationName}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n await Promise.all(promises);\n\n aggregatedTags.sort((a, b) => `${a.provider}/${a.key}`.localeCompare(`${b.provider}/${b.key}`));\n\n return {\n tags: aggregatedTags,\n errors: errors,\n };\n }\n\n // Get aggregated tag values of the specified tag key across all accounts of this cloud provider\n async getTagValues(query: TagsQuery, tagKey: string): Promise<TagsResponse> {\n const integrationConfigs = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n if (!integrationConfigs) {\n return { tags: [], errors: [] };\n }\n\n const promises = [];\n const aggregatedTags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n for (const integrationConfig of integrationConfigs) {\n const integrationName = integrationConfig.getString('name');\n\n const cachedTagValues = await getTagValuesFromCache(this.cache, this.provider, integrationName, tagKey, query);\n if (cachedTagValues) {\n this.logger.info(`Reuse ${this.provider}/${integrationName}/${tagKey} tag values from cache`);\n\n for (const tag of cachedTagValues) {\n if (!tagExists(aggregatedTags, tag)) {\n aggregatedTags.push(tag);\n }\n }\n\n continue;\n }\n\n const promise = (async () => {\n try {\n const client = await this.initCloudClient(integrationConfig);\n const response = await this.fetchTagValues(integrationConfig, client, query, tagKey);\n const tagValuesCache: Tag[] = [];\n\n for (const tagValue of response.tagValues) {\n const tag = { key: tagKey, value: tagValue, provider: response.provider };\n tagValuesCache.push(tag);\n\n if (!tagExists(aggregatedTags, tag)) {\n aggregatedTags.push(tag);\n }\n }\n await setTagValuesToCache(this.cache, tagValuesCache, this.provider, integrationName, tagKey, query);\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: `${this.provider}/${integrationName}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n await Promise.all(promises);\n\n aggregatedTags.sort((a, b) =>\n `${a.provider}/${a.key}=${a.value}`.localeCompare(`${b.provider}/${b.key}=${b.value}`),\n );\n\n return {\n tags: aggregatedTags,\n errors: errors,\n };\n }\n\n // Helper method to check if database autoload should be used\n private shouldUseAutoloadFromDatabase(query: CostQuery, autoloadCostData: boolean): boolean {\n return query.tags === '()' && query.groups === '' && autoloadCostData && this.provider !== CLOUD_PROVIDER.MOCK;\n }\n\n // Helper method to check if current month is included in the query\n private isCurrentMonthIncluded(query: CostQuery): boolean {\n const now = new Date();\n return (\n query.granularity === GRANULARITY.MONTHLY &&\n parseInt(query.endTime, 10) >= new Date(now.getFullYear(), now.getMonth(), 1).getTime()\n );\n }\n\n // Helper method to handle cached data retrieval\n private async handleCachedData(\n integrationName: string,\n query: CostQuery,\n results: Report[],\n forecasts: Record<string, number>,\n ): Promise<boolean> {\n const cachedCosts = await getReportsFromCache(this.cache, this.provider, integrationName, query);\n if (!cachedCosts) {\n return false;\n }\n\n this.logger.debug(`${this.provider}/${integrationName} costs from cache`);\n cachedCosts.forEach(cost => results.push(cost));\n\n if (this.isCurrentMonthIncluded(query)) {\n const cachedForecast = await getForecastFromCache(this.cache, this.provider, integrationName, query);\n if (cachedForecast !== undefined) {\n this.logger.debug(`${this.provider}/${integrationName} forecast from cache: ${cachedForecast}`);\n forecasts[this.provider] = cachedForecast;\n }\n }\n return true;\n }\n\n // Helper method to process fresh data from API\n private async processFreshData(\n integrationConfig: Config,\n integrationName: string,\n query: CostQuery,\n results: Report[],\n forecasts: Record<string, number>,\n ): Promise<void> {\n const client = await this.initCloudClient(integrationConfig);\n const costResponse = await this.fetchCosts(integrationConfig, client, query);\n const transformedReports = await this.transformCostsData(integrationConfig, query, costResponse);\n\n // Cache the results\n await setReportsToCache(\n this.cache,\n transformedReports,\n this.provider,\n integrationName,\n query,\n getDefaultCacheTTL(CACHE_CATEGORY.COSTS, this.provider),\n );\n\n transformedReports.forEach((value: any) => results.push(value));\n\n if (this.isCurrentMonthIncluded(query)) {\n await this.handleForecastData(integrationConfig, integrationName, query, forecasts);\n }\n }\n\n // Helper method to handle forecast data processing\n private async handleForecastData(\n integrationConfig: Config,\n integrationName: string,\n query: CostQuery,\n forecasts: Record<string, number>,\n ): Promise<void> {\n const integrationForecast = await this.fetchForecast(integrationConfig);\n if (integrationForecast !== null && integrationForecast > 0) {\n forecasts[this.provider] = integrationForecast;\n\n await setForecastToCache(\n this.cache,\n integrationForecast,\n this.provider,\n integrationName,\n query,\n getDefaultCacheTTL(CACHE_CATEGORY.COSTS, this.provider),\n );\n this.logger.debug(`${this.provider}/${integrationName} forecast cached: ${integrationForecast}`);\n }\n }\n\n async getCostReports(query: CostQuery): Promise<ClientResponse> {\n const autoloadCostData = this.config.getOptionalBoolean('backend.infraWallet.autoload.enabled') ?? false;\n const integrationConfigs = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n\n if (!integrationConfigs) {\n return { reports: [], errors: [] };\n }\n\n const results: Report[] = [];\n const forecasts: Record<string, number> = {};\n const errors: CloudProviderError[] = [];\n\n // Use autoload from database if conditions are met\n if (this.shouldUseAutoloadFromDatabase(query, autoloadCostData)) {\n const reportsFromDatabase = await this.getCostReportsFromDatabase(query);\n reportsFromDatabase.forEach(report => results.push(report));\n } else {\n const promises = [];\n\n for (const integrationConfig of integrationConfigs) {\n const integrationName = integrationConfig.getString('name');\n\n // Check for cached data first\n const foundCachedData = await this.handleCachedData(integrationName, query, results, forecasts);\n\n if (foundCachedData) {\n continue;\n }\n\n // Process fresh data from API\n const promise = (async () => {\n try {\n await this.processFreshData(integrationConfig, integrationName, query, results, forecasts);\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: `${this.provider}/${integrationName}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n await Promise.all(promises);\n }\n\n return {\n reports: results,\n forecasts: forecasts,\n errors: errors,\n };\n }\n\n async saveCostReportsToDatabase(wallet: Wallet, granularity: GRANULARITY): Promise<void> {\n const count = await countCostItems(this.database, wallet.id, this.provider, granularity);\n\n const endTime = endOfMonth(new Date());\n let startTime = startOfMonth(addMonths(new Date(), -1));\n if (count === 0) {\n // if there is no record, the first call is going to fetch the last 364 days' cost data\n // it cannot be 365 day or 1 year because Azure API will responds with the following error\n // Invalid query definition: The time period for pulling the data cannot exceed 1 year(s)\n startTime = startOfMonth(\n addMonths(new Date(), -1 * NUMBER_OF_MONTHS_FETCHING_HISTORICAL_COSTS[this.provider] + 1),\n );\n }\n\n this.logger.debug(`Fetching ${granularity} costs from ${startTime} to ${endTime} for ${this.provider}`);\n\n const results: Report[] = [];\n const usageDateFormat = granularity === GRANULARITY.DAILY ? 'yyyyMMdd' : 'yyyyMM';\n try {\n const clientResponse = await this.getCostReports({\n filters: '',\n tags: '',\n groups: '',\n granularity: granularity,\n startTime: startTime.getTime().toString(),\n endTime: endTime.getTime().toString(),\n });\n clientResponse.reports.forEach((cost: Report) => {\n results.push(cost);\n });\n } catch (e) {\n this.logger.error(e);\n }\n\n await bulkInsertCostItems(\n this.database,\n wallet.id,\n this.provider,\n granularity,\n parseInt(format(startTime, usageDateFormat), 10),\n parseInt(format(endTime, usageDateFormat), 10),\n results,\n );\n }\n\n async getCostReportsFromDatabase(query: CostQuery): Promise<Report[]> {\n // TODO: support searching for different wallets in the future, for now it is always the default wallet\n const defaultWallet = await getWallet(this.database, 'default');\n if (defaultWallet !== undefined) {\n // query the database\n const usageDateFormat = query.granularity === 'daily' ? 'yyyyMMdd' : 'yyyyMM';\n const startUsageDate = parseInt(format(parseInt(query.startTime, 10), usageDateFormat), 10);\n const endUsageDate = parseInt(format(parseInt(query.endTime, 10), usageDateFormat), 10);\n const costItems = await getCostItems(\n this.database,\n defaultWallet.id,\n this.provider,\n query.granularity,\n startUsageDate,\n endUsageDate,\n );\n\n // transform the cost items into cost reports\n const transformedData = reduce(\n costItems,\n (accumulator: { [key: string]: Report }, row: CostItem) => {\n const key = row.key;\n const otherColumns =\n typeof row.other_columns === 'string' ? JSON.parse(row.other_columns) : row.other_columns;\n\n if (!accumulator[key]) {\n accumulator[key] = {\n id: key,\n account: row.account,\n service: row.service,\n category: row.category,\n provider: row.provider,\n providerType: PROVIDER_TYPE.INTEGRATION,\n reports: {},\n ...otherColumns,\n };\n }\n accumulator[key].reports[usageDateToPeriodString(row.usage_date)] = parseFloat(row.cost as string);\n\n return accumulator;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n\n return [];\n }\n}\n"],"names":["logTransformationSummary","getTagKeysFromCache","tagExists","setTagKeysToCache","getTagValuesFromCache","setTagValuesToCache","CLOUD_PROVIDER","GRANULARITY","getReportsFromCache","getForecastFromCache","setReportsToCache","getDefaultCacheTTL","CACHE_CATEGORY","setForecastToCache","countCostItems","endOfMonth","startOfMonth","addMonths","NUMBER_OF_MONTHS_FETCHING_HISTORICAL_COSTS","bulkInsertCostItems","format","getWallet","getCostItems","reduce","PROVIDER_TYPE","usageDateToPeriodString"],"mappings":"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"}
@@ -76,6 +76,21 @@ async function getReportsFromCache(cache, provider, configKey, query) {
76
76
  const cachedCosts = await cache.get(cacheKey);
77
77
  return cachedCosts;
78
78
  }
79
+ async function getForecastFromCache(cache, provider, configKey, query) {
80
+ const cacheKey = [
81
+ "forecast",
82
+ provider,
83
+ configKey,
84
+ query.filters,
85
+ query.tags,
86
+ query.groups,
87
+ query.granularity,
88
+ query.startTime,
89
+ query.endTime
90
+ ].join("_");
91
+ const cachedForecast = await cache.get(cacheKey);
92
+ return cachedForecast;
93
+ }
79
94
  async function getMetricsFromCache(cache, provider, configKey, query) {
80
95
  const cacheKey = [
81
96
  provider,
@@ -125,6 +140,23 @@ async function setReportsToCache(cache, reports, provider, configKey, query, ttl
125
140
  ttl: ttl ?? 60 * 60 * 2 * 1e3
126
141
  });
127
142
  }
143
+ async function setForecastToCache(cache, forecast, provider, configKey, query, ttl) {
144
+ const cacheKey = [
145
+ "forecast",
146
+ provider,
147
+ configKey,
148
+ query.filters,
149
+ query.tags,
150
+ query.groups,
151
+ query.granularity,
152
+ query.startTime,
153
+ query.endTime
154
+ ].join("_");
155
+ await cache.set(cacheKey, forecast, {
156
+ ttl: ttl ?? 60 * 60 * 2 * 1e3
157
+ // cache for 2 hours by default, same as reports
158
+ });
159
+ }
128
160
  async function setMetricsToCache(cache, metrics, provider, configKey, query, ttl) {
129
161
  const cacheKey = [
130
162
  provider,
@@ -207,6 +239,7 @@ exports.getBillingPeriod = getBillingPeriod;
207
239
  exports.getBillingPeriodFormat = getBillingPeriodFormat;
208
240
  exports.getDailyPeriodStringsForOneMonth = getDailyPeriodStringsForOneMonth;
209
241
  exports.getDefaultCacheTTL = getDefaultCacheTTL;
242
+ exports.getForecastFromCache = getForecastFromCache;
210
243
  exports.getMetricsFromCache = getMetricsFromCache;
211
244
  exports.getReportsFromCache = getReportsFromCache;
212
245
  exports.getTagKeysFromCache = getTagKeysFromCache;
@@ -215,6 +248,7 @@ exports.logTransformationSummary = logTransformationSummary;
215
248
  exports.parseCost = parseCost;
216
249
  exports.parseFilters = parseFilters;
217
250
  exports.parseTags = parseTags;
251
+ exports.setForecastToCache = setForecastToCache;
218
252
  exports.setMetricsToCache = setMetricsToCache;
219
253
  exports.setReportsToCache = setReportsToCache;
220
254
  exports.setTagKeysToCache = setTagKeysToCache;
@@ -1 +1 @@
1
- {"version":3,"file":"functions.cjs.js","sources":["../../src/service/functions.ts"],"sourcesContent":["import { CacheService, LoggerService } from '@backstage/backend-plugin-api';\nimport { CACHE_CATEGORY, CLOUD_PROVIDER, DEFAULT_COSTS_CACHE_TTL, DEFAULT_TAGS_CACHE_TTL, GRANULARITY } from './consts';\nimport { CostQuery, Metric, MetricQuery, Report, Tag, TagsQuery, TransformationSummary } from './types';\nimport moment from 'moment';\n\n// In URL, tags are defined in this format:\n// tags=(provider1:key1=value1 OR provider2:key2=value2)\nexport function parseTags(tags: string): Tag[] {\n if (!tags.startsWith('(') || !tags.endsWith(')')) {\n return [];\n }\n\n const tagString = tags.slice(1, -1);\n if (!tagString) {\n return [];\n }\n\n const keyValuePairs = tagString.split(' OR ');\n return keyValuePairs.map(pair => {\n const [providerAndKey, value] = pair.split('=');\n const firstColonIndex = providerAndKey.indexOf(':');\n const provider = providerAndKey.slice(0, firstColonIndex);\n const key = providerAndKey.slice(firstColonIndex + 1);\n return { key: key, value: value, provider: provider };\n });\n}\n\n// convert Tag array to (provider1:key1=value1 OR provider2:key2=value2) format\nexport function tagsToString(tags: Tag[]): string {\n if (!tags || tags.length === 0) {\n return '()';\n }\n\n const keyValuePairs = tags.map(tag => `${tag.provider}:${tag.key}=${tag.value}`);\n return `(${keyValuePairs.join(' OR ')})`;\n}\n\n// check if targetTag exists in tags\nexport function tagExists(tags: Tag[], targetTag: Tag): boolean {\n return tags.some(\n tag => tag.provider === targetTag.provider && tag.key === targetTag.key && tag.value === targetTag.value,\n );\n}\n\nexport function getDefaultCacheTTL(cacheCategory: CACHE_CATEGORY, provider: CLOUD_PROVIDER): number {\n if (cacheCategory === CACHE_CATEGORY.TAGS) {\n return DEFAULT_TAGS_CACHE_TTL[provider];\n } else if (cacheCategory === CACHE_CATEGORY.COSTS) {\n return DEFAULT_COSTS_CACHE_TTL[provider];\n }\n\n return 0;\n}\n\nexport async function getTagKeysFromCache(\n cache: CacheService,\n provider: CLOUD_PROVIDER,\n configKey: string,\n query: TagsQuery,\n): Promise<Tag[] | undefined> {\n const cacheKey = [CACHE_CATEGORY.TAGS, 'tag-keys', provider, configKey, query.startTime, query.endTime].join('_');\n const data = (await cache.get(cacheKey)) as Tag[] | undefined;\n return data;\n}\n\nexport async function getTagValuesFromCache(\n cache: CacheService,\n provider: CLOUD_PROVIDER,\n configKey: string,\n tagKey: string,\n query: TagsQuery,\n): Promise<Tag[] | undefined> {\n const cacheKey = [\n CACHE_CATEGORY.TAGS,\n 'tag-values',\n provider,\n configKey,\n tagKey,\n query.startTime,\n query.endTime,\n ].join('_');\n const data = (await cache.get(cacheKey)) as Tag[] | undefined;\n return data;\n}\n\nexport async function getReportsFromCache(\n cache: CacheService,\n provider: string,\n configKey: string,\n query: CostQuery,\n): Promise<Report[] | undefined> {\n const cacheKey = [\n provider,\n configKey,\n query.filters,\n query.tags,\n query.groups,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n const cachedCosts = (await cache.get(cacheKey)) as Report[] | undefined;\n return cachedCosts;\n}\n\nexport async function getMetricsFromCache(\n cache: CacheService,\n provider: string,\n configKey: string,\n query: MetricQuery,\n): Promise<Metric[] | undefined> {\n const cacheKey = [\n provider,\n configKey,\n query.name,\n query.query,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n const crypto = require('crypto');\n const cachedMetrics = (await cache.get(crypto.createHash('md5').update(cacheKey).digest('hex'))) as\n | Metric[]\n | undefined;\n return cachedMetrics;\n}\n\nexport async function setTagKeysToCache(\n cache: CacheService,\n tags: Tag[],\n provider: CLOUD_PROVIDER,\n configKey: string,\n query: TagsQuery,\n ttl?: number,\n) {\n const cacheKey = [CACHE_CATEGORY.TAGS, 'tag-keys', provider, configKey, query.startTime, query.endTime].join('_');\n await cache.set(cacheKey, tags, {\n ttl: ttl ?? getDefaultCacheTTL(CACHE_CATEGORY.TAGS, provider),\n });\n}\n\nexport async function setTagValuesToCache(\n cache: CacheService,\n tags: Tag[],\n provider: CLOUD_PROVIDER,\n configKey: string,\n tagKey: string,\n query: TagsQuery,\n ttl?: number,\n) {\n const cacheKey = [\n CACHE_CATEGORY.TAGS,\n 'tag-values',\n provider,\n configKey,\n tagKey,\n query.startTime,\n query.endTime,\n ].join('_');\n await cache.set(cacheKey, tags, {\n ttl: ttl ?? getDefaultCacheTTL(CACHE_CATEGORY.TAGS, provider),\n });\n}\n\nexport async function setReportsToCache(\n cache: CacheService,\n reports: Report[],\n provider: string,\n configKey: string,\n query: CostQuery,\n ttl?: number,\n) {\n const cacheKey = [\n provider,\n configKey,\n query.filters,\n query.tags,\n query.groups,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n await cache.set(cacheKey, reports, {\n ttl: ttl ?? 60 * 60 * 2 * 1000,\n }); // cache for 2 hours by default\n}\n\nexport async function setMetricsToCache(\n cache: CacheService,\n metrics: Metric[],\n provider: string,\n configKey: string,\n query: MetricQuery,\n ttl?: number,\n) {\n const cacheKey = [\n provider,\n configKey,\n query.name,\n query.query,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n const crypto = require('crypto');\n await cache.set(crypto.createHash('md5').update(cacheKey).digest('hex'), metrics, {\n ttl: ttl ?? 60 * 60 * 2 * 1000,\n }); // cache for 2 hours by default\n}\n\nexport function parseFilters(filters: string): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n\n if (!filters.startsWith('(') || !filters.endsWith(')')) {\n return result;\n }\n\n const filterString = filters.slice(1, -1);\n if (!filterString) {\n return result;\n }\n\n const keyValuePairs = filterString.split(',').map(pair => pair.trim());\n\n keyValuePairs.forEach(pair => {\n const [key, value] = pair.split(':').map(s => s.trim());\n if (key && value) {\n if (value.startsWith('(') && value.endsWith(')')) {\n // multiple values\n const values = value\n .slice(1, -1)\n .split('|')\n .map(v => v.trim());\n result[key] = values;\n } else {\n // single value\n result[key] = [value];\n }\n }\n });\n\n return result;\n}\n\n/**\n * Returns the date format string for a billing period based on granularity.\n */\nexport function getBillingPeriodFormat(granularity: GRANULARITY): string {\n if (granularity === GRANULARITY.MONTHLY) {\n return 'YYYY-MM';\n } else if (granularity === GRANULARITY.DAILY) {\n return 'YYYY-MM-DD';\n }\n throw new Error('Invalid granularity');\n}\n\n/**\n * Converts a source date string to a billing period string based on granularity and source format.\n */\nexport function getBillingPeriod(granularity: GRANULARITY, sourceDate: string, sourceFormat: string): string {\n return moment(sourceDate, sourceFormat, true).format(getBillingPeriodFormat(granularity));\n}\n\n/**\n * Parses a cost value and rounds to 2 decimal places.\n * Returns 0 if the value is not a valid number.\n */\nexport function parseCost(value: any): number {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? Math.round(parsed * 100) / 100 : 0;\n}\n\nexport function getDailyPeriodStringsForOneMonth(yyyymm: number): string[] {\n const dateOjb = moment(yyyymm.toString(), 'YYYYMM');\n const startOfMonth = moment(dateOjb).startOf('month');\n const endOfMonth = moment(dateOjb).endOf('month');\n const periods: string[] = [];\n\n for (let date = startOfMonth; date.isBefore(endOfMonth) || date.isSame(endOfMonth); date.add(1, 'day')) {\n periods.push(date.format('YYYY-MM-DD'));\n }\n\n return periods;\n}\n\nexport function usageDateToPeriodString(usageDate: number): string {\n // usageDate format: either yyyymm (monthly) or yyyymmdd (daily)\n // output format: yyyy-mm (monthly) or yyyy-mm-dd (daily)\n const usageDateStr = usageDate.toString();\n if (usageDateStr.length === 6) {\n // Monthly format\n return `${usageDateStr.slice(0, 4)}-${usageDateStr.slice(4, 6)}`;\n } else if (usageDateStr.length === 8) {\n // Daily format\n return `${usageDateStr.slice(0, 4)}-${usageDateStr.slice(4, 6)}-${usageDateStr.slice(6, 8)}`;\n }\n throw new Error('Invalid usageDate format');\n}\n\n/**\n * Logs a standardized transformation summary for cost client data processing.\n * This provides consistent logging across all cost providers.\n */\nexport function logTransformationSummary(\n logger: LoggerService,\n provider: string,\n summary: TransformationSummary,\n): void {\n logger.info(\n `${provider} transformation summary: processed=${summary.processed}, uniqueReports=${summary.uniqueReports}, zeroAmount=${summary.zeroAmount}, missingFields=${summary.missingFields}, invalidDate=${summary.invalidDate}, timeRange=${summary.timeRange}, totalRecords=${summary.totalRecords}`,\n );\n}\n"],"names":["CACHE_CATEGORY","DEFAULT_TAGS_CACHE_TTL","DEFAULT_COSTS_CACHE_TTL","GRANULARITY","moment"],"mappings":"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"}
1
+ {"version":3,"file":"functions.cjs.js","sources":["../../src/service/functions.ts"],"sourcesContent":["import { CacheService, LoggerService } from '@backstage/backend-plugin-api';\nimport { CACHE_CATEGORY, CLOUD_PROVIDER, DEFAULT_COSTS_CACHE_TTL, DEFAULT_TAGS_CACHE_TTL, GRANULARITY } from './consts';\nimport { CostQuery, Metric, MetricQuery, Report, Tag, TagsQuery, TransformationSummary } from './types';\nimport moment from 'moment';\n\n// In URL, tags are defined in this format:\n// tags=(provider1:key1=value1 OR provider2:key2=value2)\nexport function parseTags(tags: string): Tag[] {\n if (!tags.startsWith('(') || !tags.endsWith(')')) {\n return [];\n }\n\n const tagString = tags.slice(1, -1);\n if (!tagString) {\n return [];\n }\n\n const keyValuePairs = tagString.split(' OR ');\n return keyValuePairs.map(pair => {\n const [providerAndKey, value] = pair.split('=');\n const firstColonIndex = providerAndKey.indexOf(':');\n const provider = providerAndKey.slice(0, firstColonIndex);\n const key = providerAndKey.slice(firstColonIndex + 1);\n return { key: key, value: value, provider: provider };\n });\n}\n\n// convert Tag array to (provider1:key1=value1 OR provider2:key2=value2) format\nexport function tagsToString(tags: Tag[]): string {\n if (!tags || tags.length === 0) {\n return '()';\n }\n\n const keyValuePairs = tags.map(tag => `${tag.provider}:${tag.key}=${tag.value}`);\n return `(${keyValuePairs.join(' OR ')})`;\n}\n\n// check if targetTag exists in tags\nexport function tagExists(tags: Tag[], targetTag: Tag): boolean {\n return tags.some(\n tag => tag.provider === targetTag.provider && tag.key === targetTag.key && tag.value === targetTag.value,\n );\n}\n\nexport function getDefaultCacheTTL(cacheCategory: CACHE_CATEGORY, provider: CLOUD_PROVIDER): number {\n if (cacheCategory === CACHE_CATEGORY.TAGS) {\n return DEFAULT_TAGS_CACHE_TTL[provider];\n } else if (cacheCategory === CACHE_CATEGORY.COSTS) {\n return DEFAULT_COSTS_CACHE_TTL[provider];\n }\n\n return 0;\n}\n\nexport async function getTagKeysFromCache(\n cache: CacheService,\n provider: CLOUD_PROVIDER,\n configKey: string,\n query: TagsQuery,\n): Promise<Tag[] | undefined> {\n const cacheKey = [CACHE_CATEGORY.TAGS, 'tag-keys', provider, configKey, query.startTime, query.endTime].join('_');\n const data = (await cache.get(cacheKey)) as Tag[] | undefined;\n return data;\n}\n\nexport async function getTagValuesFromCache(\n cache: CacheService,\n provider: CLOUD_PROVIDER,\n configKey: string,\n tagKey: string,\n query: TagsQuery,\n): Promise<Tag[] | undefined> {\n const cacheKey = [\n CACHE_CATEGORY.TAGS,\n 'tag-values',\n provider,\n configKey,\n tagKey,\n query.startTime,\n query.endTime,\n ].join('_');\n const data = (await cache.get(cacheKey)) as Tag[] | undefined;\n return data;\n}\n\nexport async function getReportsFromCache(\n cache: CacheService,\n provider: string,\n configKey: string,\n query: CostQuery,\n): Promise<Report[] | undefined> {\n const cacheKey = [\n provider,\n configKey,\n query.filters,\n query.tags,\n query.groups,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n const cachedCosts = (await cache.get(cacheKey)) as Report[] | undefined;\n return cachedCosts;\n}\n\nexport async function getForecastFromCache(\n cache: CacheService,\n provider: string,\n configKey: string,\n query: CostQuery,\n): Promise<number | undefined> {\n const cacheKey = [\n 'forecast',\n provider,\n configKey,\n query.filters,\n query.tags,\n query.groups,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n const cachedForecast = (await cache.get(cacheKey)) as number | undefined;\n return cachedForecast;\n}\n\nexport async function getMetricsFromCache(\n cache: CacheService,\n provider: string,\n configKey: string,\n query: MetricQuery,\n): Promise<Metric[] | undefined> {\n const cacheKey = [\n provider,\n configKey,\n query.name,\n query.query,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n const crypto = require('crypto');\n const cachedMetrics = (await cache.get(crypto.createHash('md5').update(cacheKey).digest('hex'))) as\n | Metric[]\n | undefined;\n return cachedMetrics;\n}\n\nexport async function setTagKeysToCache(\n cache: CacheService,\n tags: Tag[],\n provider: CLOUD_PROVIDER,\n configKey: string,\n query: TagsQuery,\n ttl?: number,\n) {\n const cacheKey = [CACHE_CATEGORY.TAGS, 'tag-keys', provider, configKey, query.startTime, query.endTime].join('_');\n await cache.set(cacheKey, tags, {\n ttl: ttl ?? getDefaultCacheTTL(CACHE_CATEGORY.TAGS, provider),\n });\n}\n\nexport async function setTagValuesToCache(\n cache: CacheService,\n tags: Tag[],\n provider: CLOUD_PROVIDER,\n configKey: string,\n tagKey: string,\n query: TagsQuery,\n ttl?: number,\n) {\n const cacheKey = [\n CACHE_CATEGORY.TAGS,\n 'tag-values',\n provider,\n configKey,\n tagKey,\n query.startTime,\n query.endTime,\n ].join('_');\n await cache.set(cacheKey, tags, {\n ttl: ttl ?? getDefaultCacheTTL(CACHE_CATEGORY.TAGS, provider),\n });\n}\n\nexport async function setReportsToCache(\n cache: CacheService,\n reports: Report[],\n provider: string,\n configKey: string,\n query: CostQuery,\n ttl?: number,\n) {\n const cacheKey = [\n provider,\n configKey,\n query.filters,\n query.tags,\n query.groups,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n await cache.set(cacheKey, reports, {\n ttl: ttl ?? 60 * 60 * 2 * 1000,\n }); // cache for 2 hours by default\n}\n\nexport async function setForecastToCache(\n cache: CacheService,\n forecast: number,\n provider: string,\n configKey: string,\n query: CostQuery,\n ttl?: number,\n) {\n const cacheKey = [\n 'forecast',\n provider,\n configKey,\n query.filters,\n query.tags,\n query.groups,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n await cache.set(cacheKey, forecast, {\n ttl: ttl ?? 60 * 60 * 2 * 1000, // cache for 2 hours by default, same as reports\n });\n}\n\nexport async function setMetricsToCache(\n cache: CacheService,\n metrics: Metric[],\n provider: string,\n configKey: string,\n query: MetricQuery,\n ttl?: number,\n) {\n const cacheKey = [\n provider,\n configKey,\n query.name,\n query.query,\n query.granularity,\n query.startTime,\n query.endTime,\n ].join('_');\n const crypto = require('crypto');\n await cache.set(crypto.createHash('md5').update(cacheKey).digest('hex'), metrics, {\n ttl: ttl ?? 60 * 60 * 2 * 1000,\n }); // cache for 2 hours by default\n}\n\nexport function parseFilters(filters: string): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n\n if (!filters.startsWith('(') || !filters.endsWith(')')) {\n return result;\n }\n\n const filterString = filters.slice(1, -1);\n if (!filterString) {\n return result;\n }\n\n const keyValuePairs = filterString.split(',').map(pair => pair.trim());\n\n keyValuePairs.forEach(pair => {\n const [key, value] = pair.split(':').map(s => s.trim());\n if (key && value) {\n if (value.startsWith('(') && value.endsWith(')')) {\n // multiple values\n const values = value\n .slice(1, -1)\n .split('|')\n .map(v => v.trim());\n result[key] = values;\n } else {\n // single value\n result[key] = [value];\n }\n }\n });\n\n return result;\n}\n\n/**\n * Returns the date format string for a billing period based on granularity.\n */\nexport function getBillingPeriodFormat(granularity: GRANULARITY): string {\n if (granularity === GRANULARITY.MONTHLY) {\n return 'YYYY-MM';\n } else if (granularity === GRANULARITY.DAILY) {\n return 'YYYY-MM-DD';\n }\n throw new Error('Invalid granularity');\n}\n\n/**\n * Converts a source date string to a billing period string based on granularity and source format.\n */\nexport function getBillingPeriod(granularity: GRANULARITY, sourceDate: string, sourceFormat: string): string {\n return moment(sourceDate, sourceFormat, true).format(getBillingPeriodFormat(granularity));\n}\n\n/**\n * Parses a cost value and rounds to 2 decimal places.\n * Returns 0 if the value is not a valid number.\n */\nexport function parseCost(value: any): number {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? Math.round(parsed * 100) / 100 : 0;\n}\n\nexport function getDailyPeriodStringsForOneMonth(yyyymm: number): string[] {\n const dateOjb = moment(yyyymm.toString(), 'YYYYMM');\n const startOfMonth = moment(dateOjb).startOf('month');\n const endOfMonth = moment(dateOjb).endOf('month');\n const periods: string[] = [];\n\n for (let date = startOfMonth; date.isBefore(endOfMonth) || date.isSame(endOfMonth); date.add(1, 'day')) {\n periods.push(date.format('YYYY-MM-DD'));\n }\n\n return periods;\n}\n\nexport function usageDateToPeriodString(usageDate: number): string {\n // usageDate format: either yyyymm (monthly) or yyyymmdd (daily)\n // output format: yyyy-mm (monthly) or yyyy-mm-dd (daily)\n const usageDateStr = usageDate.toString();\n if (usageDateStr.length === 6) {\n // Monthly format\n return `${usageDateStr.slice(0, 4)}-${usageDateStr.slice(4, 6)}`;\n } else if (usageDateStr.length === 8) {\n // Daily format\n return `${usageDateStr.slice(0, 4)}-${usageDateStr.slice(4, 6)}-${usageDateStr.slice(6, 8)}`;\n }\n throw new Error('Invalid usageDate format');\n}\n\n/**\n * Logs a standardized transformation summary for cost client data processing.\n * This provides consistent logging across all cost providers.\n */\nexport function logTransformationSummary(\n logger: LoggerService,\n provider: string,\n summary: TransformationSummary,\n): void {\n logger.info(\n `${provider} transformation summary: processed=${summary.processed}, uniqueReports=${summary.uniqueReports}, zeroAmount=${summary.zeroAmount}, missingFields=${summary.missingFields}, invalidDate=${summary.invalidDate}, timeRange=${summary.timeRange}, totalRecords=${summary.totalRecords}`,\n );\n}\n"],"names":["CACHE_CATEGORY","DEFAULT_TAGS_CACHE_TTL","DEFAULT_COSTS_CACHE_TTL","GRANULARITY","moment"],"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-20260112100533-68a81f8",
3
+ "version": "1.1.0-20260115072024-d6f33e2",
4
4
  "backstage": {
5
5
  "role": "backend-plugin",
6
6
  "pluginId": "infrawallet",