Skip to content

Commit e8cf08f

Browse files
andrewvcshahzad31
andauthored
Initial work on uptime homepage API (#70135)
Co-authored-by: Shahzad <shahzad31comp@gmail.com>
1 parent 5c98b11 commit e8cf08f

File tree

8 files changed

+105
-11
lines changed

8 files changed

+105
-11
lines changed

x-pack/plugins/uptime/common/runtime_types/ping/histogram.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface GetPingHistogramParams {
2121
dateEnd: string;
2222
filters?: string;
2323
monitorId?: string;
24+
bucketSize?: string;
2425
}
2526

2627
export interface HistogramResult {

x-pack/plugins/uptime/kibana.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"configPath": ["xpack", "uptime"],
33
"id": "uptime",
44
"kibanaVersion": "kibana",
5-
"optionalPlugins": ["capabilities", "data", "home"],
5+
"optionalPlugins": ["capabilities", "data", "home", "observability"],
66
"requiredPlugins": [
77
"alerts",
88
"embeddable",

x-pack/plugins/uptime/public/apps/plugin.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,14 @@ import {
2727
} from '../../../../../src/plugins/data/public';
2828
import { alertTypeInitializers } from '../lib/alert_types';
2929
import { kibanaService } from '../state/kibana_service';
30+
import { fetchIndexStatus } from '../state/api';
31+
import { ObservabilityPluginSetup } from '../../../observability/public';
32+
import { fetchUptimeOverviewData } from './uptime_overview_fetcher';
3033

3134
export interface ClientPluginsSetup {
3235
data: DataPublicPluginSetup;
3336
home: HomePublicPluginSetup;
37+
observability: ObservabilityPluginSetup;
3438
triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup;
3539
}
3640

@@ -63,6 +67,15 @@ export class UptimePlugin
6367
});
6468
}
6569

70+
plugins.observability.dashboard.register({
71+
appName: 'uptime',
72+
hasData: async () => {
73+
const status = await fetchIndexStatus();
74+
return status.docCount > 0;
75+
},
76+
fetchData: fetchUptimeOverviewData,
77+
});
78+
6679
core.application.register({
6780
appRoute: '/app/uptime#/',
6881
id: PLUGIN.ID,
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { fetchPingHistogram, fetchSnapshotCount } from '../state/api';
8+
import { UptimeFetchDataResponse } from '../../../observability/public/typings/fetch_data_response';
9+
10+
export async function fetchUptimeOverviewData({
11+
startTime,
12+
endTime,
13+
bucketSize,
14+
}: {
15+
startTime: string;
16+
endTime: string;
17+
bucketSize: string;
18+
}) {
19+
const snapshot = await fetchSnapshotCount({
20+
dateRangeStart: startTime,
21+
dateRangeEnd: endTime,
22+
});
23+
24+
const pings = await fetchPingHistogram({ dateStart: startTime, dateEnd: endTime, bucketSize });
25+
26+
const response: UptimeFetchDataResponse = {
27+
title: 'Uptime',
28+
appLink: '/app/uptime#/',
29+
stats: {
30+
monitors: {
31+
type: 'number',
32+
label: 'Monitors',
33+
value: snapshot.total,
34+
},
35+
up: {
36+
type: 'number',
37+
label: 'Up',
38+
value: snapshot.up,
39+
},
40+
down: {
41+
type: 'number',
42+
label: 'Down',
43+
value: snapshot.down,
44+
},
45+
},
46+
series: {
47+
up: {
48+
label: 'Up',
49+
coordinates: pings.histogram.map((p) => {
50+
return { x: p.x!, y: p.upCount || 0 };
51+
}),
52+
},
53+
down: {
54+
label: 'Down',
55+
coordinates: pings.histogram.map((p) => {
56+
return { x: p.x!, y: p.downCount || 0 };
57+
}),
58+
},
59+
},
60+
};
61+
return response;
62+
}

x-pack/plugins/uptime/public/state/api/ping.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ export const fetchPingHistogram: APIFn<GetPingHistogramParams, HistogramResult>
2525
dateStart,
2626
dateEnd,
2727
filters,
28+
bucketSize,
2829
}) => {
2930
const queryParams = {
3031
dateStart,
3132
dateEnd,
3233
monitorId,
3334
filters,
35+
bucketSize,
3436
};
3537

3638
return await apiService.get(API_URLS.PING_HISTOGRAM, queryParams);

x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ describe('getPingHistogram', () => {
6262
dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS,
6363
from: 'now-15m',
6464
to: 'now',
65-
filters: null,
6665
});
6766

6867
expect(mockEsClient).toHaveBeenCalledTimes(1);
@@ -81,7 +80,7 @@ describe('getPingHistogram', () => {
8180
dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS,
8281
from: 'now-15m',
8382
to: 'now',
84-
filters: null,
83+
filters: '',
8584
});
8685

8786
expect(mockEsClient).toHaveBeenCalledTimes(1);

x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ export interface GetPingHistogramParams {
1515
/** @member dateRangeEnd timestamp bounds */
1616
to: string;
1717
/** @member filters user-defined filters */
18-
filters?: string | null;
18+
filters?: string;
1919
/** @member monitorId optional limit to monitorId */
20-
monitorId?: string | null;
20+
monitorId?: string;
21+
22+
bucketSize?: string;
2123
}
2224

2325
export const getPingHistogram: UMElasticsearchQueryFn<
2426
GetPingHistogramParams,
2527
HistogramResult
26-
> = async ({ callES, dynamicSettings, from, to, filters, monitorId }) => {
28+
> = async ({ callES, dynamicSettings, from, to, filters, monitorId, bucketSize }) => {
2729
const boolFilters = filters ? JSON.parse(filters) : null;
2830
const additionalFilters = [];
2931
if (monitorId) {
@@ -34,6 +36,22 @@ export const getPingHistogram: UMElasticsearchQueryFn<
3436
}
3537
const filter = getFilterClause(from, to, additionalFilters);
3638

39+
const seriesHistogram: any = {};
40+
41+
if (bucketSize) {
42+
seriesHistogram.date_histogram = {
43+
field: '@timestamp',
44+
fixed_interval: bucketSize,
45+
missing: 0,
46+
};
47+
} else {
48+
seriesHistogram.auto_date_histogram = {
49+
field: '@timestamp',
50+
buckets: QUERY.DEFAULT_BUCKET_COUNT,
51+
missing: 0,
52+
};
53+
}
54+
3755
const params = {
3856
index: dynamicSettings.heartbeatIndices,
3957
body: {
@@ -45,10 +63,7 @@ export const getPingHistogram: UMElasticsearchQueryFn<
4563
size: 0,
4664
aggs: {
4765
timeseries: {
48-
auto_date_histogram: {
49-
field: '@timestamp',
50-
buckets: QUERY.DEFAULT_BUCKET_COUNT,
51-
},
66+
...seriesHistogram,
5267
aggs: {
5368
down: {
5469
filter: {

x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServe
1818
dateEnd: schema.string(),
1919
monitorId: schema.maybe(schema.string()),
2020
filters: schema.maybe(schema.string()),
21+
bucketSize: schema.maybe(schema.string()),
2122
}),
2223
},
2324
handler: async ({ callES, dynamicSettings }, _context, request, response): Promise<any> => {
24-
const { dateStart, dateEnd, monitorId, filters } = request.query;
25+
const { dateStart, dateEnd, monitorId, filters, bucketSize } = request.query;
2526

2627
const result = await libs.requests.getPingHistogram({
2728
callES,
@@ -30,6 +31,7 @@ export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServe
3031
to: dateEnd,
3132
monitorId,
3233
filters,
34+
bucketSize,
3335
});
3436

3537
return response.ok({

0 commit comments

Comments
 (0)