diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.test.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.test.ts new file mode 100644 index 0000000000000..2baee0b24bc60 --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.test.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { MetricsUIAggregation } from '@kbn/metrics-data-access-plugin/common'; +import { isCustomMetricRate, isInterfaceRateAgg, isMetricRate, isRate } from './is_rate'; +import { SnapshotCustomMetricInput } from '../../../../../common/http_api'; + +const customMaxMetricMock: SnapshotCustomMetricInput = { + type: 'custom', + aggregation: 'max', + field: '', + id: '', +}; + +const customRateMetricMock: SnapshotCustomMetricInput = { + type: 'custom', + aggregation: 'rate', + field: '', + id: '', +}; + +const metricMock: MetricsUIAggregation = { + mock1: { derivative: {} }, + mock2: { max: null, mock: { field: '' } }, + mock3: { + aggregations: {}, + terms: {}, + sum_bucket: {}, + }, +}; + +describe('isRate', () => { + describe('isMetricRate', () => { + it('should return false when metric is undefined', () => { + expect(isMetricRate(undefined)).toEqual(false); + }); + it('should return true when correct metric is passed', () => { + expect(isMetricRate(metricMock)).toEqual(true); + }); + }); + + describe('isCustomMetricRate', () => { + it("should return false when aggregation isn't 'rate'", () => { + expect(isCustomMetricRate(customMaxMetricMock)).toEqual(false); + }); + it("should return true when aggregation is equal to 'rate'", () => { + expect(isCustomMetricRate(customRateMetricMock)).toEqual(true); + }); + + describe('isInterfaceRateAgg', () => { + it('should return false if metric is undefined', () => { + expect(isInterfaceRateAgg(undefined)).toEqual(false); + }); + it('should return true when correct metric is passed', () => { + expect(isInterfaceRateAgg(metricMock)).toEqual(true); + }); + }); + + describe('isRate', () => { + it('should return false when incorrect metrics are provided', () => { + expect(isRate({} as MetricsUIAggregation, {} as SnapshotCustomMetricInput)).toEqual(false); + }); + + it('should return true when proper metric are provided', () => { + expect(isRate(metricMock, customRateMetricMock)).toEqual(true); + }); + }); + }); +}); diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.ts index 8da33a55d8b4d..d50f056f60196 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.ts @@ -8,10 +8,10 @@ import { has } from 'lodash'; import { MetricsUIAggregation, - ESSumBucketAggRT, - ESDerivativeAggRT, - ESBasicMetricAggRT, - ESTermsWithAggregationRT, + isBasicMetricAgg, + isDerivativeAgg, + isSumBucketAgg, + isTermsWithAggregation, } from '@kbn/metrics-data-access-plugin/common'; import { SnapshotCustomMetricInput } from '../../../../../common/http_api'; @@ -21,8 +21,8 @@ export const isMetricRate = (metric: MetricsUIAggregation | undefined): boolean } const values = Object.values(metric); return ( - values.some((agg) => ESDerivativeAggRT.is(agg)) && - values.some((agg) => ESBasicMetricAggRT.is(agg) && has(agg, 'max')) + values.some((agg) => isDerivativeAgg(agg)) && + values.some((agg) => isBasicMetricAgg(agg) && has(agg, 'max')) ); }; @@ -36,8 +36,7 @@ export const isInterfaceRateAgg = (metric: MetricsUIAggregation | undefined) => } const values = Object.values(metric); return ( - values.some((agg) => ESTermsWithAggregationRT.is(agg)) && - values.some((agg) => ESSumBucketAggRT.is(agg)) + values.some((agg) => isTermsWithAggregation(agg)) && values.some((agg) => isSumBucketAgg(agg)) ); }; diff --git a/x-pack/plugins/observability_solution/infra/server/routes/snapshot/lib/create_timerange_with_interval.ts b/x-pack/plugins/observability_solution/infra/server/routes/snapshot/lib/create_timerange_with_interval.ts index 5115aa1fcae77..cff44454d6e96 100644 --- a/x-pack/plugins/observability_solution/infra/server/routes/snapshot/lib/create_timerange_with_interval.ts +++ b/x-pack/plugins/observability_solution/infra/server/routes/snapshot/lib/create_timerange_with_interval.ts @@ -8,8 +8,8 @@ import { uniq } from 'lodash'; import { type MetricsUIAggregation, - ESBasicMetricAggRT, type MetricsAPITimerange, + isBasicMetricAgg, } from '@kbn/metrics-data-access-plugin/common'; import { ESSearchClient } from '../../../lib/metrics/types'; import { calculateMetricInterval } from '../../../utils/calculate_metric_interval'; @@ -74,7 +74,7 @@ const aggregationsToModules = async ( ): Promise => { const uniqueFields = Object.values(aggregations) .reduce>((fields, agg) => { - if (ESBasicMetricAggRT.is(agg)) { + if (isBasicMetricAgg(agg)) { return uniq(fields.concat(Object.values(agg).map((a) => a?.field))); } return fields; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/index.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/index.ts index 5afa7346a942d..c7f15d1d58ec8 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/index.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/index.ts @@ -12,6 +12,10 @@ export { findInventoryFields, metrics, type InventoryModels, + isBasicMetricAgg, + isDerivativeAgg, + isSumBucketAgg, + isTermsWithAggregation, } from './inventory_models'; export { podSnapshotMetricTypes } from './inventory_models/kubernetes/pod'; @@ -28,11 +32,7 @@ export { InventoryVisTypeRT, ItemTypeRT, SnapshotMetricTypeRT, - ESSumBucketAggRT, - ESDerivativeAggRT, - ESBasicMetricAggRT, SnapshotMetricTypeKeys, - ESTermsWithAggregationRT, } from './inventory_models/types'; export type { diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/index.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/index.ts index 7dddfab593784..033832aaa553b 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/index.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/index.ts @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; +import { estypes } from '@elastic/elasticsearch'; import { POD_FIELD, HOST_FIELD, CONTAINER_FIELD } from '../constants'; import { host } from './host'; import { pod } from './kubernetes/pod'; @@ -69,3 +70,34 @@ export const findInventoryFields = (type: InventoryItemType) => { return inventoryModel.fields; } }; + +export const isBasicMetricAgg = ( + agg: unknown +): agg is Record> => { + if (agg === null || typeof agg !== 'object') return false; + + return Object.values(agg).some( + (value) => + value === undefined || + (value && 'field' in (value as estypes.AggregationsMetricAggregationBase)) + ); +}; + +export const isDerivativeAgg = ( + agg: unknown +): agg is Pick => { + return !!(agg as estypes.AggregationsAggregationContainer).derivative; +}; + +export const isSumBucketAgg = ( + agg: unknown +): agg is Pick => { + return !!(agg as estypes.AggregationsAggregationContainer).sum_bucket; +}; + +export const isTermsWithAggregation = ( + agg: unknown +): agg is Pick => { + const aggContainer = agg as estypes.AggregationsAggregationContainer; + return !!(aggContainer.aggregations && aggContainer.terms); +}; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/types.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/types.ts index 4b675c649e144..f4054f289ae7a 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/types.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/types.ts @@ -235,37 +235,8 @@ export type TSVBMetricModelCreator = ( interval: string ) => TSVBMetricModel; -export const ESBasicMetricAggRT = rt.record( - rt.string, - rt.union([ - rt.undefined, - rt.type({ - field: rt.string, - }), - ]) -); - -export const ESDerivativeAggRT = rt.type({ - derivative: rt.type({ - buckets_path: rt.string, - gap_policy: rt.keyof({ skip: null, insert_zeros: null }), - unit: rt.string, - }), -}); - -export const ESSumBucketAggRT = rt.type({ - sum_bucket: rt.type({ - buckets_path: rt.string, - }), -}); - export type MetricsUIAggregation = Record; -export const ESTermsWithAggregationRT = rt.type({ - terms: rt.type({ field: rt.string }), - aggregations: rt.UnknownRecord, -}); - export const SnapshotMetricTypeKeys = { count: null, cpuV2: null,