From c7842bb07ef408d0105bc7874fa544b97f830393 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 1 Jul 2020 04:06:56 -0500 Subject: [PATCH] Initial work on uptime homepage API (#70135) Co-authored-by: Shahzad --- .../common/runtime_types/ping/histogram.ts | 1 + x-pack/plugins/uptime/kibana.json | 2 +- x-pack/plugins/uptime/public/apps/plugin.ts | 13 ++++ .../public/apps/uptime_overview_fetcher.ts | 62 +++++++++++++++++++ .../plugins/uptime/public/state/api/ping.ts | 2 + .../__tests__/get_ping_histogram.test.ts | 3 +- .../server/lib/requests/get_ping_histogram.ts | 29 ++++++--- .../rest_api/pings/get_ping_histogram.ts | 4 +- 8 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts diff --git a/x-pack/plugins/uptime/common/runtime_types/ping/histogram.ts b/x-pack/plugins/uptime/common/runtime_types/ping/histogram.ts index 209770a19f4aa5..47e4dd52299b16 100644 --- a/x-pack/plugins/uptime/common/runtime_types/ping/histogram.ts +++ b/x-pack/plugins/uptime/common/runtime_types/ping/histogram.ts @@ -21,6 +21,7 @@ export interface GetPingHistogramParams { dateEnd: string; filters?: string; monitorId?: string; + bucketSize?: string; } export interface HistogramResult { diff --git a/x-pack/plugins/uptime/kibana.json b/x-pack/plugins/uptime/kibana.json index 5fbd6129fd18f4..152839836ad997 100644 --- a/x-pack/plugins/uptime/kibana.json +++ b/x-pack/plugins/uptime/kibana.json @@ -2,7 +2,7 @@ "configPath": ["xpack", "uptime"], "id": "uptime", "kibanaVersion": "kibana", - "optionalPlugins": ["capabilities", "data", "home"], + "optionalPlugins": ["capabilities", "data", "home", "observability"], "requiredPlugins": [ "alerts", "embeddable", diff --git a/x-pack/plugins/uptime/public/apps/plugin.ts b/x-pack/plugins/uptime/public/apps/plugin.ts index 26810a9b1cda33..9af4dea9dbb444 100644 --- a/x-pack/plugins/uptime/public/apps/plugin.ts +++ b/x-pack/plugins/uptime/public/apps/plugin.ts @@ -27,10 +27,14 @@ import { } from '../../../../../src/plugins/data/public'; import { alertTypeInitializers } from '../lib/alert_types'; import { kibanaService } from '../state/kibana_service'; +import { fetchIndexStatus } from '../state/api'; +import { ObservabilityPluginSetup } from '../../../observability/public'; +import { fetchUptimeOverviewData } from './uptime_overview_fetcher'; export interface ClientPluginsSetup { data: DataPublicPluginSetup; home: HomePublicPluginSetup; + observability: ObservabilityPluginSetup; triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup; } @@ -63,6 +67,15 @@ export class UptimePlugin }); } + plugins.observability.dashboard.register({ + appName: 'uptime', + hasData: async () => { + const status = await fetchIndexStatus(); + return status.docCount > 0; + }, + fetchData: fetchUptimeOverviewData, + }); + core.application.register({ appRoute: '/app/uptime#/', id: PLUGIN.ID, diff --git a/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts b/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts new file mode 100644 index 00000000000000..8467714e9661e8 --- /dev/null +++ b/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { fetchPingHistogram, fetchSnapshotCount } from '../state/api'; +import { UptimeFetchDataResponse } from '../../../observability/public/typings/fetch_data_response'; + +export async function fetchUptimeOverviewData({ + startTime, + endTime, + bucketSize, +}: { + startTime: string; + endTime: string; + bucketSize: string; +}) { + const snapshot = await fetchSnapshotCount({ + dateRangeStart: startTime, + dateRangeEnd: endTime, + }); + + const pings = await fetchPingHistogram({ dateStart: startTime, dateEnd: endTime, bucketSize }); + + const response: UptimeFetchDataResponse = { + title: 'Uptime', + appLink: '/app/uptime#/', + stats: { + monitors: { + type: 'number', + label: 'Monitors', + value: snapshot.total, + }, + up: { + type: 'number', + label: 'Up', + value: snapshot.up, + }, + down: { + type: 'number', + label: 'Down', + value: snapshot.down, + }, + }, + series: { + up: { + label: 'Up', + coordinates: pings.histogram.map((p) => { + return { x: p.x!, y: p.upCount || 0 }; + }), + }, + down: { + label: 'Down', + coordinates: pings.histogram.map((p) => { + return { x: p.x!, y: p.downCount || 0 }; + }), + }, + }, + }; + return response; +} diff --git a/x-pack/plugins/uptime/public/state/api/ping.ts b/x-pack/plugins/uptime/public/state/api/ping.ts index a2937c9c794ddf..2d6a69064f277a 100644 --- a/x-pack/plugins/uptime/public/state/api/ping.ts +++ b/x-pack/plugins/uptime/public/state/api/ping.ts @@ -25,12 +25,14 @@ export const fetchPingHistogram: APIFn dateStart, dateEnd, filters, + bucketSize, }) => { const queryParams = { dateStart, dateEnd, monitorId, filters, + bucketSize, }; return await apiService.get(API_URLS.PING_HISTOGRAM, queryParams); diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts index 9042186145eb71..11c7511dec3707 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts @@ -62,7 +62,6 @@ describe('getPingHistogram', () => { dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, from: 'now-15m', to: 'now', - filters: null, }); expect(mockEsClient).toHaveBeenCalledTimes(1); @@ -81,7 +80,7 @@ describe('getPingHistogram', () => { dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, from: 'now-15m', to: 'now', - filters: null, + filters: '', }); expect(mockEsClient).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts index 863eff82c360ef..a74b55c24e227e 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts @@ -15,15 +15,17 @@ export interface GetPingHistogramParams { /** @member dateRangeEnd timestamp bounds */ to: string; /** @member filters user-defined filters */ - filters?: string | null; + filters?: string; /** @member monitorId optional limit to monitorId */ - monitorId?: string | null; + monitorId?: string; + + bucketSize?: string; } export const getPingHistogram: UMElasticsearchQueryFn< GetPingHistogramParams, HistogramResult -> = async ({ callES, dynamicSettings, from, to, filters, monitorId }) => { +> = async ({ callES, dynamicSettings, from, to, filters, monitorId, bucketSize }) => { const boolFilters = filters ? JSON.parse(filters) : null; const additionalFilters = []; if (monitorId) { @@ -34,6 +36,22 @@ export const getPingHistogram: UMElasticsearchQueryFn< } const filter = getFilterClause(from, to, additionalFilters); + const seriesHistogram: any = {}; + + if (bucketSize) { + seriesHistogram.date_histogram = { + field: '@timestamp', + fixed_interval: bucketSize, + missing: 0, + }; + } else { + seriesHistogram.auto_date_histogram = { + field: '@timestamp', + buckets: QUERY.DEFAULT_BUCKET_COUNT, + missing: 0, + }; + } + const params = { index: dynamicSettings.heartbeatIndices, body: { @@ -45,10 +63,7 @@ export const getPingHistogram: UMElasticsearchQueryFn< size: 0, aggs: { timeseries: { - auto_date_histogram: { - field: '@timestamp', - buckets: QUERY.DEFAULT_BUCKET_COUNT, - }, + ...seriesHistogram, aggs: { down: { filter: { diff --git a/x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts b/x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts index a5899978890696..4ac50d0e78c4cf 100644 --- a/x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts +++ b/x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts @@ -18,10 +18,11 @@ export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServe dateEnd: schema.string(), monitorId: schema.maybe(schema.string()), filters: schema.maybe(schema.string()), + bucketSize: schema.maybe(schema.string()), }), }, handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => { - const { dateStart, dateEnd, monitorId, filters } = request.query; + const { dateStart, dateEnd, monitorId, filters, bucketSize } = request.query; const result = await libs.requests.getPingHistogram({ callES, @@ -30,6 +31,7 @@ export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServe to: dateEnd, monitorId, filters, + bucketSize, }); return response.ok({