@electrolux-oss/plugin-infrawallet-backend 0.1.12 → 0.2.0
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.
- package/config.d.ts +29 -1
- package/dist/index.cjs.js +1021 -563
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/migrations/20241017141420_create-custom-cost-table.js +31 -0
- package/migrations/20241021105140_wallet-budgets.js +22 -0
- package/package.json +19 -13
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/controllers/MetricSettingController.ts","../src/service/functions.ts","../src/cost-clients/InfraWalletClient.ts","../src/cost-clients/AwsClient.ts","../src/cost-clients/AzureClient.ts","../src/cost-clients/GCPClient.ts","../src/metric-providers/MetricProvider.ts","../src/metric-providers/DatadogProvider.ts","../src/metric-providers/GrafanaCloudProvider.ts","../src/metric-providers/MockProvider.ts","../src/cost-clients/MockClient.ts","../src/cost-clients/ConfluentClient.ts","../src/cost-clients/MongoAtlasClient.ts","../src/service/consts.ts","../src/service/CategoryMappingService.ts","../src/service/router.ts","../src/plugin.ts"],"sourcesContent":["import { DatabaseService } from '@backstage/backend-plugin-api';\nimport { MetricSetting, Wallet } from '../service/types';\n\nexport async function getWallet(database: DatabaseService, walletName: string): Promise<Wallet | undefined> {\n const client = await database.getClient();\n const result = await client<Wallet>('wallets').where('name', walletName).first();\n\n return result;\n}\n\nexport async function getWalletMetricSettings(database: DatabaseService, walletName: string): Promise<MetricSetting[]> {\n const client = await database.getClient();\n\n const metricSettings = await client\n .select('business_metrics.*')\n .from<MetricSetting>('business_metrics')\n .where('wallets.name', walletName)\n .join('wallets', 'business_metrics.wallet_id', '=', 'wallets.id');\n\n return metricSettings;\n}\n\nexport async function updateOrInsertWalletMetricSetting(\n database: DatabaseService,\n walletSetting: MetricSetting,\n): Promise<boolean> {\n const client = await database.getClient();\n const result: number[] = await client('business_metrics').insert(walletSetting).onConflict('id').merge();\n\n if (result[0] > 0) {\n return true;\n }\n\n return false;\n}\n\nexport async function deleteWalletMetricSetting(\n database: DatabaseService,\n walletSetting: MetricSetting,\n): Promise<boolean> {\n const client = await database.getClient();\n const result: number = await client('business_metrics').where('id', walletSetting.id).del();\n\n if (result > 0) {\n return true;\n }\n\n return false;\n}\n","import { CacheService } from '@backstage/backend-plugin-api';\nimport { CACHE_CATEGORY, CLOUD_PROVIDER, DEFAULT_COSTS_CACHE_TTL, DEFAULT_TAGS_CACHE_TTL } from './consts';\nimport { CostQuery, Metric, MetricQuery, Report, Tag, TagsQuery } from './types';\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 || tags[0] !== '(' || tags[tags.length - 1] !== ')') {\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 || filters[0] !== '(' || filters[filters.length - 1] !== ')') {\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","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { CACHE_CATEGORY, CLOUD_PROVIDER } from '../service/consts';\nimport {\n getDefaultCacheTTL,\n getReportsFromCache,\n getTagKeysFromCache,\n getTagValuesFromCache,\n setReportsToCache,\n setTagKeysToCache,\n setTagValuesToCache,\n tagExists,\n} from '../service/functions';\nimport { ClientResponse, CloudProviderError, CostQuery, Report, Tag, TagsQuery, TagsResponse } 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 serviceName;\n }\n\n protected abstract initCloudClient(subAccountConfig: Config): Promise<any>;\n\n // Get all cost allocation tag keys from one account\n protected abstract fetchTagKeys(\n subAccountConfig: Config,\n client: any,\n query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }>;\n\n // Get all tag values of the specified tag key from one account\n protected abstract fetchTagValues(\n subAccountConfig: Config,\n client: any,\n query: TagsQuery,\n tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }>;\n\n protected abstract fetchCosts(subAccountConfig: Config, client: any, query: CostQuery): Promise<any>;\n\n protected abstract transformCostsData(\n subAccountConfig: Config,\n query: CostQuery,\n costResponse: any,\n ): Promise<Report[]>;\n\n // Get aggregated unique tag keys across all accounts of this cloud provider\n async getTagKeys(query: TagsQuery): Promise<TagsResponse> {\n const accounts = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n if (!accounts) {\n return { tags: [], errors: [] };\n }\n\n const promises = [];\n const aggregatedTags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n for (const account of accounts) {\n const accountName = account.getString('name');\n\n const cachedTagKeys = await getTagKeysFromCache(this.cache, this.provider, accountName, query);\n if (cachedTagKeys) {\n this.logger.info(`Reuse ${this.provider}/${accountName} 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(account);\n const response = await this.fetchTagKeys(account, 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, accountName, query);\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: `${this.provider}/${accountName}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n await Promise.all(promises);\n\n return {\n tags: aggregatedTags.sort((a, b) => `${a.provider}/${a.key}`.localeCompare(`${b.provider}/${b.key}`)),\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 accounts = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n if (!accounts) {\n return { tags: [], errors: [] };\n }\n\n const promises = [];\n const aggregatedTags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n for (const account of accounts) {\n const accountName = account.getString('name');\n\n const cachedTagValues = await getTagValuesFromCache(this.cache, this.provider, accountName, tagKey, query);\n if (cachedTagValues) {\n this.logger.info(`Reuse ${this.provider}/${accountName}/${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(account);\n const response = await this.fetchTagValues(account, 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, accountName, tagKey, query);\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: `${this.provider}/${accountName}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n await Promise.all(promises);\n\n return {\n tags: aggregatedTags.sort((a, b) =>\n `${a.provider}/${a.key}=${a.value}`.localeCompare(`${b.provider}/${b.key}=${b.value}`),\n ),\n errors: errors,\n };\n }\n\n async getCostReports(query: CostQuery): Promise<ClientResponse> {\n const accounts = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n if (!accounts) {\n return { reports: [], errors: [] };\n }\n\n const promises = [];\n const results: Report[] = [];\n const errors: CloudProviderError[] = [];\n\n for (const account of accounts) {\n const accountName = account.getString('name');\n\n // first check if there is any cached\n const cachedCosts = await getReportsFromCache(this.cache, this.provider, accountName, query);\n if (cachedCosts) {\n this.logger.debug(`${this.provider}/${accountName} costs from cache`);\n cachedCosts.map(cost => {\n results.push(cost);\n });\n continue;\n }\n\n const promise = (async () => {\n try {\n const client = await this.initCloudClient(account);\n const costResponse = await this.fetchCosts(account, client, query);\n\n const transformedReports = await this.transformCostsData(account, query, costResponse);\n\n // cache the results\n await setReportsToCache(\n this.cache,\n transformedReports,\n this.provider,\n accountName,\n query,\n getDefaultCacheTTL(CACHE_CATEGORY.COSTS, this.provider),\n );\n\n transformedReports.map((value: any) => {\n results.push(value);\n });\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: `${this.provider}/${accountName}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n await Promise.all(promises);\n return {\n reports: results,\n errors: errors,\n };\n }\n}\n","import {\n CostExplorerClient,\n Dimension,\n Expression,\n GetCostAndUsageCommand,\n GetCostAndUsageCommandInput,\n GetTagsCommand,\n GetTagsCommandInput,\n Granularity,\n GroupDefinitionType,\n} from '@aws-sdk/client-cost-explorer';\nimport { AssumeRoleCommand, STSClient } from '@aws-sdk/client-sts';\nimport { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER } from '../service/consts';\nimport { parseTags } from '../service/functions';\nimport { CostQuery, Report, TagsQuery } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class AwsClient extends InfraWalletClient {\n private accounts: Map<string, string> = new Map();\n\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new AwsClient(CLOUD_PROVIDER.AWS, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Amazon', 'AWS'];\n\n const aliases = new Map<string, string>([\n ['Elastic Compute Cloud - Compute', 'EC2 - Instances'],\n ['Virtual Private Cloud', 'VPC (Virtual Private Cloud)'],\n ['Relational Database Service', 'RDS (Relational Database Service)'],\n ['Simple Storage Service', 'S3 (Simple Storage Service)'],\n ['Managed Streaming for Apache Kafka', 'MSK (Managed Streaming for Apache Kafka)'],\n ['Elastic Container Service for Kubernetes', 'EKS (Elastic Container Service for Kubernetes)'],\n ['Elastic Container Service', 'ECS (Elastic Container Service)'],\n ['EC2 Container Registry (ECR)', 'ECR (Elastic Container Registry)'],\n ['Simple Queue Service', 'SQS (Simple Queue Service)'],\n ['Simple Notification Service', 'SNS (Simple Notification Service)'],\n ['Database Migration Service', 'DMS (Database Migration Service)'],\n ]);\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\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(subAccountConfig: Config): Promise<any> {\n const accountId = subAccountConfig.getString('accountId');\n const assumedRoleName = subAccountConfig.getString('assumedRoleName');\n const accessKeyId = subAccountConfig.getOptionalString('accessKeyId');\n const accessKeySecret = subAccountConfig.getOptionalString('accessKeySecret');\n\n let stsParams = {};\n if (accessKeyId && accessKeySecret) {\n stsParams = {\n region: 'us-east-1',\n credentials: {\n accessKeyId: accessKeyId as string,\n secretAccessKey: accessKeySecret as string,\n },\n };\n } else {\n stsParams = {\n region: 'us-east-1',\n };\n }\n const client = new STSClient(stsParams);\n const commandInput = {\n // AssumeRoleRequest\n RoleArn: `arn:aws:iam::${accountId}:role/${assumedRoleName}`,\n RoleSessionName: 'AssumeRoleSession1',\n };\n const assumeRoleCommand = new AssumeRoleCommand(commandInput);\n const assumeRoleResponse = await client.send(assumeRoleCommand);\n // init aws cost explorer client\n const awsCeClient = new CostExplorerClient({\n region: 'us-east-1',\n credentials: {\n accessKeyId: assumeRoleResponse.Credentials?.AccessKeyId as string,\n secretAccessKey: assumeRoleResponse.Credentials?.SecretAccessKey as string,\n sessionToken: assumeRoleResponse.Credentials?.SessionToken as string,\n },\n });\n\n return awsCeClient;\n }\n\n private async _fetchTags(client: any, query: TagsQuery, tagKey?: string): Promise<string[]> {\n const results: string[] = [];\n let nextPageToken = undefined;\n\n do {\n const input: GetTagsCommandInput = {\n TimePeriod: {\n Start: moment(parseInt(query.startTime, 10)).format('YYYY-MM-DD'),\n End: moment(parseInt(query.endTime, 10)).format('YYYY-MM-DD'),\n },\n TagKey: tagKey,\n };\n const command = new GetTagsCommand(input);\n const response = await client.send(command);\n for (const tag of response.Tags) {\n if (tag) {\n results.push(tag);\n }\n }\n\n nextPageToken = response.NextPageToken;\n } while (nextPageToken);\n\n results.sort();\n return results;\n }\n\n protected async fetchTagKeys(\n _subAccountConfig: Config,\n client: any,\n query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n const tagKeys = await this._fetchTags(client, query);\n return { tagKeys: tagKeys, provider: CLOUD_PROVIDER.AWS };\n }\n\n protected async fetchTagValues(\n _subAccountConfig: Config,\n client: any,\n query: TagsQuery,\n tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n const tagValues = await this._fetchTags(client, query, tagKey);\n return { tagValues: tagValues, provider: CLOUD_PROVIDER.AWS };\n }\n\n protected async fetchCosts(_subAccountConfig: Config, client: any, query: CostQuery): Promise<any> {\n // query this aws account's cost and usage using @aws-sdk/client-cost-explorer\n let costAndUsageResults: any[] = [];\n let nextPageToken = undefined;\n let filterExpression: Expression = { Dimensions: { Key: Dimension.RECORD_TYPE, Values: ['Usage'] } };\n const tags = parseTags(query.tags);\n if (tags.length) {\n let tagsExpression: Expression = {};\n\n if (tags.length === 1) {\n tagsExpression = { Tags: { Key: tags[0].key, Values: [tags[0].value as string] } };\n } else {\n const tagList: Expression[] = [];\n for (const tag of tags) {\n tagList.push({ Tags: { Key: tag.key, Values: [tag.value as string] } });\n }\n tagsExpression = { Or: tagList };\n }\n\n filterExpression = { And: [filterExpression, tagsExpression] };\n }\n\n do {\n const input: GetCostAndUsageCommandInput = {\n TimePeriod: {\n Start: moment(parseInt(query.startTime, 10)).format('YYYY-MM-DD'),\n End: moment(parseInt(query.endTime, 10)).format('YYYY-MM-DD'),\n },\n Granularity: query.granularity.toUpperCase() as Granularity,\n Filter: filterExpression,\n GroupBy: [\n { Type: GroupDefinitionType.DIMENSION, Key: Dimension.LINKED_ACCOUNT },\n { Type: GroupDefinitionType.DIMENSION, Key: Dimension.SERVICE },\n ],\n Metrics: ['UnblendedCost'],\n NextPageToken: nextPageToken,\n };\n\n const getCostCommand = new GetCostAndUsageCommand(input);\n const costAndUsageResponse = await client.send(getCostCommand);\n\n // get AWS account names\n for (const accountAttributes of costAndUsageResponse.DimensionValueAttributes) {\n const accountId = accountAttributes.Value;\n const accountName = accountAttributes.Attributes.description;\n this.accounts.set(accountId, accountName);\n }\n\n costAndUsageResults = costAndUsageResults.concat(costAndUsageResponse.ResultsByTime);\n nextPageToken = costAndUsageResponse.NextPageToken;\n } while (nextPageToken);\n\n return costAndUsageResults;\n }\n\n protected async transformCostsData(subAccountConfig: Config, query: CostQuery, costResponse: any): Promise<Report[]> {\n const categoryMappingService = CategoryMappingService.getInstance();\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 const transformedData = reduce(\n costResponse,\n (accumulator: { [key: string]: Report }, row) => {\n const rowTime = row.TimePeriod?.Start;\n let period = 'unknown';\n if (rowTime) {\n if (query.granularity.toUpperCase() === 'MONTHLY') {\n period = rowTime.substring(0, 7);\n } else {\n period = rowTime;\n }\n }\n if (row.Groups) {\n row.Groups.forEach((group: any) => {\n const accountId = group.Keys ? group.Keys[0] : '';\n const accountName = this.accounts.get(accountId) || accountId;\n const serviceName = group.Keys ? group.Keys[1] : '';\n const keyName = `${accountId}_${serviceName}`;\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName} (${accountId})`,\n service: this.convertServiceName(serviceName),\n category: categoryMappingService.getCategoryByServiceName(this.provider, serviceName),\n provider: this.provider,\n reports: {},\n ...tagKeyValues,\n };\n }\n\n const groupMetrics = group.Metrics;\n\n if (groupMetrics !== undefined) {\n accumulator[keyName].reports[period] = parseFloat(groupMetrics.UnblendedCost.Amount ?? '0.0');\n }\n });\n }\n\n return accumulator;\n },\n {},\n );\n return Object.values(transformedData);\n }\n}\n","import { CostManagementClient, QueryDefinition, QueryFilter } from '@azure/arm-costmanagement';\nimport { createHttpHeaders, createPipelineRequest } from '@azure/core-rest-pipeline';\nimport { ClientSecretCredential } from '@azure/identity';\nimport { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER } from '../service/consts';\nimport { parseTags } from '../service/functions';\nimport { CostQuery, Report, TagsQuery } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class AzureClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new AzureClient(CLOUD_PROVIDER.AZURE, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Azure'];\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n private formatDate(dateNumber: number): string | null {\n // dateNumber example: 20240407\n const dateString = dateNumber.toString();\n\n if (dateString.length !== 8) {\n return null;\n }\n\n const year = dateString.slice(0, 4);\n const month = dateString.slice(4, 6);\n const day = dateString.slice(6);\n\n return `${year}-${month}-${day}`;\n }\n\n private async fetchDataWithRetry(client: CostManagementClient, url: string, body: any, maxRetries = 5): Promise<any> {\n let retries = 0;\n\n while (retries < maxRetries) {\n const request = createPipelineRequest({\n url: url,\n method: 'POST',\n body: JSON.stringify(body),\n headers: createHttpHeaders({\n 'Content-Type': 'application/json',\n ClientType: 'InfraWallet',\n }),\n });\n const response = await client.pipeline.sendRequest(client, request);\n if (response.status === 200) {\n return JSON.parse(response.bodyAsText || '{}');\n } else if (response.status === 429) {\n const retryAfter = parseInt(\n response.headers.get('x-ms-ratelimit-microsoft.costmanagement-entity-retry-after') || '60',\n 10,\n );\n this.logger.warn(`Hit Azure rate limit, retrying after ${retryAfter} seconds...`);\n await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));\n retries++;\n } else {\n throw new Error(response.bodyAsText as string);\n }\n }\n\n throw new Error('Max retries exceeded');\n }\n\n // If tagKey is specified, returns all tag values of that key.\n // Otherwise returns all available tag keys.\n private async _fetchTags(subAccountConfig: Config, client: any, query: TagsQuery, tagKey: string): Promise<string[]> {\n const subscriptionId = subAccountConfig.getString('subscriptionId');\n const url = `https://management.azure.com/subscriptions/${subscriptionId}/providers/Microsoft.CostManagement/query?api-version=2021-10-01`;\n\n const queryDefinition: QueryDefinition = {\n type: 'ActualCost',\n dataset: {\n granularity: 'None',\n grouping: [{ type: 'TagKey', name: tagKey }],\n },\n timeframe: 'Custom',\n timePeriod: {\n from: moment(parseInt(query.startTime, 10)).toDate(),\n to: moment(parseInt(query.endTime, 10)).toDate(),\n },\n };\n\n let result = await this.fetchDataWithRetry(client, url, queryDefinition);\n let allResults = result.properties.rows;\n\n while (result.properties.nextLink) {\n result = await this.fetchDataWithRetry(client, result.properties.nextLink, queryDefinition);\n allResults = allResults.concat(result.properties.rows);\n }\n\n const tags: string[] = [];\n for (const row of allResults) {\n if (tagKey === '') {\n if (row[0] && !row[0].startsWith('hidden-')) {\n tags.push(row[0]);\n }\n } else {\n if (row[1]) {\n tags.push(row[1]);\n }\n }\n }\n tags.sort();\n\n return tags;\n }\n\n protected async initCloudClient(config: Config): Promise<any> {\n const tenantId = config.getString('tenantId');\n const clientId = config.getString('clientId');\n const clientSecret = config.getString('clientSecret');\n const credential = new ClientSecretCredential(tenantId as string, clientId as string, clientSecret as string);\n const client = new CostManagementClient(credential);\n\n return client;\n }\n\n protected async fetchTagKeys(\n subAccountConfig: Config,\n client: any,\n query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n const tagKeys = await this._fetchTags(subAccountConfig, client, query, '');\n return { tagKeys: tagKeys, provider: CLOUD_PROVIDER.AZURE };\n }\n\n protected async fetchTagValues(\n subAccountConfig: Config,\n client: any,\n query: TagsQuery,\n tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n const tagValues = await this._fetchTags(subAccountConfig, client, query, tagKey);\n return { tagValues: tagValues, provider: CLOUD_PROVIDER.AZURE };\n }\n\n protected async fetchCosts(subAccountConfig: Config, client: any, query: CostQuery): Promise<any> {\n // Azure SDK doesn't support pagination, so sending HTTP request directly\n const subscriptionId = subAccountConfig.getString('subscriptionId');\n const url = `https://management.azure.com/subscriptions/${subscriptionId}/providers/Microsoft.CostManagement/query?api-version=2023-11-01`;\n\n const groupPairs = [{ type: 'Dimension', name: 'ServiceName' }];\n let filter: QueryFilter | undefined = undefined;\n const tags = parseTags(query.tags);\n if (tags.length) {\n if (tags.length === 1) {\n filter = {\n tags: { name: tags[0].key, operator: 'In', values: [tags[0].value as string] },\n };\n } else {\n const tagList: QueryFilter[] = [];\n for (const tag of tags) {\n tagList.push({ tags: { name: tag.key, operator: 'In', values: [tag.value as string] } });\n }\n filter = { or: tagList };\n }\n }\n\n const queryDefinition: QueryDefinition = {\n type: 'ActualCost',\n dataset: {\n granularity: query.granularity,\n aggregation: { totalCostUSD: { name: 'CostUSD', function: 'Sum' } },\n grouping: groupPairs,\n filter: filter,\n },\n timeframe: 'Custom',\n timePeriod: {\n from: moment(parseInt(query.startTime, 10)).toDate(),\n to: moment(parseInt(query.endTime, 10)).toDate(),\n },\n };\n\n let result = await this.fetchDataWithRetry(client, url, queryDefinition);\n let allResults = result.properties.rows;\n\n while (result.properties.nextLink) {\n result = await this.fetchDataWithRetry(client, result.properties.nextLink, queryDefinition);\n allResults = allResults.concat(result.properties.rows);\n }\n\n return allResults;\n }\n\n protected async transformCostsData(subAccountConfig: Config, query: CostQuery, costResponse: any): Promise<Report[]> {\n /*\n Monthly cost sample:\n [\n 123.456,\n \"2024-04-07T00:00:00\", // BillingMonth\n \"Azure App Service\",\n \"EUR\"\n ]\n\n Daily cost sample:\n [\n 12.3456,\n 20240407, // UsageDate\n \"Azure App Service\",\n \"EUR\"\n ]\n */\n const categoryMappingService = CategoryMappingService.getInstance();\n const accountName = subAccountConfig.getString('name');\n const subscriptionId = subAccountConfig.getString('subscriptionId');\n const groupPairs = [{ type: 'Dimension', name: 'ServiceName' }];\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 const transformedData = reduce(\n costResponse,\n (accumulator: { [key: string]: Report }, row) => {\n const cost = row[0];\n let date = row[1];\n const serviceName = row[2];\n\n if (query.granularity.toUpperCase() === 'DAILY') {\n // 20240407 -> \"2024-04-07\"\n date = this.formatDate(date);\n }\n\n let keyName = accountName;\n for (let i = 0; i < groupPairs.length; i++) {\n keyName += `->${row[i + 2]}`;\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName} (${subscriptionId})`,\n service: this.convertServiceName(serviceName),\n category: categoryMappingService.getCategoryByServiceName(this.provider, serviceName),\n provider: this.provider,\n reports: {},\n ...tagKeyValues,\n };\n }\n\n if (!moment(date).isBefore(moment(parseInt(query.startTime, 10)))) {\n if (query.granularity.toUpperCase() === 'MONTHLY') {\n const yearMonth = date.substring(0, 7);\n accumulator[keyName].reports[yearMonth] = parseFloat(cost);\n } else {\n accumulator[keyName].reports[date] = parseFloat(cost);\n }\n }\n return accumulator;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { BigQuery } from '@google-cloud/bigquery';\nimport { reduce } from 'lodash';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER } from '../service/consts';\nimport { CostQuery, Report, TagsQuery } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class GCPClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new GCPClient(CLOUD_PROVIDER.GCP, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Google Cloud'];\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n protected async initCloudClient(subAccountConfig: Config): Promise<any> {\n const keyFilePath = subAccountConfig.getString('keyFilePath');\n const projectId = subAccountConfig.getString('projectId');\n // Configure a JWT auth client\n const options = {\n keyFilename: keyFilePath,\n projectId: projectId,\n };\n\n // Initialize the BigQuery API\n const bigqueryClient = new BigQuery(options);\n\n return bigqueryClient;\n }\n\n protected async fetchTagKeys(\n _subAccountConfig: Config,\n _client: any,\n _query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented\n return { tagKeys: [], provider: CLOUD_PROVIDER.GCP };\n }\n\n protected async fetchTagValues(\n _subAccountConfig: Config,\n _client: any,\n _query: TagsQuery,\n _tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented\n return { tagValues: [], provider: CLOUD_PROVIDER.GCP };\n }\n\n protected async fetchCosts(subAccountConfig: Config, client: any, query: CostQuery): Promise<any> {\n const projectId = subAccountConfig.getString('projectId');\n const datasetId = subAccountConfig.getString('datasetId');\n const tableId = subAccountConfig.getString('tableId');\n\n try {\n const periodFormat = query.granularity.toUpperCase() === 'MONTHLY' ? '%Y-%m' : '%Y-%m-%d';\n const sql = `\n SELECT\n project.name AS project,\n service.description AS service,\n FORMAT_TIMESTAMP('${periodFormat}', usage_start_time) AS period,\n (SUM(CAST(cost AS NUMERIC)) + SUM(IFNULL((SELECT SUM(CAST(c.amount AS NUMERIC)) FROM UNNEST(credits) AS c), 0))) AS total_cost\n FROM\n \\`${projectId}.${datasetId}.${tableId}\\`\n WHERE\n project.name IS NOT NULL\n AND cost > 0\n AND usage_start_time >= TIMESTAMP_MILLIS(${query.startTime})\n AND usage_start_time <= TIMESTAMP_MILLIS(${query.endTime})\n GROUP BY\n project, service, period\n ORDER BY\n project, period, total_cost DESC`;\n\n // Run the query as a job\n const [job] = await client.createQueryJob({\n query: sql,\n });\n\n // Wait for the query to finish\n const [rows] = await job.getQueryResults();\n\n return rows;\n } catch (err) {\n throw new Error(err.message);\n }\n }\n\n protected async transformCostsData(\n subAccountConfig: Config,\n _query: CostQuery,\n costResponse: any,\n ): Promise<Report[]> {\n const categoryMappingService = CategoryMappingService.getInstance();\n const accountName = subAccountConfig.getString('name');\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 const transformedData = reduce(\n costResponse,\n (acc: { [key: string]: Report }, row) => {\n const period = row.period;\n const keyName = `${accountName}_${row.project}_${row.service}`;\n\n if (!acc[keyName]) {\n acc[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName}`,\n service: this.convertServiceName(row.service),\n category: categoryMappingService.getCategoryByServiceName(this.provider, row.service),\n provider: this.provider,\n reports: {},\n ...{ project: row.project }, // TODO: how should we handle the project field? for now, we add project name as a field in the report\n ...tagKeyValues, // note that if there is a tag `project:foo` in config, it overrides the project field set above\n };\n }\n\n acc[keyName].reports[period] = parseFloat(row.total_cost);\n\n return acc;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { getMetricsFromCache, setMetricsToCache } from '../service/functions';\nimport { CloudProviderError, Metric, MetricQuery, MetricSetting, MetricResponse } from '../service/types';\n\nexport abstract class MetricProvider {\n constructor(\n protected readonly providerName: string,\n protected readonly config: Config,\n protected readonly database: DatabaseService,\n protected readonly cache: CacheService,\n protected readonly logger: LoggerService,\n ) {}\n\n abstract initProviderClient(metricProviderConfig: Config): Promise<any>;\n\n abstract fetchMetrics(metricProviderConfig: Config, client: any, query: MetricQuery): Promise<any>;\n\n abstract transformMetricData(\n metricProviderConfig: Config,\n query: MetricQuery,\n metricResponse: any,\n ): Promise<Metric[]>;\n\n async getMetrics(query: MetricQuery): Promise<MetricResponse> {\n const conf = this.config.getOptionalConfigArray(\n `backend.infraWallet.metricProviders.${this.providerName.toLowerCase()}`,\n );\n if (!conf) {\n return { metrics: [], errors: [] };\n }\n\n const promises = [];\n const results: Metric[] = [];\n const errors: CloudProviderError[] = [];\n\n for (const c of conf) {\n const configName = c.getString('name');\n const client = await this.initProviderClient(c);\n const dbClient = await this.database.getClient();\n\n const metricSettings = await dbClient\n .where({\n 'wallets.name': query.walletName,\n 'business_metrics.metric_provider': this.providerName.toLowerCase(),\n 'business_metrics.config_name': configName,\n })\n .select('business_metrics.*')\n .from<MetricSetting>('business_metrics')\n .join('wallets', 'business_metrics.wallet_id', '=', 'wallets.id');\n\n for (const metric of metricSettings || []) {\n const promise = (async () => {\n try {\n const fullQuery: MetricQuery = {\n name: metric.metric_name,\n query: metric.query,\n ...query,\n };\n\n // first check if there is any cached metrics\n const cachedMetrics = await getMetricsFromCache(this.cache, this.providerName, configName, fullQuery);\n if (cachedMetrics) {\n this.logger.debug(`${this.providerName}/${configName}/${fullQuery.name} metrics from cache`);\n cachedMetrics.map(m => {\n results.push({\n group: metric.group, // add group info to the metric\n ...m,\n });\n });\n return;\n }\n\n const metricResponse = await this.fetchMetrics(c, client, fullQuery);\n const transformedMetrics = await this.transformMetricData(c, fullQuery, metricResponse);\n\n // cache the results for 2 hours\n await setMetricsToCache(\n this.cache,\n transformedMetrics,\n this.providerName,\n configName,\n fullQuery,\n 60 * 60 * 2 * 1000,\n );\n\n transformedMetrics.map((value: any) => {\n results.push({\n group: metric.group, // add group info to the metric\n ...value,\n });\n });\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.providerName,\n name: `${this.providerName}/${configName}/${metric.getString('metricName')}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return {\n metrics: results,\n errors: errors,\n };\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { v1 as datadogApiV1, client as datadogClient } from '@datadog/datadog-api-client';\nimport moment from 'moment';\nimport { MetricProvider } from './MetricProvider';\nimport { Metric, MetricQuery } from '../service/types';\n\nexport class DatadogProvider extends MetricProvider {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new DatadogProvider('Datadog', config, database, cache, logger);\n }\n\n async initProviderClient(config: Config): Promise<any> {\n const apiKey = config.getString('apiKey');\n const applicationKey = config.getString('applicationKey');\n const ddSite = config.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 datadogApiV1.MetricsApi(configuration);\n return client;\n }\n\n async fetchMetrics(_metricProviderConfig: Config, client: any, query: MetricQuery): Promise<any> {\n const params: datadogApiV1.MetricsApiQueryMetricsRequest = {\n from: parseInt(query.startTime, 10) / 1000,\n to: parseInt(query.endTime, 10) / 1000,\n query: query.query?.replaceAll('IW_INTERVAL', query.granularity === 'daily' ? '86400' : '2592000') as string,\n };\n return client.queryMetrics(params).then((data: datadogApiV1.MetricsQueryResponse) => {\n if (data.status === 'ok') {\n return data;\n }\n throw new Error(data.error);\n });\n }\n\n async transformMetricData(_metricProviderConfig: Config, query: MetricQuery, metricResponse: any): Promise<Metric[]> {\n const transformedData = [];\n\n for (const series of metricResponse.series) {\n const metricName = query.name as string;\n const tagSet = series.tagSet;\n\n const metric: Metric = {\n id: `${metricName} ${tagSet.length === 0 ? '' : tagSet}`,\n provider: this.providerName,\n name: metricName,\n reports: {},\n };\n\n for (const point of series.pointlist) {\n const period = moment(point[0]).format(query.granularity === 'daily' ? 'YYYY-MM-DD' : 'YYYY-MM');\n const value = point[1];\n metric.reports[period] = value;\n }\n\n transformedData.push(metric);\n }\n\n return transformedData;\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport moment from 'moment';\nimport fetch from 'node-fetch';\nimport { MetricProvider } from './MetricProvider';\nimport { Metric, MetricQuery } from '../service/types';\n\nexport class GrafanaCloudProvider extends MetricProvider {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new GrafanaCloudProvider('GrafanaCloud', config, database, cache, logger);\n }\n\n async initProviderClient(_config: Config): Promise<any> {\n // for now we don't need to use Grafana Cloud SDK\n return null;\n }\n\n async fetchMetrics(metricProviderConfig: Config, _client: any, query: MetricQuery): Promise<any> {\n const url = metricProviderConfig.getString('url');\n const datasourceUid = metricProviderConfig.getString('datasourceUid');\n const token = metricProviderConfig.getString('token');\n\n const headers = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n };\n const payload = {\n queries: [\n {\n datasource: {\n uid: datasourceUid,\n },\n expr: query.query?.replaceAll('IW_INTERVAL', query.granularity === 'daily' ? '1d' : '30d'),\n refId: 'A',\n },\n ],\n from: query.startTime,\n to: query.endTime,\n };\n\n const response = await fetch(`${url}/api/ds/query`, {\n method: 'post',\n body: JSON.stringify(payload),\n headers: headers,\n });\n const data = await response.json();\n\n return data;\n }\n\n async transformMetricData(_metricProviderConfig: Config, query: MetricQuery, metricResponse: any): Promise<Metric[]> {\n const transformedData = [];\n\n const metricName = query.name as string;\n const metric: Metric = {\n id: metricName,\n provider: this.providerName,\n name: metricName,\n reports: {},\n };\n\n // TODO: iterate all the series\n const periods = metricResponse.results.A.frames[0].data.values[0];\n const values = metricResponse.results.A.frames[0].data.values[1];\n for (let i = 0; i < periods.length; i++) {\n const period = moment(periods[i]).format(query.granularity === 'daily' ? 'YYYY-MM-DD' : 'YYYY-MM');\n const value = values[i];\n metric.reports[period] = value;\n }\n\n transformedData.push(metric);\n return transformedData;\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport moment from 'moment';\nimport { MetricProvider } from './MetricProvider';\nimport { Metric, MetricQuery } from '../service/types';\n\nexport class MockProvider extends MetricProvider {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new MockProvider('Mock', config, database, cache, logger);\n }\n\n async initProviderClient(_config: Config): Promise<any> {\n // for now we don't need to use Grafana Cloud SDK\n return null;\n }\n\n async fetchMetrics(_metricProviderConfig: Config, _client: any, _query: MetricQuery): Promise<any> {\n return null;\n }\n\n async transformMetricData(\n _metricProviderConfig: Config,\n query: MetricQuery,\n _metricResponse: any,\n ): Promise<Metric[]> {\n const transformedData = [];\n\n const metricName = query.name as string;\n let mockSettings: { min?: number; max?: number } = {};\n try {\n mockSettings = JSON.parse(query.query as string);\n } catch (e) {\n // nothing needs to be done\n }\n const minValue = mockSettings.min ?? 0;\n const maxValue = mockSettings.max ?? 1000;\n const metric: Metric = {\n id: metricName,\n provider: this.providerName,\n name: metricName,\n reports: {},\n };\n\n let cursor = moment(parseInt(query.startTime, 10));\n while (cursor <= moment(parseInt(query.endTime, 10))) {\n const period = cursor.format(query.granularity === 'daily' ? 'YYYY-MM-DD' : 'YYYY-MM');\n metric.reports[period] = Math.floor(Math.random() * (maxValue - minValue) + minValue);\n cursor = cursor.add(1, query.granularity === 'daily' ? 'days' : 'months');\n }\n\n transformedData.push(metric);\n return transformedData;\n }\n}\n","import { promises as fsPromises } from 'fs';\nimport moment from 'moment';\nimport { CostQuery, Report, TagsQuery } from '../service/types';\nimport * as upath from 'upath';\nimport { InfraWalletClient } from './InfraWalletClient';\nimport { CacheService, DatabaseService, LoggerService, resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { CLOUD_PROVIDER } from '../service/consts';\n\nexport class MockClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new MockClient(CLOUD_PROVIDER.MOCK, config, database, cache, logger);\n }\n\n protected async initCloudClient(config: Config): Promise<any> {\n this.logger.debug(`MockClient.initCloudClient called with config: ${JSON.stringify(config)}`);\n\n return null;\n }\n\n protected async fetchTagKeys(\n _subAccountConfig: Config,\n _client: any,\n _query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n return { tagKeys: [], provider: CLOUD_PROVIDER.MOCK };\n }\n\n protected async fetchTagValues(\n _subAccountConfig: Config,\n _client: any,\n _query: TagsQuery,\n _tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n return { tagValues: [], provider: CLOUD_PROVIDER.MOCK };\n }\n\n protected async fetchCosts(_subAccountConfig: Config, _client: any, _query: CostQuery): Promise<any> {\n return null;\n }\n\n protected async transformCostsData(\n _subAccountConfig: Config,\n query: CostQuery,\n _costResponse: any,\n ): Promise<Report[]> {\n try {\n const startD = moment.unix(Number(query.startTime) / 1000);\n let endD = moment.unix(Number(query.endTime) / 1000);\n const mockDir = resolvePackagePath('@electrolux-oss/plugin-infrawallet-backend', 'mock');\n const mockFilePath = upath.join(mockDir, 'mock_response.json');\n const data = await fsPromises.readFile(mockFilePath, 'utf8');\n const jsonData: Report[] = JSON.parse(data);\n const currentDate = moment();\n\n if (endD.isAfter(currentDate)) {\n endD = currentDate.clone();\n endD.add(1, 'day');\n }\n\n const processedData = await Promise.all(\n jsonData.map(async item => {\n item.reports = {};\n\n const StartDate = moment(startD);\n\n let step: moment.unitOfTime.DurationConstructor | undefined;\n let dateFormat = 'YYYY-MM';\n\n if (query.granularity.toLowerCase() === 'monthly') {\n step = 'months';\n dateFormat = 'YYYY-MM';\n } else if (query.granularity.toLowerCase() === 'daily') {\n step = 'days';\n dateFormat = 'YYYY-MM-DD';\n }\n\n while (StartDate.isBefore(endD)) {\n const dateString = StartDate.format(dateFormat);\n\n if (query.granularity.toLowerCase() === 'monthly') {\n item.reports[dateString] = this.getRandomValue(0.4 * 30, 33.3 * 30);\n } else {\n item.reports[dateString] = this.getRandomValue(0.4, 33.3);\n }\n\n StartDate.add(1, step); // Step based on granularity\n }\n\n return item;\n }),\n );\n\n return processedData;\n } catch (err) {\n this.logger.error('Error while reading a file', err);\n throw err;\n }\n }\n\n getRandomValue(min: number, max: number): number {\n const random = Math.random();\n const amplifiedRandom = Math.pow(random, 3);\n return amplifiedRandom * (max - min) + min;\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { CostQuery, Report, TagsQuery } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\nimport moment from 'moment';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER } from '../service/consts';\n\nexport class ConfluentClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new ConfluentClient(CLOUD_PROVIDER.CONFLUENT, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Confluent'];\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n private capitalizeWords(str: string): string {\n return str\n .toLowerCase()\n .split('_')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n }\n\n private async fetchEnvDisplayName(client: any, envId: string): Promise<string> {\n const url = `https://api.confluent.cloud/org/v2/environments/${envId}`;\n const response = await fetch(url, {\n method: 'GET',\n headers: client.headers,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch environment name for ${envId}: ${response.statusText}`);\n }\n\n const jsonResponse = await response.json();\n return jsonResponse.display_name;\n }\n\n protected async initCloudClient(subAccountConfig: Config): Promise<any> {\n const apiKey = subAccountConfig.getString('apiKey');\n const apiSecret = subAccountConfig.getString('apiSecret');\n const auth = `Basic ${Buffer.from(`${apiKey}:${apiSecret}`).toString('base64')}`;\n\n const client = {\n headers: {\n Authorization: auth,\n 'Content-Type': 'application/json',\n },\n };\n\n return client;\n }\n\n protected async fetchTagKeys(\n _subAccountConfig: Config,\n _client: any,\n _query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented\n return { tagKeys: [], provider: CLOUD_PROVIDER.CONFLUENT };\n }\n\n protected async fetchTagValues(\n _subAccountConfig: Config,\n _client: any,\n _query: TagsQuery,\n _tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented\n return { tagValues: [], provider: CLOUD_PROVIDER.CONFLUENT };\n }\n\n protected async fetchCosts(_subAccountConfig: Config, client: any, query: CostQuery): Promise<any> {\n const startDate = moment(parseInt(query.startTime, 10));\n const endDate = moment(parseInt(query.endTime, 10));\n\n const currentStartDate = startDate.clone();\n let aggregatedData: any[] = [];\n\n try {\n while (currentStartDate.isBefore(endDate) || currentStartDate.isSame(endDate, 'month')) {\n const currentEndDate = moment.min(currentStartDate.clone().endOf('month'), endDate);\n\n const url = `https://api.confluent.cloud/billing/v1/costs?start_date=${currentStartDate.format(\n 'YYYY-MM-DD',\n )}&end_date=${currentEndDate.add('1', 'd').format('YYYY-MM-DD')}`;\n\n const response = await fetch(url, {\n method: 'GET',\n headers: client.headers,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch costs: ${response.statusText}`);\n }\n\n const jsonResponse: { data: any[] } = await response.json();\n\n const envIds = [...new Set(jsonResponse.data.map((item: any) => item.resource.environment.id))];\n\n const envNamePromises = envIds.map(envId => this.fetchEnvDisplayName(client, envId));\n const envNames = await Promise.all(envNamePromises);\n\n const envIdToName: { [envId: string]: string } = {};\n envIds.forEach((envId, index) => {\n envIdToName[envId] = envNames[index];\n });\n\n const dataWithEnvNames = jsonResponse.data.map((item: any) => {\n const envId = item.resource.environment.id;\n return {\n ...item,\n envDisplayName: envIdToName[envId] || 'Unknown',\n };\n });\n\n aggregatedData = aggregatedData.concat(dataWithEnvNames);\n\n currentStartDate.add(1, 'month').startOf('month');\n }\n\n return {\n data: aggregatedData,\n };\n } catch (error) {\n this.logger.error(`Error fetching costs from Confluent: ${error.message}`);\n throw error;\n }\n }\n\n protected async transformCostsData(subAccountConfig: Config, query: CostQuery, costResponse: any): Promise<Report[]> {\n const categoryMappingService = CategoryMappingService.getInstance();\n const accountName = subAccountConfig.getString('name');\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 const transformedData = costResponse.data.reduce((accumulator: { [key: string]: Report }, line: any) => {\n const amount = parseFloat(line.amount) || 0;\n let billingPeriod = 'unknown';\n\n if (amount === 0) {\n return accumulator;\n }\n\n const parsedStartDate = moment(line.start_date);\n\n if (!parsedStartDate.isValid()) {\n return accumulator;\n }\n\n if (query.granularity.toUpperCase() === 'MONTHLY') {\n billingPeriod = parsedStartDate.format('YYYY-MM');\n } else {\n billingPeriod = parsedStartDate.format('YYYY-MM-DD');\n }\n\n const serviceName = this.capitalizeWords(line.line_type);\n const resourceName = line.resource.display_name || 'Unknown';\n const envDisplayName = line.envDisplayName;\n\n const keyName = `${accountName}->${categoryMappingService.getCategoryByServiceName(\n this.provider,\n serviceName,\n )}->${resourceName}`;\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName}`,\n service: this.convertServiceName(serviceName),\n category: categoryMappingService.getCategoryByServiceName(this.provider, serviceName),\n provider: this.provider,\n reports: {},\n ...{ project: envDisplayName },\n ...{ cluster: resourceName },\n ...tagKeyValues,\n };\n }\n\n if (!moment(billingPeriod).isBefore(moment(parseInt(query.startTime, 10)))) {\n accumulator[keyName].reports[billingPeriod] = (accumulator[keyName].reports[billingPeriod] || 0) + amount;\n }\n\n return accumulator;\n }, {});\n\n return Object.values(transformedData);\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport urllib from 'urllib';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER } from '../service/consts';\nimport { CostQuery, Report, TagsQuery } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class MongoAtlasClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new MongoAtlasClient(CLOUD_PROVIDER.MONGODB_ATLAS, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Atlas'];\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n protected async initCloudClient(subAccountConfig: any): Promise<any> {\n const publicKey = subAccountConfig.getString('publicKey');\n const privateKey = subAccountConfig.getString('privateKey');\n\n const client = {\n digestAuth: `${publicKey}:${privateKey}`,\n };\n\n return client;\n }\n\n protected async fetchTagKeys(\n _subAccountConfig: Config,\n _client: any,\n _query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented\n return { tagKeys: [], provider: CLOUD_PROVIDER.MONGODB_ATLAS };\n }\n\n protected async fetchTagValues(\n _subAccountConfig: Config,\n _client: any,\n _query: TagsQuery,\n _tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n // To be implemented\n return { tagValues: [], provider: CLOUD_PROVIDER.MONGODB_ATLAS };\n }\n\n protected async fetchCosts(subAccountConfig: Config, client: any, query: CostQuery): Promise<any> {\n const orgId = subAccountConfig.getString('orgId');\n const invoicesUrl = `/orgs/${orgId}/invoices?fromDate=${moment(parseInt(query.startTime, 10)).format(\n 'YYYY-MM-DD',\n )}&toDate=${moment(parseInt(query.endTime, 10)).add(1, 'M').format('YYYY-MM-DD')}`;\n\n try {\n const fullInvoicesUrl = `https://cloud.mongodb.com/api/atlas/v2${invoicesUrl}`;\n const response = await urllib.request(fullInvoicesUrl, {\n ...client,\n method: 'GET',\n dataType: 'json',\n headers: {\n Accept: 'application/vnd.atlas.2023-01-01+json',\n },\n });\n\n if (response.status !== 200) {\n throw new Error(`Error fetching invoices: ${response.status} ${response.statusText}`);\n }\n\n const invoices = response.data.results;\n\n const allInvoicesData = await Promise.all(\n invoices.map(async (invoice: any) => {\n const invoiceId = invoice.id;\n const csvUrl = `/orgs/${orgId}/invoices/${invoiceId}/csv`;\n const fullCsvUrl = `https://cloud.mongodb.com/api/atlas/v2${csvUrl}`;\n const csvResponse = await urllib.request(fullCsvUrl, {\n ...client,\n method: 'GET',\n dataType: 'text',\n headers: {\n Accept: 'application/vnd.atlas.2023-01-01+csv',\n },\n });\n\n if (csvResponse.status !== 200) {\n throw new Error(`Error fetching invoice CSV: ${csvResponse.status} ${csvResponse.statusText}`);\n }\n\n const lines = csvResponse.data.split('\\n');\n\n let foundOrganizationIdLine = false;\n\n // Discard rows from the beginning of the CSV up to and including the row starting with \"Organization ID\"\n const filteredLines = lines\n .filter((line: string) => {\n const trimmedLine = line.trim();\n if (trimmedLine.startsWith('Organization ID,')) {\n foundOrganizationIdLine = true;\n return false;\n }\n if (!foundOrganizationIdLine) {\n return false;\n }\n return trimmedLine !== '' && !trimmedLine.includes('Credit'); // Discard empty lines and lines where SKU is 'Credit'\n })\n .join('\\n');\n\n return filteredLines;\n }),\n );\n\n return allInvoicesData.join('\\n');\n } catch (error) {\n this.logger.error(`Error fetching invoices from MongoDB Atlas: ${error.message}`);\n throw error;\n }\n }\n\n protected async transformCostsData(\n subAccountConfig: Config,\n query: CostQuery,\n costResponse: string,\n ): Promise<Report[]> {\n const categoryMappingService = CategoryMappingService.getInstance();\n const accountName = subAccountConfig.getString('name');\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 const lines = costResponse.split('\\n');\n const header = lines[0].split(',');\n const rows = lines.slice(1);\n\n const transformedData = reduce(\n rows,\n (accumulator: { [key: string]: Report }, line) => {\n const columns = line.split(',');\n const rowData: { [key: string]: string } = {};\n header.forEach((columnName, index) => {\n rowData[columnName] = columns[index];\n });\n\n const amount = parseFloat(rowData.Amount) || 0;\n let billingPeriod = 'unknown';\n\n const dateFormat = 'MM/DD/YYYY';\n const date = rowData.Date;\n const parsedDate = moment(date, dateFormat, true);\n\n if (!parsedDate.isValid()) {\n return accumulator;\n }\n\n if (query.granularity.toUpperCase() === 'MONTHLY') {\n billingPeriod = parsedDate.format('YYYY-MM');\n } else {\n billingPeriod = parsedDate.format('YYYY-MM-DD');\n }\n\n const serviceName = rowData.SKU;\n const cluster = rowData.Cluster || 'Unknown';\n const project = rowData.Project || 'Unknown';\n\n const keyName = `${accountName}->${categoryMappingService.getCategoryByServiceName(\n this.provider,\n serviceName,\n )}->${project}->${cluster}`;\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName}`,\n service: this.convertServiceName(serviceName),\n category: categoryMappingService.getCategoryByServiceName(this.provider, serviceName),\n provider: this.provider,\n reports: {},\n ...{ project: project },\n ...{ cluster: cluster },\n ...tagKeyValues,\n };\n }\n\n if (!moment(billingPeriod).isBefore(moment(parseInt(query.startTime, 10)))) {\n accumulator[keyName].reports[billingPeriod] = (accumulator[keyName].reports[billingPeriod] || 0) + amount;\n }\n\n return accumulator;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n}\n","import { AwsClient } from '../cost-clients/AwsClient';\nimport { AzureClient } from '../cost-clients/AzureClient';\nimport { GCPClient } from '../cost-clients/GCPClient';\nimport { DatadogProvider } from '../metric-providers/DatadogProvider';\nimport { GrafanaCloudProvider } from '../metric-providers/GrafanaCloudProvider';\nimport { MockProvider } from '../metric-providers/MockProvider';\nimport { MockClient } from '../cost-clients/MockClient';\nimport { ConfluentClient } from '../cost-clients/ConfluentClient';\nimport { MongoAtlasClient } from '../cost-clients/MongoAtlasClient';\n\n// Supported cloud providers to extract costs\nexport const enum CLOUD_PROVIDER {\n AWS = 'AWS',\n GCP = 'GCP',\n AZURE = 'Azure',\n MONGODB_ATLAS = 'MongoAtlas',\n CONFLUENT = 'Confluent',\n MOCK = 'Mock',\n}\n\nexport const COST_CLIENT_MAPPINGS: {\n [provider: string]: any;\n} = {\n aws: AwsClient,\n azure: AzureClient,\n gcp: GCPClient,\n confluent: ConfluentClient,\n mongoatlas: MongoAtlasClient,\n mock: MockClient,\n};\n\nexport const METRIC_PROVIDER_MAPPINGS: {\n [provider: string]: any;\n} = {\n datadog: DatadogProvider,\n grafanacloud: GrafanaCloudProvider,\n mock: MockProvider,\n};\n\nexport const enum CACHE_CATEGORY {\n COSTS = 'costs',\n TAGS = 'tags',\n METRICS = 'metrics',\n CATEGORY_MAPPINGS = 'category_mappings',\n}\n\nexport const DEFAULT_CATEGORY_MAPPING_CACHE_TTL = 12 * 60 * 60 * 1000; // 12 hours\n\nexport const DEFAULT_TAGS_CACHE_TTL: {\n [provider in CLOUD_PROVIDER]: number;\n} = {\n [CLOUD_PROVIDER.AWS]: 1 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.AZURE]: 12 * 60 * 60 * 1000, // 12 hours due to Azure rate limit\n [CLOUD_PROVIDER.GCP]: 1 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.MONGODB_ATLAS]: 1 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.CONFLUENT]: 1 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.MOCK]: 0,\n};\n\nexport const DEFAULT_COSTS_CACHE_TTL: {\n [provider in CLOUD_PROVIDER]: number;\n} = {\n [CLOUD_PROVIDER.AWS]: 2 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.AZURE]: 12 * 60 * 60 * 1000, // 12 hours due to Azure rate limit\n [CLOUD_PROVIDER.GCP]: 2 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.MONGODB_ATLAS]: 2 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.CONFLUENT]: 2 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.MOCK]: 0,\n};\n","import { CacheService, LoggerService } from '@backstage/backend-plugin-api';\nimport { CACHE_CATEGORY, DEFAULT_CATEGORY_MAPPING_CACHE_TTL } from './consts';\nimport { CategoryMappings, ServiceToCategoryMappings } from './types';\n\nexport class CategoryMappingService {\n private static instance: CategoryMappingService;\n\n constructor(protected readonly cache: CacheService, protected readonly logger: LoggerService) {}\n\n static initInstance(cache: CacheService, logger: LoggerService) {\n if (!CategoryMappingService.instance) {\n CategoryMappingService.instance = new CategoryMappingService(cache, logger);\n }\n }\n\n static getInstance(): CategoryMappingService {\n if (!CategoryMappingService.instance) {\n throw new Error('CategoryMappingService needs to be initialized first');\n }\n return CategoryMappingService.instance;\n }\n\n private categoryMappings: CategoryMappings = {};\n private serviceToCategory: ServiceToCategoryMappings = {};\n\n private generateServiceToCategoryMappings(categoryMappings: CategoryMappings): ServiceToCategoryMappings {\n const result: ServiceToCategoryMappings = {};\n for (const [category, mappings] of Object.entries(categoryMappings)) {\n for (const [provider, services] of Object.entries(mappings)) {\n const providerLowerCase = provider.toLowerCase();\n if (!(provider in result)) {\n result[providerLowerCase] = {};\n }\n services.forEach(service => {\n result[providerLowerCase][service] = category;\n });\n }\n }\n return result;\n }\n\n private async fetchCategoryMappings(): Promise<CategoryMappings> {\n const datasource =\n 'https://raw.githubusercontent.com/electrolux-oss/infrawallet-default-category-mappings/main/default_category_mappings.json';\n\n let result: CategoryMappings = {};\n\n await fetch(datasource)\n .then(async response => {\n const data = await response.json();\n this.logger.debug('Default category mappings updated');\n result = data;\n })\n .catch(_error => {\n // it might fail to retrive the mappings from our GitHub repo\n this.logger.error('Failed to fetch default category mappings from GitHub');\n this.logger.error('All services will be treated as \"Uncategorized\"');\n });\n\n return result;\n }\n\n public async refreshCategoryMappings() {\n let categoryMappings = (await this.cache.get(CACHE_CATEGORY.CATEGORY_MAPPINGS)) as CategoryMappings | undefined;\n if (categoryMappings === undefined) {\n // fetch the mappings from the GitHub repo and set it to the cache\n categoryMappings = await this.fetchCategoryMappings();\n await this.cache.set(CACHE_CATEGORY.CATEGORY_MAPPINGS, categoryMappings, {\n ttl: DEFAULT_CATEGORY_MAPPING_CACHE_TTL,\n });\n this.categoryMappings = categoryMappings;\n this.serviceToCategory = this.generateServiceToCategoryMappings(categoryMappings);\n } else {\n this.logger.debug('Reuse the category mappings from cache');\n }\n }\n\n public getCategoryByServiceName(provider: string, serviceName: string): string {\n const providerLowerCase = provider.toLowerCase();\n\n if (this.serviceToCategory[providerLowerCase] && serviceName in this.serviceToCategory[providerLowerCase]) {\n return this.serviceToCategory[providerLowerCase][serviceName];\n }\n\n // do a regex match with service name and then update the serviceToCategory mappings\n let result = 'Uncategorized';\n this.logger.debug(`${serviceName} does not belong to any category, do a regex search in the category mappings`);\n for (const [category, mappings] of Object.entries(this.categoryMappings)) {\n if (providerLowerCase in mappings) {\n for (const service of mappings[providerLowerCase]) {\n const regex = new RegExp(service);\n if (regex.test(serviceName)) {\n this.logger.debug(`${serviceName} belongs to ${category} in regex mode`);\n result = category;\n }\n }\n }\n }\n\n this.serviceToCategory[providerLowerCase][serviceName] = result;\n this.logger.debug(`serviceToCategoryMappings updated: ${providerLowerCase}/${serviceName} -> ${result}`);\n\n return result;\n }\n}\n","import { errorHandler } from '@backstage/backend-common';\nimport { CacheService, DatabaseService, LoggerService, resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport {\n deleteWalletMetricSetting,\n getWallet,\n getWalletMetricSettings,\n updateOrInsertWalletMetricSetting,\n} from '../controllers/MetricSettingController';\nimport { InfraWalletClient } from '../cost-clients/InfraWalletClient';\nimport { MetricProvider } from '../metric-providers/MetricProvider';\nimport { CategoryMappingService } from './CategoryMappingService';\nimport { COST_CLIENT_MAPPINGS, METRIC_PROVIDER_MAPPINGS } from './consts';\nimport { CloudProviderError, Metric, MetricSetting, Report, Tag } from './types';\nimport { parseTags, tagsToString, parseFilters } from './functions';\n\nexport interface RouterOptions {\n logger: LoggerService;\n config: Config;\n cache: CacheService;\n database: DatabaseService;\n}\n\nasync function setUpDatabase(database: DatabaseService) {\n // check database migrations\n const client = await database.getClient();\n const migrationsDir = resolvePackagePath('@electrolux-oss/plugin-infrawallet-backend', 'migrations');\n if (!database.migrations?.skip) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n }\n\n // insert default category_mappings to the database\n const seedsDir = resolvePackagePath('@electrolux-oss/plugin-infrawallet-backend', 'seeds');\n await client.seed.run({ directory: seedsDir });\n}\n\nexport async function createRouter(options: RouterOptions): Promise<express.Router> {\n const { logger, config, cache, database } = options;\n // do database migrations here to support the legacy backend system\n await setUpDatabase(database);\n\n // init CategoryMappingService\n CategoryMappingService.initInstance(cache, logger);\n\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n logger.info('PONG!');\n response.json({ status: 'ok' });\n });\n\n router.get('/reports', async (request, response) => {\n const filters = request.query.filters as string;\n const tags = parseTags(request.query.tags as string);\n const groups = request.query.groups as string;\n const granularity = request.query.granularity as string;\n const startTime = request.query.startTime as string;\n const endTime = request.query.endTime as string;\n const promises: Promise<void>[] = [];\n const results: Report[] = [];\n const errors: CloudProviderError[] = [];\n\n // group tags by providers\n const providerTags: Record<string, Tag[]> = {};\n for (const tag of tags) {\n const provider = tag.provider.toLowerCase();\n if (!providerTags[provider]) {\n providerTags[provider] = [];\n }\n\n providerTags[provider].push(tag);\n }\n\n const categoryMappingService = CategoryMappingService.getInstance();\n await categoryMappingService.refreshCategoryMappings();\n\n const conf = config.getConfig('backend.infraWallet.integrations');\n conf.keys().forEach((provider: string) => {\n if (provider in COST_CLIENT_MAPPINGS) {\n const client: InfraWalletClient = COST_CLIENT_MAPPINGS[provider].create(config, database, cache, logger);\n const fetchCloudCosts = (async () => {\n try {\n const clientResponse = await client.getCostReports({\n filters: filters,\n tags: tagsToString(providerTags[provider.toLowerCase()]),\n groups: groups,\n granularity: granularity,\n startTime: startTime,\n endTime: endTime,\n });\n clientResponse.errors.forEach((e: CloudProviderError) => {\n errors.push(e);\n });\n clientResponse.reports.forEach((cost: Report) => {\n results.push(cost);\n });\n } catch (e) {\n logger.error(e);\n errors.push({\n provider: client.constructor.name,\n name: client.constructor.name,\n error: e.message,\n });\n }\n })();\n promises.push(fetchCloudCosts);\n }\n });\n\n await Promise.all(promises);\n\n const parsedFilters = parseFilters(filters);\n\n const filteredResults = results.filter(report => {\n return Object.entries(parsedFilters).every(([key, values]) => {\n const reportValue = report[key];\n if (typeof reportValue !== 'string') {\n return false;\n }\n return values.includes(reportValue);\n });\n });\n\n if (errors.length > 0) {\n response.status(207).json({ data: filteredResults, errors: errors, status: 207 });\n } else {\n response.json({ data: filteredResults, errors: errors, status: 200 });\n }\n });\n\n router.get('/tag-keys', async (request, response) => {\n const tags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n const tagProvider = request.query.provider as string;\n const startTime = request.query.startTime as string;\n const endTime = request.query.endTime as string;\n const promises: Promise<void>[] = [];\n\n const conf = config.getConfig('backend.infraWallet.integrations');\n conf.keys().forEach((provider: string) => {\n if (provider.toLowerCase() === tagProvider.toLowerCase() && provider in COST_CLIENT_MAPPINGS) {\n const client: InfraWalletClient = COST_CLIENT_MAPPINGS[provider].create(config, database, cache, logger);\n const getTagKeys = (async () => {\n try {\n const clientResponse = await client.getTagKeys({\n startTime: startTime,\n endTime: endTime,\n });\n clientResponse.errors.forEach((e: CloudProviderError) => {\n errors.push(e);\n });\n clientResponse.tags.forEach((tag: Tag) => {\n tags.push(tag);\n });\n } catch (e) {\n logger.error(e);\n errors.push({\n provider: client.constructor.name,\n name: client.constructor.name,\n error: e.message,\n });\n }\n })();\n promises.push(getTagKeys);\n }\n });\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n response.status(207).json({ data: tags, errors: errors, status: 207 });\n } else {\n response.json({ data: tags, errors: errors, status: 200 });\n }\n });\n\n router.get('/tag-values', async (request, response) => {\n const tags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n const startTime = request.query.startTime as string;\n const endTime = request.query.endTime as string;\n const tagKey = request.query.tag as string;\n const tagProvider = request.query.provider as string;\n const promises: Promise<void>[] = [];\n\n const conf = config.getConfig('backend.infraWallet.integrations');\n conf.keys().forEach((provider: string) => {\n if (provider in COST_CLIENT_MAPPINGS && provider.toLowerCase() === tagProvider.toLowerCase()) {\n const client: InfraWalletClient = COST_CLIENT_MAPPINGS[provider].create(config, database, cache, logger);\n const getTagValues = (async () => {\n try {\n const clientResponse = await client.getTagValues(\n {\n startTime: startTime,\n endTime: endTime,\n },\n tagKey,\n );\n clientResponse.errors.forEach((e: CloudProviderError) => {\n errors.push(e);\n });\n clientResponse.tags.forEach((tag: Tag) => {\n tags.push(tag);\n });\n } catch (e) {\n logger.error(e);\n errors.push({\n provider: client.constructor.name,\n name: client.constructor.name,\n error: e.message,\n });\n }\n })();\n promises.push(getTagValues);\n }\n });\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n response.status(207).json({ data: tags, errors: errors, status: 207 });\n } else {\n response.json({ data: tags, errors: errors, status: 200 });\n }\n });\n\n router.get('/:walletName/metrics', async (request, response) => {\n const walletName = request.params.walletName;\n const granularity = request.query.granularity as string;\n const startTime = request.query.startTime as string;\n const endTime = request.query.endTime as string;\n const promises: Promise<void>[] = [];\n const results: Metric[] = [];\n const errors: CloudProviderError[] = [];\n\n const conf = config.getConfig('backend.infraWallet.metricProviders');\n conf.keys().forEach((provider: string) => {\n if (provider in METRIC_PROVIDER_MAPPINGS) {\n const client: MetricProvider = METRIC_PROVIDER_MAPPINGS[provider].create(config, database, cache, logger);\n const fetchMetrics = (async () => {\n try {\n const metricResponse = await client.getMetrics({\n walletName: walletName,\n granularity: granularity,\n startTime: startTime,\n endTime: endTime,\n });\n metricResponse.errors.forEach((e: CloudProviderError) => {\n errors.push(e);\n });\n metricResponse.metrics.forEach((metric: Metric) => {\n results.push(metric);\n });\n } catch (e) {\n logger.error(e);\n errors.push({\n provider: client.constructor.name,\n name: client.constructor.name,\n error: e.message,\n });\n }\n })();\n promises.push(fetchMetrics);\n }\n });\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n response.status(207).json({ data: results, errors: errors, status: 207 });\n } else {\n response.json({ data: results, errors: errors, status: 200 });\n }\n });\n\n router.get('/:walletName', async (request, response) => {\n const walletName = request.params.walletName;\n const wallet = await getWallet(database, walletName);\n if (wallet === undefined) {\n response.status(404).json({ error: 'Wallet not found', status: 404 });\n return;\n }\n\n response.json({ data: wallet, status: 200 });\n });\n\n router.get('/:walletName/metrics_setting', async (request, response) => {\n const walletName = request.params.walletName;\n const metricSettings = await getWalletMetricSettings(database, walletName);\n response.json({ data: metricSettings, status: 200 });\n });\n\n router.get('/metric/metric_configs', async (_request, response) => {\n const conf = config.getConfig('backend.infraWallet.metricProviders');\n const configNames: { metric_provider: string; config_name: string }[] = [];\n conf.keys().forEach((provider: string) => {\n const configs = conf.getOptionalConfigArray(provider);\n if (configs) {\n configs.forEach(c => {\n configNames.push({ metric_provider: provider, config_name: c.getString('name') });\n });\n }\n });\n\n response.json({ data: configNames, status: 200 });\n });\n\n router.put('/:walletName/metrics_setting', async (request, response) => {\n const readOnly = config.getOptionalBoolean('infraWallet.settings.readOnly') ?? false;\n\n if (readOnly) {\n response.status(403).json({ error: 'API not enabled in read-only mode', status: 403 });\n return;\n }\n\n const updatedMetricSetting = await updateOrInsertWalletMetricSetting(database, request.body as MetricSetting);\n response.json({ updated: updatedMetricSetting, status: 200 });\n });\n\n router.delete('/:walletName/metrics_setting', async (request, response) => {\n const readOnly = config.getOptionalBoolean('infraWallet.settings.readOnly') ?? false;\n\n if (readOnly) {\n response.status(403).json({ error: 'API not enabled in read-only mode', status: 403 });\n return;\n }\n\n const deletedMetricSetting = await deleteWalletMetricSetting(database, request.body as MetricSetting);\n response.json({ deleted: deletedMetricSetting, status: 200 });\n });\n\n router.use(errorHandler());\n return router;\n}\n","import { coreServices, createBackendPlugin } from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\n\n/**\n * infraWalletPlugin backend plugin\n *\n * @public\n */\nexport const infraWalletPlugin = createBackendPlugin({\n pluginId: 'infrawallet',\n register(env) {\n env.registerInit({\n deps: {\n httpRouter: coreServices.httpRouter,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n cache: coreServices.cache,\n database: coreServices.database,\n },\n async init({ httpRouter, logger, config, cache, database }) {\n httpRouter.use(\n await createRouter({\n logger,\n config,\n cache,\n database,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["__publicField","STSClient","AssumeRoleCommand","CostExplorerClient","moment","GetTagsCommand","Dimension","GroupDefinitionType","GetCostAndUsageCommand","reduce","_a","createPipelineRequest","createHttpHeaders","ClientSecretCredential","CostManagementClient","BigQuery","datadogClient","datadogApiV1","fetch","resolvePackagePath","upath","fsPromises","urllib","CLOUD_PROVIDER","CACHE_CATEGORY","Router","express","errorHandler","createBackendPlugin","coreServices"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/controllers/MetricSettingController.ts","../src/models/Budget.ts","../src/models/CustomCost.ts","../src/service/functions.ts","../src/cost-clients/InfraWalletClient.ts","../src/cost-clients/AwsClient.ts","../src/cost-clients/AzureClient.ts","../src/cost-clients/ConfluentClient.ts","../src/cost-clients/CustomProviderClient.ts","../src/cost-clients/DatadogClient.ts","../src/cost-clients/GCPClient.ts","../src/cost-clients/MockClient.ts","../src/cost-clients/MongoAtlasClient.ts","../src/metric-providers/MetricProvider.ts","../src/metric-providers/DatadogProvider.ts","../src/metric-providers/GrafanaCloudProvider.ts","../src/metric-providers/MockProvider.ts","../src/service/consts.ts","../src/service/CategoryMappingService.ts","../src/service/router.ts","../src/plugin.ts"],"sourcesContent":["import { DatabaseService } from '@backstage/backend-plugin-api';\nimport { MetricSetting, Wallet } from '../service/types';\n\nexport async function getWallet(database: DatabaseService, walletName: string): Promise<Wallet | undefined> {\n const client = await database.getClient();\n const result = await client<Wallet>('wallets').where('name', walletName).first();\n\n return result;\n}\n\nexport async function getWalletMetricSettings(database: DatabaseService, walletName: string): Promise<MetricSetting[]> {\n const client = await database.getClient();\n\n const metricSettings = await client\n .select('business_metrics.*')\n .from<MetricSetting>('business_metrics')\n .where('wallets.name', walletName)\n .join('wallets', 'business_metrics.wallet_id', '=', 'wallets.id');\n\n return metricSettings;\n}\n\nexport async function updateOrInsertWalletMetricSetting(\n database: DatabaseService,\n walletSetting: MetricSetting,\n): Promise<boolean> {\n const client = await database.getClient();\n const result: number[] = await client('business_metrics').insert(walletSetting).onConflict('id').merge();\n\n if (result[0] > 0) {\n return true;\n }\n\n return false;\n}\n\nexport async function deleteWalletMetricSetting(\n database: DatabaseService,\n walletSetting: MetricSetting,\n): Promise<boolean> {\n const client = await database.getClient();\n const result: number = await client('business_metrics').where('id', walletSetting.id).del();\n\n if (result > 0) {\n return true;\n }\n\n return false;\n}\n","import { DatabaseService } from '@backstage/backend-plugin-api';\n\nexport type Budget = {\n id?: string; // UUID generated by database\n wallet_id?: string;\n provider: string;\n name: string;\n amount: number;\n};\n\nexport async function getBudgets(database: DatabaseService, walletName: string): Promise<Budget[]> {\n const knex = await database.getClient();\n\n const budgets = await knex\n .select('budgets.*')\n .from<Budget>('budgets')\n .where('wallets.name', walletName)\n .join('wallets', 'budgets.wallet_id', '=', 'wallets.id');\n\n return budgets;\n}\n\nexport async function getBudget(database: DatabaseService, walletName: string, provider: string): Promise<Budget[]> {\n const knex = await database.getClient();\n\n const budgets = await knex\n .select('budgets.*')\n .from<Budget>('budgets')\n .where('budgets.provider', provider)\n .where('wallets.name', walletName)\n .join('wallets', 'budgets.wallet_id', '=', 'wallets.id');\n\n return budgets;\n}\n\nexport async function upsertBudget(database: DatabaseService, walletName: string, budget: Budget): Promise<boolean> {\n const knex = await database.getClient();\n const wallet = await knex.select('id').from('wallets').where('name', walletName).first();\n budget.wallet_id = wallet.id;\n const result: number[] = await knex('budgets').insert(budget).onConflict('id').merge();\n\n if (result[0] > 0) {\n return true;\n }\n\n return false;\n}\n","import { DatabaseService } from '@backstage/backend-plugin-api';\nimport moment from 'moment';\n\nexport type CustomCost = {\n id: string; // UUID\n provider: string;\n account: string;\n service?: string;\n category?: string;\n currency: string; // Default to 'USD'\n amortization_mode: string; // average, start_day, or end_day\n usage_month: number; // format YYYYMM\n cost?: number;\n tags?: Record<string, string>; // JSON object with key-value pairs\n};\n\n// Create a new cost record\nexport async function createCustomCost(database: DatabaseService, data: Omit<CustomCost, 'id'>): Promise<CustomCost> {\n const knex = await database.getClient();\n const [record] = await knex('custom_costs').insert(data).returning('*');\n return record;\n}\n\n// Create multiple cost records\nexport async function createCustomCosts(database: DatabaseService, data: Omit<CustomCost, 'id'>[]): Promise<number> {\n const knex = await database.getClient();\n const records = await knex('custom_costs').insert(data).returning('id');\n return records.length;\n}\n\n// Get cost records by date range\nexport async function getCustomCostsByDateRange(\n database: DatabaseService,\n startDate: Date,\n endDate: Date,\n): Promise<CustomCost[]> {\n const knex = await database.getClient();\n\n const records = await knex('custom_costs')\n .whereBetween('usage_month', [\n parseInt(moment(startDate).format('YYYYMM'), 10),\n parseInt(moment(endDate).format('YYYYMM'), 10),\n ])\n .select('*');\n\n return records;\n}\n\n// Get all cost records\nexport async function getCustomCosts(database: DatabaseService): Promise<CustomCost[]> {\n const knex = await database.getClient();\n const records = await knex('custom_costs').select('*');\n return records;\n}\n\n// Update one cost record\nexport async function updateOrInsertCustomCost(database: DatabaseService, data: CustomCost): Promise<CustomCost> {\n const knex = await database.getClient();\n const [record] = await knex('custom_costs').insert(data).onConflict('id').merge().returning('*');\n return record;\n}\n\n// Delete one cost record\nexport async function deleteCustomCost(database: DatabaseService, data: CustomCost): Promise<boolean> {\n const knex = await database.getClient();\n const result: number = await knex('custom_costs').where('id', data.id).del();\n\n if (result > 0) {\n return true;\n }\n\n return false;\n}\n","import { CacheService } from '@backstage/backend-plugin-api';\nimport { CACHE_CATEGORY, CLOUD_PROVIDER, DEFAULT_COSTS_CACHE_TTL, DEFAULT_TAGS_CACHE_TTL } from './consts';\nimport { CostQuery, Metric, MetricQuery, Report, Tag, TagsQuery } 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\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","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { CACHE_CATEGORY, CLOUD_PROVIDER } from '../service/consts';\nimport {\n getDefaultCacheTTL,\n getReportsFromCache,\n getTagKeysFromCache,\n getTagValuesFromCache,\n setReportsToCache,\n setTagKeysToCache,\n setTagValuesToCache,\n tagExists,\n} from '../service/functions';\nimport {\n ClientResponse,\n CloudProviderError,\n CostQuery,\n Filter,\n Report,\n Tag,\n TagsQuery,\n TagsResponse,\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 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\n protected abstract transformCostsData(\n integrationConfig: Config,\n query: CostQuery,\n costResponse: any,\n ): Promise<Report[]>;\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 integrationConfigs = this.config.getOptionalConfigArray(\n `backend.infraWallet.integrations.${this.provider.toLowerCase()}`,\n );\n if (!integrationConfigs) {\n return { reports: [], errors: [] };\n }\n\n const promises = [];\n const results: Report[] = [];\n const errors: CloudProviderError[] = [];\n\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 } 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 return {\n reports: results,\n errors: errors,\n };\n }\n}\n","import {\n CostExplorerClient,\n Dimension,\n Expression,\n GetCostAndUsageCommand,\n GetCostAndUsageCommandInput,\n GetTagsCommand,\n GetTagsCommandInput,\n Granularity,\n GroupDefinitionType,\n} from '@aws-sdk/client-cost-explorer';\nimport { AssumeRoleCommand, STSClient } from '@aws-sdk/client-sts';\nimport { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER, PROVIDER_TYPE } from '../service/consts';\nimport { parseTags } from '../service/functions';\nimport { CostQuery, Report, TagsQuery } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class AwsClient extends InfraWalletClient {\n private readonly accounts: Map<string, string> = new Map();\n\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new AwsClient(CLOUD_PROVIDER.AWS, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Amazon', 'AWS'];\n\n const aliases = new Map<string, string>([\n ['Elastic Compute Cloud - Compute', 'EC2 - Instances'],\n ['Virtual Private Cloud', 'VPC (Virtual Private Cloud)'],\n ['Relational Database Service', 'RDS (Relational Database Service)'],\n ['Simple Storage Service', 'S3 (Simple Storage Service)'],\n ['Managed Streaming for Apache Kafka', 'MSK (Managed Streaming for Apache Kafka)'],\n ['Elastic Container Service for Kubernetes', 'EKS (Elastic Container Service for Kubernetes)'],\n ['Elastic Container Service', 'ECS (Elastic Container Service)'],\n ['EC2 Container Registry (ECR)', 'ECR (Elastic Container Registry)'],\n ['Simple Queue Service', 'SQS (Simple Queue Service)'],\n ['Simple Notification Service', 'SNS (Simple Notification Service)'],\n ['Database Migration Service', 'DMS (Database Migration Service)'],\n ]);\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\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: Config): Promise<any> {\n const accountId = integrationConfig.getString('accountId');\n const assumedRoleName = integrationConfig.getOptionalString('assumedRoleName');\n const accessKeyId = integrationConfig.getOptionalString('accessKeyId');\n const accessKeySecret = integrationConfig.getOptionalString('accessKeySecret');\n const region = 'us-east-1';\n\n if (!accessKeyId && !accessKeySecret && !assumedRoleName) {\n // No credentials provided in configuration, assuming credentials are available in the environment\n return new CostExplorerClient({ region: region });\n }\n\n let credentials = undefined;\n if (accessKeyId || accessKeySecret) {\n if (accessKeyId && accessKeySecret) {\n credentials = {\n accessKeyId: accessKeyId,\n secretAccessKey: accessKeySecret,\n };\n } else {\n throw new Error('Both accessKeyId and accessKeySecret must be provided');\n }\n }\n\n if (assumedRoleName === undefined) {\n return new CostExplorerClient({\n region: region,\n credentials: credentials,\n });\n }\n\n // Assume role\n const client = new STSClient({\n region: region,\n credentials: credentials,\n });\n const commandInput = {\n // AssumeRoleRequest\n RoleArn: `arn:aws:iam::${accountId}:role/${assumedRoleName}`,\n RoleSessionName: 'InfraWallet',\n };\n const assumeRoleCommand = new AssumeRoleCommand(commandInput);\n const assumeRoleResponse = await client.send(assumeRoleCommand);\n // init aws cost explorer client\n const awsCeClient = new CostExplorerClient({\n region: region,\n credentials: {\n accessKeyId: assumeRoleResponse.Credentials?.AccessKeyId as string,\n secretAccessKey: assumeRoleResponse.Credentials?.SecretAccessKey as string,\n sessionToken: assumeRoleResponse.Credentials?.SessionToken as string,\n },\n });\n\n return awsCeClient;\n }\n\n private async _fetchTags(client: any, query: TagsQuery, tagKey?: string): Promise<string[]> {\n const tags: string[] = [];\n let nextPageToken = undefined;\n\n do {\n const input: GetTagsCommandInput = {\n TimePeriod: {\n Start: moment(parseInt(query.startTime, 10)).format('YYYY-MM-DD'),\n End: moment(parseInt(query.endTime, 10)).format('YYYY-MM-DD'),\n },\n TagKey: tagKey,\n };\n const command = new GetTagsCommand(input);\n const response = await client.send(command);\n for (const tag of response.Tags) {\n if (tag) {\n tags.push(tag);\n }\n }\n\n nextPageToken = response.NextPageToken;\n } while (nextPageToken);\n\n tags.sort((a, b) => a.localeCompare(b));\n return tags;\n }\n\n protected async fetchTagKeys(\n _integrationConfig: Config,\n client: any,\n query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n const tagKeys = await this._fetchTags(client, query);\n return { tagKeys: tagKeys, provider: this.provider };\n }\n\n protected async fetchTagValues(\n _integrationConfig: Config,\n client: any,\n query: TagsQuery,\n tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n const tagValues = await this._fetchTags(client, query, tagKey);\n return { tagValues: tagValues, provider: this.provider };\n }\n\n protected async fetchCosts(_integrationConfig: Config, client: any, query: CostQuery): Promise<any> {\n // query this aws account's cost and usage using @aws-sdk/client-cost-explorer\n let costAndUsageResults: any[] = [];\n let nextPageToken = undefined;\n let filterExpression: Expression = { Dimensions: { Key: Dimension.RECORD_TYPE, Values: ['Usage'] } };\n const tags = parseTags(query.tags);\n if (tags.length) {\n let tagsExpression: Expression = {};\n\n if (tags.length === 1) {\n if (tags[0].value) {\n tagsExpression = { Tags: { Key: tags[0].key, Values: [tags[0].value] } };\n }\n } else {\n const tagList: Expression[] = [];\n for (const tag of tags) {\n if (tag.value) {\n tagList.push({ Tags: { Key: tag.key, Values: [tag.value] } });\n }\n }\n tagsExpression = { Or: tagList };\n }\n\n filterExpression = { And: [filterExpression, tagsExpression] };\n }\n\n do {\n const input: GetCostAndUsageCommandInput = {\n TimePeriod: {\n Start: moment(parseInt(query.startTime, 10)).format('YYYY-MM-DD'),\n End: moment(parseInt(query.endTime, 10)).format('YYYY-MM-DD'),\n },\n Granularity: query.granularity.toUpperCase() as Granularity,\n Filter: filterExpression,\n GroupBy: [\n { Type: GroupDefinitionType.DIMENSION, Key: Dimension.LINKED_ACCOUNT },\n { Type: GroupDefinitionType.DIMENSION, Key: Dimension.SERVICE },\n ],\n Metrics: ['UnblendedCost'],\n NextPageToken: nextPageToken,\n };\n\n const getCostCommand = new GetCostAndUsageCommand(input);\n const costAndUsageResponse = await client.send(getCostCommand);\n\n // get AWS account names\n for (const accountAttributes of costAndUsageResponse.DimensionValueAttributes) {\n const accountId = accountAttributes.Value;\n const accountName = accountAttributes.Attributes.description;\n this.accounts.set(accountId, accountName);\n }\n\n costAndUsageResults = costAndUsageResults.concat(costAndUsageResponse.ResultsByTime);\n nextPageToken = costAndUsageResponse.NextPageToken;\n } while (nextPageToken);\n\n return costAndUsageResults;\n }\n\n protected async transformCostsData(\n integrationConfig: Config,\n query: CostQuery,\n costResponse: any,\n ): Promise<Report[]> {\n const categoryMappingService = CategoryMappingService.getInstance();\n const tags = integrationConfig.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 const transformedData = reduce(\n costResponse,\n (accumulator: { [key: string]: Report }, row) => {\n const rowTime = row.TimePeriod?.Start;\n let period = 'unknown';\n if (rowTime) {\n if (query.granularity.toUpperCase() === 'MONTHLY') {\n period = rowTime.substring(0, 7);\n } else {\n period = rowTime;\n }\n }\n if (row.Groups) {\n row.Groups.forEach((group: any) => {\n const accountId = group.Keys ? group.Keys[0] : '';\n const accountName = this.accounts.get(accountId) || accountId;\n\n if (!this.evaluateIntegrationFilters(accountName, integrationConfig)) {\n return;\n }\n\n const serviceName = group.Keys ? group.Keys[1] : '';\n const keyName = `${accountId}_${serviceName}`;\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName} (${accountId})`,\n service: this.convertServiceName(serviceName),\n category: categoryMappingService.getCategoryByServiceName(this.provider, serviceName),\n provider: this.provider,\n providerType: PROVIDER_TYPE.INTEGRATION,\n reports: {},\n ...tagKeyValues,\n };\n }\n\n const groupMetrics = group.Metrics;\n\n if (groupMetrics !== undefined) {\n accumulator[keyName].reports[period] = parseFloat(groupMetrics.UnblendedCost.Amount ?? '0.0');\n }\n });\n }\n\n return accumulator;\n },\n {},\n );\n return Object.values(transformedData);\n }\n}\n","import { CostManagementClient, QueryDefinition, QueryFilter } from '@azure/arm-costmanagement';\nimport { createHttpHeaders, createPipelineRequest } from '@azure/core-rest-pipeline';\nimport { ClientSecretCredential } from '@azure/identity';\nimport { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER, PROVIDER_TYPE } from '../service/consts';\nimport { parseTags } from '../service/functions';\nimport { CostQuery, Report, TagsQuery } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class AzureClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new AzureClient(CLOUD_PROVIDER.AZURE, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Azure'];\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n private formatDate(dateNumber: number): string | null {\n // dateNumber example: 20240407\n const dateString = dateNumber.toString();\n\n if (dateString.length !== 8) {\n return null;\n }\n\n const year = dateString.slice(0, 4);\n const month = dateString.slice(4, 6);\n const day = dateString.slice(6);\n\n return `${year}-${month}-${day}`;\n }\n\n private async fetchDataWithRetry(client: CostManagementClient, url: string, body: any, maxRetries = 5): Promise<any> {\n let retries = 0;\n\n while (retries < maxRetries) {\n const request = createPipelineRequest({\n url: url,\n method: 'POST',\n body: JSON.stringify(body),\n headers: createHttpHeaders({\n 'Content-Type': 'application/json',\n ClientType: 'InfraWallet',\n }),\n });\n const response = await client.pipeline.sendRequest(client, request);\n if (response.status === 200) {\n return JSON.parse(response.bodyAsText || '{}');\n } else if (response.status === 429) {\n const retryAfter = parseInt(\n response.headers.get('x-ms-ratelimit-microsoft.costmanagement-entity-retry-after') || '60',\n 10,\n );\n this.logger.warn(`Hit Azure rate limit, retrying after ${retryAfter} seconds...`);\n await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));\n retries++;\n } else {\n throw new Error(response.bodyAsText as string);\n }\n }\n\n throw new Error('Max retries exceeded');\n }\n\n // If tagKey is specified, returns all tag values of that key.\n // Otherwise returns all available tag keys.\n private async _fetchTags(subAccountConfig: Config, client: any, query: TagsQuery, tagKey: string): Promise<string[]> {\n const subscriptionId = subAccountConfig.getString('subscriptionId');\n const url = `https://management.azure.com/subscriptions/${subscriptionId}/providers/Microsoft.CostManagement/query?api-version=2021-10-01`;\n\n const queryDefinition: QueryDefinition = {\n type: 'ActualCost',\n dataset: {\n granularity: 'None',\n grouping: [{ type: 'TagKey', name: tagKey }],\n },\n timeframe: 'Custom',\n timePeriod: {\n from: moment(parseInt(query.startTime, 10)).toDate(),\n to: moment(parseInt(query.endTime, 10)).toDate(),\n },\n };\n\n let result = await this.fetchDataWithRetry(client, url, queryDefinition);\n let allResults = result.properties.rows;\n\n while (result.properties.nextLink) {\n result = await this.fetchDataWithRetry(client, result.properties.nextLink, queryDefinition);\n allResults = allResults.concat(result.properties.rows);\n }\n\n const tags: string[] = [];\n for (const row of allResults) {\n if (tagKey === '') {\n if (row[0] && !row[0].startsWith('hidden-')) {\n tags.push(row[0]);\n }\n } else if (row[1]) {\n tags.push(row[1]);\n }\n }\n tags.sort((a, b) => a.localeCompare(b));\n\n return tags;\n }\n\n protected async initCloudClient(config: Config): Promise<any> {\n const tenantId = config.getString('tenantId');\n const clientId = config.getString('clientId');\n const clientSecret = config.getString('clientSecret');\n const credential = new ClientSecretCredential(tenantId as string, clientId as string, clientSecret as string);\n const client = new CostManagementClient(credential);\n\n return client;\n }\n\n protected async fetchTagKeys(\n subAccountConfig: Config,\n client: any,\n query: TagsQuery,\n ): Promise<{ tagKeys: string[]; provider: CLOUD_PROVIDER }> {\n const tagKeys = await this._fetchTags(subAccountConfig, client, query, '');\n return { tagKeys: tagKeys, provider: this.provider };\n }\n\n protected async fetchTagValues(\n subAccountConfig: Config,\n client: any,\n query: TagsQuery,\n tagKey: string,\n ): Promise<{ tagValues: string[]; provider: CLOUD_PROVIDER }> {\n const tagValues = await this._fetchTags(subAccountConfig, client, query, tagKey);\n return { tagValues: tagValues, provider: this.provider };\n }\n\n protected async fetchCosts(subAccountConfig: Config, client: any, query: CostQuery): Promise<any> {\n // Azure SDK doesn't support pagination, so sending HTTP request directly\n const subscriptionId = subAccountConfig.getString('subscriptionId');\n const url = `https://management.azure.com/subscriptions/${subscriptionId}/providers/Microsoft.CostManagement/query?api-version=2023-11-01`;\n\n const groupPairs = [{ type: 'Dimension', name: 'ServiceName' }];\n let filter: QueryFilter | undefined = undefined;\n const tags = parseTags(query.tags);\n if (tags.length) {\n if (tags.length === 1) {\n if (tags[0].value) {\n filter = {\n tags: { name: tags[0].key, operator: 'In', values: [tags[0].value] },\n };\n }\n } else {\n const tagList: QueryFilter[] = [];\n for (const tag of tags) {\n if (tag.value) {\n tagList.push({ tags: { name: tag.key, operator: 'In', values: [tag.value] } });\n }\n }\n filter = { or: tagList };\n }\n }\n\n const queryDefinition: QueryDefinition = {\n type: 'ActualCost',\n dataset: {\n granularity: query.granularity,\n aggregation: { totalCostUSD: { name: 'CostUSD', function: 'Sum' } },\n grouping: groupPairs,\n filter: filter,\n },\n timeframe: 'Custom',\n timePeriod: {\n from: moment(parseInt(query.startTime, 10)).toDate(),\n to: moment(parseInt(query.endTime, 10)).toDate(),\n },\n };\n\n let result = await this.fetchDataWithRetry(client, url, queryDefinition);\n let allResults = result.properties.rows;\n\n while (result.properties.nextLink) {\n result = await this.fetchDataWithRetry(client, result.properties.nextLink, queryDefinition);\n allResults = allResults.concat(result.properties.rows);\n }\n\n return allResults;\n }\n\n protected async transformCostsData(subAccountConfig: Config, query: CostQuery, costResponse: any): Promise<Report[]> {\n /*\n Monthly cost sample:\n [\n 123.456,\n \"2024-04-07T00:00:00\", // BillingMonth\n \"Azure App Service\",\n \"EUR\"\n ]\n\n Daily cost sample:\n [\n 12.3456,\n 20240407, // UsageDate\n \"Azure App Service\",\n \"EUR\"\n ]\n */\n const categoryMappingService = CategoryMappingService.getInstance();\n const accountName = subAccountConfig.getString('name');\n const subscriptionId = subAccountConfig.getString('subscriptionId');\n const groupPairs = [{ type: 'Dimension', name: 'ServiceName' }];\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 const transformedData = reduce(\n costResponse,\n (accumulator: { [key: string]: Report }, row) => {\n const cost = row[0];\n let date = row[1];\n const serviceName = row[2];\n\n if (query.granularity.toUpperCase() === 'DAILY') {\n // 20240407 -> \"2024-04-07\"\n date = this.formatDate(date);\n }\n\n let keyName = accountName;\n for (let i = 0; i < groupPairs.length; i++) {\n keyName += `->${row[i + 2]}`;\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName} (${subscriptionId})`,\n service: this.convertServiceName(serviceName),\n category: categoryMappingService.getCategoryByServiceName(this.provider, serviceName),\n provider: this.provider,\n providerType: PROVIDER_TYPE.INTEGRATION,\n reports: {},\n ...tagKeyValues,\n };\n }\n\n if (!moment(date).isBefore(moment(parseInt(query.startTime, 10)))) {\n if (query.granularity.toUpperCase() === 'MONTHLY') {\n const yearMonth = date.substring(0, 7);\n accumulator[keyName].reports[yearMonth] = parseFloat(cost);\n } else {\n accumulator[keyName].reports[date] = parseFloat(cost);\n }\n }\n return accumulator;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { CostQuery, Report } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\nimport moment from 'moment';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER, PROVIDER_TYPE } from '../service/consts';\n\nexport class ConfluentClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new ConfluentClient(CLOUD_PROVIDER.CONFLUENT, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Confluent'];\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n private capitalizeWords(str: string): string {\n return str\n .toLowerCase()\n .split('_')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n }\n\n private async fetchEnvDisplayName(client: any, envId: string): Promise<string> {\n const url = `https://api.confluent.cloud/org/v2/environments/${envId}`;\n const response = await fetch(url, {\n method: 'GET',\n headers: client.headers,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch environment name for ${envId}: ${response.statusText}`);\n }\n\n const jsonResponse = await response.json();\n return jsonResponse.display_name;\n }\n\n protected async initCloudClient(subAccountConfig: Config): Promise<any> {\n const apiKey = subAccountConfig.getString('apiKey');\n const apiSecret = subAccountConfig.getString('apiSecret');\n const auth = `${apiKey}:${apiSecret}`;\n\n const client = {\n headers: {\n Authorization: `Basic ${Buffer.from(auth).toString('base64')}`,\n 'Content-Type': 'application/json',\n },\n };\n\n return client;\n }\n\n protected async fetchCosts(_subAccountConfig: Config, client: any, query: CostQuery): Promise<any> {\n const startDate = moment(parseInt(query.startTime, 10));\n const endDate = moment(parseInt(query.endTime, 10));\n\n const currentStartDate = startDate.clone();\n let aggregatedData: any[] = [];\n\n try {\n while (currentStartDate.isBefore(endDate) || currentStartDate.isSame(endDate, 'month')) {\n const currentEndDate = moment.min(currentStartDate.clone().endOf('month'), endDate);\n\n const url = `https://api.confluent.cloud/billing/v1/costs?start_date=${currentStartDate.format(\n 'YYYY-MM-DD',\n )}&end_date=${currentEndDate.add('1', 'd').format('YYYY-MM-DD')}`;\n\n const response = await fetch(url, {\n method: 'GET',\n headers: client.headers,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch costs: ${response.statusText}`);\n }\n\n const jsonResponse: { data: any[] } = await response.json();\n\n const envIds = [...new Set(jsonResponse.data.map((item: any) => item.resource.environment.id))];\n\n const envNamePromises = envIds.map(envId => this.fetchEnvDisplayName(client, envId));\n const envNames = await Promise.all(envNamePromises);\n\n const envIdToName: { [envId: string]: string } = {};\n envIds.forEach((envId, index) => {\n envIdToName[envId] = envNames[index];\n });\n\n const dataWithEnvNames = jsonResponse.data.map((item: any) => {\n const envId = item.resource.environment.id;\n return {\n ...item,\n envDisplayName: envIdToName[envId] || 'Unknown',\n };\n });\n\n aggregatedData = aggregatedData.concat(dataWithEnvNames);\n\n currentStartDate.add(1, 'month').startOf('month');\n }\n\n return {\n data: aggregatedData,\n };\n } catch (error) {\n this.logger.error(`Error fetching costs from Confluent: ${error.message}`);\n throw error;\n }\n }\n\n protected async transformCostsData(subAccountConfig: Config, query: CostQuery, costResponse: any): Promise<Report[]> {\n const categoryMappingService = CategoryMappingService.getInstance();\n const accountName = subAccountConfig.getString('name');\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 const transformedData = costResponse.data.reduce((accumulator: { [key: string]: Report }, line: any) => {\n const amount = parseFloat(line.amount) || 0;\n\n if (amount === 0) {\n return accumulator;\n }\n\n const parsedStartDate = moment(line.start_date);\n\n if (!parsedStartDate.isValid()) {\n return accumulator;\n }\n\n let billingPeriod = undefined;\n if (query.granularity.toUpperCase() === 'MONTHLY') {\n billingPeriod = parsedStartDate.format('YYYY-MM');\n } else {\n billingPeriod = parsedStartDate.format('YYYY-MM-DD');\n }\n\n const serviceName = this.capitalizeWords(line.line_type);\n const resourceName = line.resource.display_name || 'Unknown';\n const envDisplayName = line.envDisplayName;\n\n const keyName = `${accountName}->${categoryMappingService.getCategoryByServiceName(\n this.provider,\n serviceName,\n )}->${resourceName}`;\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName}`,\n service: this.convertServiceName(serviceName),\n category: categoryMappingService.getCategoryByServiceName(this.provider, serviceName),\n provider: this.provider,\n providerType: PROVIDER_TYPE.INTEGRATION,\n reports: {},\n ...{ project: envDisplayName },\n ...{ cluster: resourceName },\n ...tagKeyValues,\n };\n }\n\n if (!moment(billingPeriod).isBefore(moment(parseInt(query.startTime, 10)))) {\n accumulator[keyName].reports[billingPeriod] = (accumulator[keyName].reports[billingPeriod] || 0) + amount;\n }\n\n return accumulator;\n }, {});\n\n return Object.values(transformedData);\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { getCustomCostsByDateRange } from '../models/CustomCost';\nimport { CACHE_CATEGORY, CLOUD_PROVIDER, PROVIDER_TYPE, GRANULARITY } from '../service/consts';\nimport {\n getDailyPeriodStringsForOneMonth,\n getDefaultCacheTTL,\n getReportsFromCache,\n setReportsToCache,\n} from '../service/functions';\nimport { ClientResponse, CloudProviderError, CostQuery, Report } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class CustomProviderClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new CustomProviderClient(CLOUD_PROVIDER.CUSTOM, config, database, cache, logger);\n }\n\n protected async initCloudClient(_config: Config): Promise<any> {\n return null;\n }\n\n protected async fetchCosts(_integrationConfig: Config | null, _client: any, query: CostQuery): Promise<any> {\n const records = getCustomCostsByDateRange(\n this.database,\n moment(parseInt(query.startTime, 10)).toDate(),\n moment(parseInt(query.endTime, 10)).toDate(),\n );\n return records;\n }\n\n protected async transformCostsData(\n _subAccountConfig: Config | null,\n query: CostQuery,\n costResponse: any,\n ): Promise<Report[]> {\n const transformedData = reduce(\n costResponse,\n (accumulator: { [key: string]: Report }, record) => {\n let periodFormat = 'YYYY-MM';\n if (query.granularity === GRANULARITY.DAILY) {\n periodFormat = 'YYYY-MM-DD';\n }\n\n const keyName = `${record.provider}-${record.account}-${record.service}`;\n\n // make it compatible with SQLite database\n if (typeof record.tags === 'string') {\n try {\n record.tags = JSON.parse(record.tags);\n } catch (error) {\n this.logger.error(`Failed to parse tags for custom cost ${keyName}, tags: ${record.tags}`);\n record.tags = {};\n }\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n account: record.account,\n service: record.service,\n category: record.category,\n provider: record.provider,\n providerType: PROVIDER_TYPE.CUSTOM,\n reports: {},\n };\n }\n\n // if custom costs with same provider+account+service values, but contain different tags\n // we merge these tags, but the tag with same key will be overriden\n accumulator[keyName] = { ...accumulator[keyName], ...record.tags };\n\n const cost = parseFloat(record.cost);\n if (query.granularity === GRANULARITY.MONTHLY) {\n const period = moment(record.usage_month.toString(), 'YYYYMM').format(periodFormat);\n accumulator[keyName].reports[period] = cost;\n } else {\n if (record.amortization_mode === 'average') {\n // calculate the average daily cost\n const periods = getDailyPeriodStringsForOneMonth(record.usage_month);\n const averageCost = parseFloat(record.cost) / periods.length;\n periods.forEach(period => {\n accumulator[keyName].reports[period] = averageCost;\n });\n } else if (record.amortization_mode === 'start_day') {\n const period = moment(record.usage_month.toString(), 'YYYYMM').startOf('month').format(periodFormat);\n accumulator[keyName].reports[period] = cost;\n } else {\n const period = moment(record.usage_month.toString(), 'YYYYMM').endOf('month').format(periodFormat);\n accumulator[keyName].reports[period] = cost;\n }\n }\n\n return accumulator;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n\n // override this method so that we do not read from the config file\n async getCostReports(query: CostQuery): Promise<ClientResponse> {\n const results: Report[] = [];\n const errors: CloudProviderError[] = [];\n\n // first check if there is any cached\n const cachedCosts = await getReportsFromCache(this.cache, this.provider, 'custom', query);\n if (cachedCosts) {\n this.logger.debug(`${this.provider} costs from cache`);\n cachedCosts.forEach(cost => {\n results.push(cost);\n });\n }\n\n try {\n const costResponse = await this.fetchCosts(null, null, query);\n\n const transformedReports = await this.transformCostsData(null, query, costResponse);\n\n // cache the results\n await setReportsToCache(\n this.cache,\n transformedReports,\n this.provider,\n 'custom',\n query,\n getDefaultCacheTTL(CACHE_CATEGORY.COSTS, this.provider),\n );\n\n transformedReports.forEach((value: any) => {\n results.push(value);\n });\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.provider,\n name: this.provider,\n error: e.message,\n });\n }\n return {\n reports: results,\n errors: errors,\n };\n }\n}\n","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 { CostQuery, Report } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\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 historicalCost: datadogApiV2.CostByOrgResponse = await client.getHistoricalCostByOrg({\n startMonth: startTime,\n endMonth: firstDayOfLastMonth.subtract(1, 'd'),\n view: 'sub-org',\n });\n\n if (historicalCost.data) {\n costData.push(...historicalCost.data);\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 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 const transformedData = reduce(\n costResponse,\n (accumulator: { [key: string]: Report }, costByOrg) => {\n const account = costByOrg.orgName;\n const charges = costByOrg.charges;\n\n let periodFormat = 'YYYY-MM';\n if (query.granularity === GRANULARITY.DAILY) {\n periodFormat = 'YYYY-MM-DD';\n }\n const period = moment(costByOrg.date).format(periodFormat);\n\n if (charges) {\n charges.forEach((charge: datadogApiV2.ChargebackBreakdown) => {\n const productName = charge.productName;\n const cost = charge.cost;\n const keyName = `${account}->${productName} (${charge.chargeType})`;\n\n if (!accumulator[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] = cost || 0;\n });\n }\n\n return accumulator;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { BigQuery } from '@google-cloud/bigquery';\nimport { reduce } from 'lodash';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER, PROVIDER_TYPE } from '../service/consts';\nimport { CostQuery, Report } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class GCPClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new GCPClient(CLOUD_PROVIDER.GCP, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Google Cloud'];\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n protected async initCloudClient(subAccountConfig: Config): Promise<any> {\n const keyFilePath = subAccountConfig.getString('keyFilePath');\n const projectId = subAccountConfig.getString('projectId');\n // Configure a JWT auth client\n const options = {\n keyFilename: keyFilePath,\n projectId: projectId,\n };\n\n // Initialize the BigQuery API\n const bigqueryClient = new BigQuery(options);\n\n return bigqueryClient;\n }\n\n protected async fetchCosts(subAccountConfig: Config, client: any, query: CostQuery): Promise<any> {\n const projectId = subAccountConfig.getString('projectId');\n const datasetId = subAccountConfig.getString('datasetId');\n const tableId = subAccountConfig.getString('tableId');\n\n try {\n const periodFormat = query.granularity.toUpperCase() === 'MONTHLY' ? '%Y-%m' : '%Y-%m-%d';\n const sql = `\n SELECT\n project.name AS project,\n service.description AS service,\n FORMAT_TIMESTAMP('${periodFormat}', usage_start_time) AS period,\n (SUM(CAST(cost AS NUMERIC)) + SUM(IFNULL((SELECT SUM(CAST(c.amount AS NUMERIC)) FROM UNNEST(credits) AS c), 0))) AS total_cost\n FROM\n \\`${projectId}.${datasetId}.${tableId}\\`\n WHERE\n project.name IS NOT NULL\n AND cost > 0\n AND usage_start_time >= TIMESTAMP_MILLIS(${query.startTime})\n AND usage_start_time <= TIMESTAMP_MILLIS(${query.endTime})\n GROUP BY\n project, service, period\n ORDER BY\n project, period, total_cost DESC`;\n\n // Run the query as a job\n const [job] = await client.createQueryJob({\n query: sql,\n });\n\n // Wait for the query to finish\n const [rows] = await job.getQueryResults();\n\n return rows;\n } catch (err) {\n throw new Error(err.message);\n }\n }\n\n protected async transformCostsData(\n subAccountConfig: Config,\n _query: CostQuery,\n costResponse: any,\n ): Promise<Report[]> {\n const categoryMappingService = CategoryMappingService.getInstance();\n const accountName = subAccountConfig.getString('name');\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 const transformedData = reduce(\n costResponse,\n (acc: { [key: string]: Report }, row) => {\n const period = row.period;\n const keyName = `${accountName}_${row.project}_${row.service}`;\n\n if (!acc[keyName]) {\n acc[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName}`,\n service: this.convertServiceName(row.service),\n category: categoryMappingService.getCategoryByServiceName(this.provider, row.service),\n provider: this.provider,\n providerType: PROVIDER_TYPE.INTEGRATION,\n reports: {},\n ...{ project: row.project }, // TODO: how should we handle the project field? for now, we add project name as a field in the report\n ...tagKeyValues, // note that if there is a tag `project:foo` in config, it overrides the project field set above\n };\n }\n\n acc[keyName].reports[period] = parseFloat(row.total_cost);\n\n return acc;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n}\n","import { CacheService, DatabaseService, LoggerService, resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { promises as fsPromises } from 'fs';\nimport moment from 'moment';\nimport * as upath from 'upath';\nimport { CLOUD_PROVIDER, PROVIDER_TYPE } from '../service/consts';\nimport { CostQuery, Report } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class MockClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new MockClient(CLOUD_PROVIDER.MOCK, config, database, cache, logger);\n }\n\n protected async initCloudClient(config: Config): Promise<any> {\n this.logger.debug(`MockClient.initCloudClient called with config: ${JSON.stringify(config)}`);\n\n return null;\n }\n\n protected async fetchCosts(_subAccountConfig: Config, _client: any, _query: CostQuery): Promise<any> {\n return null;\n }\n\n protected async transformCostsData(\n _subAccountConfig: Config,\n query: CostQuery,\n _costResponse: any,\n ): Promise<Report[]> {\n try {\n const startD = moment.unix(Number(query.startTime) / 1000);\n let endD = moment.unix(Number(query.endTime) / 1000);\n const mockDir = resolvePackagePath('@electrolux-oss/plugin-infrawallet-backend', 'mock');\n const mockFilePath = upath.join(mockDir, 'mock_response.json');\n const data = await fsPromises.readFile(mockFilePath, 'utf8');\n const jsonData: Report[] = JSON.parse(data);\n const currentDate = moment();\n\n if (endD.isAfter(currentDate)) {\n endD = currentDate.clone();\n endD.add(1, 'day');\n }\n\n const processedData = await Promise.all(\n jsonData.map(async item => {\n item.providerType = PROVIDER_TYPE.INTEGRATION;\n item.reports = {};\n\n const StartDate = moment(startD);\n\n let step: moment.unitOfTime.DurationConstructor = 'months';\n let dateFormat = 'YYYY-MM';\n\n if (query.granularity.toLowerCase() === 'daily') {\n step = 'days';\n dateFormat = 'YYYY-MM-DD';\n }\n\n while (StartDate.isBefore(endD)) {\n const dateString = StartDate.format(dateFormat);\n\n if (query.granularity.toLowerCase() === 'monthly') {\n item.reports[dateString] = this.getRandomValue(0.4 * 30, 33.3 * 30);\n } else {\n item.reports[dateString] = this.getRandomValue(0.4, 33.3);\n }\n\n StartDate.add(1, step); // Step based on granularity\n }\n\n return item;\n }),\n );\n\n return processedData;\n } catch (err) {\n this.logger.error('Error while reading a file', err);\n throw err;\n }\n }\n\n getRandomValue(min: number, max: number): number {\n const random = Math.random();\n const amplifiedRandom = Math.pow(random, 3);\n return amplifiedRandom * (max - min) + min;\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport urllib from 'urllib';\nimport { CategoryMappingService } from '../service/CategoryMappingService';\nimport { CLOUD_PROVIDER, PROVIDER_TYPE } from '../service/consts';\nimport { CostQuery, Report } from '../service/types';\nimport { InfraWalletClient } from './InfraWalletClient';\n\nexport class MongoAtlasClient extends InfraWalletClient {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new MongoAtlasClient(CLOUD_PROVIDER.MONGODB_ATLAS, config, database, cache, logger);\n }\n\n protected convertServiceName(serviceName: string): string {\n let convertedName = serviceName;\n\n const prefixes = ['Atlas'];\n\n for (const prefix of prefixes) {\n if (serviceName.startsWith(prefix)) {\n convertedName = serviceName.slice(prefix.length).trim();\n }\n }\n\n return `${this.provider}/${convertedName}`;\n }\n\n protected async initCloudClient(subAccountConfig: any): Promise<any> {\n const publicKey = subAccountConfig.getString('publicKey');\n const privateKey = subAccountConfig.getString('privateKey');\n\n const client = {\n digestAuth: `${publicKey}:${privateKey}`,\n };\n\n return client;\n }\n\n protected async fetchCosts(subAccountConfig: Config, client: any, query: CostQuery): Promise<any> {\n const orgId = subAccountConfig.getString('orgId');\n const invoicesUrl = `/orgs/${orgId}/invoices?fromDate=${moment(parseInt(query.startTime, 10)).format(\n 'YYYY-MM-DD',\n )}&toDate=${moment(parseInt(query.endTime, 10)).add(1, 'M').format('YYYY-MM-DD')}`;\n\n try {\n const fullInvoicesUrl = `https://cloud.mongodb.com/api/atlas/v2${invoicesUrl}`;\n const response = await urllib.request(fullInvoicesUrl, {\n ...client,\n method: 'GET',\n dataType: 'json',\n headers: {\n Accept: 'application/vnd.atlas.2023-01-01+json',\n },\n });\n\n if (response.status !== 200) {\n throw new Error(`Error fetching invoices: ${response.status} ${response.statusText}`);\n }\n\n const invoices = response.data.results;\n\n const allInvoicesData = await Promise.all(\n invoices.map(async (invoice: any) => {\n const invoiceId = invoice.id;\n const csvUrl = `/orgs/${orgId}/invoices/${invoiceId}/csv`;\n const fullCsvUrl = `https://cloud.mongodb.com/api/atlas/v2${csvUrl}`;\n const csvResponse = await urllib.request(fullCsvUrl, {\n ...client,\n method: 'GET',\n dataType: 'text',\n headers: {\n Accept: 'application/vnd.atlas.2023-01-01+csv',\n },\n });\n\n if (csvResponse.status !== 200) {\n throw new Error(`Error fetching invoice CSV: ${csvResponse.status} ${csvResponse.statusText}`);\n }\n\n const lines = csvResponse.data.split('\\n');\n\n let foundOrganizationIdLine = false;\n\n // Discard rows from the beginning of the CSV up to and including the row starting with \"Organization ID\"\n const filteredLines = lines\n .filter((line: string) => {\n const trimmedLine = line.trim();\n if (trimmedLine.startsWith('Organization ID,')) {\n foundOrganizationIdLine = true;\n return false;\n }\n if (!foundOrganizationIdLine) {\n return false;\n }\n return trimmedLine !== '' && !trimmedLine.includes('Credit'); // Discard empty lines and lines where SKU is 'Credit'\n })\n .join('\\n');\n\n return filteredLines;\n }),\n );\n\n return allInvoicesData.join('\\n');\n } catch (error) {\n this.logger.error(`Error fetching invoices from MongoDB Atlas: ${error.message}`);\n throw error;\n }\n }\n\n protected async transformCostsData(\n subAccountConfig: Config,\n query: CostQuery,\n costResponse: string,\n ): Promise<Report[]> {\n const categoryMappingService = CategoryMappingService.getInstance();\n const accountName = subAccountConfig.getString('name');\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 const lines = costResponse.split('\\n');\n const header = lines[0].split(',');\n const rows = lines.slice(1);\n\n const transformedData = reduce(\n rows,\n (accumulator: { [key: string]: Report }, line) => {\n const columns = line.split(',');\n const rowData: { [key: string]: string } = {};\n header.forEach((columnName, index) => {\n rowData[columnName] = columns[index];\n });\n\n const amount = parseFloat(rowData.Amount) || 0;\n\n const dateFormat = 'MM/DD/YYYY';\n const date = rowData.Date;\n const parsedDate = moment(date, dateFormat, true);\n\n if (!parsedDate.isValid()) {\n return accumulator;\n }\n\n let billingPeriod = undefined;\n if (query.granularity.toUpperCase() === 'MONTHLY') {\n billingPeriod = parsedDate.format('YYYY-MM');\n } else {\n billingPeriod = parsedDate.format('YYYY-MM-DD');\n }\n\n const serviceName = rowData.SKU;\n const cluster = rowData.Cluster || 'Unknown';\n const project = rowData.Project || 'Unknown';\n\n const keyName = `${accountName}->${categoryMappingService.getCategoryByServiceName(\n this.provider,\n serviceName,\n )}->${project}->${cluster}`;\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n account: `${this.provider}/${accountName}`,\n service: this.convertServiceName(serviceName),\n category: categoryMappingService.getCategoryByServiceName(this.provider, serviceName),\n provider: this.provider,\n providerType: PROVIDER_TYPE.INTEGRATION,\n reports: {},\n ...{ project: project },\n ...{ cluster: cluster },\n ...tagKeyValues,\n };\n }\n\n if (!moment(billingPeriod).isBefore(moment(parseInt(query.startTime, 10)))) {\n accumulator[keyName].reports[billingPeriod] = (accumulator[keyName].reports[billingPeriod] || 0) + amount;\n }\n\n return accumulator;\n },\n {},\n );\n\n return Object.values(transformedData);\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { getMetricsFromCache, setMetricsToCache } from '../service/functions';\nimport { CloudProviderError, Metric, MetricQuery, MetricSetting, MetricResponse } from '../service/types';\n\nexport abstract class MetricProvider {\n constructor(\n protected readonly providerName: string,\n protected readonly config: Config,\n protected readonly database: DatabaseService,\n protected readonly cache: CacheService,\n protected readonly logger: LoggerService,\n ) {}\n\n abstract initProviderClient(metricProviderConfig: Config): Promise<any>;\n\n abstract fetchMetrics(metricProviderConfig: Config, client: any, query: MetricQuery): Promise<any>;\n\n abstract transformMetricData(\n metricProviderConfig: Config,\n query: MetricQuery,\n metricResponse: any,\n ): Promise<Metric[]>;\n\n async getMetrics(query: MetricQuery): Promise<MetricResponse> {\n const conf = this.config.getOptionalConfigArray(\n `backend.infraWallet.metricProviders.${this.providerName.toLowerCase()}`,\n );\n if (!conf) {\n return { metrics: [], errors: [] };\n }\n\n const promises = [];\n const results: Metric[] = [];\n const errors: CloudProviderError[] = [];\n\n for (const c of conf) {\n const configName = c.getString('name');\n const client = await this.initProviderClient(c);\n const dbClient = await this.database.getClient();\n\n const metricSettings = await dbClient\n .where({\n 'wallets.name': query.walletName,\n 'business_metrics.metric_provider': this.providerName.toLowerCase(),\n 'business_metrics.config_name': configName,\n })\n .select('business_metrics.*')\n .from<MetricSetting>('business_metrics')\n .join('wallets', 'business_metrics.wallet_id', '=', 'wallets.id');\n\n for (const metric of metricSettings || []) {\n const promise = (async () => {\n try {\n const fullQuery: MetricQuery = {\n name: metric.metric_name,\n query: metric.query,\n ...query,\n };\n\n // first check if there is any cached metrics\n const cachedMetrics = await getMetricsFromCache(this.cache, this.providerName, configName, fullQuery);\n if (cachedMetrics) {\n this.logger.debug(`${this.providerName}/${configName}/${fullQuery.name} metrics from cache`);\n cachedMetrics.forEach(m => {\n results.push({\n group: metric.group, // add group info to the metric\n ...m,\n });\n });\n return;\n }\n\n const metricResponse = await this.fetchMetrics(c, client, fullQuery);\n const transformedMetrics = await this.transformMetricData(c, fullQuery, metricResponse);\n\n // cache the results for 2 hours\n await setMetricsToCache(\n this.cache,\n transformedMetrics,\n this.providerName,\n configName,\n fullQuery,\n 60 * 60 * 2 * 1000,\n );\n\n transformedMetrics.forEach((value: any) => {\n results.push({\n group: metric.group, // add group info to the metric\n ...value,\n });\n });\n } catch (e) {\n this.logger.error(e);\n errors.push({\n provider: this.providerName,\n name: `${this.providerName}/${configName}/${metric.getString('metricName')}`,\n error: e.message,\n });\n }\n })();\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return {\n metrics: results,\n errors: errors,\n };\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { v1 as datadogApiV1, client as datadogClient } from '@datadog/datadog-api-client';\nimport moment from 'moment';\nimport { MetricProvider } from './MetricProvider';\nimport { Metric, MetricQuery } from '../service/types';\n\nexport class DatadogProvider extends MetricProvider {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new DatadogProvider('Datadog', config, database, cache, logger);\n }\n\n async initProviderClient(config: Config): Promise<any> {\n const apiKey = config.getString('apiKey');\n const applicationKey = config.getString('applicationKey');\n const ddSite = config.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 datadogApiV1.MetricsApi(configuration);\n return client;\n }\n\n async fetchMetrics(_metricProviderConfig: Config, client: any, query: MetricQuery): Promise<any> {\n const params: datadogApiV1.MetricsApiQueryMetricsRequest = {\n from: parseInt(query.startTime, 10) / 1000,\n to: parseInt(query.endTime, 10) / 1000,\n query: query.query?.replaceAll('IW_INTERVAL', query.granularity === 'daily' ? '86400' : '2592000') as string,\n };\n return client.queryMetrics(params).then((data: datadogApiV1.MetricsQueryResponse) => {\n if (data.status === 'ok') {\n return data;\n }\n throw new Error(data.error);\n });\n }\n\n async transformMetricData(_metricProviderConfig: Config, query: MetricQuery, metricResponse: any): Promise<Metric[]> {\n const transformedData = [];\n\n for (const series of metricResponse.series) {\n const metricName = query.name as string;\n const tagSet = series.tagSet;\n\n const metric: Metric = {\n id: `${metricName} ${tagSet.length === 0 ? '' : tagSet}`,\n provider: this.providerName,\n name: metricName,\n reports: {},\n };\n\n for (const point of series.pointlist) {\n const period = moment(point[0]).format(query.granularity === 'daily' ? 'YYYY-MM-DD' : 'YYYY-MM');\n const value = point[1];\n metric.reports[period] = value;\n }\n\n transformedData.push(metric);\n }\n\n return transformedData;\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport moment from 'moment';\nimport fetch from 'node-fetch';\nimport { MetricProvider } from './MetricProvider';\nimport { Metric, MetricQuery } from '../service/types';\n\nexport class GrafanaCloudProvider extends MetricProvider {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new GrafanaCloudProvider('GrafanaCloud', config, database, cache, logger);\n }\n\n async initProviderClient(_config: Config): Promise<any> {\n // for now we don't need to use Grafana Cloud SDK\n return null;\n }\n\n async fetchMetrics(metricProviderConfig: Config, _client: any, query: MetricQuery): Promise<any> {\n const url = metricProviderConfig.getString('url');\n const datasourceUid = metricProviderConfig.getString('datasourceUid');\n const token = metricProviderConfig.getString('token');\n\n const headers = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n };\n const payload = {\n queries: [\n {\n datasource: {\n uid: datasourceUid,\n },\n expr: query.query?.replaceAll('IW_INTERVAL', query.granularity === 'daily' ? '1d' : '30d'),\n refId: 'A',\n },\n ],\n from: query.startTime,\n to: query.endTime,\n };\n\n const response = await fetch(`${url}/api/ds/query`, {\n method: 'post',\n body: JSON.stringify(payload),\n headers: headers,\n });\n const data = await response.json();\n\n return data;\n }\n\n async transformMetricData(_metricProviderConfig: Config, query: MetricQuery, metricResponse: any): Promise<Metric[]> {\n const transformedData = [];\n\n const metricName = query.name as string;\n const metric: Metric = {\n id: metricName,\n provider: this.providerName,\n name: metricName,\n reports: {},\n };\n\n // TODO: iterate all the series\n const periods = metricResponse.results.A.frames[0].data.values[0];\n const values = metricResponse.results.A.frames[0].data.values[1];\n for (let i = 0; i < periods.length; i++) {\n const period = moment(periods[i]).format(query.granularity === 'daily' ? 'YYYY-MM-DD' : 'YYYY-MM');\n const value = values[i];\n metric.reports[period] = value;\n }\n\n transformedData.push(metric);\n return transformedData;\n }\n}\n","import { CacheService, DatabaseService, LoggerService } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport moment from 'moment';\nimport { MetricProvider } from './MetricProvider';\nimport { Metric, MetricQuery } from '../service/types';\n\nexport class MockProvider extends MetricProvider {\n static create(config: Config, database: DatabaseService, cache: CacheService, logger: LoggerService) {\n return new MockProvider('Mock', config, database, cache, logger);\n }\n\n async initProviderClient(_config: Config): Promise<any> {\n // for now we don't need to use Grafana Cloud SDK\n return null;\n }\n\n async fetchMetrics(_metricProviderConfig: Config, _client: any, _query: MetricQuery): Promise<any> {\n return null;\n }\n\n async transformMetricData(\n _metricProviderConfig: Config,\n query: MetricQuery,\n _metricResponse: any,\n ): Promise<Metric[]> {\n const transformedData = [];\n\n const metricName = query.name as string;\n let mockSettings: { min?: number; max?: number } = {};\n try {\n mockSettings = JSON.parse(query.query as string);\n } catch (e) {\n // nothing needs to be done\n }\n const minValue = mockSettings.min ?? 0;\n const maxValue = mockSettings.max ?? 1000;\n const metric: Metric = {\n id: metricName,\n provider: this.providerName,\n name: metricName,\n reports: {},\n };\n\n let cursor = moment(parseInt(query.startTime, 10));\n while (cursor <= moment(parseInt(query.endTime, 10))) {\n const period = cursor.format(query.granularity === 'daily' ? 'YYYY-MM-DD' : 'YYYY-MM');\n metric.reports[period] = Math.floor(Math.random() * (maxValue - minValue) + minValue);\n cursor = cursor.add(1, query.granularity === 'daily' ? 'days' : 'months');\n }\n\n transformedData.push(metric);\n return transformedData;\n }\n}\n","import { AwsClient } from '../cost-clients/AwsClient';\nimport { AzureClient } from '../cost-clients/AzureClient';\nimport { ConfluentClient } from '../cost-clients/ConfluentClient';\nimport { CustomProviderClient } from '../cost-clients/CustomProviderClient';\nimport { DatadogClient } from '../cost-clients/DatadogClient';\nimport { GCPClient } from '../cost-clients/GCPClient';\nimport { MockClient } from '../cost-clients/MockClient';\nimport { MongoAtlasClient } from '../cost-clients/MongoAtlasClient';\nimport { DatadogProvider } from '../metric-providers/DatadogProvider';\nimport { GrafanaCloudProvider } from '../metric-providers/GrafanaCloudProvider';\nimport { MockProvider } from '../metric-providers/MockProvider';\n\n// Supported cloud providers to extract costs\nexport const enum CLOUD_PROVIDER {\n AWS = 'AWS',\n GCP = 'GCP',\n AZURE = 'Azure',\n MONGODB_ATLAS = 'MongoAtlas',\n CONFLUENT = 'Confluent',\n DATADOG = 'Datadog',\n CUSTOM = 'Custom',\n MOCK = 'Mock',\n}\n\nexport const COST_CLIENT_MAPPINGS: {\n [provider: string]: any;\n} = {\n aws: AwsClient,\n azure: AzureClient,\n gcp: GCPClient,\n confluent: ConfluentClient,\n mongoatlas: MongoAtlasClient,\n datadog: DatadogClient,\n custom: CustomProviderClient,\n mock: MockClient,\n};\n\nexport const METRIC_PROVIDER_MAPPINGS: {\n [provider: string]: any;\n} = {\n datadog: DatadogProvider,\n grafanacloud: GrafanaCloudProvider,\n mock: MockProvider,\n};\n\nexport const enum GRANULARITY {\n DAILY = 'daily',\n MONTHLY = 'monthly',\n}\n\nexport const enum CACHE_CATEGORY {\n COSTS = 'costs',\n TAGS = 'tags',\n METRICS = 'metrics',\n CATEGORY_MAPPINGS = 'category_mappings',\n}\n\nexport const DEFAULT_CATEGORY_MAPPING_CACHE_TTL = 12 * 60 * 60 * 1000; // 12 hours\n\nexport const DEFAULT_TAGS_CACHE_TTL: {\n [provider in CLOUD_PROVIDER]: number;\n} = {\n [CLOUD_PROVIDER.AWS]: 1 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.AZURE]: 12 * 60 * 60 * 1000, // 12 hours due to Azure rate limit\n [CLOUD_PROVIDER.GCP]: 1 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.MONGODB_ATLAS]: 1 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.CONFLUENT]: 1 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.DATADOG]: 1 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.CUSTOM]: 1,\n [CLOUD_PROVIDER.MOCK]: 0, // NOTE: 0 means never expired!\n};\n\nexport const DEFAULT_COSTS_CACHE_TTL: {\n [provider in CLOUD_PROVIDER]: number;\n} = {\n [CLOUD_PROVIDER.AWS]: 2 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.AZURE]: 12 * 60 * 60 * 1000, // 12 hours due to Azure rate limit\n [CLOUD_PROVIDER.GCP]: 2 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.MONGODB_ATLAS]: 2 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.CONFLUENT]: 2 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.DATADOG]: 2 * 60 * 60 * 1000,\n [CLOUD_PROVIDER.CUSTOM]: 1, // do not cache custom costs since they are in the plugin database\n [CLOUD_PROVIDER.MOCK]: 0, // NOTE: 0 means never expired!\n};\n\nexport const enum PROVIDER_TYPE {\n INTEGRATION = 'Integration',\n CUSTOM = 'Custom',\n}\n","import { CacheService, LoggerService } from '@backstage/backend-plugin-api';\nimport { CACHE_CATEGORY, DEFAULT_CATEGORY_MAPPING_CACHE_TTL } from './consts';\nimport { CategoryMappings, ServiceToCategoryMappings } from './types';\n\nexport class CategoryMappingService {\n private static instance: CategoryMappingService;\n\n constructor(\n protected readonly cache: CacheService,\n protected readonly logger: LoggerService,\n ) {}\n\n static initInstance(cache: CacheService, logger: LoggerService) {\n if (!CategoryMappingService.instance) {\n CategoryMappingService.instance = new CategoryMappingService(cache, logger);\n }\n }\n\n static getInstance(): CategoryMappingService {\n if (!CategoryMappingService.instance) {\n throw new Error('CategoryMappingService needs to be initialized first');\n }\n return CategoryMappingService.instance;\n }\n\n private categoryMappings: CategoryMappings = {};\n private serviceToCategory: ServiceToCategoryMappings = {};\n\n private generateServiceToCategoryMappings(categoryMappings: CategoryMappings): ServiceToCategoryMappings {\n const result: ServiceToCategoryMappings = {};\n for (const [category, mappings] of Object.entries(categoryMappings)) {\n for (const [provider, services] of Object.entries(mappings)) {\n const providerLowerCase = provider.toLowerCase();\n if (!(provider in result)) {\n result[providerLowerCase] = {};\n }\n services.forEach(service => {\n result[providerLowerCase][service] = category;\n });\n }\n }\n return result;\n }\n\n private async fetchCategoryMappings(): Promise<CategoryMappings> {\n const datasource =\n 'https://raw.githubusercontent.com/electrolux-oss/infrawallet-default-category-mappings/main/default_category_mappings.json';\n\n let result: CategoryMappings = {};\n\n await fetch(datasource)\n .then(async response => {\n const data = await response.json();\n this.logger.debug('Default category mappings updated');\n result = data;\n })\n .catch(_error => {\n // it might fail to retrive the mappings from our GitHub repo\n this.logger.error('Failed to fetch default category mappings from GitHub');\n this.logger.error('All services will be treated as \"Uncategorized\"');\n });\n\n return result;\n }\n\n public async refreshCategoryMappings() {\n let categoryMappings = (await this.cache.get(CACHE_CATEGORY.CATEGORY_MAPPINGS)) as CategoryMappings | undefined;\n if (categoryMappings === undefined) {\n // fetch the mappings from the GitHub repo and set it to the cache\n categoryMappings = await this.fetchCategoryMappings();\n await this.cache.set(CACHE_CATEGORY.CATEGORY_MAPPINGS, categoryMappings, {\n ttl: DEFAULT_CATEGORY_MAPPING_CACHE_TTL,\n });\n this.categoryMappings = categoryMappings;\n this.serviceToCategory = this.generateServiceToCategoryMappings(categoryMappings);\n } else {\n this.logger.debug('Reuse the category mappings from cache');\n }\n }\n\n public getCategoryByServiceName(provider: string, serviceName: string): string {\n const providerLowerCase = provider.toLowerCase();\n\n if (this.serviceToCategory[providerLowerCase] && serviceName in this.serviceToCategory[providerLowerCase]) {\n return this.serviceToCategory[providerLowerCase][serviceName];\n }\n\n // do a regex match with service name and then update the serviceToCategory mappings\n let result = 'Uncategorized';\n this.logger.debug(`${serviceName} does not belong to any category, do a regex search in the category mappings`);\n for (const [category, mappings] of Object.entries(this.categoryMappings)) {\n if (providerLowerCase in mappings) {\n for (const service of mappings[providerLowerCase]) {\n const regex = new RegExp(service);\n if (regex.test(serviceName)) {\n this.logger.debug(`${serviceName} belongs to ${category} in regex mode`);\n result = category;\n }\n }\n }\n }\n\n this.serviceToCategory[providerLowerCase][serviceName] = result;\n this.logger.debug(`serviceToCategoryMappings updated: ${providerLowerCase}/${serviceName} -> ${result}`);\n\n return result;\n }\n}\n","import { errorHandler } from '@backstage/backend-common';\nimport { CacheService, DatabaseService, LoggerService, resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport {\n deleteWalletMetricSetting,\n getWallet,\n getWalletMetricSettings,\n updateOrInsertWalletMetricSetting,\n} from '../controllers/MetricSettingController';\nimport { InfraWalletClient } from '../cost-clients/InfraWalletClient';\nimport { MetricProvider } from '../metric-providers/MetricProvider';\nimport { Budget, getBudget, getBudgets, upsertBudget } from '../models/Budget';\nimport {\n createCustomCosts,\n CustomCost,\n deleteCustomCost,\n getCustomCosts,\n updateOrInsertCustomCost,\n} from '../models/CustomCost';\nimport { CategoryMappingService } from './CategoryMappingService';\nimport { COST_CLIENT_MAPPINGS, METRIC_PROVIDER_MAPPINGS } from './consts';\nimport { parseFilters, parseTags, tagsToString } from './functions';\nimport { CloudProviderError, Metric, MetricSetting, Report, Tag } from './types';\n\nexport interface RouterOptions {\n logger: LoggerService;\n config: Config;\n cache: CacheService;\n database: DatabaseService;\n}\n\nasync function setUpDatabase(database: DatabaseService) {\n // check database migrations\n const client = await database.getClient();\n const migrationsDir = resolvePackagePath('@electrolux-oss/plugin-infrawallet-backend', 'migrations');\n if (!database.migrations?.skip) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n }\n\n // insert default category_mappings to the database\n const seedsDir = resolvePackagePath('@electrolux-oss/plugin-infrawallet-backend', 'seeds');\n await client.seed.run({ directory: seedsDir });\n}\n\nexport async function createRouter(options: RouterOptions): Promise<express.Router> {\n const { logger, config, cache, database } = options;\n // do database migrations here to support the legacy backend system\n await setUpDatabase(database);\n\n // init CategoryMappingService\n CategoryMappingService.initInstance(cache, logger);\n\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n logger.info('PONG!');\n response.json({ status: 'ok' });\n });\n\n router.get('/reports', async (request, response) => {\n const filters = request.query.filters as string;\n const tags = parseTags(request.query.tags as string);\n const groups = request.query.groups as string;\n const granularity = request.query.granularity as string;\n const startTime = request.query.startTime as string;\n const endTime = request.query.endTime as string;\n const promises: Promise<void>[] = [];\n const results: Report[] = [];\n const errors: CloudProviderError[] = [];\n\n // group tags by providers\n const providerTags: Record<string, Tag[]> = {};\n for (const tag of tags) {\n const provider = tag.provider.toLowerCase();\n if (!providerTags[provider]) {\n providerTags[provider] = [];\n }\n\n providerTags[provider].push(tag);\n }\n\n const categoryMappingService = CategoryMappingService.getInstance();\n await categoryMappingService.refreshCategoryMappings();\n\n const conf = config.getConfig('backend.infraWallet.integrations');\n // concat['custom'] : always enable custom cost\n conf\n .keys()\n .concat(['custom'])\n .forEach((provider: string) => {\n if (provider in COST_CLIENT_MAPPINGS) {\n const client: InfraWalletClient = COST_CLIENT_MAPPINGS[provider].create(config, database, cache, logger);\n const fetchCloudCosts = (async () => {\n try {\n const clientResponse = await client.getCostReports({\n filters: filters,\n tags: tagsToString(providerTags[provider.toLowerCase()]),\n groups: groups,\n granularity: granularity,\n startTime: startTime,\n endTime: endTime,\n });\n clientResponse.errors.forEach((e: CloudProviderError) => {\n errors.push(e);\n });\n clientResponse.reports.forEach((cost: Report) => {\n results.push(cost);\n });\n } catch (e) {\n logger.error(e);\n errors.push({\n provider: client.constructor.name,\n name: client.constructor.name,\n error: e.message,\n });\n }\n })();\n promises.push(fetchCloudCosts);\n }\n });\n\n await Promise.all(promises);\n\n const parsedFilters = parseFilters(filters);\n\n const filteredResults = results.filter(report => {\n return Object.entries(parsedFilters).every(([key, values]) => {\n const reportValue = report[key];\n if (typeof reportValue !== 'string') {\n return false;\n }\n return values.includes(reportValue);\n });\n });\n\n if (errors.length > 0) {\n response.status(207).json({ data: filteredResults, errors: errors, status: 207 });\n } else {\n response.json({ data: filteredResults, errors: errors, status: 200 });\n }\n });\n\n router.get('/tag-keys', async (request, response) => {\n const tags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n const tagProvider = request.query.provider as string;\n const startTime = request.query.startTime as string;\n const endTime = request.query.endTime as string;\n const promises: Promise<void>[] = [];\n\n const conf = config.getConfig('backend.infraWallet.integrations');\n conf.keys().forEach((provider: string) => {\n if (provider.toLowerCase() === tagProvider.toLowerCase() && provider in COST_CLIENT_MAPPINGS) {\n const client: InfraWalletClient = COST_CLIENT_MAPPINGS[provider].create(config, database, cache, logger);\n const getTagKeys = (async () => {\n try {\n const clientResponse = await client.getTagKeys({\n startTime: startTime,\n endTime: endTime,\n });\n clientResponse.errors.forEach((e: CloudProviderError) => {\n errors.push(e);\n });\n clientResponse.tags.forEach((tag: Tag) => {\n tags.push(tag);\n });\n } catch (e) {\n logger.error(e);\n errors.push({\n provider: client.constructor.name,\n name: client.constructor.name,\n error: e.message,\n });\n }\n })();\n promises.push(getTagKeys);\n }\n });\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n response.status(207).json({ data: tags, errors: errors, status: 207 });\n } else {\n response.json({ data: tags, errors: errors, status: 200 });\n }\n });\n\n router.get('/tag-values', async (request, response) => {\n const tags: Tag[] = [];\n const errors: CloudProviderError[] = [];\n\n const startTime = request.query.startTime as string;\n const endTime = request.query.endTime as string;\n const tagKey = request.query.tag as string;\n const tagProvider = request.query.provider as string;\n const promises: Promise<void>[] = [];\n\n const conf = config.getConfig('backend.infraWallet.integrations');\n conf.keys().forEach((provider: string) => {\n if (provider in COST_CLIENT_MAPPINGS && provider.toLowerCase() === tagProvider.toLowerCase()) {\n const client: InfraWalletClient = COST_CLIENT_MAPPINGS[provider].create(config, database, cache, logger);\n const getTagValues = (async () => {\n try {\n const clientResponse = await client.getTagValues(\n {\n startTime: startTime,\n endTime: endTime,\n },\n tagKey,\n );\n clientResponse.errors.forEach((e: CloudProviderError) => {\n errors.push(e);\n });\n clientResponse.tags.forEach((tag: Tag) => {\n tags.push(tag);\n });\n } catch (e) {\n logger.error(e);\n errors.push({\n provider: client.constructor.name,\n name: client.constructor.name,\n error: e.message,\n });\n }\n })();\n promises.push(getTagValues);\n }\n });\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n response.status(207).json({ data: tags, errors: errors, status: 207 });\n } else {\n response.json({ data: tags, errors: errors, status: 200 });\n }\n });\n\n router.get('/:walletName/budgets', async (request, response) => {\n const walletName = request.params.walletName;\n const provider = request.query.provider as string;\n let budgets;\n\n if (provider) {\n budgets = await getBudget(database, walletName, provider);\n } else {\n budgets = await getBudgets(database, walletName);\n }\n\n response.json({ data: budgets, status: 200 });\n });\n\n router.put('/:walletName/budgets', async (request, response) => {\n const walletName = request.params.walletName;\n const result = await upsertBudget(database, walletName, request.body as Budget);\n response.json({ updated: result, status: 200 });\n });\n\n router.get('/custom-costs', async (_request, response) => {\n const customCosts = await getCustomCosts(database);\n\n // make it compatible with the SQLite database\n for (const cost of customCosts) {\n if (typeof cost.tags === 'string') {\n try {\n cost.tags = JSON.parse(cost.tags);\n } catch (error) {\n cost.tags = {};\n }\n }\n }\n\n response.json({ data: customCosts, status: 200 });\n });\n\n router.post('/custom-costs', async (request, response) => {\n const readOnly = config.getOptionalBoolean('infraWallet.settings.readOnly') ?? false;\n\n if (readOnly) {\n response.status(403).json({ error: 'API not enabled in read-only mode', status: 403 });\n return;\n }\n\n const updatedCustomCost = await createCustomCosts(database, request.body as CustomCost[]);\n response.json({ created: updatedCustomCost, status: 200 });\n });\n\n router.put('/custom-cost', async (request, response) => {\n const readOnly = config.getOptionalBoolean('infraWallet.settings.readOnly') ?? false;\n\n if (readOnly) {\n response.status(403).json({ error: 'API not enabled in read-only mode', status: 403 });\n return;\n }\n\n const updatedCustomCost = await updateOrInsertCustomCost(database, request.body as CustomCost);\n response.json({ updated: updatedCustomCost, status: 200 });\n });\n\n router.delete('/custom-cost', async (request, response) => {\n const readOnly = config.getOptionalBoolean('infraWallet.settings.readOnly') ?? false;\n\n if (readOnly) {\n response.status(403).json({ error: 'API not enabled in read-only mode', status: 403 });\n return;\n }\n\n const deletedCustomCost = await deleteCustomCost(database, request.body as CustomCost);\n response.json({ deleted: deletedCustomCost, status: 200 });\n });\n\n router.get('/:walletName/metrics', async (request, response) => {\n const walletName = request.params.walletName;\n const granularity = request.query.granularity as string;\n const startTime = request.query.startTime as string;\n const endTime = request.query.endTime as string;\n const promises: Promise<void>[] = [];\n const results: Metric[] = [];\n const errors: CloudProviderError[] = [];\n\n const conf = config.getConfig('backend.infraWallet.metricProviders');\n conf.keys().forEach((provider: string) => {\n if (provider in METRIC_PROVIDER_MAPPINGS) {\n const client: MetricProvider = METRIC_PROVIDER_MAPPINGS[provider].create(config, database, cache, logger);\n const fetchMetrics = (async () => {\n try {\n const metricResponse = await client.getMetrics({\n walletName: walletName,\n granularity: granularity,\n startTime: startTime,\n endTime: endTime,\n });\n metricResponse.errors.forEach((e: CloudProviderError) => {\n errors.push(e);\n });\n metricResponse.metrics.forEach((metric: Metric) => {\n results.push(metric);\n });\n } catch (e) {\n logger.error(e);\n errors.push({\n provider: client.constructor.name,\n name: client.constructor.name,\n error: e.message,\n });\n }\n })();\n promises.push(fetchMetrics);\n }\n });\n\n await Promise.all(promises);\n\n if (errors.length > 0) {\n response.status(207).json({ data: results, errors: errors, status: 207 });\n } else {\n response.json({ data: results, errors: errors, status: 200 });\n }\n });\n\n router.get('/:walletName', async (request, response) => {\n const walletName = request.params.walletName;\n const wallet = await getWallet(database, walletName);\n if (wallet === undefined) {\n response.status(404).json({ error: 'Wallet not found', status: 404 });\n return;\n }\n\n response.json({ data: wallet, status: 200 });\n });\n\n router.get('/:walletName/metrics-setting', async (request, response) => {\n const walletName = request.params.walletName;\n const metricSettings = await getWalletMetricSettings(database, walletName);\n response.json({ data: metricSettings, status: 200 });\n });\n\n router.get('/metric/metric-configs', async (_request, response) => {\n const conf = config.getConfig('backend.infraWallet.metricProviders');\n const configNames: { metric_provider: string; config_name: string }[] = [];\n conf.keys().forEach((provider: string) => {\n const configs = conf.getOptionalConfigArray(provider);\n if (configs) {\n configs.forEach(c => {\n configNames.push({ metric_provider: provider, config_name: c.getString('name') });\n });\n }\n });\n\n response.json({ data: configNames, status: 200 });\n });\n\n router.put('/:walletName/metrics-setting', async (request, response) => {\n const readOnly = config.getOptionalBoolean('infraWallet.settings.readOnly') ?? false;\n\n if (readOnly) {\n response.status(403).json({ error: 'API not enabled in read-only mode', status: 403 });\n return;\n }\n\n const updatedMetricSetting = await updateOrInsertWalletMetricSetting(database, request.body as MetricSetting);\n response.json({ updated: updatedMetricSetting, status: 200 });\n });\n\n router.delete('/:walletName/metrics-setting', async (request, response) => {\n const readOnly = config.getOptionalBoolean('infraWallet.settings.readOnly') ?? false;\n\n if (readOnly) {\n response.status(403).json({ error: 'API not enabled in read-only mode', status: 403 });\n return;\n }\n\n const deletedMetricSetting = await deleteWalletMetricSetting(database, request.body as MetricSetting);\n response.json({ deleted: deletedMetricSetting, status: 200 });\n });\n\n router.use(errorHandler());\n return router;\n}\n","import { coreServices, createBackendPlugin } from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\n\n/**\n * infraWalletPlugin backend plugin\n *\n * @public\n */\nexport const infraWalletPlugin = createBackendPlugin({\n pluginId: 'infrawallet',\n register(env) {\n env.registerInit({\n deps: {\n httpRouter: coreServices.httpRouter,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n cache: coreServices.cache,\n database: coreServices.database,\n },\n async init({ httpRouter, logger, config, cache, database }) {\n httpRouter.use(\n await createRouter({\n logger,\n config,\n cache,\n database,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["moment","CostExplorerClient","STSClient","AssumeRoleCommand","GetTagsCommand","Dimension","GroupDefinitionType","GetCostAndUsageCommand","reduce","createPipelineRequest","createHttpHeaders","ClientSecretCredential","CostManagementClient","datadogClient","datadogApiV2","BigQuery","resolvePackagePath","upath","fsPromises","urllib","datadogApiV1","fetch","CLOUD_PROVIDER","GRANULARITY","CACHE_CATEGORY","PROVIDER_TYPE","Router","express","errorHandler","createBackendPlugin","coreServices"],"mappings":"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"}
|