vault/ui/app/utils/metrics-helpers.ts
Vault Automation 9a6d507dec
[UI] [VAULT-42855]: billing overview poc (#12548) (#13556)
* Create billing route and add to sidebar

* WIP

* Working dynamic cards

* Update billing copy

* Fix bugs

* WIP polling

* WIP Add polling..

* Move card logic to metric-card

* Remove gcp KMS

* Working polling

* broken but just to demo normalization (#12594)

* broken but just to demo normalization

* Pair with Claire to clean up data

* Fix merge conflict issue

* Create type file and add helper

* Add unit test!

* Add copywright headers

* Update unit test name

---------



* Fixes summary card component

* Polling...

* Fix ts errors

* Write sidebar logic and add acceptance test

* Add comment explaining license feature

* Address feedback and fix styling so its responsive

* Fix failing tests

* Remove polling service and code clean up

* Add changelog and update some styling!

* Update changelog...

---------

Co-authored-by: Kianna <30884335+kiannaquach@users.noreply.github.com>
Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
2026-04-02 09:15:34 -07:00

79 lines
2.7 KiB
TypeScript

/**
* Copyright IBM Corp. 2016, 2025
* SPDX-License-Identifier: BUSL-1.1
*/
import type { Month, NormalizedMetricsData } from 'vault/vault/billing/overview';
export enum NormalizedBillingMetrics {
DATA_PROTECTION_CALLS_TRANSFORM = 'data_protection_calls_transform',
DATA_PROTECTION_CALLS_TRANSIT = 'data_protection_calls_transit',
DYNAMIC_ROLES = 'dynamic_roles',
KMIP_USED_IN_MONTH = 'kmip_used_in_month',
MANAGED_KEYS = 'managed_keys',
MANAGED_KEYS_KMSE = 'managed_keys_kmse',
MANAGED_KEYS_TOTP = 'managed_keys_totp',
PKI_UNITS_TOTAL = 'pki_units_total',
SSH_UNITS = 'ssh_units',
SSH_UNITS_CERTIFICATE_UNITS = 'ssh_units_certificate_units',
SSH_UNITS_OTP_UNITS = 'ssh_units_otp_units',
STATIC_ROLES = 'static_roles',
STATIC_SECRETS_KV = 'static_secrets_kv',
STATIC_SECRETS_TOTAL = 'static_secrets_total',
DATA_PROTECTION_CALLS_TOTAL = `data_protection_calls_total`,
MANAGED_KEYS_TOTAL = `managed_keys_total`,
EXTERNAL_PLUGINS_TOTAL = 'external_plugins_total',
}
export enum BillingMetricsKeys {
USED_IN_MONTH = 'used_in_month',
KMIP = 'kmip',
TOTAL = 'total',
}
export function normalizeMetricData(metric: Month | null | undefined) {
const { usage_metrics } = metric || {};
if (!usage_metrics) return;
const normalized: NormalizedMetricsData = {};
for (const metric of usage_metrics) {
if (metric.metric_name === 'kmip') {
const kmipKey = `${metric.metric_name}_used_in_month`;
normalized[kmipKey] = metric.metric_data.used_in_month;
}
const metricName = metric.metric_name;
const total = metric.metric_data?.total;
if (typeof total === 'number') {
normalized[`${metricName}_total`] = total;
}
for (const detail of metric.metric_data?.metric_details ?? []) {
// Skip detail entries that are missing a type or a numeric count — both are required to build a valid normalized key.
if (!detail.type || typeof detail.count !== 'number') continue;
// Prefix parent metric_name to detail "type" to avoid future naming collisions.
// For example the 'kv' type in the `metrics_details`
// becomes `static_secrets_kv`:
// {
// metric_name: 'static_secrets',
// metric_data: {
// total: 10,
// metric_details: [{ type: 'kv', count: 10 }],
// },
// },
const detailName = `${metricName}_${detail.type}`;
normalized[detailName] = detail.count;
}
}
// The API omits metrics that have zero usage rather than returning them with a count of 0.
// To avoid blank values in the UI, we explicitly set any missing metric keys to 0.
for (const metricsKey of Object.values(NormalizedBillingMetrics)) {
if (!(metricsKey in normalized)) {
normalized[metricsKey] = 0;
}
}
return normalized;
}