= async ({
+ basePath,
+ monitorId,
+ dateStart,
+ dateEnd,
+ statusFilter,
+ filters,
+}) => {
+ const url = getApiPath(`/api/uptime/ping/histogram`, basePath);
+ const params = {
+ dateStart,
+ dateEnd,
+ ...(monitorId && { monitorId }),
+ ...(statusFilter && { statusFilter }),
+ ...(filters && { filters }),
+ };
+ const urlParams = qs.stringify(params).toString();
+ const response = await fetch(`${url}?${urlParams}`);
+ if (!response.ok) {
+ throw new Error(response.statusText);
+ }
+ const responseData = await response.json();
+ return responseData;
+};
diff --git a/x-pack/legacy/plugins/uptime/public/state/api/types.ts b/x-pack/legacy/plugins/uptime/public/state/api/types.ts
index 278cfce29986f..c88e111d778d5 100644
--- a/x-pack/legacy/plugins/uptime/public/state/api/types.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/api/types.ts
@@ -12,3 +12,5 @@ export interface BaseParams {
statusFilter?: string;
location?: string;
}
+
+export type APIFn = (params: { basePath: string } & P) => Promise;
diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/index.ts b/x-pack/legacy/plugins/uptime/public/state/effects/index.ts
index 41dda145edb4e..21d4f7a66ad67 100644
--- a/x-pack/legacy/plugins/uptime/public/state/effects/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/effects/index.ts
@@ -9,10 +9,12 @@ import { fetchMonitorDetailsEffect } from './monitor';
import { fetchOverviewFiltersEffect } from './overview_filters';
import { fetchSnapshotCountEffect } from './snapshot';
import { fetchMonitorStatusEffect } from './monitor_status';
+import { fetchPingHistogramEffect } from './ping';
export function* rootEffect() {
yield fork(fetchMonitorDetailsEffect);
yield fork(fetchSnapshotCountEffect);
yield fork(fetchOverviewFiltersEffect);
yield fork(fetchMonitorStatusEffect);
+ yield fork(fetchPingHistogramEffect);
}
diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts b/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts
new file mode 100644
index 0000000000000..acb9b31915fa9
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts
@@ -0,0 +1,17 @@
+/*
+ * 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 { takeLatest } from 'redux-saga/effects';
+import { getPingHistogram, getPingHistogramSuccess, getPingHistogramFail } from '../actions';
+import { fetchPingHistogram } from '../api';
+import { fetchEffectFactory } from './fetch_effect';
+
+export function* fetchPingHistogramEffect() {
+ yield takeLatest(
+ String(getPingHistogram),
+ fetchEffectFactory(fetchPingHistogram, getPingHistogramSuccess, getPingHistogramFail)
+ );
+}
diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts
index 5f915d970e543..c80ada4f63182 100644
--- a/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts
@@ -10,6 +10,7 @@ import { overviewFiltersReducer } from './overview_filters';
import { snapshotReducer } from './snapshot';
import { uiReducer } from './ui';
import { monitorStatusReducer } from './monitor_status';
+import { pingReducer } from './ping';
export const rootReducer = combineReducers({
monitor: monitorReducer,
@@ -17,4 +18,5 @@ export const rootReducer = combineReducers({
snapshot: snapshotReducer,
ui: uiReducer,
monitorStatus: monitorStatusReducer,
+ ping: pingReducer,
});
diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts
new file mode 100644
index 0000000000000..76775e6a0a355
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts
@@ -0,0 +1,45 @@
+/*
+ * 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 { handleActions, Action } from 'redux-actions';
+import { getPingHistogram, getPingHistogramSuccess, getPingHistogramFail } from '../actions';
+import { HistogramResult } from '../../../common/types';
+
+export interface PingState {
+ pingHistogram: HistogramResult | null;
+ errors: any[];
+ loading: boolean;
+}
+
+const initialState: PingState = {
+ pingHistogram: null,
+ loading: false,
+ errors: [],
+};
+
+type MonitorStatusPayload = HistogramResult & Error;
+
+export const pingReducer = handleActions(
+ {
+ [String(getPingHistogram)]: state => ({
+ ...state,
+ loading: true,
+ }),
+
+ [String(getPingHistogramSuccess)]: (state: PingState, action: Action) => ({
+ ...state,
+ loading: false,
+ pingHistogram: { ...action.payload },
+ }),
+
+ [String(getPingHistogramFail)]: (state, action: Action) => ({
+ ...state,
+ errors: [...state.errors, action.payload],
+ loading: false,
+ }),
+ },
+ initialState
+);
diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts
index 38fb3edea4768..5e3bf95d81292 100644
--- a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts
@@ -45,6 +45,11 @@ describe('state selectors', () => {
monitor: null,
loading: false,
},
+ ping: {
+ pingHistogram: null,
+ loading: false,
+ errors: [],
+ },
};
it('selects base path from state', () => {
diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts
index 337e99f6ede16..0066241dcc217 100644
--- a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts
+++ b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts
@@ -28,3 +28,7 @@ export const selectSelectedMonitor = (state: AppState) => {
export const selectMonitorStatus = (state: AppState) => {
return state.monitorStatus.status;
};
+
+export const selectPingHistogram = ({ ping, ui }: AppState) => {
+ return { data: ping.pingHistogram, loading: ping.loading, lastRefresh: ui.lastRefresh };
+};
diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts b/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts
index 897d67dde807e..cc5744eac6ea1 100644
--- a/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts
+++ b/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts
@@ -4,19 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { UMGqlRange } from '../../../common/domain_types';
import { UMResolver } from '../../../common/graphql/resolver_types';
-import {
- GetFilterBarQueryArgs,
- GetMonitorChartsDataQueryArgs,
- MonitorChart,
- GetSnapshotHistogramQueryArgs,
-} from '../../../common/graphql/types';
+import { GetMonitorChartsDataQueryArgs, MonitorChart } from '../../../common/graphql/types';
import { UMServerLibs } from '../../lib/lib';
import { CreateUMGraphQLResolvers, UMContext } from '../types';
-import { HistogramResult } from '../../../common/domain_types';
-
-export type UMMonitorsResolver = UMResolver, any, UMGqlRange, UMContext>;
export type UMGetMonitorChartsResolver = UMResolver<
any | Promise,
@@ -25,49 +16,20 @@ export type UMGetMonitorChartsResolver = UMResolver<
UMContext
>;
-export type UMGetFilterBarResolver = UMResolver<
- any | Promise,
- any,
- GetFilterBarQueryArgs,
- UMContext
->;
-
-export type UMGetSnapshotHistogram = UMResolver<
- HistogramResult | Promise,
- any,
- GetSnapshotHistogramQueryArgs,
- UMContext
->;
-
export const createMonitorsResolvers: CreateUMGraphQLResolvers = (
libs: UMServerLibs
): {
Query: {
- getSnapshotHistogram: UMGetSnapshotHistogram;
getMonitorChartsData: UMGetMonitorChartsResolver;
};
} => ({
Query: {
- async getSnapshotHistogram(
- _resolver,
- { dateRangeStart, dateRangeEnd, filters, monitorId, statusFilter },
- { APICaller }
- ): Promise {
- return await libs.pings.getPingHistogram({
- callES: APICaller,
- dateRangeStart,
- dateRangeEnd,
- filters,
- monitorId,
- statusFilter,
- });
- },
async getMonitorChartsData(
_resolver,
{ monitorId, dateRangeStart, dateRangeEnd, location },
{ APICaller }
): Promise {
- return await libs.monitors.getMonitorChartsData({
+ return libs.monitors.getMonitorChartsData({
callES: APICaller,
monitorId,
dateRangeStart,
diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts b/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts
index 8a86d97b4cd8e..6b8a896c4c60b 100644
--- a/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts
+++ b/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts
@@ -7,19 +7,6 @@
import gql from 'graphql-tag';
export const monitorsSchema = gql`
- type HistogramDataPoint {
- upCount: Int
- downCount: Int
- x: UnsignedInteger
- x0: UnsignedInteger
- y: UnsignedInteger
- }
-
- type DataPoint {
- x: UnsignedInteger
- y: Float
- }
-
"Represents a bucket of monitor status information."
type StatusData {
"The timeseries point for this status data."
@@ -93,11 +80,6 @@ export const monitorsSchema = gql`
monitors: [LatestMonitor!]
}
- type HistogramResult {
- histogram: [HistogramDataPoint]!
- interval: UnsignedInteger!
- }
-
extend type Query {
getMonitors(
dateRangeStart: String!
@@ -106,14 +88,6 @@ export const monitorsSchema = gql`
statusFilter: String
): LatestMonitorsResult
- getSnapshotHistogram(
- dateRangeStart: String!
- dateRangeEnd: String!
- filters: String
- statusFilter: String
- monitorId: String
- ): HistogramResult
-
getMonitorChartsData(
monitorId: String!
dateRangeStart: String!
diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap
index b73595d539e93..1b31f44557df0 100644
--- a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap
+++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap
@@ -22,7 +22,7 @@ Object {
"y": 1,
},
],
- "interval": 36000,
+ "interval": "1m",
}
`;
@@ -48,7 +48,7 @@ Object {
"y": 1,
},
],
- "interval": 5609564928000,
+ "interval": "1h",
}
`;
@@ -68,7 +68,7 @@ Object {
"y": 1,
},
],
- "interval": 5609564928000,
+ "interval": "1d",
}
`;
@@ -88,7 +88,7 @@ Object {
"y": 1,
},
],
- "interval": 5609564928000,
+ "interval": "1s",
}
`;
@@ -102,7 +102,7 @@ Object {
"y": 1,
},
],
- "interval": 36000,
+ "interval": "10s",
}
`;
@@ -122,6 +122,6 @@ Object {
"y": 1,
},
],
- "interval": 36000,
+ "interval": "1m",
}
`;
diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts
index e6a025759d5fe..8422ac5cd1ee8 100644
--- a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts
+++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts
@@ -5,8 +5,7 @@
*/
import { set } from 'lodash';
-import { elasticsearchPingsAdapter as adapter } from '../elasticsearch_pings_adapter';
-import { assertCloseTo } from '../../../helper';
+import { elasticsearchPingsAdapter as adapter } from '../es_pings';
describe('ElasticsearchPingsAdapter class', () => {
let mockHits: any[];
@@ -35,6 +34,7 @@ describe('ElasticsearchPingsAdapter class', () => {
},
},
],
+ interval: '1s',
},
},
};
@@ -98,12 +98,11 @@ describe('ElasticsearchPingsAdapter class', () => {
});
const result = await adapter.getPingHistogram({
callES: mockEsClient,
- dateRangeStart: 'now-15m',
- dateRangeEnd: 'now',
- filters: null,
+ dateStart: 'now-15m',
+ dateEnd: 'now',
+ filters: '',
});
- assertCloseTo(result.interval, 36000, 100);
- result.interval = 36000;
+ result.interval = '10s';
expect(mockEsClient).toHaveBeenCalledTimes(1);
expect(result).toMatchSnapshot();
});
@@ -116,12 +115,11 @@ describe('ElasticsearchPingsAdapter class', () => {
const result = await adapter.getPingHistogram({
callES: mockEsClient,
- dateRangeStart: 'now-15m',
- dateRangeEnd: 'now',
- filters: null,
+ dateStart: 'now-15m',
+ dateEnd: 'now',
+ filters: '',
});
- assertCloseTo(result.interval, 36000, 100);
- result.interval = 36000;
+ result.interval = '1m';
expect(mockEsClient).toHaveBeenCalledTimes(1);
expect(result).toMatchSnapshot();
@@ -175,14 +173,13 @@ describe('ElasticsearchPingsAdapter class', () => {
};
const result = await adapter.getPingHistogram({
callES: mockEsClient,
- dateRangeStart: '1234',
- dateRangeEnd: '5678',
+ dateStart: '1234',
+ dateEnd: '5678',
filters: JSON.stringify(searchFilter),
monitorId: undefined,
statusFilter: 'down',
});
- assertCloseTo(result.interval, 5609564928000, 1000);
- result.interval = 5609564928000;
+ result.interval = '1h';
expect(mockEsClient).toHaveBeenCalledTimes(1);
expect(result).toMatchSnapshot();
@@ -229,13 +226,12 @@ describe('ElasticsearchPingsAdapter class', () => {
const filters = `{"bool":{"must":[{"simple_query_string":{"query":"http"}}]}}`;
const result = await adapter.getPingHistogram({
callES: mockEsClient,
- dateRangeStart: 'now-15m',
- dateRangeEnd: 'now',
+ dateStart: 'now-15m',
+ dateEnd: 'now',
filters,
});
- assertCloseTo(result.interval, 36000, 100);
- result.interval = 36000;
+ result.interval = '1m';
expect(mockEsClient).toHaveBeenCalledTimes(1);
expect(result).toMatchSnapshot();
});
@@ -246,14 +242,14 @@ describe('ElasticsearchPingsAdapter class', () => {
mockEsClient.mockReturnValue(standardMockResponse);
const result = await adapter.getPingHistogram({
callES: mockEsClient,
- dateRangeStart: '1234',
- dateRangeEnd: '5678',
+ dateStart: '1234',
+ dateEnd: '5678',
filters: '',
monitorId: undefined,
statusFilter: 'down',
});
- assertCloseTo(result.interval, 5609564928000, 1000);
- result.interval = 5609564928000;
+
+ result.interval = '1d';
expect(mockEsClient).toHaveBeenCalledTimes(1);
expect(result).toMatchSnapshot();
@@ -267,8 +263,8 @@ describe('ElasticsearchPingsAdapter class', () => {
const result = await adapter.getPingHistogram({
callES: mockEsClient,
- dateRangeStart: '1234',
- dateRangeEnd: '5678',
+ dateStart: '1234',
+ dateEnd: '5678',
filters: '',
monitorId: undefined,
statusFilter: 'up',
diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/es_get_ping_historgram.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/es_get_ping_historgram.ts
new file mode 100644
index 0000000000000..66cae497eb081
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/es_get_ping_historgram.ts
@@ -0,0 +1,82 @@
+/*
+ * 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 { get } from 'lodash';
+import { INDEX_NAMES, QUERY } from '../../../../common/constants';
+import { parseFilterQuery, getFilterClause } from '../../helper';
+import { UMElasticsearchQueryFn } from '../framework';
+import { GetPingHistogramParams, HistogramResult } from '../../../../common/types';
+import { HistogramQueryResult } from './types';
+
+export const esGetPingHistogram: UMElasticsearchQueryFn<
+ GetPingHistogramParams,
+ HistogramResult
+> = async ({ callES, dateStart, dateEnd, filters, monitorId, statusFilter }) => {
+ const boolFilters = parseFilterQuery(filters);
+ const additionalFilters = [];
+ if (monitorId) {
+ additionalFilters.push({ match: { 'monitor.id': monitorId } });
+ }
+ if (boolFilters) {
+ additionalFilters.push(boolFilters);
+ }
+ const filter = getFilterClause(dateStart, dateEnd, additionalFilters);
+
+ const params = {
+ index: INDEX_NAMES.HEARTBEAT,
+ body: {
+ query: {
+ bool: {
+ filter,
+ },
+ },
+ size: 0,
+ aggs: {
+ timeseries: {
+ auto_date_histogram: {
+ field: '@timestamp',
+ buckets: QUERY.DEFAULT_BUCKET_COUNT,
+ },
+ aggs: {
+ down: {
+ filter: {
+ term: {
+ 'monitor.status': 'down',
+ },
+ },
+ },
+ up: {
+ filter: {
+ term: {
+ 'monitor.status': 'up',
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+
+ const result = await callES('search', params);
+ const interval = result.aggregations.timeseries?.interval;
+ const buckets: HistogramQueryResult[] = get(result, 'aggregations.timeseries.buckets', []);
+ const histogram = buckets.map(bucket => {
+ const x: number = get(bucket, 'key');
+ const downCount: number = get(bucket, 'down.doc_count');
+ const upCount: number = get(bucket, 'up.doc_count');
+ return {
+ x,
+ downCount: statusFilter && statusFilter !== 'down' ? 0 : downCount,
+ upCount: statusFilter && statusFilter !== 'up' ? 0 : upCount,
+ y: 1,
+ };
+ });
+ return {
+ histogram,
+ interval,
+ };
+};
diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/es_pings.ts
similarity index 67%
rename from x-pack/legacy/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts
rename to x-pack/legacy/plugins/uptime/server/lib/adapters/pings/es_pings.ts
index adabffcb1ea4a..93e3a1bd9397b 100644
--- a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts
+++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/es_pings.ts
@@ -7,9 +7,8 @@
import { get } from 'lodash';
import { INDEX_NAMES } from '../../../../common/constants';
import { HttpBody, Ping, PingResults } from '../../../../common/graphql/types';
-import { parseFilterQuery, getFilterClause, getHistogramIntervalFormatted } from '../../helper';
-import { UMPingsAdapter, HistogramQueryResult } from './adapter_types';
-import { getHistogramInterval } from '../../helper/get_histogram_interval';
+import { UMPingsAdapter } from './types';
+import { esGetPingHistogram } from './es_get_ping_historgram';
export const elasticsearchPingsAdapter: UMPingsAdapter = {
getAll: async ({
@@ -174,80 +173,7 @@ export const elasticsearchPingsAdapter: UMPingsAdapter = {
return result.hits.hits[0]?._source;
},
- getPingHistogram: async ({
- callES,
- dateRangeStart,
- dateRangeEnd,
- filters,
- monitorId,
- statusFilter,
- }) => {
- const boolFilters = parseFilterQuery(filters);
- const additionalFilters = [];
- if (monitorId) {
- additionalFilters.push({ match: { 'monitor.id': monitorId } });
- }
- if (boolFilters) {
- additionalFilters.push(boolFilters);
- }
- const filter = getFilterClause(dateRangeStart, dateRangeEnd, additionalFilters);
- const interval = getHistogramInterval(dateRangeStart, dateRangeEnd);
- const intervalFormatted = getHistogramIntervalFormatted(dateRangeStart, dateRangeEnd);
-
- const params = {
- index: INDEX_NAMES.HEARTBEAT,
- body: {
- query: {
- bool: {
- filter,
- },
- },
- size: 0,
- aggs: {
- timeseries: {
- date_histogram: {
- field: '@timestamp',
- fixed_interval: intervalFormatted,
- },
- aggs: {
- down: {
- filter: {
- term: {
- 'monitor.status': 'down',
- },
- },
- },
- up: {
- filter: {
- term: {
- 'monitor.status': 'up',
- },
- },
- },
- },
- },
- },
- },
- };
-
- const result = await callES('search', params);
- const buckets: HistogramQueryResult[] = get(result, 'aggregations.timeseries.buckets', []);
- const histogram = buckets.map(bucket => {
- const x: number = get(bucket, 'key');
- const downCount: number = get(bucket, 'down.doc_count');
- const upCount: number = get(bucket, 'up.doc_count');
- return {
- x,
- downCount: statusFilter && statusFilter !== 'down' ? 0 : downCount,
- upCount: statusFilter && statusFilter !== 'up' ? 0 : upCount,
- y: 1,
- };
- });
- return {
- histogram,
- interval,
- };
- },
+ getPingHistogram: esGetPingHistogram,
getDocCount: async ({ callES }) => {
const { count } = await callES('count', { index: INDEX_NAMES.HEARTBEAT });
diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/index.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/index.ts
index 6d93785e01527..37324a8f521f6 100644
--- a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/index.ts
+++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/index.ts
@@ -4,5 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export * from './adapter_types';
-export { elasticsearchPingsAdapter } from './elasticsearch_pings_adapter';
+export * from './types';
+export { elasticsearchPingsAdapter } from './es_pings';
diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/adapter_types.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/types.ts
similarity index 79%
rename from x-pack/legacy/plugins/uptime/server/lib/adapters/pings/adapter_types.ts
rename to x-pack/legacy/plugins/uptime/server/lib/adapters/pings/types.ts
index 8b2a49c0c9ffe..b1b1589af2ca7 100644
--- a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/adapter_types.ts
+++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/types.ts
@@ -5,8 +5,8 @@
*/
import { DocCount, Ping, PingResults } from '../../../../common/graphql/types';
-import { HistogramResult } from '../../../../common/domain_types';
import { UMElasticsearchQueryFn } from '../framework';
+import { GetPingHistogramParams, HistogramResult } from '../../../../common/types';
export interface GetAllParams {
/** @member dateRangeStart timestamp bounds */
@@ -42,19 +42,6 @@ export interface GetLatestMonitorDocsParams {
monitorId?: string | null;
}
-export interface GetPingHistogramParams {
- /** @member dateRangeStart timestamp bounds */
- dateRangeStart: string;
- /** @member dateRangeEnd timestamp bounds */
- dateRangeEnd: string;
- /** @member filters user-defined filters */
- filters?: string | null;
- /** @member monitorId optional limit to monitorId */
- monitorId?: string | null;
- /** @member statusFilter special filter targeting the latest status of each monitor */
- statusFilter?: string | null;
-}
-
/**
* Count the number of documents in heartbeat indices
*/
diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/assert_close_to.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/assert_close_to.ts
index 13b6f3688809c..45b76ba25470b 100644
--- a/x-pack/legacy/plugins/uptime/server/lib/helper/assert_close_to.ts
+++ b/x-pack/legacy/plugins/uptime/server/lib/helper/assert_close_to.ts
@@ -8,4 +8,9 @@ export const assertCloseTo = (actual: number, expected: number, precision: numbe
if (Math.abs(expected - actual) > precision) {
throw new Error(`expected [${expected}] to be within ${precision} of ${actual}`);
}
+
+ // if actual is undefined above math condition will be NAN and it will be always false
+ if (actual === undefined) {
+ throw new Error(`expected close to [${expected}] but got [${actual}]`);
+ }
};
diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/index.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/index.ts
index f9a8de81332d5..eae8023b66ff4 100644
--- a/x-pack/legacy/plugins/uptime/server/lib/helper/index.ts
+++ b/x-pack/legacy/plugins/uptime/server/lib/helper/index.ts
@@ -5,7 +5,6 @@
*/
export { getFilterClause } from './get_filter_clause';
-export { getHistogramInterval } from './get_histogram_interval';
export { getHistogramIntervalFormatted } from './get_histogram_interval_formatted';
export { parseFilterQuery } from './parse_filter_query';
export { assertCloseTo } from './assert_close_to';
diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/index.ts b/x-pack/legacy/plugins/uptime/server/rest_api/index.ts
index e64b317e67f98..91936b499d8e6 100644
--- a/x-pack/legacy/plugins/uptime/server/rest_api/index.ts
+++ b/x-pack/legacy/plugins/uptime/server/rest_api/index.ts
@@ -16,6 +16,7 @@ import {
createGetMonitorLocationsRoute,
createGetStatusBarRoute,
} from './monitors';
+import { createGetPingHistogramRoute } from './pings/get_ping_histogram';
export * from './types';
export { createRouteWithAuth } from './create_route_with_auth';
@@ -31,4 +32,5 @@ export const restApiRoutes: UMRestApiRouteFactory[] = [
createGetSnapshotCount,
createLogMonitorPageRoute,
createLogOverviewPageRoute,
+ createGetPingHistogramRoute,
];
diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts b/x-pack/legacy/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts
new file mode 100644
index 0000000000000..c8eb2a1e40ad4
--- /dev/null
+++ b/x-pack/legacy/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts
@@ -0,0 +1,44 @@
+/*
+ * 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 { schema } from '@kbn/config-schema';
+import { UMServerLibs } from '../../lib/lib';
+import { UMRestApiRouteFactory } from '../types';
+
+export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServerLibs) => ({
+ method: 'GET',
+ path: '/api/uptime/ping/histogram',
+ validate: {
+ query: schema.object({
+ dateStart: schema.string(),
+ dateEnd: schema.string(),
+ monitorId: schema.maybe(schema.string()),
+ statusFilter: schema.maybe(schema.string()),
+ filters: schema.maybe(schema.string()),
+ }),
+ },
+ options: {
+ tags: ['access:uptime'],
+ },
+ handler: async ({ callES }, _context, request, response): Promise => {
+ const { dateStart, dateEnd, statusFilter, monitorId, filters } = request.query;
+
+ const result = await libs.pings.getPingHistogram({
+ callES,
+ dateStart,
+ dateEnd,
+ monitorId,
+ statusFilter,
+ filters,
+ });
+
+ return response.ok({
+ body: {
+ ...result,
+ },
+ });
+ },
+});
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram.json
deleted file mode 100644
index cf88ccae9cb99..0000000000000
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram.json
+++ /dev/null
@@ -1,188 +0,0 @@
-{
- "queryResult": {
- "histogram": [
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172657286,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172680087,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172702888,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172725689,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172748490,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172771291,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 92,
- "downCount": 8,
- "x": 1568172794092,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172816893,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172839694,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172862495,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172885296,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172908097,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172930898,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172953699,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 92,
- "downCount": 8,
- "x": 1568172976500,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172999301,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173022102,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173044903,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173067704,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568173090505,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173113306,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173136107,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 92,
- "downCount": 8,
- "x": 1568173158908,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173181709,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568173204510,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173227311,
- "x0": null,
- "y": 1
- }
- ]
- }
-}
\ No newline at end of file
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_filter.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_filter.json
deleted file mode 100644
index 383d4acd96340..0000000000000
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_filter.json
+++ /dev/null
@@ -1,188 +0,0 @@
-{
- "queryResult": {
- "histogram": [
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172657286,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172680087,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172702888,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172725689,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172748490,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172771291,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 92,
- "downCount": 0,
- "x": 1568172794092,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172816893,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172839694,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172862495,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172885296,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172908097,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172930898,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568172953699,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 92,
- "downCount": 0,
- "x": 1568172976500,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172999301,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568173022102,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568173044903,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568173067704,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568173090505,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568173113306,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568173136107,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 92,
- "downCount": 0,
- "x": 1568173158908,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568173181709,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568173204510,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 0,
- "x": 1568173227311,
- "x0": null,
- "y": 1
- }
- ]
- }
-}
\ No newline at end of file
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_id.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_id.json
deleted file mode 100644
index cf88ccae9cb99..0000000000000
--- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_id.json
+++ /dev/null
@@ -1,188 +0,0 @@
-{
- "queryResult": {
- "histogram": [
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172657286,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172680087,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172702888,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172725689,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172748490,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172771291,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 92,
- "downCount": 8,
- "x": 1568172794092,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172816893,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172839694,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172862495,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172885296,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172908097,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172930898,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568172953699,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 92,
- "downCount": 8,
- "x": 1568172976500,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568172999301,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173022102,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173044903,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173067704,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568173090505,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173113306,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173136107,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 92,
- "downCount": 8,
- "x": 1568173158908,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173181709,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 0,
- "downCount": 0,
- "x": 1568173204510,
- "x0": null,
- "y": 1
- },
- {
- "upCount": 93,
- "downCount": 7,
- "x": 1568173227311,
- "x0": null,
- "y": 1
- }
- ]
- }
-}
\ No newline at end of file
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/index.js b/x-pack/test/api_integration/apis/uptime/graphql/index.js
index 64999761fde4e..54284377ec430 100644
--- a/x-pack/test/api_integration/apis/uptime/graphql/index.js
+++ b/x-pack/test/api_integration/apis/uptime/graphql/index.js
@@ -14,6 +14,5 @@ export default function({ loadTestFile }) {
loadTestFile(require.resolve('./monitor_charts'));
loadTestFile(require.resolve('./monitor_states'));
loadTestFile(require.resolve('./ping_list'));
- loadTestFile(require.resolve('./snapshot_histogram'));
});
}
diff --git a/x-pack/test/api_integration/apis/uptime/graphql/snapshot_histogram.ts b/x-pack/test/api_integration/apis/uptime/graphql/snapshot_histogram.ts
deleted file mode 100644
index 02fd3fd630d4b..0000000000000
--- a/x-pack/test/api_integration/apis/uptime/graphql/snapshot_histogram.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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 { snapshotHistogramQueryString } from '../../../../../legacy/plugins/uptime/public/queries/snapshot_histogram_query';
-import { expectFixtureEql } from './helpers/expect_fixture_eql';
-import { FtrProviderContext } from '../../../ftr_provider_context';
-import { assertCloseTo } from '../../../../../legacy/plugins/uptime/server/lib/helper';
-
-export default function({ getService }: FtrProviderContext) {
- describe('snapshotHistogram', () => {
- before('load heartbeat data', () => getService('esArchiver').load('uptime/full_heartbeat'));
- after('unload heartbeat index', () => getService('esArchiver').unload('uptime/full_heartbeat'));
-
- const supertest = getService('supertest');
-
- it('will fetch histogram data for all monitors', async () => {
- const getSnapshotHistogramQuery = {
- operationName: 'SnapshotHistogram',
- query: snapshotHistogramQueryString,
- variables: {
- dateRangeStart: '2019-09-11T03:31:04.380Z',
- dateRangeEnd: '2019-09-11T03:40:34.410Z',
- },
- };
-
- const {
- body: { data },
- } = await supertest
- .post('/api/uptime/graphql')
- .set('kbn-xsrf', 'foo')
- .send({ ...getSnapshotHistogramQuery });
- // manually testing this value and then removing it to avoid flakiness
- const { interval } = data.queryResult;
- assertCloseTo(interval, 22801, 100);
- delete data.queryResult.interval;
- expectFixtureEql(data, 'snapshot_histogram');
- });
-
- it('will fetch histogram data for a given monitor id', async () => {
- const getSnapshotHistogramQuery = {
- operationName: 'SnapshotHistogram',
- query: snapshotHistogramQueryString,
- variables: {
- dateRangeStart: '2019-09-11T03:31:04.380Z',
- dateRangeEnd: '2019-09-11T03:40:34.410Z',
- },
- };
-
- const {
- body: { data },
- } = await supertest
- .post('/api/uptime/graphql')
- .set('kbn-xsrf', 'foo')
- .send({ ...getSnapshotHistogramQuery });
- const { interval } = data.queryResult;
- assertCloseTo(interval, 22801, 100);
- delete data.queryResult.interval;
- expectFixtureEql(data, 'snapshot_histogram_by_id');
- });
-
- it('will fetch histogram data for a given filter', async () => {
- const getSnapshotHistogramQuery = {
- operationName: 'SnapshotHistogram',
- query: snapshotHistogramQueryString,
- variables: {
- dateRangeStart: '2019-09-11T03:31:04.380Z',
- dateRangeEnd: '2019-09-11T03:40:34.410Z',
- filters:
- '{"bool":{"must":[{"match":{"monitor.status":{"query":"up","operator":"and"}}}]}}',
- },
- };
-
- const {
- body: { data },
- } = await supertest
- .post('/api/uptime/graphql')
- .set('kbn-xsrf', 'foo')
- .send({ ...getSnapshotHistogramQuery });
- const { interval } = data.queryResult;
- assertCloseTo(interval, 22801, 100);
- delete data.queryResult.interval;
- expectFixtureEql(data, 'snapshot_histogram_by_filter');
- });
- });
-}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/ping_histogram.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/ping_histogram.json
new file mode 100644
index 0000000000000..972d1fd51760c
--- /dev/null
+++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/ping_histogram.json
@@ -0,0 +1,24 @@
+{
+ "histogram": [
+ { "x": 1568172664000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172694000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172724000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172754000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172784000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172814000, "downCount": 8, "upCount": 92, "y": 1 },
+ { "x": 1568172844000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172874000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172904000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172934000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172964000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568172994000, "downCount": 8, "upCount": 92, "y": 1 },
+ { "x": 1568173024000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568173054000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568173084000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568173114000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568173144000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568173174000, "downCount": 8, "upCount": 92, "y": 1 },
+ { "x": 1568173204000, "downCount": 7, "upCount": 93, "y": 1 },
+ { "x": 1568173234000, "downCount": 7, "upCount": 93, "y": 1 }
+ ]
+}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/ping_histogram_by_filter.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/ping_histogram_by_filter.json
new file mode 100644
index 0000000000000..72b2d5276e025
--- /dev/null
+++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/ping_histogram_by_filter.json
@@ -0,0 +1,24 @@
+{
+ "histogram": [
+ { "x": 1568172664000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172694000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172724000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172754000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172784000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172814000, "downCount": 0, "upCount": 92, "y": 1 },
+ { "x": 1568172844000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172874000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172904000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172934000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172964000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568172994000, "downCount": 0, "upCount": 92, "y": 1 },
+ { "x": 1568173024000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568173054000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568173084000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568173114000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568173144000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568173174000, "downCount": 0, "upCount": 92, "y": 1 },
+ { "x": 1568173204000, "downCount": 0, "upCount": 93, "y": 1 },
+ { "x": 1568173234000, "downCount": 0, "upCount": 93, "y": 1 }
+ ]
+}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/ping_histogram_by_id.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/ping_histogram_by_id.json
new file mode 100644
index 0000000000000..8e184b247ab52
--- /dev/null
+++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/ping_histogram_by_id.json
@@ -0,0 +1,24 @@
+{
+ "histogram": [
+ { "x": 1568172664000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172694000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172724000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172754000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172784000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172814000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172844000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172874000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172904000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172934000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172964000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568172994000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568173024000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568173054000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568173084000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568173114000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568173144000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568173174000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568173204000, "downCount": 0, "upCount": 1, "y": 1 },
+ { "x": 1568173234000, "downCount": 0, "upCount": 1, "y": 1 }
+ ]
+}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/index.ts b/x-pack/test/api_integration/apis/uptime/rest/index.ts
index a86411f7c49ec..30c301c5ecb17 100644
--- a/x-pack/test/api_integration/apis/uptime/rest/index.ts
+++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts
@@ -19,6 +19,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) {
after('unload', () => esArchiver.unload('uptime/full_heartbeat'));
loadTestFile(require.resolve('./monitor_latest_status'));
loadTestFile(require.resolve('./selected_monitor'));
+ loadTestFile(require.resolve('./ping_histogram'));
});
});
}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/ping_histogram.ts b/x-pack/test/api_integration/apis/uptime/rest/ping_histogram.ts
new file mode 100644
index 0000000000000..429f50ec0aa5b
--- /dev/null
+++ b/x-pack/test/api_integration/apis/uptime/rest/ping_histogram.ts
@@ -0,0 +1,64 @@
+/*
+ * 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 { expectFixtureEql } from '../graphql/helpers/expect_fixture_eql';
+import { FtrProviderContext } from '../../../ftr_provider_context';
+import { assertCloseTo } from '../../../../../legacy/plugins/uptime/server/lib/helper';
+
+export default function({ getService }: FtrProviderContext) {
+ describe('pingHistogram', () => {
+ const supertest = getService('supertest');
+
+ it('will fetch histogram data for all monitors', async () => {
+ const dateStart = '2019-09-11T03:31:04.380Z';
+ const dateEnd = '2019-09-11T03:40:34.410Z';
+
+ const apiResponse = await supertest.get(
+ `/api/uptime/ping/histogram?dateStart=${dateStart}&dateEnd=${dateEnd}`
+ );
+ const data = apiResponse.body;
+
+ // manually testing this value and then removing it to avoid flakiness
+ const { interval } = data;
+ assertCloseTo(interval, 22801, 100);
+ delete data.interval;
+ expectFixtureEql(data, 'ping_histogram');
+ });
+
+ it('will fetch histogram data for a given monitor id', async () => {
+ const dateStart = '2019-09-11T03:31:04.380Z';
+ const dateEnd = '2019-09-11T03:40:34.410Z';
+ const monitorId = '0002-up';
+
+ const apiResponse = await supertest.get(
+ `/api/uptime/ping/histogram?monitorId=${monitorId}&dateStart=${dateStart}&dateEnd=${dateEnd}`
+ );
+ const data = apiResponse.body;
+
+ const { interval } = data;
+ assertCloseTo(interval, 22801, 100);
+ delete data.interval;
+ expectFixtureEql(data, 'ping_histogram_by_id');
+ });
+
+ it('will fetch histogram data for a given filter', async () => {
+ const dateStart = '2019-09-11T03:31:04.380Z';
+ const dateEnd = '2019-09-11T03:40:34.410Z';
+ const filters =
+ '{"bool":{"must":[{"match":{"monitor.status":{"query":"up","operator":"and"}}}]}}';
+
+ const apiResponse = await supertest.get(
+ `/api/uptime/ping/histogram?dateStart=${dateStart}&dateEnd=${dateEnd}&filters=${filters}`
+ );
+ const data = apiResponse.body;
+
+ const { interval } = data;
+ assertCloseTo(interval, 22801, 100);
+ delete data.interval;
+ expectFixtureEql(data, 'ping_histogram_by_filter');
+ });
+ });
+}