mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* update ping histogram API * update test * fix tests * update test * unused code Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
7da3097d89
commit
63e6c81b85
53 changed files with 646 additions and 1182 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
7
x-pack/legacy/plugins/uptime/common/types/index.ts
Normal file
7
x-pack/legacy/plugins/uptime/common/types/index.ts
Normal file
|
@ -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';
|
32
x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts
Normal file
32
x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts
Normal file
|
@ -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;
|
||||
}
|
|
@ -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<Props> = ({
|
||||
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 (
|
||||
<PingHistogramComponent
|
||||
data={data}
|
||||
absoluteStartDate={absoluteStartDate}
|
||||
absoluteEndDate={absoluteEndDate}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
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));
|
|
@ -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';
|
|
@ -1,7 +1,7 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ChartWrapper component renders the component with loading false 1`] = `
|
||||
<Fragment>
|
||||
<EuiErrorBoundary>
|
||||
<div
|
||||
intl={
|
||||
Object {
|
||||
|
@ -127,11 +127,11 @@ exports[`ChartWrapper component renders the component with loading false 1`] = `
|
|||
width={144}
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
</EuiErrorBoundary>
|
||||
`;
|
||||
|
||||
exports[`ChartWrapper component renders the component with loading true 1`] = `
|
||||
<Fragment>
|
||||
<EuiErrorBoundary>
|
||||
<div
|
||||
intl={
|
||||
Object {
|
||||
|
@ -276,5 +276,5 @@ exports[`ChartWrapper component renders the component with loading true 1`] = `
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</Fragment>
|
||||
</EuiErrorBoundary>
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PingHistogram component renders the component without errors 1`] = `
|
||||
<Fragment>
|
||||
<EuiTitle
|
||||
size="xs"
|
||||
>
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
defaultMessage="Pings over time"
|
||||
id="xpack.uptime.snapshot.pingsOverTimeTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
<EuiPanel
|
||||
paddingSize="s"
|
||||
style={
|
||||
Object {
|
||||
"height": 170,
|
||||
}
|
||||
}
|
||||
>
|
||||
<EuiEmptyPrompt
|
||||
body={
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Sorry, there is no data available for the histogram"
|
||||
id="xpack.uptime.snapshot.noDataDescription"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
}
|
||||
title={
|
||||
<EuiTitle>
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
defaultMessage="No histogram data available"
|
||||
id="xpack.uptime.snapshot.noDataTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
}
|
||||
/>
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
`;
|
|
@ -1,7 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SnapshotHistogram component renders the component without errors 1`] = `
|
||||
<ApolloConsumer>
|
||||
<Component />
|
||||
</ApolloConsumer>
|
||||
`;
|
|
@ -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(<SnapshotHistogram {...props} variables={{}} />);
|
||||
const component = shallowWithIntl(<PingHistogramComponent {...props} />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -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<Props> = ({
|
|||
const opacity = loading === true ? 0.3 : 1;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiErrorBoundary>
|
||||
<div
|
||||
style={{
|
||||
height,
|
||||
|
@ -53,6 +53,6 @@ export const ChartWrapper: FC<Props> = ({
|
|||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
)}
|
||||
</Fragment>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
|
||||
data?: HistogramResult;
|
||||
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
export type SnapshotHistogramProps = HistogramProps & ResponsiveWrapperProps;
|
||||
|
||||
interface SnapshotHistogramQueryResult {
|
||||
queryResult?: HistogramResult;
|
||||
}
|
||||
|
||||
type Props = UptimeGraphQLQueryProps<SnapshotHistogramQueryResult> &
|
||||
SnapshotHistogramProps &
|
||||
ResponsiveWrapperProps;
|
||||
|
||||
export const SnapshotHistogramComponent: React.FC<Props> = ({
|
||||
export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
|
||||
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<Props> = ({
|
|||
</EuiPanel>
|
||||
</>
|
||||
);
|
||||
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 (
|
||||
<>
|
||||
<EuiTitle size="xs">
|
||||
|
@ -131,7 +118,6 @@ export const SnapshotHistogramComponent: React.FC<Props> = ({
|
|||
<Chart>
|
||||
<Settings
|
||||
xDomain={{
|
||||
minInterval: interval,
|
||||
min: absoluteStartDate,
|
||||
max: absoluteEndDate,
|
||||
}}
|
||||
|
@ -139,7 +125,7 @@ export const SnapshotHistogramComponent: React.FC<Props> = ({
|
|||
/>
|
||||
<Axis
|
||||
id={i18n.translate('xpack.uptime.snapshotHistogram.xAxisId', {
|
||||
defaultMessage: 'Snapshot X Axis',
|
||||
defaultMessage: 'Ping X Axis',
|
||||
})}
|
||||
position={Position.Bottom}
|
||||
showOverlappingTicks={false}
|
||||
|
@ -147,7 +133,7 @@ export const SnapshotHistogramComponent: React.FC<Props> = ({
|
|||
/>
|
||||
<Axis
|
||||
id={i18n.translate('xpack.uptime.snapshotHistogram.yAxisId', {
|
||||
defaultMessage: 'Snapshot Y Axis',
|
||||
defaultMessage: 'Ping Y Axis',
|
||||
})}
|
||||
position="left"
|
||||
title={i18n.translate('xpack.uptime.snapshotHistogram.yAxis.title', {
|
||||
|
@ -173,7 +159,7 @@ export const SnapshotHistogramComponent: React.FC<Props> = ({
|
|||
<BarSeries
|
||||
customSeriesColors={[gray]}
|
||||
data={histogram.map(({ x, upCount }) => [x, upCount || 0])}
|
||||
id={upSpecId}
|
||||
id={upMonitorsId}
|
||||
name={upMonitorsId}
|
||||
stackAccessors={[0]}
|
||||
timeZone="local"
|
||||
|
@ -187,8 +173,3 @@ export const SnapshotHistogramComponent: React.FC<Props> = ({
|
|||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const SnapshotHistogram = withUptimeGraphQL<
|
||||
SnapshotHistogramQueryResult,
|
||||
SnapshotHistogramProps
|
||||
>(withResponsiveWrapper<Props>(SnapshotHistogramComponent), snapshotHistogramQuery);
|
|
@ -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';
|
||||
|
|
|
@ -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 = ({
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<SnapshotHistogram
|
||||
<PingHistogram
|
||||
absoluteStartDate={absoluteDateRangeStart}
|
||||
absoluteEndDate={absoluteDateRangeEnd}
|
||||
height="400px"
|
||||
isResponsive={false}
|
||||
variables={{ dateRangeStart, dateRangeEnd, monitorId }}
|
||||
dateStart={dateRangeStart}
|
||||
dateEnd={dateRangeEnd}
|
||||
monitorId={monitorId}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -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) => (
|
||||
<EuiPanel>
|
||||
<EuiFlexGroup gutterSize="l">
|
||||
|
@ -42,12 +40,15 @@ export const StatusPanel = ({
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={10}>
|
||||
<SnapshotHistogram
|
||||
<PingHistogram
|
||||
absoluteStartDate={absoluteDateRangeStart}
|
||||
absoluteEndDate={absoluteDateRangeEnd}
|
||||
dateStart={dateRangeStart}
|
||||
dateEnd={dateRangeEnd}
|
||||
filters={filters}
|
||||
height={STATUS_CHART_HEIGHT}
|
||||
statusFilter={statusFilter}
|
||||
isResponsive={true}
|
||||
variables={sharedProps}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -135,7 +135,6 @@ export const OverviewPage = ({ autocomplete, setBreadcrumbs }: Props) => {
|
|||
dateRangeEnd={dateRangeEnd}
|
||||
filters={filters}
|
||||
statusFilter={statusFilter}
|
||||
sharedProps={sharedProps}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
<MonitorList
|
||||
|
|
|
@ -1,38 +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 gql from 'graphql-tag';
|
||||
|
||||
export const snapshotHistogramQueryString = `
|
||||
query SnapshotHistogram(
|
||||
$dateRangeStart: String!
|
||||
$dateRangeEnd: String!
|
||||
$filters: String
|
||||
$monitorId: String
|
||||
$statusFilter: String
|
||||
) {
|
||||
queryResult: getSnapshotHistogram(
|
||||
dateRangeStart: $dateRangeStart
|
||||
dateRangeEnd: $dateRangeEnd
|
||||
filters: $filters
|
||||
statusFilter: $statusFilter
|
||||
monitorId: $monitorId
|
||||
) {
|
||||
histogram {
|
||||
upCount
|
||||
downCount
|
||||
x
|
||||
x0
|
||||
y
|
||||
}
|
||||
interval
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const snapshotHistogramQuery = gql`
|
||||
${snapshotHistogramQueryString}
|
||||
`;
|
|
@ -8,3 +8,4 @@ export * from './overview_filters';
|
|||
export * from './snapshot';
|
||||
export * from './ui';
|
||||
export * from './monitor_status';
|
||||
export * from './ping';
|
||||
|
|
12
x-pack/legacy/plugins/uptime/public/state/actions/ping.ts
Normal file
12
x-pack/legacy/plugins/uptime/public/state/actions/ping.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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 { createAction } from 'redux-actions';
|
||||
import { GetPingHistogramParams, HistogramResult } from '../../../common/types';
|
||||
|
||||
export const getPingHistogram = createAction<GetPingHistogramParams>('GET_PING_HISTOGRAM');
|
||||
export const getPingHistogramSuccess = createAction<HistogramResult>('GET_PING_HISTOGRAM_SUCCESS');
|
||||
export const getPingHistogramFail = createAction<Error>('GET_PING_HISTOGRAM_FAIL');
|
|
@ -8,3 +8,4 @@ export * from './monitor';
|
|||
export * from './overview_filters';
|
||||
export * from './snapshot';
|
||||
export * from './monitor_status';
|
||||
export * from './ping';
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
};
|
||||
|
|
35
x-pack/legacy/plugins/uptime/public/state/api/ping.ts
Normal file
35
x-pack/legacy/plugins/uptime/public/state/api/ping.ts
Normal file
|
@ -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<GetPingHistogramParams, HistogramResult> = 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;
|
||||
};
|
|
@ -12,3 +12,5 @@ export interface BaseParams {
|
|||
statusFilter?: string;
|
||||
location?: string;
|
||||
}
|
||||
|
||||
export type APIFn<P, R = any> = (params: { basePath: string } & P) => Promise<R>;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
17
x-pack/legacy/plugins/uptime/public/state/effects/ping.ts
Normal file
17
x-pack/legacy/plugins/uptime/public/state/effects/ping.ts
Normal file
|
@ -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)
|
||||
);
|
||||
}
|
|
@ -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,
|
||||
});
|
||||
|
|
45
x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts
Normal file
45
x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts
Normal file
|
@ -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<PingState, MonitorStatusPayload>(
|
||||
{
|
||||
[String(getPingHistogram)]: state => ({
|
||||
...state,
|
||||
loading: true,
|
||||
}),
|
||||
|
||||
[String(getPingHistogramSuccess)]: (state: PingState, action: Action<HistogramResult>) => ({
|
||||
...state,
|
||||
loading: false,
|
||||
pingHistogram: { ...action.payload },
|
||||
}),
|
||||
|
||||
[String(getPingHistogramFail)]: (state, action: Action<Error>) => ({
|
||||
...state,
|
||||
errors: [...state.errors, action.payload],
|
||||
loading: false,
|
||||
}),
|
||||
},
|
||||
initialState
|
||||
);
|
|
@ -45,6 +45,11 @@ describe('state selectors', () => {
|
|||
monitor: null,
|
||||
loading: false,
|
||||
},
|
||||
ping: {
|
||||
pingHistogram: null,
|
||||
loading: false,
|
||||
errors: [],
|
||||
},
|
||||
};
|
||||
|
||||
it('selects base path from state', () => {
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
@ -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 | Promise<any>, any, UMGqlRange, UMContext>;
|
||||
|
||||
export type UMGetMonitorChartsResolver = UMResolver<
|
||||
any | Promise<any>,
|
||||
|
@ -25,49 +16,20 @@ export type UMGetMonitorChartsResolver = UMResolver<
|
|||
UMContext
|
||||
>;
|
||||
|
||||
export type UMGetFilterBarResolver = UMResolver<
|
||||
any | Promise<any>,
|
||||
any,
|
||||
GetFilterBarQueryArgs,
|
||||
UMContext
|
||||
>;
|
||||
|
||||
export type UMGetSnapshotHistogram = UMResolver<
|
||||
HistogramResult | Promise<HistogramResult>,
|
||||
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<HistogramResult> {
|
||||
return await libs.pings.getPingHistogram({
|
||||
callES: APICaller,
|
||||
dateRangeStart,
|
||||
dateRangeEnd,
|
||||
filters,
|
||||
monitorId,
|
||||
statusFilter,
|
||||
});
|
||||
},
|
||||
async getMonitorChartsData(
|
||||
_resolver,
|
||||
{ monitorId, dateRangeStart, dateRangeEnd, location },
|
||||
{ APICaller }
|
||||
): Promise<MonitorChart> {
|
||||
return await libs.monitors.getMonitorChartsData({
|
||||
return libs.monitors.getMonitorChartsData({
|
||||
callES: APICaller,
|
||||
monitorId,
|
||||
dateRangeStart,
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
};
|
|
@ -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 });
|
|
@ -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';
|
||||
|
|
|
@ -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
|
||||
*/
|
|
@ -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}]`);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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,
|
||||
];
|
||||
|
|
|
@ -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<any> => {
|
||||
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,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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 }
|
||||
]
|
||||
}
|
|
@ -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 }
|
||||
]
|
||||
}
|
|
@ -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 }
|
||||
]
|
||||
}
|
|
@ -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'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue