diff --git a/x-pack/plugins/infra/common/http_api/snapshot_api.ts b/x-pack/plugins/infra/common/http_api/snapshot_api.ts index 6b666b39b00945..8e00484be375e2 100644 --- a/x-pack/plugins/infra/common/http_api/snapshot_api.ts +++ b/x-pack/plugins/infra/common/http_api/snapshot_api.ts @@ -6,6 +6,7 @@ import * as rt from 'io-ts'; import { SnapshotMetricTypeRT, ItemTypeRT } from '../inventory_models/types'; +import { metricsExplorerSeriesRT } from './metrics_explorer'; export const SnapshotNodePathRT = rt.intersection([ rt.type({ @@ -21,6 +22,7 @@ const SnapshotNodeMetricOptionalRT = rt.partial({ value: rt.union([rt.number, rt.null]), avg: rt.union([rt.number, rt.null]), max: rt.union([rt.number, rt.null]), + timeseries: metricsExplorerSeriesRT, }); const SnapshotNodeMetricRequiredRT = rt.type({ @@ -41,11 +43,16 @@ export const SnapshotNodeResponseRT = rt.type({ interval: rt.string, }); -export const InfraTimerangeInputRT = rt.type({ - interval: rt.string, - to: rt.number, - from: rt.number, -}); +export const InfraTimerangeInputRT = rt.intersection([ + rt.type({ + interval: rt.string, + to: rt.number, + from: rt.number, + }), + rt.partial({ + lookbackSize: rt.number, + }), +]); export const SnapshotGroupByRT = rt.array( rt.partial({ @@ -97,6 +104,9 @@ export const SnapshotRequestRT = rt.intersection([ accountId: rt.string, region: rt.string, filterQuery: rt.union([rt.string, rt.null]), + includeTimeseries: rt.boolean, + limit: rt.number, + afterKey: rt.record(rt.string, rt.string), }), ]); diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_snaphot.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_snaphot.ts index 3ec63d7b2de286..721a2d5792dca9 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_snaphot.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_snaphot.ts @@ -14,6 +14,8 @@ import { SnapshotNodeResponseRT, SnapshotNodeResponse, SnapshotGroupBy, + SnapshotRequest, + InfraTimerangeInput, } from '../../../../../common/http_api/snapshot_api'; import { InventoryItemType, @@ -37,10 +39,11 @@ export function useSnapshot( ); }; - const timerange = { + const timerange: InfraTimerangeInput = { interval: '1m', to: currentTime, from: currentTime - 360 * 1000, + lookbackSize: 20, }; const { error, loading, response, makeRequest } = useHTTPRequest( @@ -55,7 +58,8 @@ export function useSnapshot( sourceId, accountId, region, - }), + includeTimeseries: true, + } as SnapshotRequest), decodeResponse ); diff --git a/x-pack/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts b/x-pack/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts index c75ee6d6440442..eeb7b7e13a1fe2 100644 --- a/x-pack/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts +++ b/x-pack/plugins/infra/server/lib/snapshot/create_timerange_with_interval.ts @@ -32,9 +32,10 @@ export const createTimeRangeWithInterval = async ( )) || 60, 60 ); + const lookbackSize = options.timerange.lookbackSize || 5; return { interval: `${interval}s`, - from: options.timerange.to - interval * 5000, // We need at least 5 buckets worth of data + from: options.timerange.to - interval * lookbackSize * 1000, // We need at least 5 buckets worth of data to: options.timerange.to, }; }; diff --git a/x-pack/plugins/infra/server/lib/snapshot/response_helpers.ts b/x-pack/plugins/infra/server/lib/snapshot/response_helpers.ts index 12f284c363bd53..4de5fa15c48f19 100644 --- a/x-pack/plugins/infra/server/lib/snapshot/response_helpers.ts +++ b/x-pack/plugins/infra/server/lib/snapshot/response_helpers.ts @@ -7,6 +7,7 @@ import { isNumber, last, max, sum, get } from 'lodash'; import moment from 'moment'; +import { MetricsExplorerSeries } from '../../../common/http_api/metrics_explorer'; import { getIntervalInSeconds } from '../../utils/get_interval_in_seconds'; import { InfraSnapshotRequestOptions } from './types'; import { findInventoryModel } from '../../../common/inventory_models'; @@ -127,12 +128,15 @@ export const getNodeMetrics = ( }; } const lastBucket = findLastFullBucket(nodeBuckets, options); - const result = { + const result: SnapshotNodeMetric = { name: options.metric.type, value: getMetricValueFromBucket(options.metric.type, lastBucket), max: calculateMax(nodeBuckets, options.metric.type), avg: calculateAvg(nodeBuckets, options.metric.type), }; + if (options.includeTimeseries) { + result.timeseries = getTimeseriesData(nodeBuckets, options.metric.type); + } return result; }; @@ -164,3 +168,20 @@ function calculateMax(buckets: InfraSnapshotMetricsBucket[], type: SnapshotMetri function calculateAvg(buckets: InfraSnapshotMetricsBucket[], type: SnapshotMetricType) { return sum(buckets.map(bucket => getMetricValueFromBucket(type, bucket))) / buckets.length || 0; } + +function getTimeseriesData( + buckets: InfraSnapshotMetricsBucket[], + type: SnapshotMetricType +): MetricsExplorerSeries { + return { + id: type, + columns: [ + { name: 'timestamp', type: 'date' }, + { name: 'metric_0', type: 'number' }, + ], + rows: buckets.map(bucket => ({ + timestamp: bucket.key as number, + metric_0: getMetricValueFromBucket(type, bucket), + })), + }; +} diff --git a/x-pack/plugins/infra/server/routes/snapshot/index.ts b/x-pack/plugins/infra/server/routes/snapshot/index.ts index 2d951d426b03a0..3a0326fb6ae84c 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/index.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/index.ts @@ -39,6 +39,7 @@ export const initSnapshotRoute = (libs: InfraBackendLibs) => { timerange, accountId, region, + includeTimeseries, } = pipe( SnapshotRequestRT.decode(request.body), fold(throwErrors(Boom.badRequest), identity) @@ -57,6 +58,7 @@ export const initSnapshotRoute = (libs: InfraBackendLibs) => { sourceConfiguration: source.configuration, metric, timerange, + includeTimeseries, }; const searchES = (