Better example data

This commit is contained in:
Tim Hansen
2020-10-02 21:02:10 -06:00
parent 34c6f38bf9
commit 49ac6cec38
4 changed files with 88 additions and 45 deletions
+3
View File
@@ -36,6 +36,7 @@
"@roadiehq/backstage-plugin-github-pull-requests": "0.3.0",
"@roadiehq/backstage-plugin-travis-ci": "^0.2.3",
"history": "^5.0.0",
"moment": "^2.27.0",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
@@ -43,6 +44,7 @@
"react-router": "6.0.0-beta.0",
"react-router-dom": "6.0.0-beta.0",
"react-use": "^15.3.3",
"regression": "^2.0.1",
"zen-observable": "^0.8.15"
},
"devDependencies": {
@@ -54,6 +56,7 @@
"@types/jquery": "^3.3.34",
"@types/node": "^12.0.0",
"@types/react-dom": "^16.9.8",
"@types/regression": "^2.0.0",
"@types/zen-observable": "^0.8.0",
"cross-env": "^7.0.0",
"cypress": "^4.2.0",
@@ -15,16 +15,72 @@
*/
/* eslint-disable no-restricted-imports */
import moment from 'moment';
import regression from 'regression';
import {
CostInsightsApi,
Alert,
ChangeStatistic,
Cost,
CostInsightsApi,
DateAggregation,
Duration,
Project,
ProductCost,
Group,
ProductCost,
Project,
Trendline,
} from '@backstage/plugin-cost-insights';
function durationOf(intervals: string): Duration {
const match = intervals.match(/\/(?<duration>P\d+[DM])\//);
const { duration } = match!.groups!;
return duration as Duration;
}
function aggregationFor(
duration: Duration,
baseline: number,
): DateAggregation[] {
const days = moment.duration(duration).asDays() * 2;
return [...Array(days).keys()].reduce(
(values: DateAggregation[], i: number): DateAggregation[] => {
const last = values.length ? values[values.length - 1].amount : baseline;
values.push({
date: moment()
.subtract(days, 'days')
.add(i, 'days')
.format('YYYY-MM-DD'),
amount: last + (baseline / 20) * (Math.random() * 2 - 1),
});
return values;
},
[],
);
}
function trendlineOf(aggregation: DateAggregation[]): Trendline {
const data = [...aggregation.map(a => [Date.parse(a.date) / 1000, a.amount])];
const result = regression.linear(data, { precision: 5 });
return {
slope: result.equation[0],
intercept: result.equation[1],
};
}
function changeOf(aggregation: DateAggregation[]): ChangeStatistic {
const half = Math.ceil(aggregation.length / 2);
const before = aggregation
.slice(0, half)
.reduce((sum, a) => sum + a.amount, 0);
const after = aggregation
.slice(half, aggregation.length)
.reduce((sum, a) => sum + a.amount, 0);
return {
ratio: (after - before) / before,
amount: after - before,
};
}
export class ExampleCostInsightsClient implements CostInsightsApi {
private request(_: any, res: any): Promise<any> {
return new Promise(resolve => setTimeout(resolve, 0, res));
@@ -53,30 +109,17 @@ export class ExampleCostInsightsClient implements CostInsightsApi {
metric: string | null,
intervals: string,
): Promise<Cost> {
const aggregation = aggregationFor(
durationOf(intervals),
metric ? 0.3 : 8_000,
);
const groupDailyCost: Cost = await this.request(
{ group, metric, intervals },
{
id: metric, // costs with null ids will appear as "All Projects" in Cost Overview panel
aggregation: [
{ date: '2020-08-01', amount: 75_000 / (metric ? 200_000 : 1) },
{ date: '2020-08-02', amount: 120_000 / (metric ? 200_000 : 1) },
{ date: '2020-08-03', amount: 110_000 / (metric ? 200_000 : 1) },
{ date: '2020-08-04', amount: 90_000 / (metric ? 200_000 : 1) },
{ date: '2020-08-05', amount: 80_000 / (metric ? 200_000 : 1) },
{ date: '2020-08-06', amount: 85_000 / (metric ? 200_000 : 1) },
{ date: '2020-08-07', amount: 82_500 / (metric ? 200_000 : 1) },
{ date: '2020-08-08', amount: 100_000 / (metric ? 200_000 : 1) },
{ date: '2020-08-09', amount: 130_000 / (metric ? 200_000 : 1) },
{ date: '2020-08-10', amount: 140_000 / (metric ? 200_000 : 1) },
],
change: {
ratio: 0.86,
amount: 65_000,
},
trendline: {
slope: 0,
intercept: 90_000,
},
aggregation: aggregation,
change: changeOf(aggregation),
trendline: trendlineOf(aggregation),
},
);
@@ -88,30 +131,17 @@ export class ExampleCostInsightsClient implements CostInsightsApi {
metric: string | null,
intervals: string,
): Promise<Cost> {
const aggregation = aggregationFor(
durationOf(intervals),
metric ? 0.1 : 1_500,
);
const projectDailyCost: Cost = await this.request(
{ project, metric, intervals },
{
id: 'project-a',
aggregation: [
{ date: '2020-08-01', amount: 1000 },
{ date: '2020-08-02', amount: 2000 },
{ date: '2020-08-03', amount: 3000 },
{ date: '2020-08-04', amount: 4000 },
{ date: '2020-08-05', amount: 5000 },
{ date: '2020-08-06', amount: 6000 },
{ date: '2020-08-07', amount: 7000 },
{ date: '2020-08-08', amount: 8000 },
{ date: '2020-08-09', amount: 9000 },
{ date: '2020-08-10', amount: 10_000 },
],
change: {
ratio: 0.5,
amount: 10000,
},
trendline: {
slope: 0,
intercept: 0,
},
aggregation: aggregation,
change: changeOf(aggregation),
trendline: trendlineOf(aggregation),
},
);
@@ -134,7 +164,7 @@ export class ExampleCostInsightsClient implements CostInsightsApi {
entities: [
{
id: null, // entities with null ids will be appear as "Unlabeled" in product panels
aggregation: [45_000, 50_000],
aggregation: [15_000, 30_000],
},
{
id: 'entity-a',
@@ -64,7 +64,7 @@ const CostOverviewCard = ({
</CostOverviewHeader>
<Divider />
<Box marginY={1} display="flex" flexDirection="column">
<CostOverviewChartLegend change={change} title={name} />
<CostOverviewChartLegend change={change} title={`${name} Trend`} />
<CostOverviewChart
responsive
metric={metric}
+10
View File
@@ -5457,6 +5457,11 @@
dependencies:
"@types/node" "*"
"@types/regression@^2.0.0":
version "2.0.0"
resolved "https://registry.npmjs.org/@types/regression/-/regression-2.0.0.tgz#0677ea78d7bdb37039c02ebbccf062042f756ae3"
integrity sha512-Ch2FD53M1HpFLL6zSTc/sfuyqQcIPy+/PV3xFT6QYtk9EOiMI29XOYmLNxBb1Y0lfMOR/NNa86J1gRc/1jGLyw==
"@types/relateurl@*":
version "0.2.28"
resolved "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6"
@@ -19842,6 +19847,11 @@ regjsparser@^0.6.4:
dependencies:
jsesc "~0.5.0"
regression@^2.0.1:
version "2.0.1"
resolved "https://artifactory.spotify.net/artifactory/api/npm/virtual-npm/regression/-/regression-2.0.1.tgz#8d29c3e8224a10850c35e337e85a8b2fac3b0c87"
integrity sha1-jSnD6CJKEIUMNeM36FqLL6w7DIc=
relateurl@^0.2.7:
version "0.2.7"
resolved "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"