Merge pull request #12298 from andrewthauer/cost-insights-isomorphic

refactor: create cost-insights-common isomorphic package
This commit is contained in:
Fredrik Adelöw
2022-07-01 17:07:35 +02:00
committed by GitHub
34 changed files with 551 additions and 254 deletions
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
@@ -0,0 +1 @@
# @backstage/plugin-cost-insights-common
+8
View File
@@ -0,0 +1,8 @@
# Cost Insights Common
Shared isomorphic code for the cost-insights plugin.
## Links
- [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/cost-insights)
- [The Backstage homepage](https://backstage.io)
@@ -0,0 +1,92 @@
## API Report File for "@backstage/plugin-cost-insights-common"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
// @public (undocumented)
export interface ChangeStatistic {
amount: number;
ratio?: number;
}
// @public (undocumented)
export interface Cost {
// (undocumented)
aggregation: DateAggregation[];
// (undocumented)
change?: ChangeStatistic;
// (undocumented)
groupedCosts?: Record<string, Cost[]>;
// (undocumented)
id: string;
// (undocumented)
trendline?: Trendline;
}
// @public (undocumented)
export type DateAggregation = {
date: string;
amount: number;
};
// @public
export interface Entity {
// (undocumented)
aggregation: [number, number];
// (undocumented)
change: ChangeStatistic;
// (undocumented)
entities: Record<string, Entity[]>;
// (undocumented)
id: Maybe<string>;
}
// @public (undocumented)
export type Group = {
id: string;
};
// @public (undocumented)
export type Maybe<T> = T | null;
// @public (undocumented)
export type Metric = {
kind: string;
name: string;
default: boolean;
};
// @public (undocumented)
export interface MetricData {
// (undocumented)
aggregation: DateAggregation[];
// (undocumented)
change: ChangeStatistic;
// (undocumented)
format: 'number' | 'currency';
// (undocumented)
id: string;
}
// @public (undocumented)
export interface Product {
// (undocumented)
kind: string;
// (undocumented)
name: string;
}
// @public (undocumented)
export interface Project {
// (undocumented)
id: string;
// (undocumented)
name?: string;
}
// @public (undocumented)
export type Trendline = {
slope: number;
intercept: number;
};
```
+42
View File
@@ -0,0 +1,42 @@
{
"name": "@backstage/plugin-cost-insights-common",
"description": "Common functionalities for the cost-insights plugin",
"version": "0.0.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
"backstage": {
"role": "common-library"
},
"homepage": "https://backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "plugins/cost-insights-common"
},
"keywords": [
"backstage"
],
"scripts": {
"build": "backstage-cli package build",
"lint": "backstage-cli package lint",
"test": "backstage-cli package test",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack",
"clean": "backstage-cli package clean"
},
"dependencies": {},
"devDependencies": {
"@backstage/cli": "^0.18.0-next.1"
},
"files": [
"dist"
]
}
+23
View File
@@ -0,0 +1,23 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Provides shared objects useful for interacting with the cost-insights plugin.
*
* @packageDocumentation
*/
export * from './types';
@@ -0,0 +1,17 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export {};
@@ -0,0 +1,32 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @public
*/
export interface ChangeStatistic {
/**
* The ratio of change from one duration to another, expressed as: (newSum - oldSum) / oldSum
* If a ratio cannot be calculated - such as when a new or old sum is zero,
* the ratio can be omitted and where applicable, ∞ or -∞ will display based on amount.
*/
ratio?: number;
/**
* The actual USD change between time periods (can be negative if costs decreased)
*/
amount: number;
}
@@ -18,6 +18,9 @@ import { DateAggregation } from './DateAggregation';
import { ChangeStatistic } from './ChangeStatistic';
import { Trendline } from './Trendline';
/**
* @public
*/
export interface Cost {
id: string;
aggregation: DateAggregation[];
@@ -14,7 +14,15 @@
* limitations under the License.
*/
/**
* @public
*/
export type DateAggregation = {
date: string; // YYYY-MM-DD
/**
* The date aggregation as string.
* @example YYYY-MM-DD
*/
date: string;
amount: number;
};
@@ -0,0 +1,124 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ChangeStatistic } from './ChangeStatistic';
import { Maybe } from './Maybe';
/**
*
* An entity is a tree-like structure that represents any unique
* product or service that generates cost over a fixed period of time.
* An entity could be atomic or composite. An atomic entity is indivisible
* and cannot be broken into sub-entities.
*
* A composite entity is divided into sub-entities that account for portions
* of the total cost **over the same time period**. The root entity is
* expected to only have _one_ Record consisting of the sub-entities to display
* in the product panel (keyed by the entity type, such as "service" for
* compute entities).
*
* The root sub-entities may have multiple breakdowns - for example, a
* breakdown of an entity cost by SKU vs deployment environment. The sum
* aggregated cost of each keyed breakdown should equal the sub-entity's cost.
*
* Entities with null ids are considered "unlabeled" - costs without attribution.
* If an entity is a composite, it may only have one (1) null child but may have any number of
* null grandchildren.
*
* @public
*
* @example
* Here's an example composite entity:
* ```
* const compositeEntity = {
* id: 'product',
* aggregation: [0, 200],
* change: {
* ratio: 2000,
* amount: 200
* },
* entities: {
* service: [
* {
* id: 'service-a',
* aggregation: [0, 100],
* change: {
* ratio: 100,
* amount: 100
* },
* entities: {}
* },
* {
* id: 'service-b',
* aggregation: [0, 100],
* change: {
* ratio: 100,
* amount: 100
* },
* entities: {
* SKU: [
* {
* id: 'service-b-sku-a',
* aggregation: [0, 25],
* change: {
* ratio: 25,
* amount: 25
* },
* entities: {}
* },
* {
* id: null, // Unlabeled cost for service-b
* aggregation: [0, 75],
* change: {
* ratio: 75,
* amount: 75
* },
* entities: {}
* },
* ],
* deployment: [
* {
* id: 'service-b-env-a',
* aggregation: [0, 50],
* change: {
* ratio: 50,
* amount: 50
* },
* entities: {}
* },
* {
* id: 'service-b-env-b',
* aggregation: [0, 50],
* change: {
* ratio: 50,
* amount: 50
* },
* entities: {}
* },
* ]
* }
* },
* ]
* }
* }
* ```
*/
export interface Entity {
id: Maybe<string>;
aggregation: [number, number];
entities: Record<string, Entity[]>;
change: ChangeStatistic;
}
@@ -14,6 +14,9 @@
* limitations under the License.
*/
/**
* @public
*/
export type Group = {
id: string;
};
@@ -14,4 +14,7 @@
* limitations under the License.
*/
/**
* @public
*/
export type Maybe<T> = T | null;
@@ -14,6 +14,9 @@
* limitations under the License.
*/
/**
* @public
*/
export type Metric = {
kind: string;
name: string;
@@ -17,6 +17,9 @@
import { DateAggregation } from './DateAggregation';
import { ChangeStatistic } from './ChangeStatistic';
/**
* @public
*/
export interface MetricData {
id: string;
format: 'number' | 'currency';
@@ -14,6 +14,9 @@
* limitations under the License.
*/
/**
* @public
*/
export interface Product {
kind: string;
name: string;
@@ -14,6 +14,9 @@
* limitations under the License.
*/
/**
* @public
*/
export interface Project {
id: string;
name?: string;
@@ -13,6 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @public
*/
export type Trendline = {
slope: number;
intercept: number;
@@ -0,0 +1,27 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './ChangeStatistic';
export * from './Cost';
export * from './DateAggregation';
export * from './Entity';
export * from './Group';
export * from './Maybe';
export * from './MetricData';
export * from './Metric';
export * from './Product';
export * from './Project';
export * from './Trendline';
+45 -99
View File
@@ -9,9 +9,12 @@ import { ApiRef } from '@backstage/core-plugin-api';
import { BackstagePalette } from '@backstage/theme';
import { BackstagePlugin } from '@backstage/core-plugin-api';
import { BackstageTheme } from '@backstage/theme';
import { ChangeStatistic as ChangeStatistic_2 } from '@backstage/plugin-cost-insights-common';
import * as common from '@backstage/plugin-cost-insights-common';
import { ContentRenderer } from 'recharts';
import { Dispatch } from 'react';
import { ForwardRefExoticComponent } from 'react';
import { Maybe as Maybe_2 } from '@backstage/plugin-cost-insights-common';
import { PaletteOptions } from '@material-ui/core/styles/createPalette';
import { PropsWithChildren } from 'react';
import { ReactNode } from 'react';
@@ -32,9 +35,9 @@ export type Alert = {
status?: AlertStatus;
url?: string;
buttonText?: string;
SnoozeForm?: Maybe<AlertForm>;
AcceptForm?: Maybe<AlertForm>;
DismissForm?: Maybe<AlertForm>;
SnoozeForm?: Maybe_2<AlertForm>;
AcceptForm?: Maybe_2<AlertForm>;
DismissForm?: Maybe_2<AlertForm>;
onSnoozed?(options: AlertOptions): Promise<Alert[]>;
onAccepted?(options: AlertOptions): Promise<Alert[]>;
onDismissed?(options: AlertOptions): Promise<Alert[]>;
@@ -55,9 +58,9 @@ export interface AlertCost {
// @public (undocumented)
export interface AlertDismissFormData {
// (undocumented)
feedback: Maybe<string>;
feedback: Maybe_2<string>;
// (undocumented)
other: Maybe<string>;
other: Maybe_2<string>;
// (undocumented)
reason: AlertDismissReason;
}
@@ -269,15 +272,11 @@ export type BarChartTooltipProps = {
actions?: ReactNode;
};
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "ChangeStatistic" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface ChangeStatistic {
// (undocumented)
amount: number;
// (undocumented)
ratio?: number;
}
// @public @deprecated (undocumented)
export type ChangeStatistic = common.ChangeStatistic;
// Warning: (ae-missing-release-tag) "ChangeThreshold" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -289,8 +288,6 @@ export enum ChangeThreshold {
upper = 0.05,
}
// Warning: (ae-missing-release-tag) "ChartData" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type ChartData = {
date: number;
@@ -299,21 +296,11 @@ export type ChartData = {
[key: string]: number;
};
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "Cost" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface Cost {
// (undocumented)
aggregation: DateAggregation[];
// (undocumented)
change?: ChangeStatistic;
// (undocumented)
groupedCosts?: Record<string, Cost[]>;
// (undocumented)
id: string;
// (undocumented)
trendline?: Trendline;
}
// @public @deprecated (undocumented)
export type Cost = common.Cost;
// Warning: (ae-missing-release-tag) "CostGrowth" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -423,8 +410,6 @@ export interface CostInsightsThemeOptions extends PaletteOptions {
palette: CostInsightsPaletteOptions;
}
// Warning: (ae-missing-release-tag) "Currency" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface Currency {
// (undocumented)
@@ -465,21 +450,17 @@ export enum DataKey {
Previous = 'previous',
}
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "DateAggregation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type DateAggregation = {
date: string;
amount: number;
};
// @public @deprecated (undocumented)
export type DateAggregation = common.DateAggregation;
// Warning: (ae-missing-release-tag) "DEFAULT_DATE_FORMAT" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const DEFAULT_DATE_FORMAT = 'yyyy-LL-dd';
// Warning: (ae-missing-release-tag) "Duration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export enum Duration {
// (undocumented)
@@ -497,19 +478,11 @@ export enum Duration {
// @public (undocumented)
export const EngineerThreshold = 0.5;
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "Entity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface Entity {
// (undocumented)
aggregation: [number, number];
// (undocumented)
change: ChangeStatistic;
// (undocumented)
entities: Record<string, Entity[]>;
// (undocumented)
id: Maybe<string>;
}
// @public @deprecated (undocumented)
export type Entity = common.Entity;
// Warning: (ae-missing-release-tag) "ExampleCostInsightsClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -533,12 +506,11 @@ export class ExampleCostInsightsClient implements CostInsightsApi {
getUserGroups(userId: string): Promise<Group[]>;
}
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "Group" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type Group = {
id: string;
};
// @public @deprecated (undocumented)
export type Group = common.Group;
// Warning: (ae-missing-release-tag) "GrowthType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -602,33 +574,23 @@ export type LegendItemProps = {
// @public (undocumented)
export type Loading = Record<string, boolean>;
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "Maybe" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type Maybe<T> = T | null;
// @public @deprecated (undocumented)
export type Maybe<T> = common.Maybe<T>;
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "Metric" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type Metric = {
kind: string;
name: string;
default: boolean;
};
// @public @deprecated (undocumented)
export type Metric = common.Metric;
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "MetricData" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface MetricData {
// (undocumented)
aggregation: DateAggregation[];
// (undocumented)
change: ChangeStatistic;
// (undocumented)
format: 'number' | 'currency';
// (undocumented)
id: string;
}
// @public @deprecated (undocumented)
export type MetricData = common.MetricData;
// Warning: (ae-forgotten-export) The symbol "MockConfigProviderProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "MockConfigProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -648,32 +610,24 @@ export const MockCurrencyProvider: ({
...context
}: MockCurrencyProviderProps) => JSX.Element;
// Warning: (ae-missing-release-tag) "PageFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface PageFilters {
// (undocumented)
duration: Duration;
// (undocumented)
group: Maybe<string>;
group: Maybe_2<string>;
// (undocumented)
metric: string | null;
// (undocumented)
project: Maybe<string>;
project: Maybe_2<string>;
}
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "Product" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface Product {
// (undocumented)
kind: string;
// (undocumented)
name: string;
}
// @public @deprecated (undocumented)
export type Product = common.Product;
// Warning: (ae-missing-release-tag) "ProductFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type ProductFilters = Array<ProductPeriod>;
@@ -687,8 +641,6 @@ export type ProductInsightsOptions = {
project: Maybe<string>;
};
// Warning: (ae-missing-release-tag) "ProductPeriod" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface ProductPeriod {
// (undocumented)
@@ -697,15 +649,11 @@ export interface ProductPeriod {
productType: string;
}
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "Project" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface Project {
// (undocumented)
id: string;
// (undocumented)
name?: string;
}
// @public @deprecated (undocumented)
export type Project = common.Project;
// Warning: (ae-missing-release-tag) "ProjectGrowthAlert" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -731,7 +679,7 @@ export interface ProjectGrowthData {
// (undocumented)
aggregation: [number, number];
// (undocumented)
change: ChangeStatistic;
change: ChangeStatistic_2;
// (undocumented)
periodEnd: string;
// (undocumented)
@@ -749,7 +697,7 @@ export interface ResourceData {
// (undocumented)
current: number;
// (undocumented)
name: Maybe<string>;
name: Maybe_2<string>;
// (undocumented)
previous: number;
}
@@ -763,13 +711,11 @@ export type TooltipItem = {
value: string;
};
// Warning: (tsdoc-characters-after-block-tag) The token "@backstage" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
// Warning: (ae-missing-release-tag) "Trendline" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type Trendline = {
slope: number;
intercept: number;
};
// @public @deprecated (undocumented)
export type Trendline = common.Trendline;
// Warning: (ae-missing-release-tag) "UnlabeledDataflowAlert" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -77,7 +77,7 @@ We can use the data provided by the Cost Explorer API to implement CostInsightsA
### 1. [getGroupDailyCost](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts#L93)
The `getGroupDailyCost` method is expected to return daily cost aggregations for a given group and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/types/Cost.ts).
The `getGroupDailyCost` method is expected to return daily cost aggregations for a given group and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights-common/src/types/Cost.ts).
#### Total Daily cost
@@ -208,13 +208,13 @@ Sample `groupedCosts` based on the response:
### 2. [getProjectDailyCost](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts#L111)
The `getProjectDailyCost` method is expected to return daily cost aggregations for a given billing entity and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/types/Cost.ts).
The `getProjectDailyCost` method is expected to return daily cost aggregations for a given billing entity and interval time frame as a [`Cost`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights-common/src/types/Cost.ts).
This should be similar to the `getGroupDailyCost` method implementation, but with an updated `LINKED_ACCOUNT` filter to get narrower cost data for a lower-level linked account.
### 3. [getProductInsights](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/api/CostInsightsApi.ts#L111)
The `getProductInsights` method is expected to return cost aggregations for a particular cloud product and interval time frame as an [`Entity`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights/src/types/Entity.ts).
The `getProductInsights` method is expected to return cost aggregations for a particular cloud product and interval time frame as an [`Entity`](https://github.com/backstage/backstage/blob/master/plugins/cost-insights-common/src/types/Entity.ts).
#### Cloud product cost by resource
+1
View File
@@ -38,6 +38,7 @@
"@backstage/config": "^1.0.1",
"@backstage/core-components": "^0.9.6-next.1",
"@backstage/core-plugin-api": "^1.0.3",
"@backstage/plugin-cost-insights-common": "^0.0.0",
"@backstage/theme": "^0.2.16-next.0",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
+2 -2
View File
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ForwardRefExoticComponent, RefAttributes } from 'react';
import { ChangeStatistic } from './ChangeStatistic';
import { ChangeStatistic, Maybe } from '@backstage/plugin-cost-insights-common';
import { Duration } from './Duration';
import { Maybe } from './Maybe';
/**
* Generic alert type with required fields for display. The `element` field will be rendered in
@@ -14,15 +14,6 @@
* limitations under the License.
*/
export interface ChangeStatistic {
// The ratio of change from one duration to another, expressed as: (newSum - oldSum) / oldSum
// If a ratio cannot be calculated - such as when a new or old sum is zero,
// the ratio can be omitted and where applicable, ∞ or -∞ will display based on amount.
ratio?: number;
// The actual USD change between time periods (can be negative if costs decreased)
amount: number;
}
export const EngineerThreshold = 0.5;
export enum ChangeThreshold {
@@ -14,6 +14,9 @@
* limitations under the License.
*/
/**
* @public
*/
export type ChartData = {
date: number;
trend: number;
+3 -7
View File
@@ -14,6 +14,9 @@
* limitations under the License.
*/
/**
* @public
*/
export interface Currency {
kind: string | null;
label: string;
@@ -21,10 +24,3 @@ export interface Currency {
prefix?: string;
rate?: number;
}
export enum CurrencyType {
USD = 'USD',
CarbonOffsetTons = 'CARBON_OFFSET_TONS',
Beers = 'BEERS',
IceCream = 'PINTS_OF_ICE_CREAM',
}
@@ -0,0 +1,22 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export enum CurrencyType {
USD = 'USD',
CarbonOffsetTons = 'CARBON_OFFSET_TONS',
Beers = 'BEERS',
IceCream = 'PINTS_OF_ICE_CREAM',
}
@@ -0,0 +1,17 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const DEFAULT_DATE_FORMAT = 'yyyy-LL-dd';
+2 -2
View File
@@ -19,6 +19,8 @@
* 'last completed quarter', and P30D/P90D to be '[month|quarter] relative to today'. So if
* it's September 15, P3M represents costs for Q2 and P30D represents August 16 -
* September 15.
*
* @public
*/
export enum Duration {
P7D = 'P7D',
@@ -26,5 +28,3 @@ export enum Duration {
P90D = 'P90D',
P3M = 'P3M',
}
export const DEFAULT_DATE_FORMAT = 'yyyy-LL-dd';
-118
View File
@@ -1,118 +0,0 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ChangeStatistic } from './ChangeStatistic';
import { Maybe } from './Maybe';
export interface Entity {
id: Maybe<string>;
aggregation: [number, number];
entities: Record<string, Entity[]>;
change: ChangeStatistic;
}
/*
An entity is a tree-like structure that represents any unique
product or service that generates cost over a fixed period of time.
An entity could be atomic or composite. An atomic entity is indivisible
and cannot be broken into sub-entities.
A composite entity is divided into sub-entities that account for portions
of the total cost **over the same time period**. The root entity is
expected to only have _one_ Record consisting of the sub-entities to display
in the product panel (keyed by the entity type, such as "service" for
compute entities).
The root sub-entities may have multiple breakdowns - for example, a
breakdown of an entity cost by SKU vs deployment environment. The sum
aggregated cost of each keyed breakdown should equal the sub-entity's cost.
Entities with null ids are considered "unlabeled" - costs without attribution.
If an entity is a composite, it may only have one (1) null child but may have any number of
null grandchildren.
{
id: 'product',
aggregation: [0, 200],
change: {
ratio: 2000,
amount: 200
},
entities: {
service: [
{
id: 'service-a',
aggregation: [0, 100],
change: {
ratio: 100,
amount: 100
},
entities: {}
},
{
id: 'service-b',
aggregation: [0, 100],
change: {
ratio: 100,
amount: 100
},
entities: {
SKU: [
{
id: 'service-b-sku-a',
aggregation: [0, 25],
change: {
ratio: 25,
amount: 25
},
entities: {}
},
{
id: null, // Unlabeled cost for service-b
aggregation: [0, 75],
change: {
ratio: 75,
amount: 75
},
entities: {}
},
],
deployment: [
{
id: 'service-b-env-a',
aggregation: [0, 50],
change: {
ratio: 50,
amount: 50
},
entities: {}
},
{
id: 'service-b-env-b',
aggregation: [0, 50],
change: {
ratio: 50,
amount: 50
},
entities: {}
},
]
}
},
]
}
}
*/
+10 -1
View File
@@ -14,9 +14,12 @@
* limitations under the License.
*/
import { Maybe } from './Maybe';
import { Maybe } from '@backstage/plugin-cost-insights-common';
import { Duration } from './Duration';
/**
* @public
*/
export interface PageFilters {
group: Maybe<string>;
project: Maybe<string>;
@@ -24,8 +27,14 @@ export interface PageFilters {
metric: string | null;
}
/**
* @public
*/
export type ProductFilters = Array<ProductPeriod>;
/**
* @public
*/
export interface ProductPeriod {
duration: Duration;
productType: string;
+30 -12
View File
@@ -14,22 +14,40 @@
* limitations under the License.
*/
import * as common from '@backstage/plugin-cost-insights-common';
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type ChangeStatistic = common.ChangeStatistic;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type Cost = common.Cost;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type DateAggregation = common.DateAggregation;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type Entity = common.Entity;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type Group = common.Group;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type Maybe<T> = common.Maybe<T>;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type Metric = common.Metric;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type MetricData = common.MetricData;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type Product = common.Product;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type Project = common.Project;
/** * @deprecated use the same type from @backstage/plugin-cost-insights-common instead */
export type Trendline = common.Trendline;
// TODO: Split some of these up into `@backstage/plugin-cost-insights-react` for presentation types
// and `@backstage/plugin-cost-insights-common` for data transfer object types.
export * from './Alert';
export * from './ChangeStatistic';
export * from './ChartData';
export * from './Cost';
export * from './DateAggregation';
export * from './Duration';
export * from './Currency';
export * from './Entity';
export * from './Icon';
export * from './CurrencyType';
export * from './DateFormat';
export * from './Duration';
export * from './Filters';
export * from './Group';
export * from './Icon';
export * from './Loading';
export * from './Maybe';
export * from './MetricData';
export * from './Metric';
export * from './Product';
export * from './Project';
export * from './Theme';
export * from './Trendline';