diff --git a/x-pack/plugins/infra/common/inventory_models/types.ts b/x-pack/plugins/infra/common/inventory_models/types.ts index 764f41966261..35fd7a13a408 100644 --- a/x-pack/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/plugins/infra/common/inventory_models/types.ts @@ -282,8 +282,10 @@ export const ESSumBucketAggRT = rt.type({ }), }); -export const ESTopHitsAggRT = rt.type({ - top_hits: rt.object, +export const ESTopMetricsAggRT = rt.type({ + top_metrics: rt.type({ + metrics: rt.union([rt.array(rt.type({ field: rt.string })), rt.type({ field: rt.string })]), + }), }); export interface SnapshotTermsWithAggregation { @@ -309,7 +311,7 @@ export const ESAggregationRT = rt.union([ ESSumBucketAggRT, ESTermsWithAggregationRT, ESCaridnalityAggRT, - ESTopHitsAggRT, + ESTopMetricsAggRT, ]); export const MetricsUIAggregationRT = rt.record(rt.string, ESAggregationRT); diff --git a/x-pack/plugins/infra/server/lib/metrics/lib/__snapshots__/convert_histogram_buckets_to_timeseries.test.ts.snap b/x-pack/plugins/infra/server/lib/metrics/lib/__snapshots__/convert_histogram_buckets_to_timeseries.test.ts.snap index 9f4cd67c07b6..6d3c0bf71cae 100644 --- a/x-pack/plugins/infra/server/lib/metrics/lib/__snapshots__/convert_histogram_buckets_to_timeseries.test.ts.snap +++ b/x-pack/plugins/infra/server/lib/metrics/lib/__snapshots__/convert_histogram_buckets_to_timeseries.test.ts.snap @@ -81,6 +81,46 @@ Object { } `; +exports[`convertHistogramBucketsToTimeseies(keys, options, buckets) should tranform top_metric aggregations 1`] = ` +Object { + "columns": Array [ + Object { + "name": "timestamp", + "type": "date", + }, + Object { + "name": "metric_0", + "type": "number", + }, + Object { + "name": "__metadata__", + "type": "number", + }, + ], + "id": "example-0", + "keys": Array [ + "example-0", + ], + "rows": Array [ + Object { + "__metadata__": Array [ + Object { + "host.ip": "testHostIp", + "host.name": "testHostName", + }, + ], + "metric_0": 1, + "timestamp": 1577836800000, + }, + Object { + "__metadata__": Array [], + "metric_0": null, + "timestamp": 1577836860000, + }, + ], +} +`; + exports[`convertHistogramBucketsToTimeseies(keys, options, buckets) should work with keyed percentiles 1`] = ` Object { "columns": Array [ diff --git a/x-pack/plugins/infra/server/lib/metrics/lib/convert_histogram_buckets_to_timeseries.test.ts b/x-pack/plugins/infra/server/lib/metrics/lib/convert_histogram_buckets_to_timeseries.test.ts index 72356ecabee2..31478c5f1aa4 100644 --- a/x-pack/plugins/infra/server/lib/metrics/lib/convert_histogram_buckets_to_timeseries.test.ts +++ b/x-pack/plugins/infra/server/lib/metrics/lib/convert_histogram_buckets_to_timeseries.test.ts @@ -118,4 +118,56 @@ describe('convertHistogramBucketsToTimeseies(keys, options, buckets)', () => { convertHistogramBucketsToTimeseries(keys, { ...options }, bucketsWithMultipleKeyedPercentiles) ).toThrow(); }); + + it('should tranform top_metric aggregations', () => { + const topMetricOptions: MetricsAPIRequest = { + ...options, + metrics: [ + { id: 'metric_0', aggregations: { metric_0: { avg: { field: 'system.cpu.user.pct' } } } }, + { + id: '__metadata__', + aggregations: { + __metadata__: { + top_metrics: { + metrics: [{ field: 'host.name' }, { field: 'host.ip' }], + }, + }, + }, + }, + ], + }; + + const bucketsWithTopAggregation = [ + { + key: 1577836800000, + key_as_string: '2020-01-01T00:00:00.000Z', + doc_count: 1, + metric_0: { value: 1 }, + __metadata__: { + top: [ + { + sort: ['2021-03-30T13:46:27.684Z'], + metrics: { + 'host.name': 'testHostName', + 'host.ip': 'testHostIp', + }, + }, + ], + }, + }, + { + key: 1577836860000, + key_as_string: '2020-01-01T00:01:00.000Z', + doc_count: 1, + metric_0: { value: null }, + __metadata__: { + top: [], + }, + }, + ]; + + expect( + convertHistogramBucketsToTimeseries(keys, topMetricOptions, bucketsWithTopAggregation) + ).toMatchSnapshot(); + }); }); diff --git a/x-pack/plugins/infra/server/lib/metrics/lib/convert_histogram_buckets_to_timeseries.ts b/x-pack/plugins/infra/server/lib/metrics/lib/convert_histogram_buckets_to_timeseries.ts index e86f90e18740..ed1ffe4e364d 100644 --- a/x-pack/plugins/infra/server/lib/metrics/lib/convert_histogram_buckets_to_timeseries.ts +++ b/x-pack/plugins/infra/server/lib/metrics/lib/convert_histogram_buckets_to_timeseries.ts @@ -19,7 +19,7 @@ import { NormalizedMetricValueRT, PercentilesTypeRT, PercentilesKeyedTypeRT, - TopHitsTypeRT, + TopMetricsTypeRT, MetricValueTypeRT, } from '../types'; @@ -57,8 +57,8 @@ const getValue = (valueObject: ValueObjectType) => { return valueObject.value; } - if (TopHitsTypeRT.is(valueObject)) { - return valueObject.hits.hits.map((hit) => hit._source); + if (TopMetricsTypeRT.is(valueObject)) { + return valueObject.top.map((res) => res.metrics); } return null; diff --git a/x-pack/plugins/infra/server/lib/metrics/types.ts b/x-pack/plugins/infra/server/lib/metrics/types.ts index cb4bcf6609ba..e1f5ecd45e36 100644 --- a/x-pack/plugins/infra/server/lib/metrics/types.ts +++ b/x-pack/plugins/infra/server/lib/metrics/types.ts @@ -26,27 +26,13 @@ export const PercentilesKeyedTypeRT = rt.type({ values: rt.array(rt.type({ key: rt.string, value: NumberOrNullRT })), }); -export const TopHitsTypeRT = rt.type({ - hits: rt.type({ - total: rt.type({ - value: rt.number, - relation: rt.string, - }), - hits: rt.array( - rt.intersection([ - rt.type({ - _index: rt.string, - _id: rt.string, - _score: NumberOrNullRT, - _source: rt.object, - }), - rt.partial({ - sort: rt.array(rt.union([rt.string, rt.number])), - max_score: NumberOrNullRT, - }), - ]) - ), - }), +export const TopMetricsTypeRT = rt.type({ + top: rt.array( + rt.type({ + sort: rt.union([rt.array(rt.number), rt.array(rt.string)]), + metrics: rt.record(rt.string, rt.union([rt.number, rt.string, rt.null])), + }) + ), }); export const MetricValueTypeRT = rt.union([ @@ -54,7 +40,7 @@ export const MetricValueTypeRT = rt.union([ NormalizedMetricValueRT, PercentilesTypeRT, PercentilesKeyedTypeRT, - TopHitsTypeRT, + TopMetricsTypeRT, ]); export type MetricValueType = rt.TypeOf; diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/apply_metadata_to_last_path.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/apply_metadata_to_last_path.ts index 943c6c379376..7de63ae59a32 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/apply_metadata_to_last_path.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/apply_metadata_to_last_path.ts @@ -20,7 +20,7 @@ import { InfraSource } from '../../../lib/sources'; export const isIPv4 = (subject: string) => /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/.test(subject); type RowWithMetadata = MetricsAPIRow & { - [META_KEY]: object[]; + [META_KEY]: Array>; }; export const applyMetadataToLastPath = ( @@ -47,7 +47,7 @@ export const applyMetadataToLastPath = ( source.configuration.fields ); // Set the label as the name and fallback to the id OR path.value - lastPath.label = get(firstMetaDoc, inventoryFields.name, lastPath.value); + lastPath.label = (firstMetaDoc[inventoryFields.name] ?? lastPath.value) as string; // If the inventory fields contain an ip address, we need to try and set that // on the path object. IP addersses are typically stored as multiple fields. We will // use the first IPV4 address we find. diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts index 128137efa272..a71e1fb1f1f1 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts @@ -72,16 +72,19 @@ export const transformRequestToMetricsAPIRequest = async ( id: META_KEY, aggregations: { [META_KEY]: { - top_hits: { + top_metrics: { size: 1, - _source: [inventoryFields.name], - sort: [{ [sourceOverrides?.timestamp ?? source.configuration.fields.timestamp]: 'desc' }], + metrics: [{ field: inventoryFields.name }], + sort: { + [source.configuration.fields.timestamp]: 'desc', + }, }, }, }, }; + if (inventoryFields.ip) { - metaAggregation.aggregations[META_KEY].top_hits._source.push(inventoryFields.ip); + metaAggregation.aggregations[META_KEY].top_metrics.metrics.push({ field: inventoryFields.ip }); } metricsApiRequest.metrics.push(metaAggregation);