diff --git a/x-pack/legacy/plugins/uptime/common/domain_types/monitors.ts b/x-pack/legacy/plugins/uptime/common/domain_types/monitors.ts index 296df279b8eec..7f5699eb7e8a4 100644 --- a/x-pack/legacy/plugins/uptime/common/domain_types/monitors.ts +++ b/x-pack/legacy/plugins/uptime/common/domain_types/monitors.ts @@ -4,14 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HistogramDataPoint } from '../graphql/types'; - export interface UMGqlRange { dateRangeStart: string; dateRangeEnd: string; } - -export interface HistogramResult { - histogram: HistogramDataPoint[]; - interval: number; -} diff --git a/x-pack/legacy/plugins/uptime/common/graphql/introspection.json b/x-pack/legacy/plugins/uptime/common/graphql/introspection.json index 19d9cf19cc7f8..e5d9816ebd28e 100644 --- a/x-pack/legacy/plugins/uptime/common/graphql/introspection.json +++ b/x-pack/legacy/plugins/uptime/common/graphql/introspection.json @@ -166,65 +166,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "getSnapshotHistogram", - "description": "", - "args": [ - { - "name": "dateRangeStart", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "dateRangeEnd", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filters", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "statusFilter", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "monitorId", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HistogramDataPoint", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "getMonitorChartsData", "description": "", @@ -2172,57 +2113,6 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "OBJECT", - "name": "HistogramDataPoint", - "description": "", - "fields": [ - { - "name": "upCount", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Int", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "downCount", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Int", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "x", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "UnsignedInteger", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "x0", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "UnsignedInteger", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "y", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "UnsignedInteger", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, { "kind": "OBJECT", "name": "MonitorChart", @@ -3944,33 +3834,6 @@ ], "possibleTypes": null }, - { - "kind": "OBJECT", - "name": "DataPoint", - "description": "", - "fields": [ - { - "name": "x", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "UnsignedInteger", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "y", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, { "kind": "OBJECT", "name": "MonitorDurationAreaPoint", diff --git a/x-pack/legacy/plugins/uptime/common/graphql/types.ts b/x-pack/legacy/plugins/uptime/common/graphql/types.ts index 92e27d20323a7..c58dd9111cc3f 100644 --- a/x-pack/legacy/plugins/uptime/common/graphql/types.ts +++ b/x-pack/legacy/plugins/uptime/common/graphql/types.ts @@ -24,8 +24,6 @@ export interface Query { getSnapshot?: Snapshot | null; - getSnapshotHistogram: HistogramDataPoint[]; - getMonitorChartsData?: MonitorChart | null; /** Fetch the most recent event data for a monitor ID, date range, location. */ getLatestMonitors: Ping[]; @@ -419,17 +417,7 @@ export interface SnapshotCount { total: number; } -export interface HistogramDataPoint { - upCount?: number | null; - - downCount?: number | null; - - x?: UnsignedInteger | null; - - x0?: UnsignedInteger | null; - y?: UnsignedInteger | null; -} /** The data used to populate the monitor charts. */ export interface MonitorChart { /** The average values for the monitor duration. */ @@ -616,47 +604,6 @@ export interface StatesIndexStatus { docCount?: DocCount | null; } -export interface DataPoint { - x?: UnsignedInteger | null; - - y?: number | null; -} -/** Represents a monitor's duration performance in microseconds at a point in time. */ -export interface MonitorDurationAreaPoint { - /** The timeseries value for this point in time. */ - x: UnsignedInteger; - /** The min duration value in microseconds at this time. */ - yMin?: number | null; - /** The max duration value in microseconds at this point. */ - yMax?: number | null; -} - -export interface MonitorSummaryUrl { - domain?: string | null; - - fragment?: string | null; - - full?: string | null; - - original?: string | null; - - password?: string | null; - - path?: string | null; - - port?: number | null; - - query?: string | null; - - scheme?: string | null; - - username?: string | null; -} - -// ==================================================== -// Arguments -// ==================================================== - export interface AllPingsQueryArgs { /** Optional: the direction to sort by. Accepts 'asc' and 'desc'. Defaults to 'desc'. */ sort?: string | null; @@ -673,35 +620,7 @@ export interface AllPingsQueryArgs { /** Optional: agent location to filter by. */ location?: string | null; } -export interface GetMonitorsQueryArgs { - dateRangeStart: string; - - dateRangeEnd: string; - - filters?: string | null; - - statusFilter?: string | null; -} -export interface GetSnapshotQueryArgs { - dateRangeStart: string; - - dateRangeEnd: string; - - filters?: string | null; - statusFilter?: string | null; -} -export interface GetSnapshotHistogramQueryArgs { - dateRangeStart: string; - - dateRangeEnd: string; - - filters?: string | null; - - statusFilter?: string | null; - - monitorId?: string | null; -} export interface GetMonitorChartsDataQueryArgs { monitorId: string; @@ -711,11 +630,6 @@ export interface GetMonitorChartsDataQueryArgs { location?: string | null; } -export interface GetFilterBarQueryArgs { - dateRangeStart: string; - - dateRangeEnd: string; -} export interface GetMonitorStatesQueryArgs { dateRangeStart: string; diff --git a/x-pack/legacy/plugins/uptime/common/types/index.ts b/x-pack/legacy/plugins/uptime/common/types/index.ts new file mode 100644 index 0000000000000..34bfbc540672f --- /dev/null +++ b/x-pack/legacy/plugins/uptime/common/types/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export * from './ping/histogram'; diff --git a/x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts b/x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts new file mode 100644 index 0000000000000..7ac8d1f7b0151 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts @@ -0,0 +1,32 @@ +/* + * 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. + */ + +export type UnsignedInteger = any; + +export interface HistogramDataPoint { + upCount?: number | null; + + downCount?: number | null; + + x?: UnsignedInteger | null; + + x0?: UnsignedInteger | null; + + y?: UnsignedInteger | null; +} + +export interface GetPingHistogramParams { + dateStart: string; + dateEnd: string; + filters?: string; + monitorId?: string; + statusFilter?: string; +} + +export interface HistogramResult { + histogram: HistogramDataPoint[]; + interval: string; +} diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx new file mode 100644 index 0000000000000..a6607ca81fc18 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx @@ -0,0 +1,76 @@ +/* + * 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 React, { useEffect } from 'react'; +import { connect } from 'react-redux'; +import { AppState } from '../../../state'; +import { + PingHistogramComponent, + PingHistogramComponentProps, +} from '../../functional/charts/ping_histogram'; +import { getPingHistogram } from '../../../state/actions'; +import { selectPingHistogram } from '../../../state/selectors'; +import { withResponsiveWrapper, ResponsiveWrapperProps } from '../../higher_order'; +import { GetPingHistogramParams, HistogramResult } from '../../../../common/types'; + +type Props = GetPingHistogramParams & + ResponsiveWrapperProps & + PingHistogramComponentProps & + DispatchProps & { lastRefresh: number }; + +const PingHistogramContainer: React.FC = ({ + data, + loadData, + statusFilter, + filters, + dateStart, + dateEnd, + absoluteStartDate, + absoluteEndDate, + monitorId, + lastRefresh, + ...props +}) => { + useEffect(() => { + loadData({ monitorId, dateStart, dateEnd, statusFilter, filters }); + }, [loadData, dateStart, dateEnd, monitorId, filters, statusFilter, lastRefresh]); + return ( + + ); +}; + +interface StateProps { + data: HistogramResult | null; + loading: boolean; + lastRefresh: number; +} + +interface DispatchProps { + loadData: typeof getPingHistogram; +} + +const mapStateToProps = (state: AppState): StateProps => ({ ...selectPingHistogram(state) }); + +const mapDispatchToProps = (dispatch: any): DispatchProps => ({ + loadData: (params: GetPingHistogramParams) => { + return dispatch(getPingHistogram(params)); + }, +}); + +export const PingHistogram = connect< + StateProps, + DispatchProps, + PingHistogramComponentProps, + AppState +>( + mapStateToProps, + mapDispatchToProps +)(withResponsiveWrapper(PingHistogramContainer)); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/index.ts b/x-pack/legacy/plugins/uptime/public/components/connected/index.ts new file mode 100644 index 0000000000000..f9f6aa263ed27 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/connected/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { PingHistogram } from './charts/ping_histogram'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/chart_wrapper.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/chart_wrapper.test.tsx.snap index 3f3e6b0b929e1..c1b5970f6456c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/chart_wrapper.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/chart_wrapper.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ChartWrapper component renders the component with loading false 1`] = ` - +
-
+ `; exports[`ChartWrapper component renders the component with loading true 1`] = ` - +
- + `; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/ping_histogram.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/ping_histogram.test.tsx.snap new file mode 100644 index 0000000000000..8ee4dc3575469 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/ping_histogram.test.tsx.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PingHistogram component renders the component without errors 1`] = ` + + +
+ +
+
+ + + +

+ } + title={ + +
+ +
+
+ } + /> +
+
+`; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/snapshot_histogram.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/snapshot_histogram.test.tsx.snap deleted file mode 100644 index a725f97d3e0fb..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/snapshot_histogram.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SnapshotHistogram component renders the component without errors 1`] = ` - - - -`; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/snapshot_histogram.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/ping_histogram.test.tsx similarity index 64% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/snapshot_histogram.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/ping_histogram.test.tsx index db78c063b7ed5..de7cfc86abc0c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/snapshot_histogram.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/ping_histogram.test.tsx @@ -6,17 +6,16 @@ import React from 'react'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { SnapshotHistogram, SnapshotHistogramProps } from '../snapshot_histogram'; +import { PingHistogramComponent, PingHistogramComponentProps } from '../ping_histogram'; -describe('SnapshotHistogram component', () => { - const props: SnapshotHistogramProps = { +describe('PingHistogram component', () => { + const props: PingHistogramComponentProps = { absoluteStartDate: 1548697920000, absoluteEndDate: 1548700920000, - isResponsive: false, }; it('renders the component without errors', () => { - const component = shallowWithIntl(); + const component = shallowWithIntl(); expect(component).toMatchSnapshot(); }); }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_wrapper/chart_wrapper.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_wrapper/chart_wrapper.tsx index deeb1411052c3..7286c59956887 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_wrapper/chart_wrapper.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_wrapper/chart_wrapper.tsx @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC, Fragment, HTMLAttributes } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiLoadingChart } from '@elastic/eui'; +import React, { FC, HTMLAttributes } from 'react'; +import { EuiErrorBoundary, EuiFlexGroup, EuiFlexItem, EuiLoadingChart } from '@elastic/eui'; interface Props { /** @@ -31,7 +31,7 @@ export const ChartWrapper: FC = ({ const opacity = loading === true ? 0.3 : 1; return ( - +
= ({ )} - + ); }; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/index.ts b/x-pack/legacy/plugins/uptime/public/components/functional/charts/index.ts index f7c1283dc9e07..2cbd9a2b3aa32 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/index.ts @@ -7,4 +7,4 @@ export { DonutChart } from './donut_chart'; export { DurationChart } from './duration_chart'; export { MonitorBarSeries } from './monitor_bar_series'; -export { SnapshotHistogram } from './snapshot_histogram'; +export { PingHistogramComponent } from './ping_histogram'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/snapshot_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx similarity index 76% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/snapshot_histogram.tsx rename to x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx index 92b04534b7331..2d44cff0108cd 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/snapshot_histogram.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx @@ -4,21 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Axis, BarSeries, Chart, Position, timeFormatter, Settings } from '@elastic/charts'; -import { EuiEmptyPrompt, EuiTitle, EuiPanel } from '@elastic/eui'; +import { Axis, BarSeries, Chart, Position, Settings, timeFormatter } from '@elastic/charts'; +import { EuiEmptyPrompt, EuiPanel, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useContext } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import moment from 'moment'; import { getChartDateLabel } from '../../../lib/helper'; -import { withUptimeGraphQL, UptimeGraphQLQueryProps } from '../../higher_order'; -import { snapshotHistogramQuery } from '../../../queries/snapshot_histogram_query'; import { ChartWrapper } from './chart_wrapper'; import { UptimeThemeContext } from '../../../contexts'; -import { ResponsiveWrapperProps, withResponsiveWrapper } from '../../higher_order'; -import { HistogramResult } from '../../../../common/domain_types'; +import { HistogramResult } from '../../../../common/types'; -interface HistogramProps { +export interface PingHistogramComponentProps { /** * The date/time for the start of the timespan. */ @@ -32,29 +29,23 @@ interface HistogramProps { * Height is needed, since by default charts takes height of 100% */ height?: string; -} -export type SnapshotHistogramProps = HistogramProps & ResponsiveWrapperProps; + data?: HistogramResult; -interface SnapshotHistogramQueryResult { - queryResult?: HistogramResult; + loading?: boolean; } -type Props = UptimeGraphQLQueryProps & - SnapshotHistogramProps & - ResponsiveWrapperProps; - -export const SnapshotHistogramComponent: React.FC = ({ +export const PingHistogramComponent: React.FC = ({ absoluteStartDate, absoluteEndDate, data, loading = false, height, -}: Props) => { +}) => { const { colors: { danger, gray }, } = useContext(UptimeThemeContext); - if (!data || !data.queryResult) + if (!data || !data.histogram) /** * TODO: the Fragment, EuiTitle, and EuiPanel should be extracted to a dumb component * that we can reuse in the subsequent return statement at the bottom of this function. @@ -93,19 +84,15 @@ export const SnapshotHistogramComponent: React.FC = ({ ); - const { - queryResult: { histogram, interval }, - } = data; + const { histogram } = data; - const downMonitorsId = i18n.translate('xpack.uptime.snapshotHistogram.downMonitorsId', { + const downSpecId = i18n.translate('xpack.uptime.snapshotHistogram.downMonitorsId', { defaultMessage: 'Down Monitors', }); - const downSpecId = downMonitorsId; const upMonitorsId = i18n.translate('xpack.uptime.snapshotHistogram.series.upLabel', { defaultMessage: 'Up', }); - const upSpecId = upMonitorsId; return ( <> @@ -131,7 +118,6 @@ export const SnapshotHistogramComponent: React.FC = ({ = ({ /> = ({ /> = ({ [x, upCount || 0])} - id={upSpecId} + id={upMonitorsId} name={upMonitorsId} stackAccessors={[0]} timeZone="local" @@ -187,8 +173,3 @@ export const SnapshotHistogramComponent: React.FC = ({ ); }; - -export const SnapshotHistogram = withUptimeGraphQL< - SnapshotHistogramQueryResult, - SnapshotHistogramProps ->(withResponsiveWrapper(SnapshotHistogramComponent), snapshotHistogramQuery); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/index.ts b/x-pack/legacy/plugins/uptime/public/components/functional/index.ts index 7370faa12f393..b9f0014322062 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/functional/index.ts @@ -15,5 +15,5 @@ export { MonitorList } from './monitor_list'; export { OverviewPageParsingErrorCallout } from './overview_page_parsing_error_callout'; export { PingList } from './ping_list'; export { Snapshot } from './snapshot'; -export { SnapshotHistogram } from './charts'; +export { PingHistogramComponent } from './charts'; export { StatusPanel } from './status_panel'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx index 809618f07a6c1..ae99d08ab634e 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx @@ -11,8 +11,8 @@ import { MonitorChart } from '../../../common/graphql/types'; import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../higher_order'; import { monitorChartsQuery } from '../../queries'; import { DurationChart } from './charts'; -import { SnapshotHistogram } from './charts/snapshot_histogram'; import { useUrlParams } from '../../hooks'; +import { PingHistogram } from '../connected'; interface MonitorChartsQueryResult { monitorChartsData?: MonitorChart; @@ -58,12 +58,14 @@ export const MonitorChartsComponent = ({ /> - diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/status_panel.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/status_panel.tsx index b74bc943dc3eb..03ab9fb5cf194 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/status_panel.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/status_panel.tsx @@ -6,8 +6,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; import React from 'react'; -import { SnapshotHistogram } from './charts'; import { Snapshot } from './snapshot'; +import { PingHistogram } from '../connected'; interface StatusPanelProps { absoluteDateRangeStart: number; @@ -16,7 +16,6 @@ interface StatusPanelProps { dateRangeEnd: string; filters?: string; statusFilter?: string; - sharedProps: { [key: string]: any }; } const STATUS_CHART_HEIGHT = '160px'; @@ -28,7 +27,6 @@ export const StatusPanel = ({ dateRangeEnd, filters, statusFilter, - sharedProps, }: StatusPanelProps) => ( @@ -42,12 +40,15 @@ export const StatusPanel = ({ /> - diff --git a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx index 36abee673b682..b9c2284edb0cf 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx @@ -135,7 +135,6 @@ export const OverviewPage = ({ autocomplete, setBreadcrumbs }: Props) => { dateRangeEnd={dateRangeEnd} filters={filters} statusFilter={statusFilter} - sharedProps={sharedProps} /> ('GET_PING_HISTOGRAM'); +export const getPingHistogramSuccess = createAction('GET_PING_HISTOGRAM_SUCCESS'); +export const getPingHistogramFail = createAction('GET_PING_HISTOGRAM_FAIL'); diff --git a/x-pack/legacy/plugins/uptime/public/state/api/index.ts b/x-pack/legacy/plugins/uptime/public/state/api/index.ts index 1d0cac5f87854..be79317dc97c2 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/index.ts @@ -8,3 +8,4 @@ export * from './monitor'; export * from './overview_filters'; export * from './snapshot'; export * from './monitor_status'; +export * from './ping'; diff --git a/x-pack/legacy/plugins/uptime/public/state/api/monitor.ts b/x-pack/legacy/plugins/uptime/public/state/api/monitor.ts index 8b1220830f091..80fd311c3ec7e 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/monitor.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/monitor.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ThrowReporter } from 'io-ts/lib/ThrowReporter'; +import { PathReporter } from 'io-ts/lib/PathReporter'; import { getApiPath } from '../../lib/helper'; import { BaseParams } from './types'; import { @@ -41,7 +41,7 @@ export const fetchMonitorDetails = async ({ throw new Error(response.statusText); } return response.json().then(data => { - ThrowReporter.report(MonitorDetailsType.decode(data)); + PathReporter.report(MonitorDetailsType.decode(data)); return data; }); }; @@ -68,7 +68,7 @@ export const fetchMonitorLocations = async ({ throw new Error(response.statusText); } return response.json().then(data => { - ThrowReporter.report(MonitorLocationsType.decode(data)); + PathReporter.report(MonitorLocationsType.decode(data)); return data; }); }; diff --git a/x-pack/legacy/plugins/uptime/public/state/api/ping.ts b/x-pack/legacy/plugins/uptime/public/state/api/ping.ts new file mode 100644 index 0000000000000..e0c358fe40e71 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/api/ping.ts @@ -0,0 +1,35 @@ +/* + * 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 qs from 'querystring'; +import { getApiPath } from '../../lib/helper'; +import { APIFn } from './types'; +import { GetPingHistogramParams, HistogramResult } from '../../../common/types'; + +export const fetchPingHistogram: APIFn = 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'); + }); + }); +}