Skip to content

Commit dcaff09

Browse files
authored
Add Azure benchmark analytics dashboard and seeding infrastructure (#2163)
Fixes OPS-3973, OPS-3942.
1 parent 458ff6f commit dcaff09

19 files changed

Lines changed: 1808 additions & 0 deletions

packages/server/api/src/app/openops-analytics/benchmark/benchmark-dashboard-service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { BenchmarkProviders } from '@openops/shared';
22
import { throwValidationError } from '../../benchmark/errors';
33
import { createAwsBenchmarkDashboard } from './create-aws-benchmark-dashboard';
4+
import { createAzureBenchmarkDashboard } from './create-azure-benchmark-dashboard';
45

56
export async function createBenchmarkDashboard(
67
provider: string,
@@ -9,6 +10,9 @@ export async function createBenchmarkDashboard(
910
case BenchmarkProviders.AWS:
1011
await createAwsBenchmarkDashboard();
1112
break;
13+
case BenchmarkProviders.AZURE:
14+
await createAzureBenchmarkDashboard();
15+
break;
1216
default:
1317
throwValidationError(
1418
`Unsupported benchmark dashboard provider: ${provider}`,
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import {
2+
authenticateOpenOpsAnalyticsAdmin,
3+
enableDashboardEmbedding,
4+
} from '@openops/common';
5+
import { logger } from '@openops/server-shared';
6+
import { assertNotNullOrUndefined } from '@openops/shared';
7+
import { SEED_OPENOPS_TABLE_NAME as OPPORTUNITIES_TABLE_NAME } from '../../openops-tables/template-tables/create-opportunities-table';
8+
import { TIMESERIES_TABLE_NAME } from '../../openops-tables/template-tables/create-timeseries-table';
9+
import { organizationService } from '../../organization/organization.service';
10+
import { upsertDashboard } from '../analytics-dashboard-registry-service';
11+
import { getOrCreateOpenOpsTablesDatabaseConnection } from '../create-database-connection';
12+
import { getDefaultProjectForOrganization } from '../project-selector';
13+
import {
14+
createDashboardZipBuffer,
15+
importDashboardFromZip,
16+
resolveTableIds,
17+
} from './benchmark-dashboard-helpers';
18+
import { createAzureBenchmarkDatasets } from './create-azure-benchmark-datasets';
19+
20+
const USER_FRIENDLY_TABLE_SUFFIX = '_userfriendly';
21+
const AZURE_BENCHMARK_DASHBOARD_SLUG = 'azure_benchmark';
22+
const AZURE_BENCHMARK_DASHBOARD_DISPLAY_NAME = 'Azure Benchmark';
23+
24+
export async function createAzureBenchmarkDashboard(): Promise<void> {
25+
logger.info('Starting Azure Benchmark dashboard seeding');
26+
27+
const { access_token } = await authenticateOpenOpsAnalyticsAdmin();
28+
29+
const dbConnection = await getOrCreateOpenOpsTablesDatabaseConnection(
30+
access_token,
31+
);
32+
33+
const organization = await organizationService.getOldestOrganization();
34+
assertNotNullOrUndefined(organization, 'Organization not found');
35+
36+
const project = await getDefaultProjectForOrganization(organization.id);
37+
assertNotNullOrUndefined(project, 'Project not found');
38+
39+
const tableIds = await resolveTableIds(project, [
40+
OPPORTUNITIES_TABLE_NAME,
41+
TIMESERIES_TABLE_NAME,
42+
]);
43+
44+
const opportunitiesTableName = `${OPPORTUNITIES_TABLE_NAME}_${tableIds[OPPORTUNITIES_TABLE_NAME]}${USER_FRIENDLY_TABLE_SUFFIX}`;
45+
const timeseriesTableName = `${TIMESERIES_TABLE_NAME}_${tableIds[TIMESERIES_TABLE_NAME]}${USER_FRIENDLY_TABLE_SUFFIX}`;
46+
47+
const datasets = await createAzureBenchmarkDatasets(
48+
access_token,
49+
dbConnection.id,
50+
opportunitiesTableName,
51+
timeseriesTableName,
52+
);
53+
54+
const dashboardZipBuffer = await createDashboardZipBuffer('azure');
55+
56+
await importDashboardFromZip(
57+
access_token,
58+
dashboardZipBuffer,
59+
dbConnection.uuid,
60+
{
61+
Azure_Benchmark_Opportunities: datasets.opportunities.uuid,
62+
Azure_Benchmark_KPI_efficiency: datasets.kpi.uuid,
63+
Azure_Benchmark_Timeseries: datasets.timeseries.uuid,
64+
},
65+
);
66+
67+
const embedResponse = await enableDashboardEmbedding(
68+
access_token,
69+
AZURE_BENCHMARK_DASHBOARD_SLUG,
70+
);
71+
72+
await upsertDashboard(
73+
{
74+
id: AZURE_BENCHMARK_DASHBOARD_SLUG,
75+
name: AZURE_BENCHMARK_DASHBOARD_DISPLAY_NAME,
76+
slug: AZURE_BENCHMARK_DASHBOARD_SLUG,
77+
embedId: embedResponse.result.uuid,
78+
enabled: true,
79+
},
80+
access_token,
81+
);
82+
83+
logger.info('Azure Benchmark dashboard seeding completed successfully');
84+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { createVirtualDataset } from '../virtual-dataset';
2+
3+
export async function createAzureBenchmarkDatasets(
4+
token: string,
5+
databaseId: number,
6+
opportunitiesTableName: string,
7+
timeseriesTableName: string,
8+
) {
9+
const opportunities = await createVirtualDataset(token, {
10+
tableName: 'Azure_Benchmark_Opportunities',
11+
sql: `
12+
SELECT *
13+
FROM public."${opportunitiesTableName}"
14+
WHERE "Workflow" LIKE 'Azure Benchmark%'
15+
`,
16+
databaseId,
17+
schema: 'public',
18+
recreateIfExists: true,
19+
});
20+
21+
const kpi = await createVirtualDataset(token, {
22+
tableName: 'Azure_Benchmark_KPI_efficiency',
23+
sql: `
24+
WITH opp AS (
25+
SELECT
26+
"Account" AS opp_account,
27+
COALESCE(SUM("Estimated savings USD per month"), 0) AS opp_sum
28+
FROM public."${opportunitiesTableName}"
29+
WHERE "Workflow" LIKE 'Azure Benchmark%'
30+
GROUP BY "Account"
31+
),
32+
ts AS (
33+
SELECT
34+
"Account" AS ts_account,
35+
COALESCE(SUM("Value"), 0) AS ts_value
36+
FROM public."${timeseriesTableName}"
37+
WHERE "Workflow" = 'Run Azure Benchmark'
38+
AND "Date" = (date_trunc('month', current_date) - interval '1 month')::date
39+
GROUP BY "Account"
40+
)
41+
SELECT
42+
COALESCE(opp.opp_account, ts.ts_account) AS "Account",
43+
COALESCE(opp.opp_sum, 0) AS savings,
44+
COALESCE(ts.ts_value, 0) AS monthly_cost,
45+
CASE
46+
WHEN COALESCE(ts.ts_value, 0) = 0 THEN 100.0
47+
ELSE (1 - (COALESCE(opp.opp_sum, 0) / COALESCE(ts.ts_value, 0))) * 100.0
48+
END AS kpi
49+
FROM opp
50+
FULL OUTER JOIN ts
51+
ON opp.opp_account = ts.ts_account;
52+
`,
53+
databaseId,
54+
schema: 'public',
55+
recreateIfExists: true,
56+
});
57+
58+
const timeseries = await createVirtualDataset(token, {
59+
tableName: 'Azure_Benchmark_Timeseries',
60+
sql: `
61+
SELECT *
62+
FROM public."${timeseriesTableName}"
63+
WHERE "Workflow" = 'Run Azure Benchmark' AND "Account" IS NOT NULL
64+
`,
65+
databaseId,
66+
schema: 'public',
67+
recreateIfExists: true,
68+
});
69+
70+
return { opportunities, kpi, timeseries };
71+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
slice_name: Azure By Account
2+
description: null
3+
certified_by: null
4+
certification_details: null
5+
viz_type: table
6+
params:
7+
datasource: 5__table
8+
viz_type: table
9+
slice_id: 11
10+
query_mode: aggregate
11+
groupby:
12+
- Account
13+
temporal_columns_lookup:
14+
Snoozed until: true
15+
Creation time: true
16+
Last modified time: true
17+
metrics:
18+
- aggregate: COUNT
19+
column:
20+
advanced_data_type: null
21+
certification_details: null
22+
certified_by: null
23+
column_name: Resource Id
24+
description: null
25+
expression: null
26+
filterable: true
27+
groupby: true
28+
id: 9
29+
is_certified: false
30+
is_dttm: false
31+
python_date_format: null
32+
type: TEXT
33+
type_generic: 1
34+
verbose_name: null
35+
warning_markdown: null
36+
datasourceWarning: false
37+
expressionType: SIMPLE
38+
hasCustomLabel: true
39+
label: Opportunities
40+
optionName: metric_upbxycs62f8_iv8c55qsu8
41+
sqlExpression: null
42+
- aggregate: SUM
43+
column:
44+
advanced_data_type: null
45+
certification_details: null
46+
certified_by: null
47+
column_name: Estimated savings USD per month
48+
description: null
49+
expression: null
50+
filterable: true
51+
groupby: true
52+
id: 10
53+
is_certified: false
54+
is_dttm: false
55+
python_date_format: null
56+
type: NUMERIC(52, 2)
57+
type_generic: 0
58+
verbose_name: null
59+
warning_markdown: null
60+
datasourceWarning: false
61+
expressionType: SIMPLE
62+
hasCustomLabel: true
63+
label: Savings
64+
optionName: metric_yn31eazkkq7_t03e9fakmqr
65+
sqlExpression: null
66+
all_columns: []
67+
percent_metrics: []
68+
adhoc_filters:
69+
- clause: WHERE
70+
comparator: No filter
71+
datasourceWarning: false
72+
expressionType: SIMPLE
73+
filterOptionName: filter_shtjwp73xz_l1xeidimdkm
74+
isExtra: false
75+
isNew: false
76+
operator: TEMPORAL_RANGE
77+
sqlExpression: null
78+
subject: Snoozed until
79+
timeseries_limit_metric:
80+
aggregate: SUM
81+
column:
82+
advanced_data_type: null
83+
certification_details: null
84+
certified_by: null
85+
column_name: Estimated savings USD per month
86+
description: null
87+
expression: null
88+
filterable: true
89+
groupby: true
90+
id: 10
91+
is_certified: false
92+
is_dttm: false
93+
python_date_format: null
94+
type: NUMERIC(52, 2)
95+
type_generic: 0
96+
verbose_name: null
97+
warning_markdown: null
98+
datasourceWarning: false
99+
expressionType: SIMPLE
100+
hasCustomLabel: false
101+
label: SUM(Estimated savings USD per month)
102+
optionName: metric_x3rtagury6_pq0mdfhfuad
103+
sqlExpression: null
104+
order_by_cols: []
105+
row_limit: 1000
106+
server_page_length: 10
107+
order_desc: true
108+
show_totals: true
109+
table_timestamp_format: smart_date
110+
allow_render_html: false
111+
column_config:
112+
Savings:
113+
d3NumberFormat: $,.2f
114+
show_cell_bars: false
115+
color_pn: true
116+
comparison_color_scheme: Green
117+
conditional_formatting: []
118+
comparison_type: values
119+
extra_form_data: {}
120+
dashboards:
121+
- 3
122+
query_context: '{"datasource":{"id":5,"type":"table"},"force":false,"queries":[{"filters":[{"col":"Snoozed
123+
until","op":"TEMPORAL_RANGE","val":"No filter"}],"extras":{"having":"","where":""},"applied_time_extras":{},"columns":["Account"],"metrics":[{"aggregate":"COUNT","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Resource
124+
Id","description":null,"expression":null,"filterable":true,"groupby":true,"id":9,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"TEXT","type_generic":1,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":true,"label":"Opportunities","optionName":"metric_upbxycs62f8_iv8c55qsu8","sqlExpression":null},{"aggregate":"SUM","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Estimated
125+
savings USD per month","description":null,"expression":null,"filterable":true,"groupby":true,"id":10,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"NUMERIC(52,
126+
2)","type_generic":0,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":true,"label":"Savings","optionName":"metric_yn31eazkkq7_t03e9fakmqr","sqlExpression":null}],"orderby":[[{"aggregate":"SUM","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Estimated
127+
savings USD per month","description":null,"expression":null,"filterable":true,"groupby":true,"id":10,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"NUMERIC(52,
128+
2)","type_generic":0,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":false,"label":"SUM(Estimated
129+
savings USD per month)","optionName":"metric_x3rtagury6_pq0mdfhfuad","sqlExpression":null},false]],"annotation_layers":[],"row_limit":1000,"series_limit":0,"series_limit_metric":{"aggregate":"SUM","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Estimated
130+
savings USD per month","description":null,"expression":null,"filterable":true,"groupby":true,"id":10,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"NUMERIC(52,
131+
2)","type_generic":0,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":false,"label":"SUM(Estimated
132+
savings USD per month)","optionName":"metric_x3rtagury6_pq0mdfhfuad","sqlExpression":null},"order_desc":true,"url_params":{},"custom_params":{},"custom_form_data":{},"post_processing":[],"time_offsets":[]},{"filters":[{"col":"Snoozed
133+
until","op":"TEMPORAL_RANGE","val":"No filter"}],"extras":{"having":"","where":""},"applied_time_extras":{},"columns":[],"metrics":[{"aggregate":"COUNT","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Resource
134+
Id","description":null,"expression":null,"filterable":true,"groupby":true,"id":9,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"TEXT","type_generic":1,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":true,"label":"Opportunities","optionName":"metric_upbxycs62f8_iv8c55qsu8","sqlExpression":null},{"aggregate":"SUM","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Estimated
135+
savings USD per month","description":null,"expression":null,"filterable":true,"groupby":true,"id":10,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"NUMERIC(52,
136+
2)","type_generic":0,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":true,"label":"Savings","optionName":"metric_yn31eazkkq7_t03e9fakmqr","sqlExpression":null}],"annotation_layers":[],"row_limit":0,"row_offset":0,"series_limit":0,"series_limit_metric":{"aggregate":"SUM","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Estimated
137+
savings USD per month","description":null,"expression":null,"filterable":true,"groupby":true,"id":10,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"NUMERIC(52,
138+
2)","type_generic":0,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":false,"label":"SUM(Estimated
139+
savings USD per month)","optionName":"metric_x3rtagury6_pq0mdfhfuad","sqlExpression":null},"url_params":{},"custom_params":{},"custom_form_data":{},"post_processing":[],"time_offsets":[]}],"form_data":{"datasource":"5__table","viz_type":"table","slice_id":11,"query_mode":"aggregate","groupby":["Account"],"temporal_columns_lookup":{"Snoozed
140+
until":true,"Creation time":true,"Last modified time":true},"metrics":[{"aggregate":"COUNT","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Resource
141+
Id","description":null,"expression":null,"filterable":true,"groupby":true,"id":9,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"TEXT","type_generic":1,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":true,"label":"Opportunities","optionName":"metric_upbxycs62f8_iv8c55qsu8","sqlExpression":null},{"aggregate":"SUM","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Estimated
142+
savings USD per month","description":null,"expression":null,"filterable":true,"groupby":true,"id":10,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"NUMERIC(52,
143+
2)","type_generic":0,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":true,"label":"Savings","optionName":"metric_yn31eazkkq7_t03e9fakmqr","sqlExpression":null}],"all_columns":[],"percent_metrics":[],"adhoc_filters":[{"clause":"WHERE","comparator":"No
144+
filter","datasourceWarning":false,"expressionType":"SIMPLE","filterOptionName":"filter_shtjwp73xz_l1xeidimdkm","isExtra":false,"isNew":false,"operator":"TEMPORAL_RANGE","sqlExpression":null,"subject":"Snoozed
145+
until"}],"timeseries_limit_metric":{"aggregate":"SUM","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"Estimated
146+
savings USD per month","description":null,"expression":null,"filterable":true,"groupby":true,"id":10,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"NUMERIC(52,
147+
2)","type_generic":0,"verbose_name":null,"warning_markdown":null},"datasourceWarning":false,"expressionType":"SIMPLE","hasCustomLabel":false,"label":"SUM(Estimated
148+
savings USD per month)","optionName":"metric_x3rtagury6_pq0mdfhfuad","sqlExpression":null},"order_by_cols":[],"row_limit":1000,"server_page_length":10,"order_desc":true,"show_totals":true,"table_timestamp_format":"smart_date","allow_render_html":false,"column_config":{"Savings":{"d3NumberFormat":"$,.2f"}},"show_cell_bars":false,"color_pn":true,"comparison_color_scheme":"Green","conditional_formatting":[],"comparison_type":"values","extra_form_data":{},"dashboards":[3],"force":false,"result_format":"json","result_type":"full"},"result_format":"json","result_type":"full"}'
149+
cache_timeout: null
150+
uuid: 73348aac-c6e4-4c39-85c8-8657b23dff63
151+
version: 1.0.0
152+
dataset_uuid: 37e4125c-dbc1-4a8f-a709-54305d151bba

0 commit comments

Comments
 (0)