From e3eed0baed5f9fd3d396d8f9108f4aece01a1f3f Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Thu, 16 Apr 2020 21:21:12 -0400 Subject: [PATCH 01/22] [Ingest] Fix agent config key sorting (#63488) --- .../details_page/components/yaml/index.tsx | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/yaml/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/yaml/index.tsx index c1cdde730837f..56b109a9bc062 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/yaml/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/yaml/index.tsx @@ -25,7 +25,15 @@ import { import { ShellEnrollmentInstructions } from '../../../../../components/enrollment_instructions'; import { Loading } from '../../../../../components'; -const CONFIG_KEYS_ORDER = ['id', 'revision', 'outputs', 'datasources']; +const CONFIG_KEYS_ORDER = [ + 'id', + 'revision', + 'outputs', + 'datasources', + 'enabled', + 'package', + 'input', +]; export const ConfigYamlView = memo<{ config: AgentConfig }>(({ config }) => { const core = useCore(); @@ -47,7 +55,17 @@ export const ConfigYamlView = memo<{ config: AgentConfig }>(({ config }) => { {dump(fullConfigRequest.data.item, { sortKeys: (keyA: string, keyB: string) => { - return CONFIG_KEYS_ORDER.indexOf(keyA) - CONFIG_KEYS_ORDER.indexOf(keyB); + const indexA = CONFIG_KEYS_ORDER.indexOf(keyA); + const indexB = CONFIG_KEYS_ORDER.indexOf(keyB); + if (indexA >= 0 && indexB < 0) { + return -1; + } + + if (indexA < 0 && indexB >= 0) { + return 1; + } + + return indexA - indexB; }, })} From 420ccffcd63f8f46073cf454592f6ce1b3aba653 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 16 Apr 2020 19:22:02 -0600 Subject: [PATCH 02/22] [Maps] fix term join agg key collision (#63324) * [Maps] fix term join agg key collision * fix tslint and jest errors * fix join functional test * revert LayerDescriptor union and cast to VectorLayerDescriptor instead * move getJoinKey out of constants and into its own file Co-authored-by: Elastic Machine --- .../plugins/maps/common/get_join_key.ts | 8 + .../common/migrations/join_agg_key.test.ts | 140 ++++++++++++++++++ .../maps/common/migrations/join_agg_key.ts | 121 +++++++++++++++ x-pack/legacy/plugins/maps/migrations.js | 9 ++ x-pack/plugins/maps/common/constants.ts | 8 +- x-pack/plugins/maps/common/get_join_key.ts | 22 +++ .../public/layers/joins/inner_join.test.js | 2 +- .../sources/es_agg_source/es_agg_source.js | 4 +- .../sources/es_term_source/es_term_source.js | 17 +-- .../es_term_source/es_term_source.test.js | 15 +- .../api_integration/apis/maps/migrations.js | 2 +- x-pack/test/functional/apps/maps/joins.js | 2 +- .../functional/apps/maps/mapbox_styles.js | 8 +- 13 files changed, 325 insertions(+), 33 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/common/get_join_key.ts create mode 100644 x-pack/legacy/plugins/maps/common/migrations/join_agg_key.test.ts create mode 100644 x-pack/legacy/plugins/maps/common/migrations/join_agg_key.ts create mode 100644 x-pack/plugins/maps/common/get_join_key.ts diff --git a/x-pack/legacy/plugins/maps/common/get_join_key.ts b/x-pack/legacy/plugins/maps/common/get_join_key.ts new file mode 100644 index 0000000000000..004f12ca08d2e --- /dev/null +++ b/x-pack/legacy/plugins/maps/common/get_join_key.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export * from '../../../../plugins/maps/common/get_join_key'; diff --git a/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.test.ts b/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.test.ts new file mode 100644 index 0000000000000..d92bf06541433 --- /dev/null +++ b/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.test.ts @@ -0,0 +1,140 @@ +/* + * 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 { LAYER_TYPE } from '../constants'; +import { migrateJoinAggKey } from './join_agg_key'; + +describe('migrateJoinAggKey', () => { + const joins = [ + { + leftField: 'machine.os', + right: { + id: '9055b4aa-136a-4b6d-90ab-9f94ccfe5eb5', + indexPatternTitle: 'kibana_sample_data_logs', + term: 'machine.os.keyword', + metrics: [ + { + type: 'avg', + field: 'bytes', + }, + { + type: 'count', + }, + ], + whereQuery: { + query: 'bytes > 10000', + language: 'kuery', + }, + indexPatternRefName: 'layer_1_join_0_index_pattern', + }, + }, + { + leftField: 'machine.os', + right: { + id: '9a7f4e71-9500-4512-82f1-b7eaee3d87ff', + indexPatternTitle: 'kibana_sample_data_logs', + term: 'machine.os.keyword', + whereQuery: { + query: 'bytes < 10000', + language: 'kuery', + }, + metrics: [ + { + type: 'avg', + field: 'bytes', + }, + ], + indexPatternRefName: 'layer_1_join_1_index_pattern', + }, + }, + ]; + + test('Should handle missing layerListJSON attribute', () => { + const attributes = { + title: 'my map', + }; + expect(migrateJoinAggKey({ attributes })).toEqual({ + title: 'my map', + }); + }); + + test('Should migrate vector styles from legacy join agg key to new join agg key', () => { + const layerListJSON = JSON.stringify([ + { + type: LAYER_TYPE.VECTOR, + joins, + style: { + properties: { + fillColor: { + type: 'DYNAMIC', + options: { + color: 'Blues', + colorCategory: 'palette_0', + field: { + name: + '__kbnjoin__avg_of_bytes_groupby_kibana_sample_data_logs.machine.os.keyword', + origin: 'join', + }, + fieldMetaOptions: { + isEnabled: true, + sigma: 3, + }, + type: 'ORDINAL', + }, + }, + lineColor: { + type: 'DYNAMIC', + options: { + color: 'Blues', + colorCategory: 'palette_0', + field: { + name: '__kbnjoin__count_groupby_kibana_sample_data_logs.machine.os.keyword', + origin: 'join', + }, + fieldMetaOptions: { + isEnabled: true, + sigma: 3, + }, + type: 'ORDINAL', + }, + }, + lineWidth: { + type: 'DYNAMIC', + options: { + color: 'Blues', + colorCategory: 'palette_0', + field: { + name: 'mySourceField', + origin: 'source', + }, + fieldMetaOptions: { + isEnabled: true, + sigma: 3, + }, + type: 'ORDINAL', + }, + }, + }, + }, + }, + ]); + const attributes = { + title: 'my map', + layerListJSON, + }; + const { layerListJSON: migratedLayerListJSON } = migrateJoinAggKey({ attributes }); + const migratedLayerList = JSON.parse(migratedLayerListJSON!); + expect(migratedLayerList[0].style.properties.fillColor.options.field.name).toBe( + '__kbnjoin__avg_of_bytes__9055b4aa-136a-4b6d-90ab-9f94ccfe5eb5' + ); + expect(migratedLayerList[0].style.properties.lineColor.options.field.name).toBe( + '__kbnjoin__count__9055b4aa-136a-4b6d-90ab-9f94ccfe5eb5' + ); + expect(migratedLayerList[0].style.properties.lineWidth.options.field.name).toBe( + 'mySourceField' + ); + }); +}); diff --git a/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.ts b/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.ts new file mode 100644 index 0000000000000..29661aedb550c --- /dev/null +++ b/x-pack/legacy/plugins/maps/common/migrations/join_agg_key.ts @@ -0,0 +1,121 @@ +/* + * 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 _ from 'lodash'; +import { + AGG_DELIMITER, + AGG_TYPE, + FIELD_ORIGIN, + JOIN_FIELD_NAME_PREFIX, + LAYER_TYPE, + VECTOR_STYLES, +} from '../constants'; +import { getJoinAggKey } from '../get_join_key'; +import { + AggDescriptor, + JoinDescriptor, + LayerDescriptor, + VectorLayerDescriptor, +} from '../descriptor_types'; +import { MapSavedObjectAttributes } from '../../../../../plugins/maps/common/map_saved_object_type'; + +const GROUP_BY_DELIMITER = '_groupby_'; + +function getLegacyAggKey({ + aggType, + aggFieldName, + indexPatternTitle, + termFieldName, +}: { + aggType: AGG_TYPE; + aggFieldName?: string; + indexPatternTitle: string; + termFieldName: string; +}): string { + const metricKey = + aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${aggFieldName}` : aggType; + return `${JOIN_FIELD_NAME_PREFIX}${metricKey}${GROUP_BY_DELIMITER}${indexPatternTitle}.${termFieldName}`; +} + +function parseLegacyAggKey(legacyAggKey: string): { aggType: AGG_TYPE; aggFieldName?: string } { + const groupBySplit = legacyAggKey + .substring(JOIN_FIELD_NAME_PREFIX.length) + .split(GROUP_BY_DELIMITER); + const metricKey = groupBySplit[0]; + const metricKeySplit = metricKey.split(AGG_DELIMITER); + return { + aggType: metricKeySplit[0] as AGG_TYPE, + aggFieldName: metricKeySplit.length === 2 ? metricKeySplit[1] : undefined, + }; +} + +export function migrateJoinAggKey({ + attributes, +}: { + attributes: MapSavedObjectAttributes; +}): MapSavedObjectAttributes { + if (!attributes || !attributes.layerListJSON) { + return attributes; + } + + const layerList: LayerDescriptor[] = JSON.parse(attributes.layerListJSON); + layerList.forEach((layerDescriptor: LayerDescriptor) => { + if ( + layerDescriptor.type === LAYER_TYPE.VECTOR || + layerDescriptor.type === LAYER_TYPE.BLENDED_VECTOR + ) { + const vectorLayerDescriptor = layerDescriptor as VectorLayerDescriptor; + + if ( + !vectorLayerDescriptor.style || + !vectorLayerDescriptor.joins || + vectorLayerDescriptor.joins.length === 0 + ) { + return; + } + + const legacyJoinFields = new Map(); + vectorLayerDescriptor.joins.forEach((joinDescriptor: JoinDescriptor) => { + _.get(joinDescriptor, 'right.metrics', []).forEach((aggDescriptor: AggDescriptor) => { + const legacyAggKey = getLegacyAggKey({ + aggType: aggDescriptor.type, + aggFieldName: aggDescriptor.field, + indexPatternTitle: _.get(joinDescriptor, 'right.indexPatternTitle', ''), + termFieldName: _.get(joinDescriptor, 'right.term', ''), + }); + // The legacy getAggKey implemenation has a naming collision bug where + // aggType, aggFieldName, indexPatternTitle, and termFieldName would result in the identical aggKey. + // The VectorStyle implemenation used the first matching join descriptor + // so, in the event of a name collision, the first join descriptor will be used here as well. + if (!legacyJoinFields.has(legacyAggKey)) { + legacyJoinFields.set(legacyAggKey, joinDescriptor); + } + }); + }); + + Object.keys(vectorLayerDescriptor.style.properties).forEach(key => { + const style: any = vectorLayerDescriptor.style!.properties[key as VECTOR_STYLES]; + if (_.get(style, 'options.field.origin') === FIELD_ORIGIN.JOIN) { + const joinDescriptor = legacyJoinFields.get(style.options.field.name); + if (joinDescriptor) { + const { aggType, aggFieldName } = parseLegacyAggKey(style.options.field.name); + // Update legacy join agg key to new join agg key + style.options.field.name = getJoinAggKey({ + aggType, + aggFieldName, + rightSourceId: joinDescriptor.right.id!, + }); + } + } + }); + } + }); + + return { + ...attributes, + layerListJSON: JSON.stringify(layerList), + }; +} diff --git a/x-pack/legacy/plugins/maps/migrations.js b/x-pack/legacy/plugins/maps/migrations.js index 6a1f5bc937497..a8e69eef7a02f 100644 --- a/x-pack/legacy/plugins/maps/migrations.js +++ b/x-pack/legacy/plugins/maps/migrations.js @@ -11,6 +11,7 @@ import { moveApplyGlobalQueryToSources } from './common/migrations/move_apply_gl import { addFieldMetaOptions } from './common/migrations/add_field_meta_options'; import { migrateSymbolStyleDescriptor } from './common/migrations/migrate_symbol_style_descriptor'; import { migrateUseTopHitsToScalingType } from './common/migrations/scaling_type'; +import { migrateJoinAggKey } from './common/migrations/join_agg_key'; export const migrations = { map: { @@ -57,5 +58,13 @@ export const migrations = { attributes: attributesPhase2, }; }, + '7.8.0': doc => { + const attributes = migrateJoinAggKey(doc); + + return { + ...doc, + attributes, + }; + }, }, }; diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index 9808a62852a94..a4006732224ce 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -1,9 +1,3 @@ -/* - * 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. - */ - /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License; @@ -75,6 +69,7 @@ export enum FIELD_ORIGIN { SOURCE = 'source', JOIN = 'join', } +export const JOIN_FIELD_NAME_PREFIX = '__kbnjoin__'; export const SOURCE_DATA_ID_ORIGIN = 'source'; export const META_ID_ORIGIN_SUFFIX = 'meta'; @@ -132,6 +127,7 @@ export enum DRAW_TYPE { POLYGON = 'POLYGON', } +export const AGG_DELIMITER = '_of_'; export enum AGG_TYPE { AVG = 'avg', COUNT = 'count', diff --git a/x-pack/plugins/maps/common/get_join_key.ts b/x-pack/plugins/maps/common/get_join_key.ts new file mode 100644 index 0000000000000..f1ee95126b9a9 --- /dev/null +++ b/x-pack/plugins/maps/common/get_join_key.ts @@ -0,0 +1,22 @@ +/* + * 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 { AGG_DELIMITER, AGG_TYPE, JOIN_FIELD_NAME_PREFIX } from './constants'; + +// function in common since its needed by migration +export function getJoinAggKey({ + aggType, + aggFieldName, + rightSourceId, +}: { + aggType: AGG_TYPE; + aggFieldName?: string; + rightSourceId: string; +}) { + const metricKey = + aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${aggFieldName}` : aggType; + return `${JOIN_FIELD_NAME_PREFIX}${metricKey}__${rightSourceId}`; +} diff --git a/x-pack/plugins/maps/public/layers/joins/inner_join.test.js b/x-pack/plugins/maps/public/layers/joins/inner_join.test.js index 65c37860ffa18..f197a67becfae 100644 --- a/x-pack/plugins/maps/public/layers/joins/inner_join.test.js +++ b/x-pack/plugins/maps/public/layers/joins/inner_join.test.js @@ -35,7 +35,7 @@ const leftJoin = new InnerJoin( }, mockSource ); -const COUNT_PROPERTY_NAME = '__kbnjoin__count_groupby_kibana_sample_data_logs.geo.dest'; +const COUNT_PROPERTY_NAME = '__kbnjoin__count__d3625663-5b34-4d50-a784-0d743f676a0c'; describe('joinPropertiesToFeature', () => { it('Should add join property to features in feature collection', () => { diff --git a/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js index c6197f137f212..58c56fe32f766 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js @@ -7,16 +7,14 @@ import { i18n } from '@kbn/i18n'; import { AbstractESSource } from '../es_source'; import { esAggFieldsFactory } from '../../fields/es_agg_field'; - import { + AGG_DELIMITER, AGG_TYPE, COUNT_PROP_LABEL, COUNT_PROP_NAME, FIELD_ORIGIN, } from '../../../../common/constants'; -export const AGG_DELIMITER = '_of_'; - export class AbstractESAggSource extends AbstractESSource { constructor(descriptor, inspectorAdapters) { super(descriptor, inspectorAdapters); diff --git a/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js index 826197cc4fec7..cb07bb0e7d2ed 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js @@ -7,15 +7,14 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; -import { DEFAULT_MAX_BUCKETS_LIMIT, FIELD_ORIGIN, AGG_TYPE } from '../../../../common/constants'; +import { AGG_TYPE, DEFAULT_MAX_BUCKETS_LIMIT, FIELD_ORIGIN } from '../../../../common/constants'; +import { getJoinAggKey } from '../../../../common/get_join_key'; import { ESDocField } from '../../fields/es_doc_field'; -import { AbstractESAggSource, AGG_DELIMITER } from '../es_agg_source'; +import { AbstractESAggSource } from '../es_agg_source'; import { getField, addFieldToDSL, extractPropertiesFromBucket } from '../../util/es_agg_utils'; const TERMS_AGG_NAME = 'join'; -const FIELD_NAME_PREFIX = '__kbnjoin__'; -const GROUP_BY_DELIMITER = '_groupby_'; const TERMS_BUCKET_KEYS_TO_IGNORE = ['key', 'doc_count']; export function extractPropertiesMap(rawEsData, countPropertyName) { @@ -64,11 +63,11 @@ export class ESTermSource extends AbstractESAggSource { } getAggKey(aggType, fieldName) { - const metricKey = - aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${fieldName}` : aggType; - return `${FIELD_NAME_PREFIX}${metricKey}${GROUP_BY_DELIMITER}${ - this._descriptor.indexPatternTitle - }.${this._termField.getName()}`; + return getJoinAggKey({ + aggType, + aggFieldName: fieldName, + rightSourceId: this._descriptor.id, + }); } getAggLabel(aggType, fieldName) { diff --git a/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.test.js b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.test.js index b6cd3b670d3ce..14eb39180a6b8 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.test.js +++ b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.test.js @@ -32,33 +32,32 @@ const metricExamples = [ describe('getMetricFields', () => { it('should override name and label of count metric', async () => { const source = new ESTermSource({ + id: '1234', indexPatternTitle: indexPatternTitle, term: termFieldName, }); const metrics = source.getMetricFields(); - expect(metrics[0].getName()).toEqual('__kbnjoin__count_groupby_myIndex.myTermField'); + expect(metrics[0].getName()).toEqual('__kbnjoin__count__1234'); expect(await metrics[0].getLabel()).toEqual('Count of myIndex'); }); it('should override name and label of sum metric', async () => { const source = new ESTermSource({ + id: '1234', indexPatternTitle: indexPatternTitle, term: termFieldName, metrics: metricExamples, }); const metrics = source.getMetricFields(); - expect(metrics[0].getName()).toEqual( - '__kbnjoin__sum_of_myFieldGettingSummed_groupby_myIndex.myTermField' - ); + expect(metrics[0].getName()).toEqual('__kbnjoin__sum_of_myFieldGettingSummed__1234'); expect(await metrics[0].getLabel()).toEqual('my custom label'); - expect(metrics[1].getName()).toEqual('__kbnjoin__count_groupby_myIndex.myTermField'); + expect(metrics[1].getName()).toEqual('__kbnjoin__count__1234'); expect(await metrics[1].getLabel()).toEqual('Count of myIndex'); }); }); describe('extractPropertiesMap', () => { - const minPropName = - '__kbnjoin__min_of_avlAirTemp_groupby_kibana_sample_data_ky_avl.kytcCountyNmbr'; + const minPropName = '__kbnjoin__min_of_avlAirTemp__1234'; const responseWithNumberTypes = { aggregations: { join: { @@ -81,7 +80,7 @@ describe('extractPropertiesMap', () => { }, }, }; - const countPropName = '__kbnjoin__count_groupby_kibana_sample_data_ky_avl.kytcCountyNmbr'; + const countPropName = '__kbnjoin__count__1234'; let propertiesMap; beforeAll(() => { diff --git a/x-pack/test/api_integration/apis/maps/migrations.js b/x-pack/test/api_integration/apis/maps/migrations.js index c4587530e160b..cd575899118a3 100644 --- a/x-pack/test/api_integration/apis/maps/migrations.js +++ b/x-pack/test/api_integration/apis/maps/migrations.js @@ -41,7 +41,7 @@ export default function({ getService }) { type: 'index-pattern', }, ]); - expect(resp.body.migrationVersion).to.eql({ map: '7.7.0' }); + expect(resp.body.migrationVersion).to.eql({ map: '7.8.0' }); expect(resp.body.attributes.layerListJSON.includes('indexPatternRefName')).to.be(true); }); }); diff --git a/x-pack/test/functional/apps/maps/joins.js b/x-pack/test/functional/apps/maps/joins.js index 89a6c6ea82e53..4b36109a4de9c 100644 --- a/x-pack/test/functional/apps/maps/joins.js +++ b/x-pack/test/functional/apps/maps/joins.js @@ -9,7 +9,7 @@ import _ from 'lodash'; import { MAPBOX_STYLES } from './mapbox_styles'; -const JOIN_PROPERTY_NAME = '__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name'; +const JOIN_PROPERTY_NAME = '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1'; const EXPECTED_JOIN_VALUES = { alpha: 10, bravo: 3, diff --git a/x-pack/test/functional/apps/maps/mapbox_styles.js b/x-pack/test/functional/apps/maps/mapbox_styles.js index 508a019db1764..63bfc331d8886 100644 --- a/x-pack/test/functional/apps/maps/mapbox_styles.js +++ b/x-pack/test/functional/apps/maps/mapbox_styles.js @@ -27,7 +27,7 @@ export const MAPBOX_STYLES = { 'case', [ '==', - ['feature-state', '__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name'], + ['feature-state', '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1'], null, ], 2, @@ -39,7 +39,7 @@ export const MAPBOX_STYLES = { 'to-number', [ 'feature-state', - '__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name', + '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1', ], ], 12, @@ -97,7 +97,7 @@ export const MAPBOX_STYLES = { 'case', [ '==', - ['feature-state', '__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name'], + ['feature-state', '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1'], null, ], 2, @@ -109,7 +109,7 @@ export const MAPBOX_STYLES = { 'to-number', [ 'feature-state', - '__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name', + '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1', ], ], 12, From c2293cb11dfb19e87454e48b604ac4fad27b0efe Mon Sep 17 00:00:00 2001 From: Andrew Goldstein Date: Thu, 16 Apr 2020 22:17:28 -0600 Subject: [PATCH 03/22] [SIEM] Threat hunting enhancements: Filter for/out value, Show top field, Copy to Clipboard, Draggable chart legends (#61207) ## [SIEM] Threat hunting enhancements: Filter for/out value, Show top field, Copy to Clipboard, Draggable chart legends Enhancements to the threat hunting experience ![show-top-field](https://user-images.githubusercontent.com/4459398/79180753-f9bb7f80-7dc7-11ea-9ae2-d4e4fc79208c.gif) ### New draggable context menu A new context menu with the following items has been added to all draggables: - Filter for value - Filter out value - Show top _field name_ - Copy to Clipboard as shown in the following animated gif: ![new-context-menu](https://user-images.githubusercontent.com/4459398/79173935-4dbd6880-7db6-11ea-9253-7746481e1b17.gif) ### Filter for value The _Filter for value_ context menu action adds the draggable to the global filter bar, which is applicable to all pages in the SIEM app, per the following animated gif: ![filter-in-value](https://user-images.githubusercontent.com/4459398/79176624-f91deb80-7dbd-11ea-9b01-799145d776c8.gif) ### Filter out value The _Filter out value_ context menu action adds the draggable to the global filter bar as a _negated_ (`NOT`) filter, per the following animated gif: ![filter-out-value](https://user-images.githubusercontent.com/4459398/79178474-9f6bf000-7dc2-11ea-9423-512ad7f89a18.gif) ### Show top _field_ The _Show top field_ context menu action displays an interactive Top 10 histogram, per the following animated gif: ![show-top-field](https://user-images.githubusercontent.com/4459398/79180753-f9bb7f80-7dc7-11ea-9ae2-d4e4fc79208c.gif) - The contents of the histogram are filtered by the global KQL bar / filters and current date range - Brushing over the bars in the histogram updates the global date range / picker - Select _Events_ or _Signals_ - The _Show top field_ action is also available in the Fields Browser, per the following animated gif: ![in-fields-browser](https://user-images.githubusercontent.com/4459398/79179548-1a360a80-7dc5-11ea-9ad7-cdd7fef0cc64.gif) ### Copy to Clipboard The _Copy to clipboard_ context menu action copies the draggable field and value to the clipboard in KQL format (e.g. `process.name: "nice"`). Per the following animated gifs, it's now possible to copy _any_ draggable to the clipboard, and paste it in KQL format, which addresses [this feature request from a user](https://github.com/elastic/kibana/issues/59472): ![copy-to-clipboard](https://user-images.githubusercontent.com/4459398/79178893-a7785f80-7dc3-11ea-868a-5d7bc2824912.gif) ![pasted-value](https://user-images.githubusercontent.com/4459398/79179126-2c637900-7dc4-11ea-92a7-86c7d6377688.gif) ### Draggable chart legends You may now pivot from chart legends by dragging and dropping them to a timeline, or by selecting the Filter for / out context menu action, per the following animated gif: ![draggable-legend](https://user-images.githubusercontent.com/4459398/79179769-9deff700-7dc5-11ea-9153-b472914f2dfe.gif) #### Desk testing Desk tested in: - Chrome `81.0.4044.92` - Firefox `75.0` - Safari `13.1` --- .../legacy/plugins/siem/common/constants.ts | 17 + .../components/charts/barchart.test.tsx | 116 +++- .../public/components/charts/barchart.tsx | 65 +- .../charts/draggable_legend.test.tsx | 149 +++++ .../components/charts/draggable_legend.tsx | 68 +++ .../charts/draggable_legend_item.test.tsx | 143 +++++ .../charts/draggable_legend_item.tsx | 62 ++ .../public/components/charts/translation.ts | 4 + .../drag_drop_context_wrapper.tsx | 3 + .../drag_and_drop/draggable_wrapper.test.tsx | 65 +- .../drag_and_drop/draggable_wrapper.tsx | 173 ++++-- .../draggable_wrapper_hover_content.test.tsx | 559 ++++++++++++++++++ .../draggable_wrapper_hover_content.tsx | 145 +++++ .../components/drag_and_drop/helpers.test.ts | 95 +++ .../components/drag_and_drop/helpers.ts | 97 ++- .../components/drag_and_drop/translations.ts | 33 ++ .../__snapshots__/index.test.tsx.snap | 1 + .../public/components/draggables/index.tsx | 2 +- .../components/event_details/columns.tsx | 37 +- .../events_viewer/events_viewer.tsx | 7 +- .../fields_browser/category_columns.test.tsx | 24 - .../fields_browser/category_columns.tsx | 52 +- .../fields_browser/field_name.test.tsx | 59 -- .../components/fields_browser/field_name.tsx | 98 +-- .../public/components/header_page/title.tsx | 4 +- .../__snapshots__/index.test.tsx.snap | 7 +- .../components/header_section/index.test.tsx | 4 +- .../components/header_section/index.tsx | 8 +- .../public/components/links/index.test.tsx | 2 + .../__snapshots__/index.test.tsx.snap | 4 +- .../matrix_histogram/index.test.tsx | 11 + .../components/matrix_histogram/index.tsx | 113 ++-- .../components/matrix_histogram/types.ts | 11 + .../components/matrix_histogram/utils.ts | 13 + .../notes/note_card/note_card_body.tsx | 48 +- .../__snapshots__/index.test.tsx.snap | 24 +- .../helpers.test.tsx | 16 + .../helpers.ts | 8 +- .../add_filter_to_global_search_bar/index.tsx | 57 +- .../translations.ts | 7 + .../page/hosts/hosts_table/columns.tsx | 4 +- .../siem/public/components/page/index.tsx | 16 +- .../public/components/page/manage_query.tsx | 2 +- .../components/paginated_table/index.tsx | 12 +- .../source_destination_ip.tsx | 2 +- .../__snapshots__/timeline.test.tsx.snap | 36 ++ .../body/column_headers/actions/index.tsx | 2 +- .../column_headers/header/header_content.tsx | 2 +- .../auditd/generic_row_renderer.test.tsx | 2 + .../renderers/suricata/suricata_signature.tsx | 4 +- .../body/renderers/system/generic_details.tsx | 2 +- .../renderers/system/generic_file_details.tsx | 2 +- .../system/generic_row_renderer.test.tsx | 2 + .../body/renderers/zeek/zeek_signature.tsx | 2 +- .../timeline/data_providers/index.tsx | 2 +- .../data_providers/provider_badge.tsx | 142 +++-- .../data_providers/provider_item_badge.tsx | 2 +- .../data_providers/providers.test.tsx | 21 +- .../timeline/data_providers/translations.ts | 12 + .../header/__snapshots__/index.test.tsx.snap | 36 ++ .../components/timeline/header/index.test.tsx | 7 + .../components/timeline/header/index.tsx | 6 +- .../timeline/query_bar/index.test.tsx | 10 + .../components/timeline/query_bar/index.tsx | 6 +- .../timeline/search_or_filter/index.tsx | 10 +- .../search_or_filter/search_or_filter.tsx | 9 +- .../public/components/timeline/timeline.tsx | 18 +- .../components/timeline/timeline_context.tsx | 39 +- .../public/components/top_n/helpers.test.tsx | 25 + .../siem/public/components/top_n/helpers.ts | 66 +++ .../public/components/top_n/index.test.tsx | 379 ++++++++++++ .../siem/public/components/top_n/index.tsx | 166 ++++++ .../public/components/top_n/top_n.test.tsx | 261 ++++++++ .../siem/public/components/top_n/top_n.tsx | 158 +++++ .../public/components/top_n/translations.ts | 23 + .../components/with_hover_actions/index.tsx | 68 +-- .../containers/matrix_histogram/index.ts | 15 +- .../signals_histogram_panel/helpers.tsx | 73 ++- .../signals_histogram_panel/index.tsx | 116 ++-- .../signals_histogram.test.tsx | 9 +- .../signals_histogram.tsx | 57 +- .../signals_histogram_panel/translations.ts | 6 + .../alerts_by_category/index.test.tsx | 4 +- .../events_by_dataset/__mocks__/index.tsx | 7 + .../overview/events_by_dataset/index.tsx | 89 ++- .../siem/public/pages/overview/overview.tsx | 2 +- .../overview/signals_by_category/index.tsx | 16 +- .../public/pages/overview/translations.ts | 6 + .../pages/timelines/timelines_page.test.tsx | 2 + .../query.events_over_time.dsl.ts | 14 +- .../lib/matrix_histogram/translations.ts | 14 + 91 files changed, 3716 insertions(+), 681 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper_hover_content.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper_hover_content.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/drag_and_drop/translations.ts create mode 100644 x-pack/legacy/plugins/siem/public/components/top_n/helpers.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/top_n/helpers.ts create mode 100644 x-pack/legacy/plugins/siem/public/components/top_n/index.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/top_n/index.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/top_n/top_n.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/top_n/top_n.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/top_n/translations.ts create mode 100644 x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/__mocks__/index.tsx create mode 100644 x-pack/legacy/plugins/siem/server/lib/matrix_histogram/translations.ts diff --git a/x-pack/legacy/plugins/siem/common/constants.ts b/x-pack/legacy/plugins/siem/common/constants.ts index 22f1b3beffa35..e0acc7ecfe036 100644 --- a/x-pack/legacy/plugins/siem/common/constants.ts +++ b/x-pack/legacy/plugins/siem/common/constants.ts @@ -111,3 +111,20 @@ export const NOTIFICATION_SUPPORTED_ACTION_TYPES_IDS = [ ]; export const NOTIFICATION_THROTTLE_NO_ACTIONS = 'no_actions'; export const NOTIFICATION_THROTTLE_RULE = 'rule'; + +/** + * Histograms for fields named in this list should be displayed with an + * "All others" bucket, to count events that don't specify a value for + * the field being counted + */ +export const showAllOthersBucket: string[] = [ + 'destination.ip', + 'event.action', + 'event.category', + 'event.dataset', + 'event.module', + 'signal.rule.threat.tactic.name', + 'source.ip', + 'destination.ip', + 'user.name', +]; diff --git a/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx index 272c41833f368..635d48cca10fc 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx @@ -4,15 +4,29 @@ * you may not use this file except in compliance with the Elastic License. */ -import { shallow, ShallowWrapper } from 'enzyme'; +import { Chart, BarSeries, Axis, ScaleType } from '@elastic/charts'; +import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; +import { mount, ReactWrapper, shallow, ShallowWrapper } from 'enzyme'; import React from 'react'; +import { ThemeProvider } from 'styled-components'; + +import { escapeDataProviderId } from '../drag_and_drop/helpers'; +import { TestProviders } from '../../mock'; import { BarChartBaseComponent, BarChartComponent } from './barchart'; import { ChartSeriesData } from './common'; -import { Chart, BarSeries, Axis, ScaleType } from '@elastic/charts'; jest.mock('../../lib/kibana'); +jest.mock('uuid', () => { + return { + v1: jest.fn(() => 'uuid.v1()'), + v4: jest.fn(() => 'uuid.v4()'), + }; +}); + +const theme = () => ({ eui: euiDarkVars, darkMode: true }); + const customHeight = '100px'; const customWidth = '120px'; const chartDataSets = [ @@ -116,6 +130,19 @@ const mockConfig = { customHeight: 324, }; +// Suppress warnings about "react-beautiful-dnd" +/* eslint-disable no-console */ +const originalError = console.error; +const originalWarn = console.warn; +beforeAll(() => { + console.warn = jest.fn(); + console.error = jest.fn(); +}); +afterAll(() => { + console.error = originalError; + console.warn = originalWarn; +}); + describe('BarChartBaseComponent', () => { let shallowWrapper: ShallowWrapper; const mockBarChartData: ChartSeriesData[] = [ @@ -280,6 +307,91 @@ describe.each(chartDataSets)('BarChart with valid data [%o]', data => { expect(shallowWrapper.find('BarChartBase')).toHaveLength(1); expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(0); }); + + it('it does NOT render a draggable legend because stackByField is not provided', () => { + expect(shallowWrapper.find('[data-test-subj="draggable-legend"]').exists()).toBe(false); + }); +}); + +describe.each(chartDataSets)('BarChart with stackByField', () => { + let wrapper: ReactWrapper; + + const data = [ + { + key: 'python.exe', + value: [ + { + x: 1586754900000, + y: 9675, + g: 'python.exe', + }, + ], + }, + { + key: 'kernel', + value: [ + { + x: 1586754900000, + y: 8708, + g: 'kernel', + }, + { + x: 1586757600000, + y: 9282, + g: 'kernel', + }, + ], + }, + { + key: 'sshd', + value: [ + { + x: 1586754900000, + y: 5907, + g: 'sshd', + }, + ], + }, + ]; + + const expectedColors = ['#1EA593', '#2B70F7', '#CE0060']; + + const stackByField = 'process.name'; + + beforeAll(() => { + wrapper = mount( + + + + + + ); + }); + + it('it renders a draggable legend', () => { + expect(wrapper.find('[data-test-subj="draggable-legend"]').exists()).toBe(true); + }); + + expectedColors.forEach((color, i) => { + test(`it renders the expected legend color ${color} for legend item ${i}`, () => { + expect(wrapper.find(`div [color="${color}"]`).exists()).toBe(true); + }); + }); + + data.forEach(datum => { + test(`it renders the expected draggable legend text for datum ${datum.key}`, () => { + const dataProviderId = `draggableId.content.draggable-legend-item-uuid_v4()-${escapeDataProviderId( + stackByField + )}-${escapeDataProviderId(datum.key)}`; + + expect( + wrapper + .find(`div [data-rbd-draggable-id="${dataProviderId}"]`) + .first() + .text() + ).toEqual(datum.key); + }); + }); }); describe.each(chartHolderDataSets)('BarChart with invalid data [%o]', data => { diff --git a/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx b/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx index 2ae0e05850a37..64d15cd6731cb 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/barchart.tsx @@ -4,13 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import React, { useMemo } from 'react'; import { Chart, BarSeries, Axis, Position, ScaleType, Settings } from '@elastic/charts'; import { getOr, get, isNumber } from 'lodash/fp'; import deepmerge from 'deepmerge'; +import uuid from 'uuid'; +import styled from 'styled-components'; -import { useThrottledResizeObserver } from '../utils'; +import { escapeDataProviderId } from '../drag_and_drop/helpers'; import { useTimeZone } from '../../lib/kibana'; +import { defaultLegendColors } from '../matrix_histogram/utils'; +import { useThrottledResizeObserver } from '../utils'; + import { ChartPlaceHolder } from './chart_place_holder'; import { chartDefaultSettings, @@ -22,6 +28,12 @@ import { WrappedByAutoSizer, useTheme, } from './common'; +import { DraggableLegend } from './draggable_legend'; +import { LegendItem } from './draggable_legend_item'; + +const LegendFlexItem = styled(EuiFlexItem)` + overview: hidden; +`; const checkIfAllTheDataInTheSeriesAreValid = (series: ChartSeriesData): series is ChartSeriesData => series != null && @@ -38,12 +50,14 @@ const checkIfAnyValidSeriesExist = ( // Bar chart rotation: https://ela.st/chart-rotations export const BarChartBaseComponent = ({ data, + forceHiddenLegend = false, ...chartConfigs }: { data: ChartSeriesData[]; width: string | null | undefined; height: string | null | undefined; configs?: ChartSeriesConfigs | undefined; + forceHiddenLegend?: boolean; }) => { const theme = useTheme(); const timeZone = useTimeZone(); @@ -59,10 +73,10 @@ export const BarChartBaseComponent = ({ return chartConfigs.width && chartConfigs.height ? ( - + {data.map(series => { const barSeriesKey = series.key; - return checkIfAllTheDataInTheSeriesAreValid ? ( + return checkIfAllTheDataInTheSeriesAreValid(series) ? ( = ({ barChart, configs }) => { +const NO_LEGEND_DATA: LegendItem[] = []; + +export const BarChartComponent: React.FC = ({ + barChart, + configs, + stackByField, +}) => { const { ref: measureRef, width, height } = useThrottledResizeObserver(); + const legendItems: LegendItem[] = useMemo( + () => + barChart != null && stackByField != null + ? barChart.map((d, i) => ({ + color: d.color ?? i < defaultLegendColors.length ? defaultLegendColors[i] : undefined, + dataProviderId: escapeDataProviderId( + `draggable-legend-item-${uuid.v4()}-${stackByField}-${d.key}` + ), + field: stackByField, + value: d.key, + })) + : NO_LEGEND_DATA, + [barChart, stackByField] + ); + const customHeight = get('customHeight', configs); const customWidth = get('customWidth', configs); const chartHeight = getChartHeight(customHeight, height); const chartWidth = getChartWidth(customWidth, width); return checkIfAnyValidSeriesExist(barChart) ? ( - - - + + + + + + + + + + ) : ( ); diff --git a/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.test.tsx new file mode 100644 index 0000000000000..0da0c2bdc35f2 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.test.tsx @@ -0,0 +1,149 @@ +/* + * 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 euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; +import { mount, ReactWrapper } from 'enzyme'; +import React from 'react'; +import { ThemeProvider } from 'styled-components'; + +import { TestProviders } from '../../mock'; + +import { MIN_LEGEND_HEIGHT, DraggableLegend } from './draggable_legend'; +import { LegendItem } from './draggable_legend_item'; + +const theme = () => ({ eui: euiDarkVars, darkMode: true }); + +const allOthersDataProviderId = + 'draggable-legend-item-527adabe-8e1c-4a1f-965c-2f3d65dda9e1-event_dataset-All others'; + +const legendItems: LegendItem[] = [ + { + color: '#1EA593', + dataProviderId: 'draggable-legend-item-3207fda7-d008-402a-86a0-8ad632081bad-event_dataset-flow', + field: 'event.dataset', + value: 'flow', + }, + { + color: '#2B70F7', + dataProviderId: + 'draggable-legend-item-83f6c824-811d-4ec8-b373-eba2b0de6398-event_dataset-suricata_eve', + field: 'event.dataset', + value: 'suricata.eve', + }, + { + color: '#CE0060', + dataProviderId: + 'draggable-legend-item-ec57bb8f-82cd-4e07-bd38-1d11b3f0ee5f-event_dataset-traefik_access', + field: 'event.dataset', + value: 'traefik.access', + }, + { + color: '#38007E', + dataProviderId: + 'draggable-legend-item-25d5fcd6-87ba-46b5-893e-c655d7d504e3-event_dataset-esensor', + field: 'event.dataset', + value: 'esensor', + }, + { + color: '#F37020', + dataProviderId: allOthersDataProviderId, + field: 'event.dataset', + value: 'All others', + }, +]; + +describe('DraggableLegend', () => { + const height = 400; + + // Suppress warnings about "react-beautiful-dnd" + /* eslint-disable no-console */ + const originalError = console.error; + const originalWarn = console.warn; + beforeAll(() => { + console.warn = jest.fn(); + console.error = jest.fn(); + }); + afterAll(() => { + console.error = originalError; + console.warn = originalWarn; + }); + + describe('rendering', () => { + let wrapper: ReactWrapper; + + beforeEach(() => { + wrapper = mount( + + + + + + ); + }); + + it(`renders a container with the specified non-zero 'height'`, () => { + expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( + 'height', + `${height}px` + ); + }); + + it('scrolls when necessary', () => { + expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( + 'overflow', + 'auto' + ); + }); + + it('renders the legend items', () => { + legendItems.forEach(item => + expect( + wrapper + .find( + item.dataProviderId !== allOthersDataProviderId + ? `[data-test-subj="legend-item-${item.dataProviderId}"]` + : '[data-test-subj="all-others-legend-item"]' + ) + .first() + .text() + ).toEqual(item.value) + ); + }); + + it('renders a spacer for every legend item', () => { + expect(wrapper.find('[data-test-subj="draggable-legend-spacer"]').hostNodes().length).toEqual( + legendItems.length + ); + }); + }); + + it('does NOT render the legend when an empty collection of legendItems is provided', () => { + const wrapper = mount( + + + + + + ); + + expect(wrapper.find('[data-test-subj="draggable-legend"]').exists()).toBe(false); + }); + + it(`renders a legend with the minimum height when 'height' is zero`, () => { + const wrapper = mount( + + + + + + ); + + expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( + 'height', + `${MIN_LEGEND_HEIGHT}px` + ); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.tsx b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.tsx new file mode 100644 index 0000000000000..ef3fbb8780d15 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend.tsx @@ -0,0 +1,68 @@ +/* + * 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 { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; +import { rgba } from 'polished'; +import React from 'react'; +import styled from 'styled-components'; + +import { DraggableLegendItem, LegendItem } from './draggable_legend_item'; + +export const MIN_LEGEND_HEIGHT = 175; + +const DraggableLegendContainer = styled.div<{ height: number }>` + height: ${({ height }) => `${height}px`}; + overflow: auto; + scrollbar-width: thin; + width: 165px; + + &::-webkit-scrollbar { + height: ${({ theme }) => theme.eui.euiScrollBar}; + width: ${({ theme }) => theme.eui.euiScrollBar}; + } + + &::-webkit-scrollbar-thumb { + background-clip: content-box; + background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)}; + border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent; + } + + &::-webkit-scrollbar-corner, + &::-webkit-scrollbar-track { + background-color: transparent; + } +`; + +const DraggableLegendComponent: React.FC<{ + height: number; + legendItems: LegendItem[]; +}> = ({ height, legendItems }) => { + if (legendItems.length === 0) { + return null; + } + + return ( + + + + {legendItems.map(item => ( + + + + + ))} + + + + ); +}; + +DraggableLegendComponent.displayName = 'DraggableLegendComponent'; + +export const DraggableLegend = React.memo(DraggableLegendComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.test.tsx new file mode 100644 index 0000000000000..581952a8415f6 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.test.tsx @@ -0,0 +1,143 @@ +/* + * 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 euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; +import { mount, ReactWrapper } from 'enzyme'; +import React from 'react'; +import { ThemeProvider } from 'styled-components'; + +import { TestProviders } from '../../mock'; + +import { DraggableLegendItem, LegendItem } from './draggable_legend_item'; + +const theme = () => ({ eui: euiDarkVars, darkMode: true }); + +describe('DraggableLegendItem', () => { + // Suppress warnings about "react-beautiful-dnd" + /* eslint-disable no-console */ + const originalError = console.error; + const originalWarn = console.warn; + beforeAll(() => { + console.warn = jest.fn(); + console.error = jest.fn(); + }); + afterAll(() => { + console.error = originalError; + console.warn = originalWarn; + }); + + describe('rendering a regular (non "All others") legend item', () => { + const legendItem: LegendItem = { + color: '#1EA593', + dataProviderId: + 'draggable-legend-item-3207fda7-d008-402a-86a0-8ad632081bad-event_dataset-flow', + field: 'event.dataset', + value: 'flow', + }; + + let wrapper: ReactWrapper; + + beforeEach(() => { + wrapper = mount( + + + + + + ); + }); + + it('renders a colored circle with the expected legend item color', () => { + expect( + wrapper + .find('[data-test-subj="legend-color"]') + .first() + .props().color + ).toEqual(legendItem.color); + }); + + it('renders draggable legend item text', () => { + expect( + wrapper + .find(`[data-test-subj="legend-item-${legendItem.dataProviderId}"]`) + .first() + .text() + ).toEqual(legendItem.value); + }); + + it('does NOT render a non-draggable "All others" legend item', () => { + expect(wrapper.find(`[data-test-subj="all-others-legend-item"]`).exists()).toBe(false); + }); + }); + + describe('rendering an "All others" legend item', () => { + const allOthersLegendItem: LegendItem = { + color: '#F37020', + dataProviderId: + 'draggable-legend-item-527adabe-8e1c-4a1f-965c-2f3d65dda9e1-event_dataset-All others', + field: 'event.dataset', + value: 'All others', + }; + + let wrapper: ReactWrapper; + + beforeEach(() => { + wrapper = mount( + + + + + + ); + }); + + it('renders a colored circle with the expected legend item color', () => { + expect( + wrapper + .find('[data-test-subj="legend-color"]') + .first() + .props().color + ).toEqual(allOthersLegendItem.color); + }); + + it('does NOT render a draggable legend item', () => { + expect( + wrapper + .find(`[data-test-subj="legend-item-${allOthersLegendItem.dataProviderId}"]`) + .exists() + ).toBe(false); + }); + + it('renders NON-draggable `All others` legend item text', () => { + expect( + wrapper + .find(`[data-test-subj="all-others-legend-item"]`) + .first() + .text() + ).toEqual(allOthersLegendItem.value); + }); + }); + + it('does NOT render a colored circle when the legend item has no color', () => { + const noColorLegendItem: LegendItem = { + // no `color` attribute for this `LegendItem`! + dataProviderId: + 'draggable-legend-item-3207fda7-d008-402a-86a0-8ad632081bad-event_dataset-flow', + field: 'event.dataset', + value: 'flow', + }; + + const wrapper = mount( + + + + + + ); + + expect(wrapper.find('[data-test-subj="legend-color"]').exists()).toBe(false); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.tsx b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.tsx new file mode 100644 index 0000000000000..cdda1733932d5 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/charts/draggable_legend_item.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiText } from '@elastic/eui'; +import React from 'react'; +import styled from 'styled-components'; + +import { DefaultDraggable } from '../draggables'; + +import * as i18n from './translation'; + +// The "All others" legend item is not draggable +const AllOthers = styled.span` + padding-left: 7px; +`; + +export interface LegendItem { + color?: string; + dataProviderId: string; + field: string; + value: string; +} + +const DraggableLegendItemComponent: React.FC<{ + legendItem: LegendItem; +}> = ({ legendItem }) => { + const { color, dataProviderId, field, value } = legendItem; + + return ( + + + {color != null && ( + + + + )} + + + {value !== i18n.ALL_OTHERS ? ( + + ) : ( + <> + {value} + + )} + + + + ); +}; + +DraggableLegendItemComponent.displayName = 'DraggableLegendItemComponent'; + +export const DraggableLegendItem = React.memo(DraggableLegendItemComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/charts/translation.ts b/x-pack/legacy/plugins/siem/public/components/charts/translation.ts index 341cb7782f87c..891f59fc97bd1 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/translation.ts +++ b/x-pack/legacy/plugins/siem/public/components/charts/translation.ts @@ -13,3 +13,7 @@ export const ALL_VALUES_ZEROS_TITLE = i18n.translate('xpack.siem.chart.dataAllVa export const DATA_NOT_AVAILABLE_TITLE = i18n.translate('xpack.siem.chart.dataNotAvailableTitle', { defaultMessage: 'Chart Data Not Available', }); + +export const ALL_OTHERS = i18n.translate('xpack.siem.chart.allOthersGroupingLabel', { + defaultMessage: 'All others', +}); diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx index 11db33fff6d72..248ae671550ef 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx @@ -27,6 +27,9 @@ import { draggableIsField, } from './helpers'; +// @ts-ignore +window['__react-beautiful-dnd-disable-dev-warnings'] = true; + interface Props { browserFields: BrowserFields; children: React.ReactNode; diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx index 11891afabbf3d..cd9e1dc95ff01 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.test.tsx @@ -7,12 +7,13 @@ import { shallow } from 'enzyme'; import React from 'react'; import { MockedProvider } from 'react-apollo/test-utils'; +import { DraggableStateSnapshot, DraggingStyle } from 'react-beautiful-dnd'; import { mockBrowserFields, mocksSource } from '../../containers/source/mock'; import { TestProviders } from '../../mock'; import { mockDataProviders } from '../timeline/data_providers/mock/mock_data_providers'; import { DragDropContextWrapper } from './drag_drop_context_wrapper'; -import { DraggableWrapper, ConditionalPortal } from './draggable_wrapper'; +import { ConditionalPortal, DraggableWrapper, getStyle } from './draggable_wrapper'; import { useMountAppended } from '../../utils/use_mount_appended'; describe('DraggableWrapper', () => { @@ -48,6 +49,36 @@ describe('DraggableWrapper', () => { expect(wrapper.text()).toEqual(message); }); + + test('it does NOT render hover actions when the mouse is NOT over the draggable wrapper', () => { + const wrapper = mount( + + + + message} /> + + + + ); + + expect(wrapper.find('[data-test-subj="copy-to-clipboard"]').exists()).toBe(false); + }); + + test('it renders hover actions when the mouse is over the draggable wrapper', () => { + const wrapper = mount( + + + + message} /> + + + + ); + + wrapper.simulate('mouseenter'); + wrapper.update(); + expect(wrapper.find('[data-test-subj="copy-to-clipboard"]').exists()).toBe(true); + }); }); describe('text truncation styling', () => { @@ -100,4 +131,36 @@ describe('ConditionalPortal', () => { expect(props.registerProvider.mock.calls.length).toEqual(1); }); + + describe('getStyle', () => { + const style: DraggingStyle = { + boxSizing: 'border-box', + height: 10, + left: 1, + pointerEvents: 'none', + position: 'fixed', + transition: 'none', + top: 123, + width: 50, + zIndex: 9999, + }; + + it('returns a style with no transitionDuration when the snapshot is not drop animating', () => { + const snapshot: DraggableStateSnapshot = { + isDragging: true, + isDropAnimating: false, // <-- NOT drop animating + }; + + expect(getStyle(style, snapshot)).not.toHaveProperty('transitionDuration'); + }); + + it('returns a style with a transitionDuration when the snapshot is drop animating', () => { + const snapshot: DraggableStateSnapshot = { + isDragging: true, + isDropAnimating: true, // <-- it is drop animating + }; + + expect(getStyle(style, snapshot)).toHaveProperty('transitionDuration', '0.00000001s'); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx index 3a6a4de7984db..c7da5b5c58951 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx @@ -4,12 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Draggable, DraggableProvided, DraggableStateSnapshot, + DraggingStyle, Droppable, + NotDraggingStyle, } from 'react-beautiful-dnd'; import { useDispatch } from 'react-redux'; import styled from 'styled-components'; @@ -18,6 +20,9 @@ import deepEqual from 'fast-deep-equal'; import { dragAndDropActions } from '../../store/drag_and_drop'; import { DataProvider } from '../timeline/data_providers/data_provider'; import { TruncatableText } from '../truncatable_text'; +import { WithHoverActions } from '../with_hover_actions'; + +import { DraggableWrapperHoverContent } from './draggable_wrapper_hover_content'; import { getDraggableId, getDroppableId } from './helpers'; import { ProviderContainer } from './provider_container'; @@ -67,23 +72,42 @@ type RenderFunctionProp = ( state: DraggableStateSnapshot ) => React.ReactNode; -interface OwnProps { +interface Props { dataProvider: DataProvider; inline?: boolean; render: RenderFunctionProp; truncate?: boolean; + onFilterAdded?: () => void; } -type Props = OwnProps; - /** * Wraps a draggable component to handle registration / unregistration of the * data provider associated with the item being dropped */ +export const getStyle = ( + style: DraggingStyle | NotDraggingStyle | undefined, + snapshot: DraggableStateSnapshot +) => { + if (!snapshot.isDropAnimating) { + return style; + } + + return { + ...style, + transitionDuration: '0.00000001s', // cannot be 0, but can be a very short duration + }; +}; + export const DraggableWrapper = React.memo( - ({ dataProvider, render, truncate }) => { + ({ dataProvider, onFilterAdded, render, truncate }) => { + const [showTopN, setShowTopN] = useState(false); + const toggleTopN = useCallback(() => { + setShowTopN(!showTopN); + }, [setShowTopN, showTopN]); + const [providerRegistered, setProviderRegistered] = useState(false); + const dispatch = useDispatch(); const registerProvider = useCallback(() => { @@ -105,65 +129,90 @@ export const DraggableWrapper = React.memo( [] ); - return ( - - - ( - -
- ( + + ), + [dataProvider, onFilterAdded, showTopN, toggleTopN] + ); + + const renderContent = useCallback( + () => ( + + + ( + +
- {render(dataProvider, provided, snapshot)} - -
-
- )} - > - {droppableProvided => ( -
- - {(provided, snapshot) => ( - - {truncate && !snapshot.isDragging ? ( - - {render(dataProvider, provided, snapshot)} - - ) : ( - - {render(dataProvider, provided, snapshot)} - - )} - - )} - - {droppableProvided.placeholder} -
- )} -
-
-
+ {render(dataProvider, provided, snapshot)} +
+
+
+ )} + > + {droppableProvided => ( +
+ + {(provided, snapshot) => ( + + {truncate && !snapshot.isDragging ? ( + + {render(dataProvider, provided, snapshot)} + + ) : ( + + {render(dataProvider, provided, snapshot)} + + )} + + )} + + {droppableProvided.placeholder} +
+ )} +
+
+
+ ), + [dataProvider, render, registerProvider, truncate] + ); + + return ( + ); }, (prevProps, nextProps) => diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper_hover_content.test.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper_hover_content.test.tsx new file mode 100644 index 0000000000000..f8b5eb7209ff4 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper_hover_content.test.tsx @@ -0,0 +1,559 @@ +/* + * 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 { mount, ReactWrapper } from 'enzyme'; +import React from 'react'; +import { MockedProvider } from 'react-apollo/test-utils'; + +import { mocksSource } from '../../containers/source/mock'; +import { wait } from '../../lib/helpers'; +import { useKibana } from '../../lib/kibana'; +import { TestProviders } from '../../mock'; +import { createKibanaCoreStartMock } from '../../mock/kibana_core'; +import { FilterManager } from '../../../../../../../src/plugins/data/public'; +import { TimelineContext } from '../timeline/timeline_context'; + +import { DraggableWrapperHoverContent } from './draggable_wrapper_hover_content'; + +jest.mock('../../lib/kibana'); + +jest.mock('uuid', () => { + return { + v1: jest.fn(() => 'uuid.v1()'), + v4: jest.fn(() => 'uuid.v4()'), + }; +}); + +const mockUiSettingsForFilterManager = createKibanaCoreStartMock().uiSettings; +const field = 'process.name'; +const value = 'nice'; + +describe('DraggableWrapperHoverContent', () => { + // Suppress warnings about "react-beautiful-dnd" + /* eslint-disable no-console */ + const originalError = console.error; + const originalWarn = console.warn; + beforeAll(() => { + console.warn = jest.fn(); + console.error = jest.fn(); + }); + afterAll(() => { + console.error = originalError; + console.warn = originalWarn; + }); + + /** + * The tests for "Filter for value" and "Filter out value" are similar enough + * to combine them into "table tests" using this array + */ + const forOrOut = ['for', 'out']; + + forOrOut.forEach(hoverAction => { + describe(`Filter ${hoverAction} value`, () => { + test(`it renders the 'Filter ${hoverAction} value' button when showTopN is false`, () => { + const wrapper = mount( + + + + ); + + expect( + wrapper + .find(`[data-test-subj="filter-${hoverAction}-value"]`) + .first() + .exists() + ).toBe(true); + }); + + test(`it does NOT render the 'Filter ${hoverAction} value' button when showTopN is true`, () => { + const wrapper = mount( + + + + ); + + expect( + wrapper + .find(`[data-test-subj="filter-${hoverAction}-value"]`) + .first() + .exists() + ).toBe(false); + }); + + describe('when run in the context of a timeline', () => { + let filterManager: FilterManager; + let wrapper: ReactWrapper; + let onFilterAdded: () => void; + + beforeEach(() => { + filterManager = new FilterManager(mockUiSettingsForFilterManager); + filterManager.addFilters = jest.fn(); + onFilterAdded = jest.fn(); + + wrapper = mount( + + + + + + ); + }); + + test('when clicked, it adds a filter to the timeline when running in the context of a timeline', () => { + wrapper + .find(`[data-test-subj="filter-${hoverAction}-value"]`) + .first() + .simulate('click'); + wrapper.update(); + + expect(filterManager.addFilters).toBeCalledWith({ + meta: { + alias: null, + disabled: false, + key: 'process.name', + negate: hoverAction === 'out' ? true : false, + params: { query: 'nice' }, + type: 'phrase', + value: 'nice', + }, + query: { match: { 'process.name': { query: 'nice', type: 'phrase' } } }, + }); + }); + + test('when clicked, invokes onFilterAdded when running in the context of a timeline', () => { + wrapper + .find(`[data-test-subj="filter-${hoverAction}-value"]`) + .first() + .simulate('click'); + wrapper.update(); + + expect(onFilterAdded).toBeCalled(); + }); + }); + + describe('when NOT run in the context of a timeline', () => { + let wrapper: ReactWrapper; + let onFilterAdded: () => void; + const kibana = useKibana(); + + beforeEach(() => { + kibana.services.data.query.filterManager.addFilters = jest.fn(); + onFilterAdded = jest.fn(); + + wrapper = mount( + + + + ); + }); + + test('when clicked, it adds a filter to the global filters when NOT running in the context of a timeline', () => { + wrapper + .find(`[data-test-subj="filter-${hoverAction}-value"]`) + .first() + .simulate('click'); + wrapper.update(); + + expect(kibana.services.data.query.filterManager.addFilters).toBeCalledWith({ + meta: { + alias: null, + disabled: false, + key: 'process.name', + negate: hoverAction === 'out' ? true : false, + params: { query: 'nice' }, + type: 'phrase', + value: 'nice', + }, + query: { match: { 'process.name': { query: 'nice', type: 'phrase' } } }, + }); + }); + + test('when clicked, invokes onFilterAdded when NOT running in the context of a timeline', () => { + wrapper + .find(`[data-test-subj="filter-${hoverAction}-value"]`) + .first() + .simulate('click'); + wrapper.update(); + + expect(onFilterAdded).toBeCalled(); + }); + }); + + describe('an empty string value when run in the context of a timeline', () => { + let filterManager: FilterManager; + let wrapper: ReactWrapper; + let onFilterAdded: () => void; + + beforeEach(() => { + filterManager = new FilterManager(mockUiSettingsForFilterManager); + filterManager.addFilters = jest.fn(); + onFilterAdded = jest.fn(); + + wrapper = mount( + + + + + + ); + }); + + const expectedFilterTypeDescription = + hoverAction === 'for' ? 'a "NOT exists"' : 'an "exists"'; + test(`when clicked, it adds ${expectedFilterTypeDescription} filter to the timeline when run in the context of a timeline`, () => { + const expected = + hoverAction === 'for' + ? { + exists: { field: 'process.name' }, + meta: { + alias: null, + disabled: false, + key: 'process.name', + negate: true, + type: 'exists', + value: 'exists', + }, + } + : { + exists: { field: 'process.name' }, + meta: { + alias: null, + disabled: false, + key: 'process.name', + negate: false, + type: 'exists', + value: 'exists', + }, + }; + + wrapper + .find(`[data-test-subj="filter-${hoverAction}-value"]`) + .first() + .simulate('click'); + wrapper.update(); + + expect(filterManager.addFilters).toBeCalledWith(expected); + }); + }); + + describe('an empty string value when NOT run in the context of a timeline', () => { + let wrapper: ReactWrapper; + let onFilterAdded: () => void; + const kibana = useKibana(); + + beforeEach(() => { + kibana.services.data.query.filterManager.addFilters = jest.fn(); + onFilterAdded = jest.fn(); + + wrapper = mount( + + + + ); + }); + + const expectedFilterTypeDescription = + hoverAction === 'for' ? 'a "NOT exists"' : 'an "exists"'; + test(`when clicked, it adds ${expectedFilterTypeDescription} filter to the global filters when NOT running in the context of a timeline`, () => { + const expected = + hoverAction === 'for' + ? { + exists: { field: 'process.name' }, + meta: { + alias: null, + disabled: false, + key: 'process.name', + negate: true, + type: 'exists', + value: 'exists', + }, + } + : { + exists: { field: 'process.name' }, + meta: { + alias: null, + disabled: false, + key: 'process.name', + negate: false, + type: 'exists', + value: 'exists', + }, + }; + + wrapper + .find(`[data-test-subj="filter-${hoverAction}-value"]`) + .first() + .simulate('click'); + wrapper.update(); + + expect(kibana.services.data.query.filterManager.addFilters).toBeCalledWith(expected); + }); + }); + }); + }); + + describe('Top N', () => { + test(`it renders the 'Show top field' button when showTopN is false and an aggregatable string field is provided`, async () => { + const aggregatableStringField = 'cloud.account.id'; + const wrapper = mount( + + + + + + ); + + await wait(); // https://github.com/apollographql/react-apollo/issues/1711 + wrapper.update(); + + expect( + wrapper + .find('[data-test-subj="show-top-field"]') + .first() + .exists() + ).toBe(true); + }); + + test(`it renders the 'Show top field' button when showTopN is false and a whitelisted signal field is provided`, async () => { + const whitelistedField = 'signal.rule.name'; + const wrapper = mount( + + + + + + ); + + await wait(); + wrapper.update(); + + expect( + wrapper + .find('[data-test-subj="show-top-field"]') + .first() + .exists() + ).toBe(true); + }); + + test(`it does NOT render the 'Show top field' button when showTopN is false and a field not known to BrowserFields is provided`, async () => { + const notKnownToBrowserFields = 'unknown.field'; + const wrapper = mount( + + + + + + ); + + await wait(); + wrapper.update(); + + expect( + wrapper + .find('[data-test-subj="show-top-field"]') + .first() + .exists() + ).toBe(false); + }); + + test(`invokes the toggleTopN function when the 'Show top field' button is clicked`, async () => { + const toggleTopN = jest.fn(); + const whitelistedField = 'signal.rule.name'; + const wrapper = mount( + + + + + + ); + + await wait(); + wrapper.update(); + + wrapper + .find('[data-test-subj="show-top-field"]') + .first() + .simulate('click'); + wrapper.update(); + + expect(toggleTopN).toBeCalled(); + }); + + test(`it does NOT render the Top N histogram when when showTopN is false`, async () => { + const whitelistedField = 'signal.rule.name'; + const wrapper = mount( + + + + + + ); + + await wait(); + wrapper.update(); + + expect( + wrapper + .find('[data-test-subj="eventsByDatasetOverviewPanel"]') + .first() + .exists() + ).toBe(false); + }); + + test(`it does NOT render the 'Show top field' button when showTopN is true`, async () => { + const whitelistedField = 'signal.rule.name'; + const wrapper = mount( + + + + + + ); + + await wait(); + wrapper.update(); + + expect( + wrapper + .find('[data-test-subj="show-top-field"]') + .first() + .exists() + ).toBe(false); + }); + + test(`it renders the Top N histogram when when showTopN is true`, async () => { + const whitelistedField = 'signal.rule.name'; + const wrapper = mount( + + + + + + ); + + await wait(); + wrapper.update(); + + expect( + wrapper + .find('[data-test-subj="eventsByDatasetOverview-uuid.v4()Panel"]') + .first() + .exists() + ).toBe(true); + }); + }); + + describe('Copy to Clipboard', () => { + test(`it renders the 'Copy to Clipboard' button when showTopN is false`, () => { + const wrapper = mount( + + + + ); + + expect( + wrapper + .find(`[data-test-subj="copy-to-clipboard"]`) + .first() + .exists() + ).toBe(true); + }); + + test(`it does NOT render the 'Copy to Clipboard' button when showTopN is true`, () => { + const wrapper = mount( + + + + ); + + expect( + wrapper + .find(`[data-test-subj="copy-to-clipboard"]`) + .first() + .exists() + ).toBe(false); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper_hover_content.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper_hover_content.tsx new file mode 100644 index 0000000000000..40725bea498f1 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper_hover_content.tsx @@ -0,0 +1,145 @@ +/* + * 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 { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; +import React, { useCallback, useMemo } from 'react'; + +import { getAllFieldsByName, WithSource } from '../../containers/source'; +import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard'; +import { useKibana } from '../../lib/kibana'; +import { createFilter } from '../page/add_filter_to_global_search_bar'; +import { useTimelineContext } from '../timeline/timeline_context'; +import { StatefulTopN } from '../top_n'; + +import { allowTopN } from './helpers'; +import * as i18n from './translations'; + +interface Props { + field: string; + onFilterAdded?: () => void; + showTopN: boolean; + toggleTopN: () => void; + value?: string[] | string | null; +} + +const DraggableWrapperHoverContentComponent: React.FC = ({ + field, + onFilterAdded, + showTopN, + toggleTopN, + value, +}) => { + const kibana = useKibana(); + const { filterManager: timelineFilterManager } = useTimelineContext(); + const filterManager = useMemo(() => kibana.services.data.query.filterManager, [ + kibana.services.data.query.filterManager, + ]); + + const filterForValue = useCallback(() => { + const filter = + value?.length === 0 ? createFilter(field, undefined) : createFilter(field, value); + const activeFilterManager = timelineFilterManager ?? filterManager; + + if (activeFilterManager != null) { + activeFilterManager.addFilters(filter); + + if (onFilterAdded != null) { + onFilterAdded(); + } + } + }, [field, value, timelineFilterManager, filterManager, onFilterAdded]); + + const filterOutValue = useCallback(() => { + const filter = + value?.length === 0 ? createFilter(field, null, false) : createFilter(field, value, true); + const activeFilterManager = timelineFilterManager ?? filterManager; + + if (activeFilterManager != null) { + activeFilterManager.addFilters(filter); + + if (onFilterAdded != null) { + onFilterAdded(); + } + } + }, [field, value, timelineFilterManager, filterManager, onFilterAdded]); + + return ( + <> + {!showTopN && value != null && ( + + + + )} + + {!showTopN && value != null && ( + + + + )} + + + {({ browserFields }) => ( + <> + {allowTopN({ + browserField: getAllFieldsByName(browserFields)[field], + fieldName: field, + }) && ( + <> + {!showTopN && ( + + + + )} + + {showTopN && ( + + )} + + )} + + )} + + + {!showTopN && ( + + + + )} + + ); +}; + +DraggableWrapperHoverContentComponent.displayName = 'DraggableWrapperHoverContentComponent'; + +export const DraggableWrapperHoverContent = React.memo(DraggableWrapperHoverContentComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/helpers.test.ts b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/helpers.test.ts index af4b9b280f3cd..753fa5b54eade 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/helpers.test.ts +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/helpers.test.ts @@ -4,7 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ +import { omit } from 'lodash/fp'; + import { + allowTopN, destinationIsTimelineButton, destinationIsTimelineColumns, destinationIsTimelineProviders, @@ -717,4 +720,96 @@ describe('helpers', () => { expect(escaped).toEqual('hello.how.are.you?'); }); }); + + describe('#allowTopN', () => { + const aggregatableAllowedType = { + category: 'cloud', + description: + 'The cloud account or organization id used to identify different entities in a multi-tenant environment. Examples: AWS account id, Google Cloud ORG Id, or other unique identifier.', + example: '666777888999', + indexes: ['auditbeat', 'filebeat', 'packetbeat'], + name: 'cloud.account.id', + searchable: true, + type: 'string', + aggregatable: true, + format: '', + }; + + test('it returns true for an aggregatable field that is an allowed type', () => { + expect( + allowTopN({ + browserField: aggregatableAllowedType, + fieldName: aggregatableAllowedType.name, + }) + ).toBe(true); + }); + + test('it returns true for a whitelisted non-BrowserField', () => { + expect( + allowTopN({ + browserField: undefined, + fieldName: 'signal.rule.name', + }) + ).toBe(true); + }); + + test('it returns false for a NON-aggregatable field that is an allowed type', () => { + const nonAggregatableAllowedType = { + ...aggregatableAllowedType, + aggregatable: false, + }; + + expect( + allowTopN({ + browserField: nonAggregatableAllowedType, + fieldName: nonAggregatableAllowedType.name, + }) + ).toBe(false); + }); + + test('it returns false for a aggregatable field that is NOT an allowed type', () => { + const aggregatableNotAllowedType = { + ...aggregatableAllowedType, + type: 'not-an-allowed-type', + }; + + expect( + allowTopN({ + browserField: aggregatableNotAllowedType, + fieldName: aggregatableNotAllowedType.name, + }) + ).toBe(false); + }); + + test('it returns false if the BrowserField is missing the aggregatable property', () => { + const missingAggregatable = omit('aggregatable', aggregatableAllowedType); + + expect( + allowTopN({ + browserField: missingAggregatable, + fieldName: missingAggregatable.name, + }) + ).toBe(false); + }); + + test('it returns false if the BrowserField is missing the type property', () => { + const missingType = omit('type', aggregatableAllowedType); + + expect( + allowTopN({ + browserField: missingType, + fieldName: missingType.name, + }) + ).toBe(false); + }); + + test('it returns false for a non-whitelisted field when a BrowserField is not provided', () => { + expect( + allowTopN({ + browserField: undefined, + fieldName: 'non-whitelisted', + }) + ).toBe(false); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/helpers.ts b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/helpers.ts index 82ddd2c9f29d7..cd3d7cc68d537 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/helpers.ts @@ -9,7 +9,7 @@ import { DropResult } from 'react-beautiful-dnd'; import { Dispatch } from 'redux'; import { ActionCreator } from 'typescript-fsa'; -import { BrowserFields, getAllFieldsByName } from '../../containers/source'; +import { BrowserField, BrowserFields, getAllFieldsByName } from '../../containers/source'; import { IdToDataProvider } from '../../store/drag_and_drop/model'; import { ColumnHeaderOptions } from '../../store/timeline/model'; import { DEFAULT_COLUMN_MIN_WIDTH } from '../timeline/body/constants'; @@ -227,3 +227,98 @@ export const IS_DRAGGING_CLASS_NAME = 'is-dragging'; /** This class is added to the document body while timeline field dragging */ export const IS_TIMELINE_FIELD_DRAGGING_CLASS_NAME = 'is-timeline-field-dragging'; + +export const allowTopN = ({ + browserField, + fieldName, +}: { + browserField: Partial | undefined; + fieldName: string; +}): boolean => { + const isAggregatable = browserField?.aggregatable ?? false; + const fieldType = browserField?.type ?? ''; + const isAllowedType = [ + 'boolean', + 'geo-point', + 'geo-shape', + 'ip', + 'keyword', + 'number', + 'numeric', + 'string', + ].includes(fieldType); + + // TODO: remove this explicit whitelist when the ECS documentation includes signals + const isWhitelistedNonBrowserField = [ + 'signal.ancestors.depth', + 'signal.ancestors.id', + 'signal.ancestors.rule', + 'signal.ancestors.type', + 'signal.original_event.action', + 'signal.original_event.category', + 'signal.original_event.code', + 'signal.original_event.created', + 'signal.original_event.dataset', + 'signal.original_event.duration', + 'signal.original_event.end', + 'signal.original_event.hash', + 'signal.original_event.id', + 'signal.original_event.kind', + 'signal.original_event.module', + 'signal.original_event.original', + 'signal.original_event.outcome', + 'signal.original_event.provider', + 'signal.original_event.risk_score', + 'signal.original_event.risk_score_norm', + 'signal.original_event.sequence', + 'signal.original_event.severity', + 'signal.original_event.start', + 'signal.original_event.timezone', + 'signal.original_event.type', + 'signal.original_time', + 'signal.parent.depth', + 'signal.parent.id', + 'signal.parent.index', + 'signal.parent.rule', + 'signal.parent.type', + 'signal.rule.created_by', + 'signal.rule.description', + 'signal.rule.enabled', + 'signal.rule.false_positives', + 'signal.rule.filters', + 'signal.rule.from', + 'signal.rule.id', + 'signal.rule.immutable', + 'signal.rule.index', + 'signal.rule.interval', + 'signal.rule.language', + 'signal.rule.max_signals', + 'signal.rule.name', + 'signal.rule.note', + 'signal.rule.output_index', + 'signal.rule.query', + 'signal.rule.references', + 'signal.rule.risk_score', + 'signal.rule.rule_id', + 'signal.rule.saved_id', + 'signal.rule.severity', + 'signal.rule.size', + 'signal.rule.tags', + 'signal.rule.threat', + 'signal.rule.threat.tactic.id', + 'signal.rule.threat.tactic.name', + 'signal.rule.threat.tactic.reference', + 'signal.rule.threat.technique.id', + 'signal.rule.threat.technique.name', + 'signal.rule.threat.technique.reference', + 'signal.rule.timeline_id', + 'signal.rule.timeline_title', + 'signal.rule.to', + 'signal.rule.type', + 'signal.rule.updated_by', + 'signal.rule.version', + 'signal.status', + ].includes(fieldName); + + return isWhitelistedNonBrowserField || (isAggregatable && isAllowedType); +}; diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/translations.ts b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/translations.ts new file mode 100644 index 0000000000000..61d036635a250 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/translations.ts @@ -0,0 +1,33 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const COPY_TO_CLIPBOARD = i18n.translate('xpack.siem.dragAndDrop.copyToClipboardTooltip', { + defaultMessage: 'Copy to Clipboard', +}); + +export const FIELD = i18n.translate('xpack.siem.dragAndDrop.fieldLabel', { + defaultMessage: 'Field', +}); + +export const FILTER_FOR_VALUE = i18n.translate('xpack.siem.dragAndDrop.filterForValueHoverAction', { + defaultMessage: 'Filter for value', +}); + +export const FILTER_OUT_VALUE = i18n.translate('xpack.siem.dragAndDrop.filterOutValueHoverAction', { + defaultMessage: 'Filter out value', +}); + +export const CLOSE = i18n.translate('xpack.siem.dragAndDrop.closeButtonLabel', { + defaultMessage: 'Close', +}); + +export const SHOW_TOP = (fieldName: string) => + i18n.translate('xpack.siem.overview.showTopTooltip', { + values: { fieldName }, + defaultMessage: `Show top {fieldName}`, + }); diff --git a/x-pack/legacy/plugins/siem/public/components/draggables/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/draggables/__snapshots__/index.test.tsx.snap index 63ba13306ecd8..93608a181adff 100644 --- a/x-pack/legacy/plugins/siem/public/components/draggables/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/draggables/__snapshots__/index.test.tsx.snap @@ -10,6 +10,7 @@ exports[`draggables rendering it renders the default Badge 1`] = ` A child of this diff --git a/x-pack/legacy/plugins/siem/public/components/draggables/index.tsx b/x-pack/legacy/plugins/siem/public/components/draggables/index.tsx index 1fe6c936d2823..a0b825ea24441 100644 --- a/x-pack/legacy/plugins/siem/public/components/draggables/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/draggables/index.tsx @@ -167,7 +167,7 @@ export const DraggableBadge = React.memo( tooltipContent={tooltipContent} queryValue={queryValue} > - + {children ? children : value !== '' ? value : getEmptyStringTag()} diff --git a/x-pack/legacy/plugins/siem/public/components/event_details/columns.tsx b/x-pack/legacy/plugins/siem/public/components/event_details/columns.tsx index cd94a9fdcb5ac..131a3a63bae30 100644 --- a/x-pack/legacy/plugins/siem/public/components/event_details/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/event_details/columns.tsx @@ -21,7 +21,6 @@ import styled from 'styled-components'; import { BrowserFields } from '../../containers/source'; import { ToStringArray } from '../../graphql/types'; -import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard'; import { ColumnHeaderOptions } from '../../store/timeline/model'; import { DragEffects } from '../drag_and_drop/draggable_wrapper'; import { DroppableWrapper } from '../drag_and_drop/droppable_wrapper'; @@ -35,7 +34,6 @@ import { DEFAULT_COLUMN_MIN_WIDTH } from '../timeline/body/constants'; import { MESSAGE_FIELD_NAME } from '../timeline/body/renderers/constants'; import { FormattedFieldValue } from '../timeline/body/renderers/formatted_field'; import { OnUpdateColumns } from '../timeline/events'; -import { WithHoverActions } from '../with_hover_actions'; import { getIconFromType, getExampleText, getColumnsWithTimestamp } from './helpers'; import * as i18n from './translations'; import { EventFieldsData } from './types'; @@ -172,29 +170,18 @@ export const getColumns = ({ component="span" key={`event-details-value-flex-item-${contextId}-${eventId}-${data.field}-${i}-${value}`} > - - - - - - } - render={() => - data.field === MESSAGE_FIELD_NAME ? ( - - ) : ( - - ) - } - /> + {data.field === MESSAGE_FIELD_NAME ? ( + + ) : ( + + )} ))} diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx index ea2cb661763fa..d210c749dae9c 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx @@ -95,6 +95,7 @@ const EventsViewerComponent: React.FC = ({ }) => { const columnsHeader = isEmpty(columns) ? defaultHeaders : columns; const kibana = useKibana(); + const { filterManager } = useKibana().services.data.query; const combinedQueries = combineQueries({ config: esQuery.getEsQueryConfig(kibana.services.uiSettings), dataProviders, @@ -168,7 +169,11 @@ const EventsViewerComponent: React.FC = ({ {utilityBar?.(refetch, totalCountMinusDeleted)} - + { }); }); - test('it renders a hover actions panel for the category name', () => { - const wrapper = mount( - - - - ); - expect( - wrapper - .find('[data-test-subj="category-link"]') - .first() - .find('[data-test-subj="hover-actions-panel-container"]') - .first() - .exists() - ).toBe(true); - }); - test('it renders the selected category with bold text', () => { const selectedCategoryId = 'auditd'; diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.tsx index 0c7dd7e908ce3..7133e9b848c5c 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.tsx @@ -6,15 +6,7 @@ /* eslint-disable react/display-name */ -import { - EuiIcon, - EuiFlexGroup, - EuiFlexItem, - EuiLink, - EuiPanel, - EuiText, - EuiToolTip, -} from '@elastic/eui'; +import { EuiIcon, EuiFlexGroup, EuiFlexItem, EuiLink, EuiText, EuiToolTip } from '@elastic/eui'; import React, { useContext } from 'react'; import styled from 'styled-components'; @@ -35,22 +27,6 @@ const CategoryName = styled.span<{ bold: boolean }>` CategoryName.displayName = 'CategoryName'; -const HoverActionsContainer = styled(EuiPanel)` - cursor: default; - left: 5px; - padding: 8px; - position: absolute; - top: -8px; -`; - -HoverActionsContainer.displayName = 'HoverActionsContainer'; - -const HoverActionsFlexGroup = styled(EuiFlexGroup)` - cursor: pointer; -`; - -HoverActionsFlexGroup.displayName = 'HoverActionsFlexGroup'; - const LinkContainer = styled.div` width: 100%; .euiLink { @@ -71,7 +47,7 @@ interface ToolTipProps { } const ToolTip = React.memo(({ categoryId, browserFields, onUpdateColumns }) => { - const isLoading = useContext(TimelineContext); + const { isLoading } = useContext(TimelineContext); return ( {!isLoading ? ( @@ -127,25 +103,11 @@ export const getCategoryColumns = ({ - - - - - - + } render={() => ( { expect(wrapper.find('[data-test-subj="copy-to-clipboard"]').exists()).toBe(true); }); - test('it renders a view category action menu item a user hovers over the name', () => { - const wrapper = mount( - - - - ); - - wrapper.simulate('mouseenter'); - wrapper.update(); - expect(wrapper.find('[data-test-subj="view-category"]').exists()).toBe(true); - }); - - test('it invokes onUpdateColumns when the view category action menu item is clicked', () => { - const onUpdateColumns = jest.fn(); - - const wrapper = mount( - - - - ); - - wrapper.simulate('mouseenter'); - wrapper.update(); - wrapper - .find('[data-test-subj="view-category"]') - .first() - .simulate('click'); - - expect(onUpdateColumns).toBeCalledWith([ - { - aggregatable: true, - category: 'base', - columnHeaderType: 'not-filtered', - description: - 'Date/time when the event originated. For log events this is the date/time when the event was generated, and not when it was read. Required field for all events.', - example: '2016-05-23T08:05:34.853Z', - id: '@timestamp', - type: 'date', - width: 190, - }, - ]); - }); - test('it highlights the text specified by the `highlight` prop', () => { const highlight = 'stamp'; diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/field_name.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/field_name.tsx index fe434a6ad63ce..fc9633b6f8748 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/field_name.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/field_name.tsx @@ -4,26 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiButtonIcon, - EuiHighlight, - EuiIcon, - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiText, - EuiToolTip, -} from '@elastic/eui'; -import React, { useContext } from 'react'; +import { EuiButtonIcon, EuiHighlight, EuiIcon, EuiText, EuiToolTip } from '@elastic/eui'; +import React, { useCallback, useContext, useState, useMemo } from 'react'; import styled from 'styled-components'; -import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard'; import { ColumnHeaderOptions } from '../../store/timeline/model'; import { OnUpdateColumns } from '../timeline/events'; import { TimelineContext } from '../timeline/timeline_context'; import { WithHoverActions } from '../with_hover_actions'; import { LoadingSpinner } from './helpers'; import * as i18n from './translations'; +import { DraggableWrapperHoverContent } from '../drag_and_drop/draggable_wrapper_hover_content'; /** * The name of a (draggable) field @@ -82,22 +73,6 @@ export const FieldNameContainer = styled.span` FieldNameContainer.displayName = 'FieldNameContainer'; -const HoverActionsContainer = styled(EuiPanel)` - cursor: default; - left: 5px; - padding: 4px; - position: absolute; - top: -6px; -`; - -HoverActionsContainer.displayName = 'HoverActionsContainer'; - -const HoverActionsFlexGroup = styled(EuiFlexGroup)` - cursor: pointer; -`; - -HoverActionsFlexGroup.displayName = 'HoverActionsFlexGroup'; - const ViewCategoryIcon = styled(EuiIcon)` margin-left: 5px; `; @@ -112,7 +87,7 @@ interface ToolTipProps { const ViewCategory = React.memo( ({ categoryId, onUpdateColumns, categoryColumns }) => { - const isLoading = useContext(TimelineContext); + const { isLoading } = useContext(TimelineContext); return ( {!isLoading ? ( @@ -142,48 +117,33 @@ export const FieldName = React.memo<{ fieldId: string; highlight?: string; onUpdateColumns: OnUpdateColumns; -}>(({ categoryId, categoryColumns, fieldId, highlight = '', onUpdateColumns }) => ( - - - - - - - - - {categoryColumns.length > 0 && ( - - - - )} - - - } - render={() => ( - - +}>(({ fieldId, highlight = '' }) => { + const [showTopN, setShowTopN] = useState(false); + const toggleTopN = useCallback(() => { + setShowTopN(!showTopN); + }, [setShowTopN, showTopN]); + + const hoverContent = useMemo( + () => ( + + ), + [fieldId, showTopN, toggleTopN] + ); + + const render = useCallback( + () => ( + + {fieldId} - - - )} - /> -)); + + + ), + [fieldId, highlight] + ); + + return ; +}); FieldName.displayName = 'FieldName'; diff --git a/x-pack/legacy/plugins/siem/public/components/header_page/title.tsx b/x-pack/legacy/plugins/siem/public/components/header_page/title.tsx index a1f3cfd857148..59039ddd6a23b 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_page/title.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_page/title.tsx @@ -51,7 +51,9 @@ const TitleComponent: React.FC = ({ draggableArguments, title, badgeOptio tooltipPosition="bottom" /> ) : ( - {badgeOptions.text} + + {badgeOptions.text} + )} )} diff --git a/x-pack/legacy/plugins/siem/public/components/header_section/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/header_section/__snapshots__/index.test.tsx.snap index d4c3763f51460..53b41e2240de2 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_section/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/header_section/__snapshots__/index.test.tsx.snap @@ -11,13 +11,18 @@ exports[`HeaderSection it renders 1`] = ` responsive={false} > - +

Test title

+
diff --git a/x-pack/legacy/plugins/siem/public/components/header_section/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/header_section/index.test.tsx index bc4692b6fe0c5..e61b39691203c 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_section/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_section/index.test.tsx @@ -48,7 +48,7 @@ describe('HeaderSection', () => { ).toBe(true); }); - test('it DOES NOT render the subtitle when not provided', () => { + test('renders the subtitle when not provided (to prevent layout thrash)', () => { const wrapper = mount( @@ -60,7 +60,7 @@ describe('HeaderSection', () => { .find('[data-test-subj="header-section-subtitle"]') .first() .exists() - ).toBe(false); + ).toBe(true); }); test('it renders supplements when children provided', () => { diff --git a/x-pack/legacy/plugins/siem/public/components/header_section/index.tsx b/x-pack/legacy/plugins/siem/public/components/header_section/index.tsx index 3153e785a8a32..43245121dd393 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_section/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_section/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiTitle } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiTitle, EuiTitleSize } from '@elastic/eui'; import React from 'react'; import styled, { css } from 'styled-components'; @@ -36,6 +36,7 @@ export interface HeaderSectionProps extends HeaderProps { split?: boolean; subtitle?: string | React.ReactNode; title: string | React.ReactNode; + titleSize?: EuiTitleSize; tooltip?: string; } @@ -46,6 +47,7 @@ const HeaderSectionComponent: React.FC = ({ split, subtitle, title, + titleSize = 'm', tooltip, }) => (
@@ -53,7 +55,7 @@ const HeaderSectionComponent: React.FC = ({ - +

{title} {tooltip && ( @@ -65,7 +67,7 @@ const HeaderSectionComponent: React.FC = ({

- {subtitle && } +
{id && ( diff --git a/x-pack/legacy/plugins/siem/public/components/links/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/links/index.test.tsx index d2d1d6569854d..214c0294f2cf4 100644 --- a/x-pack/legacy/plugins/siem/public/components/links/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/links/index.test.tsx @@ -24,6 +24,8 @@ import { ExternalLink, } from '.'; +jest.mock('../../pages/overview/events_by_dataset'); + jest.mock('../../lib/kibana', () => { return { useUiSetting$: jest.fn(), diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/__snapshots__/index.test.tsx.snap index 0e518e48e2e88..5aa846d15b684 100644 --- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/__snapshots__/index.test.tsx.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Matrix Histogram Component not initial load it renders no MatrixLoader 1`] = `"
"`; +exports[`Matrix Histogram Component not initial load it renders no MatrixLoader 1`] = `"
"`; -exports[`Matrix Histogram Component on initial load it renders MatrixLoader 1`] = `"
"`; +exports[`Matrix Histogram Component on initial load it renders MatrixLoader 1`] = `"
"`; diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.test.tsx index db5b1f7f03ee3..3b8a43a0f395a 100644 --- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.test.tsx @@ -87,6 +87,17 @@ describe('Matrix Histogram Component', () => { }); }); + describe('spacer', () => { + test('it renders a spacer by default', () => { + expect(wrapper.find('[data-test-subj="spacer"]').exists()).toBe(true); + }); + + test('it does NOT render a spacer when showSpacer is false', () => { + wrapper = mount(); + expect(wrapper.find('[data-test-subj="spacer"]').exists()).toBe(false); + }); + }); + describe('not initial load', () => { beforeAll(() => { (useQuery as jest.Mock).mockReturnValue({ diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx index 12a474009dc5b..3d4eebd68319c 100644 --- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx @@ -37,6 +37,7 @@ import { import { SetQuery } from '../../pages/hosts/navigation/types'; import { QueryTemplateProps } from '../../containers/query_template'; import { setAbsoluteRangeDatePicker } from '../../store/inputs/actions'; +import { InputsModelId } from '../../store/inputs/constants'; import { HistogramType } from '../../graphql/types'; export interface OwnProps extends QueryTemplateProps { @@ -46,9 +47,12 @@ export interface OwnProps extends QueryTemplateProps { hideHistogramIfEmpty?: boolean; histogramType: HistogramType; id: string; + indexToAdd?: string[] | null; legendPosition?: Position; mapping?: MatrixHistogramMappingTypes; + showSpacer?: boolean; setQuery: SetQuery; + setAbsoluteRangeDatePickerTarget?: InputsModelId; showLegend?: boolean; stackByOptions: MatrixHistogramOption[]; subtitle?: string | GetSubTitle; @@ -62,6 +66,7 @@ const HeaderChildrenFlexItem = styled(EuiFlexItem)` margin-left: 24px; `; +// @ts-ignore - the EUI type definitions for Panel do no play nice with styled-components const HistogramPanel = styled(Panel)<{ height?: number }>` display: flex; flex-direction: column; @@ -79,16 +84,20 @@ export const MatrixHistogramComponent: React.FC { @@ -100,7 +109,11 @@ export const MatrixHistogramComponent: React.FC { - dispatchSetAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + dispatchSetAbsoluteRangeDatePicker({ + id: setAbsoluteRangeDatePickerTarget, + from: min, + to: max, + }); }, yTickFormatter, showLegend, @@ -122,7 +135,7 @@ export const MatrixHistogramComponent: React.FC) => { setSelectedStackByOption( - stackByOptions?.find(co => co.value === event.target.value) ?? defaultStackByOption + stackByOptions.find(co => co.value === event.target.value) ?? defaultStackByOption ); }, [] @@ -134,6 +147,7 @@ export const MatrixHistogramComponent: React.FC (title != null && typeof title === 'function' ? title(selectedStackByOption) : title), [title, selectedStackByOption] ); - const subtitleWithCounts = useMemo( - () => (subtitle != null && typeof subtitle === 'function' ? subtitle(totalCount) : subtitle), - [subtitle, totalCount] - ); + const subtitleWithCounts = useMemo(() => { + if (isInitialLoading) { + return null; + } + + if (typeof subtitle === 'function') { + return totalCount >= 0 ? subtitle(totalCount) : null; + } + + return subtitle; + }, [isInitialLoading, subtitle, totalCount]); const hideHistogram = useMemo(() => (totalCount <= 0 && hideHistogramIfEmpty ? true : false), [ totalCount, hideHistogramIfEmpty, @@ -155,7 +176,9 @@ export const MatrixHistogramComponent: React.FC getCustomChartData(data, mapping), [data, mapping]); useEffect(() => { - setQuery({ id, inspect, loading, refetch }); + if (!loading && !isInitialLoading) { + setQuery({ id, inspect, loading, refetch }); + } if (isInitialLoading && !!barChartData && data) { setIsInitialLoading(false); @@ -189,59 +212,39 @@ export const MatrixHistogramComponent: React.FC )} + + + + {stackByOptions.length > 1 && ( + + )} + + {headerChildren} + + + {isInitialLoading ? ( - <> - = 0 ? subtitleWithCounts : null)} - > - - - {stackByOptions?.length > 1 && ( - - )} - - {headerChildren} - - - - + ) : ( - <> - = 0 ? subtitleWithCounts : null) - } - > - - - {stackByOptions?.length > 1 && ( - - )} - - {headerChildren} - - - - + )} - + {showSpacer && } ); }; diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/types.ts b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/types.ts index a435c7be6c890..c59775ad325d0 100644 --- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/types.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { EuiTitleSize } from '@elastic/eui'; import { ScaleType, Position, TickFormatter } from '@elastic/charts'; import { ActionCreator } from 'redux'; import { ESQuery } from '../../../common/typed_json'; @@ -34,6 +35,7 @@ export interface MatrixHisrogramConfigs { stackByOptions: MatrixHistogramOption[]; subtitle?: string | GetSubTitle; title: string | GetTitle; + titleSize?: EuiTitleSize; } interface MatrixHistogramBasicProps { @@ -57,14 +59,22 @@ interface MatrixHistogramBasicProps { stackByOptions: MatrixHistogramOption[]; subtitle?: string | GetSubTitle; title?: string | GetTitle; + titleSize?: EuiTitleSize; } export interface MatrixHistogramQueryProps { endDate: number; errorMessage: string; filterQuery?: ESQuery | string | undefined; + setAbsoluteRangeDatePicker?: ActionCreator<{ + id: InputsModelId; + from: number; + to: number; + }>; + setAbsoluteRangeDatePickerTarget?: InputsModelId; stackByField: string; startDate: number; + indexToAdd?: string[] | null; isInspected: boolean; histogramType: HistogramType; } @@ -73,6 +83,7 @@ export interface MatrixHistogramProps extends MatrixHistogramBasicProps { scaleType?: ScaleType; yTickFormatter?: (value: number) => string; showLegend?: boolean; + showSpacer?: boolean; legendPosition?: Position; } diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts index ddac615cef50a..d31eb1da15ea1 100644 --- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/utils.ts @@ -69,6 +69,19 @@ export const getBarchartConfigs = ({ customHeight: chartHeight ?? DEFAULT_CHART_HEIGHT, }); +export const defaultLegendColors = [ + '#1EA593', + '#2B70F7', + '#CE0060', + '#38007E', + '#FCA5D3', + '#F37020', + '#E49E29', + '#B0916F', + '#7B000B', + '#34130C', +]; + export const formatToChartDataItem = ([key, value]: [ string, MatrixOverTimeHistogramData[] diff --git a/x-pack/legacy/plugins/siem/public/components/notes/note_card/note_card_body.tsx b/x-pack/legacy/plugins/siem/public/components/notes/note_card/note_card_body.tsx index 11761c8fd39b0..4463f8d4ff602 100644 --- a/x-pack/legacy/plugins/siem/public/components/notes/note_card/note_card_body.tsx +++ b/x-pack/legacy/plugins/siem/public/components/notes/note_card/note_card_body.tsx @@ -5,7 +5,7 @@ */ import { EuiPanel, EuiToolTip } from '@elastic/eui'; -import React from 'react'; +import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; import { WithCopyToClipboard } from '../../../lib/clipboard/with_copy_to_clipboard'; @@ -19,33 +19,23 @@ const BodyContainer = styled(EuiPanel)` BodyContainer.displayName = 'BodyContainer'; -const HoverActionsContainer = styled(EuiPanel)` - align-items: center; - display: flex; - flex-direction: row; - height: 25px; - justify-content: center; - left: 5px; - position: absolute; - top: -5px; - width: 30px; -`; - -HoverActionsContainer.displayName = 'HoverActionsContainer'; - -export const NoteCardBody = React.memo<{ rawNote: string }>(({ rawNote }) => ( - - - - - - - } - render={() => } - /> - -)); +export const NoteCardBody = React.memo<{ rawNote: string }>(({ rawNote }) => { + const hoverContent = useMemo( + () => ( + + + + ), + [rawNote] + ); + + const render = useCallback(() => , [rawNote]); + + return ( + + + + ); +}); NoteCardBody.displayName = 'NoteCardBody'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/__snapshots__/index.test.tsx.snap index 42ef4e5404faa..ef02311c0629e 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/__snapshots__/index.test.tsx.snap @@ -3,22 +3,36 @@ exports[`AddFilterToGlobalSearchBar Component Rendering 1`] = ` - - + + + + } render={[Function]} /> diff --git a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.test.tsx index 7e5e53f575be8..5c920d923d9a4 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.test.tsx @@ -24,6 +24,22 @@ describe('helpers', () => { }); }); + test('returns a negated filter when `negate` is true', () => { + const filter = createFilter('host.name', 'siem-xavier', true); + expect(filter).toEqual({ + meta: { + alias: null, + disabled: false, + key: 'host.name', + negate: true, // <-- filter is negated + params: { query: 'siem-xavier' }, + type: 'phrase', + value: 'siem-xavier', + }, + query: { match: { 'host.name': { query: 'siem-xavier', type: 'phrase' } } }, + }); + }); + test('return valid exists filter when valid key and null value are provided', () => { const filter = createFilter('host.name', null); expect(filter).toEqual({ diff --git a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.ts b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.ts index bafe033368c83..d88bc2bf3b7e6 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/helpers.ts @@ -6,13 +6,17 @@ import { Filter } from '../../../../../../../../src/plugins/data/public'; -export const createFilter = (key: string, value: string[] | string | null | undefined): Filter => { +export const createFilter = ( + key: string, + value: string[] | string | null | undefined, + negate: boolean = false +): Filter => { const queryValue = value != null ? (Array.isArray(value) ? value[0] : value) : null; return queryValue != null ? { meta: { alias: null, - negate: false, + negate, disabled: false, type: 'phrase', key, diff --git a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.tsx index 160cd020796db..127eb3bae0284 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/index.tsx @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiIcon, EuiPanel, EuiToolTip } from '@elastic/eui'; +import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import React, { useCallback } from 'react'; -import styled from 'styled-components'; import { Filter } from '../../../../../../../../src/plugins/data/public'; import { WithHoverActions } from '../../with_hover_actions'; @@ -26,21 +25,52 @@ export const AddFilterToGlobalSearchBar = React.memo( ({ children, filter, onFilterAdded }) => { const { filterManager } = useKibana().services.data.query; - const addToKql = useCallback(() => { + const filterForValue = useCallback(() => { filterManager.addFilters(filter); + if (onFilterAdded != null) { onFilterAdded(); } - }, [filter, filterManager, onFilterAdded]); + }, [filterManager, filter, onFilterAdded]); + + const filterOutValue = useCallback(() => { + filterManager.addFilters({ + ...filter, + meta: { + ...filter.meta, + negate: true, + }, + }); + + if (onFilterAdded != null) { + onFilterAdded(); + } + }, [filterManager, filter, onFilterAdded]); return ( +
- + + + + + - +
} render={() => children} /> @@ -49,16 +79,3 @@ export const AddFilterToGlobalSearchBar = React.memo( ); AddFilterToGlobalSearchBar.displayName = 'AddFilterToGlobalSearchBar'; - -export const HoverActionsContainer = styled(EuiPanel)` - align-items: center; - display: flex; - flex-direction: row; - height: 34px; - justify-content: center; - left: 5px; - position: absolute; - top: -10px; - width: 34px; - cursor: pointer; -`; diff --git a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/translations.ts b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/translations.ts index 81772527e59db..f192c5c26fa49 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/translations.ts +++ b/x-pack/legacy/plugins/siem/public/components/page/add_filter_to_global_search_bar/translations.ts @@ -12,3 +12,10 @@ export const FILTER_FOR_VALUE = i18n.translate( defaultMessage: 'Filter for value', } ); + +export const FILTER_OUT_VALUE = i18n.translate( + 'xpack.siem.add_filter_to_global_search_bar.filterOutValueHoverAction', + { + defaultMessage: 'Filter out value', + } +); diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/columns.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/columns.tsx index 8d490d2c152d9..6bd82f3192f9b 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/columns.tsx @@ -46,9 +46,7 @@ export const getHostsColumns = (): HostsTableColumns => [ ) : ( - - - + ) } /> diff --git a/x-pack/legacy/plugins/siem/public/components/page/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/index.tsx index ef6a19f4b7448..3a36a2dce476b 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/index.tsx @@ -17,7 +17,7 @@ export const AppGlobalStyle = createGlobalStyle` position: static; } /* end of dirty hack to fix draggables with tooltip on FF */ - + div.app-wrapper { background-color: rgba(0,0,0,0); } @@ -28,12 +28,13 @@ export const AppGlobalStyle = createGlobalStyle` .euiPopover__panel.euiPopover__panel-isOpen { z-index: 9900 !important; + min-width: 24px; } .euiToolTip { z-index: 9950 !important; } - /* + /* overrides the default styling of euiComboBoxOptionsList because it's implemented as a popover, so it's not selectable as a child of the styled component */ @@ -45,6 +46,17 @@ export const AppGlobalStyle = createGlobalStyle` .euiPanel-loading-hide-border { border: none; } + + /* hide open popovers when a modal is being displayed to prevent them from covering the modal */ + body.euiBody-hasOverlayMask .euiPopover__panel-isOpen { + visibility: hidden !important; + } + + /* ensure elastic charts tooltips appear above open euiPopovers */ + .echTooltip { + z-index: 9950; + } + `; export const DescriptionListStyled = styled(EuiDescriptionList)` diff --git a/x-pack/legacy/plugins/siem/public/components/page/manage_query.tsx b/x-pack/legacy/plugins/siem/public/components/page/manage_query.tsx index 138c38c02065b..3b723c66f5af5 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/manage_query.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/manage_query.tsx @@ -42,6 +42,6 @@ export function manageQuery(WrappedComponent: React.ComponentClass | React return ; } } - ManageQuery.displayName = `ManageQuery (${WrappedComponent.displayName || 'Unknown'})`; + ManageQuery.displayName = `ManageQuery (${WrappedComponent?.displayName ?? 'Unknown'})`; return ManageQuery; } diff --git a/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx index 5cd200cbb41b7..73c3d2da184e7 100644 --- a/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import { EuiBasicTable, EuiBasicTableProps, @@ -246,21 +247,16 @@ const PaginatedTableComponent: FC = ({ ) : ( <> - { - // @ts-ignore avoid some type mismatches - } = ({ export const PaginatedTable = memo(PaginatedTableComponent); type BasicTableType = ComponentType>; // eslint-disable-line @typescript-eslint/no-explicit-any -const BasicTable: typeof EuiBasicTable & { displayName: string } = styled( - EuiBasicTable as BasicTableType -)` +const BasicTable = styled(EuiBasicTable as BasicTableType)` tbody { th, td { diff --git a/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx b/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx index b8192cce11e5a..62f01dfc020f5 100644 --- a/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx +++ b/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx @@ -171,7 +171,7 @@ export const SourceDestinationIp = React.memo( return isIpFieldPopulated({ destinationIp, sourceIp, type }) || hasPorts({ destinationPort, sourcePort, type }) ? ( - + (({ header, onColumnRemoved, sort }) => { - const isLoading = useTimelineContext(); + const { isLoading } = useTimelineContext(); return ( <> {sort.columnId === header.id && isLoading ? ( diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/header_content.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/header_content.tsx index 84781e6a24300..0a69cef618570 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/header_content.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/column_headers/header/header_content.tsx @@ -32,7 +32,7 @@ const HeaderContentComponent: React.FC = ({ onClick, sort, }) => { - const isLoading = useTimelineContext(); + const { isLoading } = useTimelineContext(); return ( diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/auditd/generic_row_renderer.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/auditd/generic_row_renderer.test.tsx index 5f59915eac418..417a078a08150 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/auditd/generic_row_renderer.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/auditd/generic_row_renderer.test.tsx @@ -19,6 +19,8 @@ import { createGenericFileRowRenderer, } from './generic_row_renderer'; +jest.mock('../../../../../pages/overview/events_by_dataset'); + describe('GenericRowRenderer', () => { const mount = useMountAppended(); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/suricata/suricata_signature.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/suricata/suricata_signature.tsx index 9ccd1fb7a0519..24c52f3372d62 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/suricata/suricata_signature.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/suricata/suricata_signature.tsx @@ -44,7 +44,7 @@ export const Tokens = React.memo<{ tokens: string[] }>(({ tokens }) => ( <> {tokens.map(token => ( - + {token} @@ -81,7 +81,7 @@ export const DraggableSignatureId = React.memo<{ id: string; signatureId: number data-test-subj="signature-id-tooltip" content={SURICATA_SIGNATURE_ID_FIELD_NAME} > - + {signatureId} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_details.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_details.tsx index e1524c8e5aecb..2ad3eb4681454 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_details.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_details.tsx @@ -119,7 +119,7 @@ export const SystemGenericLine = React.memo( - + diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_file_details.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_file_details.tsx index c47d9603cbea2..ef7c3b3ccf859 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_file_details.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_file_details.tsx @@ -193,7 +193,7 @@ export const SystemGenericFileLine = React.memo( - + diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_row_renderer.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_row_renderer.test.tsx index abe77a63f4a27..2f5fa76855f2b 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_row_renderer.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/system/generic_row_renderer.test.tsx @@ -48,6 +48,8 @@ import { } from './generic_row_renderer'; import * as i18n from './translations'; +jest.mock('../../../../../pages/overview/events_by_dataset'); + describe('GenericRowRenderer', () => { const mount = useMountAppended(); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.tsx index f13a236e8ec36..39c21c4ffa33b 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/renderers/zeek/zeek_signature.tsx @@ -92,7 +92,7 @@ export const DraggableZeekElement = React.memo<{ ) : ( - + {stringRenderer(value)} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/index.tsx index 525cc8e301d11..f369b961807af 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/index.tsx @@ -109,7 +109,7 @@ export const DataProviders = React.memo( data-test-subj="dataProviders" > - {isLoading => ( + {({ isLoading }) => ( {dataProviders != null && dataProviders.length ? ( ( ({ deleteProvider, field, isEnabled, isExcluded, operator, providerId, togglePopover, val }) => { - const deleteFilter: React.MouseEventHandler = ( - event: React.MouseEvent - ) => { - // Make sure it doesn't also trigger the onclick for the whole badge - if (event.stopPropagation) { - event.stopPropagation(); - } - deleteProvider(); - }; - const classes = classNames('globalFilterItem', { - 'globalFilterItem-isDisabled': !isEnabled, - 'globalFilterItem-isExcluded': isExcluded, - }); - const formattedValue = isString(val) && val === '' ? getEmptyString() : val; - const prefix = isExcluded ? {i18n.NOT} : null; - const title = `${field}: "${formattedValue}"`; - - return ( - - {prefix} - {operator !== EXISTS_OPERATOR ? ( - <> - {`${field}: `} - {`"${formattedValue}"`} - - ) : ( - - {field} {i18n.EXISTS_LABEL} - - )} - + const deleteFilter: React.MouseEventHandler = useCallback( + (event: React.MouseEvent) => { + // Make sure it doesn't also trigger the onclick for the whole badge + if (event.stopPropagation) { + event.stopPropagation(); + } + deleteProvider(); + }, + [deleteProvider] + ); + + const classes = useMemo( + () => + classNames('globalFilterItem', { + 'globalFilterItem-isDisabled': !isEnabled, + 'globalFilterItem-isExcluded': isExcluded, + }), + [isEnabled, isExcluded] + ); + + const formattedValue = useMemo(() => (isString(val) && val === '' ? getEmptyString() : val), [ + val, + ]); + + const prefix = useMemo(() => (isExcluded ? {i18n.NOT} : null), [isExcluded]); + + const title = useMemo(() => `${field}: "${formattedValue}"`, [field, formattedValue]); + + const hoverContent = useMemo( + () => ( + + ), + [field, val] ); + + const badge = useCallback( + () => ( + + {prefix} + {operator !== EXISTS_OPERATOR ? ( + <> + {`${field}: `} + {`"${formattedValue}"`} + + ) : ( + + {field} {i18n.EXISTS_LABEL} + + )} + + ), + [ + providerId, + field, + val, + classes, + title, + deleteFilter, + togglePopover, + formattedValue, + closeButtonProps, + prefix, + operator, + ] + ); + + return ; } ); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx index 79f9c32a176f5..2cc19537d6a63 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx @@ -71,7 +71,7 @@ export const ProviderItemBadge = React.memo( return ( - {isLoading => ( + {({ isLoading }) => ( { - const mockTimelineContext: boolean = true; + const isLoading: boolean = true; const mount = useMountAppended(); + const filterManager = new FilterManager(mockUiSettingsForFilterManager); describe('rendering', () => { test('renders correctly against snapshot', () => { @@ -96,7 +101,7 @@ describe('Providers', () => { const mockOnDataProviderRemoved = jest.fn(); const wrapper = mount( - + { const mockOnDataProviderRemoved = jest.fn(); const wrapper = mount( - + { const mockOnToggleDataProviderEnabled = jest.fn(); const wrapper = mount( - + { const wrapper = mount( - + { const wrapper = mount( - + { const wrapper = mount( - + { const wrapper = mount( - + { @@ -26,6 +30,7 @@ describe('Header', () => { { { = ({ id, indexPattern, dataProviders, + filterManager, onChangeDataProviderKqlQuery, onChangeDroppableAndProvider, onDataProviderEdited, @@ -77,6 +79,7 @@ const TimelineHeaderComponent: React.FC = ({ /> @@ -90,6 +93,7 @@ export const TimelineHeader = React.memo( prevProps.id === nextProps.id && deepEqual(prevProps.indexPattern, nextProps.indexPattern) && deepEqual(prevProps.dataProviders, nextProps.dataProviders) && + prevProps.filterManager === nextProps.filterManager && prevProps.onChangeDataProviderKqlQuery === nextProps.onChangeDataProviderKqlQuery && prevProps.onChangeDroppableAndProvider === nextProps.onChangeDroppableAndProvider && prevProps.onDataProviderEdited === nextProps.onDataProviderEdited && diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.test.tsx index b978ef3d478d8..943133dc2063c 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.test.tsx @@ -11,12 +11,16 @@ import { DEFAULT_FROM, DEFAULT_TO } from '../../../../common/constants'; import { mockBrowserFields } from '../../../containers/source/mock'; import { convertKueryToElasticSearchQuery } from '../../../lib/keury'; import { mockIndexPattern, TestProviders } from '../../../mock'; +import { createKibanaCoreStartMock } from '../../../mock/kibana_core'; import { QueryBar } from '../../query_bar'; +import { FilterManager } from '../../../../../../../../src/plugins/data/public'; import { mockDataProviders } from '../data_providers/mock/mock_data_providers'; import { buildGlobalQuery } from '../helpers'; import { QueryBarTimeline, QueryBarTimelineComponentProps, getDataProviderFilter } from './index'; +const mockUiSettingsForFilterManager = createKibanaCoreStartMock().uiSettings; + jest.mock('../../../lib/kibana'); describe('Timeline QueryBar ', () => { @@ -58,6 +62,7 @@ describe('Timeline QueryBar ', () => { browserFields={mockBrowserFields} dataProviders={mockDataProviders} filters={[]} + filterManager={new FilterManager(mockUiSettingsForFilterManager)} filterQuery={{ expression: 'here: query', kind: 'kuery' }} filterQueryDraft={{ expression: 'here: query', kind: 'kuery' }} from={0} @@ -99,6 +104,7 @@ describe('Timeline QueryBar ', () => { browserFields={mockBrowserFields} dataProviders={mockDataProviders} filters={[]} + filterManager={new FilterManager(mockUiSettingsForFilterManager)} filterQuery={{ expression: 'here: query', kind: 'kuery' }} filterQueryDraft={{ expression: 'here: query', kind: 'kuery' }} from={0} @@ -145,6 +151,7 @@ describe('Timeline QueryBar ', () => { browserFields={mockBrowserFields} dataProviders={mockDataProviders} filters={[]} + filterManager={new FilterManager(mockUiSettingsForFilterManager)} filterQuery={{ expression: 'here: query', kind: 'kuery' }} filterQueryDraft={{ expression: 'here: query', kind: 'kuery' }} from={0} @@ -189,6 +196,7 @@ describe('Timeline QueryBar ', () => { browserFields={mockBrowserFields} dataProviders={mockDataProviders} filters={[]} + filterManager={new FilterManager(mockUiSettingsForFilterManager)} filterQuery={{ expression: 'here: query', kind: 'kuery' }} filterQueryDraft={{ expression: 'here: query', kind: 'kuery' }} from={0} @@ -235,6 +243,7 @@ describe('Timeline QueryBar ', () => { browserFields={mockBrowserFields} dataProviders={mockDataProviders} filters={[]} + filterManager={new FilterManager(mockUiSettingsForFilterManager)} filterQuery={{ expression: 'here: query', kind: 'kuery' }} filterQueryDraft={{ expression: 'here: query', kind: 'kuery' }} from={0} @@ -279,6 +288,7 @@ describe('Timeline QueryBar ', () => { browserFields={mockBrowserFields} dataProviders={mockDataProviders} filters={[]} + filterManager={new FilterManager(mockUiSettingsForFilterManager)} filterQuery={{ expression: 'here: query', kind: 'kuery' }} filterQueryDraft={{ expression: 'here: query', kind: 'kuery' }} from={0} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx index 7f662cdb2f1b4..f53f7bb56e2f4 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx @@ -21,7 +21,6 @@ import { import { BrowserFields } from '../../../containers/source'; import { convertKueryToElasticSearchQuery } from '../../../lib/keury'; -import { useKibana } from '../../../lib/kibana'; import { KueryFilterQuery, KueryFilterQueryKind } from '../../../store'; import { KqlMode } from '../../../store/timeline/model'; import { useSavedQueryServices } from '../../../utils/saved_query_services'; @@ -35,6 +34,7 @@ export interface QueryBarTimelineComponentProps { browserFields: BrowserFields; dataProviders: DataProvider[]; filters: Filter[]; + filterManager: FilterManager; filterQuery: KueryFilterQuery; filterQueryDraft: KueryFilterQuery; from: number; @@ -61,6 +61,7 @@ export const QueryBarTimeline = memo( browserFields, dataProviders, filters, + filterManager, filterQuery, filterQueryDraft, from, @@ -94,9 +95,6 @@ export const QueryBarTimeline = memo( const [dataProvidersDsl, setDataProvidersDsl] = useState( convertKueryToElasticSearchQuery(buildGlobalQuery(dataProviders, browserFields), indexPattern) ); - const kibana = useKibana(); - const [filterManager] = useState(new FilterManager(kibana.services.uiSettings)); - const savedQueryServices = useSavedQueryServices(); useEffect(() => { diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx index 87061bdbb5d02..a0a0ac4c2b85c 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx @@ -10,7 +10,11 @@ import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import deepEqual from 'fast-deep-equal'; -import { Filter, IIndexPattern } from '../../../../../../../../src/plugins/data/public'; +import { + Filter, + FilterManager, + IIndexPattern, +} from '../../../../../../../../src/plugins/data/public'; import { BrowserFields } from '../../../containers/source'; import { convertKueryToElasticSearchQuery } from '../../../lib/keury'; import { @@ -29,6 +33,7 @@ import { SearchOrFilter } from './search_or_filter'; interface OwnProps { browserFields: BrowserFields; + filterManager: FilterManager; indexPattern: IIndexPattern; timelineId: string; } @@ -42,6 +47,7 @@ const StatefulSearchOrFilterComponent = React.memo( dataProviders, eventType, filters, + filterManager, filterQuery, filterQueryDraft, from, @@ -122,6 +128,7 @@ const StatefulSearchOrFilterComponent = React.memo( dataProviders={dataProviders} eventType={eventType} filters={filters} + filterManager={filterManager} filterQuery={filterQuery} filterQueryDraft={filterQueryDraft} from={from} @@ -146,6 +153,7 @@ const StatefulSearchOrFilterComponent = React.memo( (prevProps, nextProps) => { return ( prevProps.eventType === nextProps.eventType && + prevProps.filterManager === nextProps.filterManager && prevProps.from === nextProps.from && prevProps.fromStr === nextProps.fromStr && prevProps.to === nextProps.to && diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/search_or_filter.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/search_or_filter.tsx index 7bdd92e745f21..02a575db259bb 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/search_or_filter.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/search_or_filter.tsx @@ -8,7 +8,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiSuperSelect, EuiToolTip } from '@elastic/ import React from 'react'; import styled, { createGlobalStyle } from 'styled-components'; -import { Filter, IIndexPattern } from '../../../../../../../../src/plugins/data/public'; +import { + Filter, + FilterManager, + IIndexPattern, +} from '../../../../../../../../src/plugins/data/public'; import { BrowserFields } from '../../../containers/source'; import { KueryFilterQuery, KueryFilterQueryKind } from '../../../store'; import { KqlMode, EventType } from '../../../store/timeline/model'; @@ -44,6 +48,7 @@ interface Props { browserFields: BrowserFields; dataProviders: DataProvider[]; eventType: EventType; + filterManager: FilterManager; filterQuery: KueryFilterQuery; filterQueryDraft: KueryFilterQuery; from: number; @@ -95,6 +100,7 @@ export const SearchOrFilter = React.memo( indexPattern, isRefreshPaused, filters, + filterManager, filterQuery, filterQueryDraft, from, @@ -135,6 +141,7 @@ export const SearchOrFilter = React.memo( browserFields={browserFields} dataProviders={dataProviders} filters={filters} + filterManager={filterManager} filterQuery={filterQuery} filterQueryDraft={filterQueryDraft} from={from} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx index 098dd82791610..222cc0530bddb 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx @@ -6,7 +6,7 @@ import { EuiFlyoutHeader, EuiFlyoutBody, EuiFlyoutFooter } from '@elastic/eui'; import { getOr, isEmpty } from 'lodash/fp'; -import React, { useMemo } from 'react'; +import React, { useState, useMemo } from 'react'; import styled from 'styled-components'; import { FlyoutHeaderWithCloseButton } from '../flyout/header_with_close_button'; @@ -34,7 +34,12 @@ import { TimelineHeader } from './header'; import { combineQueries } from './helpers'; import { TimelineRefetch } from './refetch_timeline'; import { ManageTimelineContext } from './timeline_context'; -import { esQuery, Filter, IIndexPattern } from '../../../../../../../src/plugins/data/public'; +import { + esQuery, + Filter, + FilterManager, + IIndexPattern, +} from '../../../../../../../src/plugins/data/public'; const TimelineContainer = styled.div` height: 100%; @@ -143,6 +148,7 @@ export const TimelineComponent: React.FC = ({ usersViewing, }) => { const kibana = useKibana(); + const [filterManager] = useState(new FilterManager(kibana.services.uiSettings)); const combinedQueries = combineQueries({ config: esQuery.getEsQueryConfig(kibana.services.uiSettings), dataProviders, @@ -178,6 +184,7 @@ export const TimelineComponent: React.FC = ({ id={id} indexPattern={indexPattern} dataProviders={dataProviders} + filterManager={filterManager} onChangeDataProviderKqlQuery={onChangeDataProviderKqlQuery} onChangeDroppableAndProvider={onChangeDroppableAndProvider} onDataProviderEdited={onDataProviderEdited} @@ -211,7 +218,12 @@ export const TimelineComponent: React.FC = ({ getUpdatedAt, refetch, }) => ( - + (initTimelineContext); +interface TimelineContextState { + filterManager: FilterManager | undefined; + isLoading: boolean; +} + +const initTimelineContext: TimelineContextState = { filterManager: undefined, isLoading: false }; +export const TimelineContext = createContext(initTimelineContext); export const useTimelineContext = () => useContext(TimelineContext); export interface TimelineTypeContextProps { documentType?: string; footerText?: string; + id?: string; + indexToAdd?: string[] | null; loadingText?: string; queryFields?: string[]; selectAll?: boolean; @@ -24,6 +34,8 @@ export interface TimelineTypeContextProps { const initTimelineType: TimelineTypeContextProps = { documentType: undefined, footerText: undefined, + id: undefined, + indexToAdd: undefined, loadingText: undefined, queryFields: [], selectAll: false, @@ -36,6 +48,8 @@ export const useTimelineTypeContext = () => useContext(TimelineTypeContext); interface ManageTimelineContextProps { children: React.ReactNode; + filterManager: FilterManager; + indexToAdd?: string[] | null; loading: boolean; type?: TimelineTypeContextProps; } @@ -44,22 +58,27 @@ interface ManageTimelineContextProps { // to avoid so many Context, at least the separation of code is there now const ManageTimelineContextComponent: React.FC = ({ children, + filterManager, + indexToAdd, loading, - type = initTimelineType, + type = { ...initTimelineType, indexToAdd }, }) => { - const [myLoading, setLoading] = useState(initTimelineContext); - const [myType, setType] = useState(initTimelineType); + const [myContextState, setMyContextState] = useState({ + filterManager, + isLoading: false, + }); + const [myType, setType] = useState(type); useEffect(() => { - setLoading(loading); - }, [loading]); + setMyContextState({ filterManager, isLoading: loading }); + }, [setMyContextState, filterManager, loading]); useEffect(() => { - setType(type); - }, [type]); + setType({ ...type, indexToAdd }); + }, [type, indexToAdd]); return ( - + {children} ); diff --git a/x-pack/legacy/plugins/siem/public/components/top_n/helpers.test.tsx b/x-pack/legacy/plugins/siem/public/components/top_n/helpers.test.tsx new file mode 100644 index 0000000000000..da0f6f59b533f --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/top_n/helpers.test.tsx @@ -0,0 +1,25 @@ +/* + * 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 { allEvents, defaultOptions, getOptions, rawEvents, signalEvents } from './helpers'; + +describe('getOptions', () => { + test(`it returns the default options when 'activeTimelineEventType' is undefined`, () => { + expect(getOptions()).toEqual(defaultOptions); + }); + + test(`it returns 'allEvents' when 'activeTimelineEventType' is 'all'`, () => { + expect(getOptions('all')).toEqual(allEvents); + }); + + test(`it returns 'rawEvents' when 'activeTimelineEventType' is 'raw'`, () => { + expect(getOptions('raw')).toEqual(rawEvents); + }); + + test(`it returns 'signalEvents' when 'activeTimelineEventType' is 'signal'`, () => { + expect(getOptions('signal')).toEqual(signalEvents); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/top_n/helpers.ts b/x-pack/legacy/plugins/siem/public/components/top_n/helpers.ts new file mode 100644 index 0000000000000..8d9ae48d29b69 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/top_n/helpers.ts @@ -0,0 +1,66 @@ +/* + * 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 { EventType } from '../../store/timeline/model'; + +import * as i18n from './translations'; + +export interface TopNOption { + inputDisplay: string; + value: EventType; + 'data-test-subj': string; +} + +/** A (stable) array containing only the 'All events' option */ +export const allEvents: TopNOption[] = [ + { + value: 'all', + inputDisplay: i18n.ALL_EVENTS, + 'data-test-subj': 'option-all', + }, +]; + +/** A (stable) array containing only the 'Raw events' option */ +export const rawEvents: TopNOption[] = [ + { + value: 'raw', + inputDisplay: i18n.RAW_EVENTS, + 'data-test-subj': 'option-raw', + }, +]; + +/** A (stable) array containing only the 'Signal events' option */ +export const signalEvents: TopNOption[] = [ + { + value: 'signal', + inputDisplay: i18n.SIGNAL_EVENTS, + 'data-test-subj': 'option-signal', + }, +]; + +/** A (stable) array containing the default Top N options */ +export const defaultOptions = [...rawEvents, ...signalEvents]; + +/** + * Returns the options to be displayed in a Top N view select. When + * an `activeTimelineEventType` is provided, an array containing + * just one option (corresponding to `activeTimelineEventType`) + * will be returned, to ensure the data displayed in the Top N + * is always in sync with the `EventType` chosen by the user in + * the active timeline. + */ +export const getOptions = (activeTimelineEventType?: EventType): TopNOption[] => { + switch (activeTimelineEventType) { + case 'all': + return allEvents; + case 'raw': + return rawEvents; + case 'signal': + return signalEvents; + default: + return defaultOptions; + } +}; diff --git a/x-pack/legacy/plugins/siem/public/components/top_n/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/top_n/index.test.tsx new file mode 100644 index 0000000000000..61772f1dc7a7a --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/top_n/index.test.tsx @@ -0,0 +1,379 @@ +/* + * 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 { mount, ReactWrapper } from 'enzyme'; +import React from 'react'; + +import { mockBrowserFields } from '../../containers/source/mock'; +import { apolloClientObservable, mockGlobalState, TestProviders } from '../../mock'; +import { createKibanaCoreStartMock } from '../../mock/kibana_core'; +import { FilterManager } from '../../../../../../../src/plugins/data/public'; +import { createStore, State } from '../../store'; +import { TimelineContext, TimelineTypeContext } from '../timeline/timeline_context'; + +import { Props } from './top_n'; +import { ACTIVE_TIMELINE_REDUX_ID, StatefulTopN } from '.'; + +jest.mock('../../lib/kibana'); + +const mockUiSettingsForFilterManager = createKibanaCoreStartMock().uiSettings; + +const field = 'process.name'; +const value = 'nice'; + +const state: State = { + ...mockGlobalState, + inputs: { + ...mockGlobalState.inputs, + global: { + ...mockGlobalState.inputs.global, + query: { + query: 'host.name : end*', + language: 'kuery', + }, + filters: [ + { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'host.os.name', + params: { + query: 'Linux', + }, + }, + query: { + match: { + 'host.os.name': { + query: 'Linux', + type: 'phrase', + }, + }, + }, + }, + ], + }, + timeline: { + ...mockGlobalState.inputs.timeline, + timerange: { + kind: 'relative', + fromStr: 'now-24h', + toStr: 'now', + from: 1586835969047, + to: 1586922369047, + }, + }, + }, + timeline: { + ...mockGlobalState.timeline, + timelineById: { + [ACTIVE_TIMELINE_REDUX_ID]: { + ...mockGlobalState.timeline.timelineById.test, + id: ACTIVE_TIMELINE_REDUX_ID, + dataProviders: [ + { + id: + 'draggable-badge-default-draggable-netflow-renderer-timeline-1-_qpBe3EBD7k-aQQL7v7--_qpBe3EBD7k-aQQL7v7--network_transport-tcp', + name: 'tcp', + enabled: true, + excluded: false, + kqlQuery: '', + queryMatch: { + field: 'network.transport', + value: 'tcp', + operator: ':', + }, + and: [], + }, + ], + eventType: 'all', + filters: [ + { + meta: { + alias: null, + disabled: false, + key: 'source.port', + negate: false, + params: { + query: '30045', + }, + type: 'phrase', + }, + query: { + match: { + 'source.port': { + query: '30045', + type: 'phrase', + }, + }, + }, + }, + ], + kqlMode: 'filter', + kqlQuery: { + filterQuery: { + kuery: { + kind: 'kuery', + expression: 'host.name : *', + }, + serializedQuery: + '{"bool":{"should":[{"exists":{"field":"host.name"}}],"minimum_should_match":1}}', + }, + filterQueryDraft: { + kind: 'kuery', + expression: 'host.name : *', + }, + }, + }, + }, + }, +}; +const store = createStore(state, apolloClientObservable); + +describe('StatefulTopN', () => { + // Suppress warnings about "react-beautiful-dnd" + /* eslint-disable no-console */ + const originalError = console.error; + const originalWarn = console.warn; + beforeAll(() => { + console.warn = jest.fn(); + console.error = jest.fn(); + }); + afterAll(() => { + console.error = originalError; + console.warn = originalWarn; + }); + + describe('rendering in a global NON-timeline context', () => { + let wrapper: ReactWrapper; + + beforeEach(() => { + wrapper = mount( + + + + ); + }); + + test('it has undefined combinedQueries when rendering in a global context', () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.combinedQueries).toBeUndefined(); + }); + + test(`defaults to the 'Raw events' view when rendering in a global context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.defaultView).toEqual('raw'); + }); + + test(`provides a 'deleteQuery' when rendering in a global context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.deleteQuery).toBeDefined(); + }); + + test(`provides filters from Redux state (inputs > global > filters) when rendering in a global context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.filters).toEqual([ + { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'host.os.name', + params: { query: 'Linux' }, + }, + query: { match: { 'host.os.name': { query: 'Linux', type: 'phrase' } } }, + }, + ]); + }); + + test(`provides 'from' via GlobalTime when rendering in a global context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.from).toEqual(0); + }); + + test('provides the global query from Redux state (inputs > global > query) when rendering in a global context', () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.query).toEqual({ query: 'host.name : end*', language: 'kuery' }); + }); + + test(`provides a 'global' 'setAbsoluteRangeDatePickerTarget' when rendering in a global context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.setAbsoluteRangeDatePickerTarget).toEqual('global'); + }); + + test(`provides 'to' via GlobalTime when rendering in a global context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.to).toEqual(1); + }); + }); + + describe('rendering in a timeline context', () => { + let filterManager: FilterManager; + let wrapper: ReactWrapper; + + beforeEach(() => { + filterManager = new FilterManager(mockUiSettingsForFilterManager); + + wrapper = mount( + + + + + + + + ); + }); + + test('it has a combinedQueries value from Redux state composed of the timeline [data providers + kql + filter-bar-filters] when rendering in a timeline context', () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.combinedQueries).toEqual( + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"network.transport":"tcp"}}],"minimum_should_match":1}},{"bool":{"should":[{"exists":{"field":"host.name"}}],"minimum_should_match":1}}]}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1586835969047}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1586922369047}}}],"minimum_should_match":1}}]}}]}},{"match_phrase":{"source.port":{"query":"30045"}}}],"should":[],"must_not":[]}}' + ); + }); + + test('it provides only one view option that matches the `eventType` from redux when rendering in the context of the active timeline', () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.defaultView).toEqual('all'); + }); + + test(`provides an undefined 'deleteQuery' when rendering in a timeline context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.deleteQuery).toBeUndefined(); + }); + + test(`provides empty filters when rendering in a timeline context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.filters).toEqual([]); + }); + + test(`provides 'from' via redux state (inputs > timeline > timerange) when rendering in a timeline context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.from).toEqual(1586835969047); + }); + + test('provides an empty query when rendering in a timeline context', () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.query).toEqual({ query: '', language: 'kuery' }); + }); + + test(`provides a 'timeline' 'setAbsoluteRangeDatePickerTarget' when rendering in a timeline context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.setAbsoluteRangeDatePickerTarget).toEqual('timeline'); + }); + + test(`provides 'to' via redux state (inputs > timeline > timerange) when rendering in a timeline context`, () => { + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.to).toEqual(1586922369047); + }); + }); + + test(`defaults to the 'Signals events' option when rendering in a NON-active timeline context (e.g. the Signals table on the Detections page) when 'documentType' from 'useTimelineTypeContext()' is 'signals'`, () => { + const filterManager = new FilterManager(mockUiSettingsForFilterManager); + const wrapper = mount( + + + + + + + + ); + + const props = wrapper + .find('[data-test-subj="top-n"]') + .first() + .props() as Props; + + expect(props.defaultView).toEqual('signal'); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/top_n/index.tsx b/x-pack/legacy/plugins/siem/public/components/top_n/index.tsx new file mode 100644 index 0000000000000..983b234a04eaa --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/top_n/index.tsx @@ -0,0 +1,166 @@ +/* + * 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 from 'react'; +import { connect, ConnectedProps } from 'react-redux'; + +import { GlobalTime } from '../../containers/global_time'; +import { BrowserFields, WithSource } from '../../containers/source'; +import { useKibana } from '../../lib/kibana'; +import { esQuery, Filter, Query } from '../../../../../../../src/plugins/data/public'; +import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store'; +import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; +import { timelineDefaults } from '../../store/timeline/defaults'; +import { TimelineModel } from '../../store/timeline/model'; +import { combineQueries } from '../timeline/helpers'; +import { useTimelineTypeContext } from '../timeline/timeline_context'; + +import { getOptions } from './helpers'; +import { TopN } from './top_n'; + +/** The currently active timeline always has this Redux ID */ +export const ACTIVE_TIMELINE_REDUX_ID = 'timeline-1'; + +const EMPTY_FILTERS: Filter[] = []; +const EMPTY_QUERY: Query = { query: '', language: 'kuery' }; + +const makeMapStateToProps = () => { + const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); + const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); + const getTimeline = timelineSelectors.getTimelineByIdSelector(); + const getInputsTimeline = inputsSelectors.getTimelineSelector(); + const getKqlQueryTimeline = timelineSelectors.getKqlFilterQuerySelector(); + + // The mapped Redux state provided to this component includes the global + // filters that appear at the top of most views in the app, and all the + // filters in the active timeline: + const mapStateToProps = (state: State) => { + const activeTimeline: TimelineModel = + getTimeline(state, ACTIVE_TIMELINE_REDUX_ID) ?? timelineDefaults; + const activeTimelineFilters = activeTimeline.filters ?? EMPTY_FILTERS; + const activeTimelineInput: inputsModel.InputsRange = getInputsTimeline(state); + + return { + activeTimelineEventType: activeTimeline.eventType, + activeTimelineFilters, + activeTimelineFrom: activeTimelineInput.timerange.from, + activeTimelineKqlQueryExpression: getKqlQueryTimeline(state, ACTIVE_TIMELINE_REDUX_ID), + activeTimelineTo: activeTimelineInput.timerange.to, + dataProviders: activeTimeline.dataProviders, + globalQuery: getGlobalQuerySelector(state), + globalFilters: getGlobalFiltersQuerySelector(state), + kqlMode: activeTimeline.kqlMode, + }; + }; + + return mapStateToProps; +}; + +const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker }; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +interface OwnProps { + browserFields: BrowserFields; + field: string; + toggleTopN: () => void; + onFilterAdded?: () => void; + value?: string[] | string | null; +} +type PropsFromRedux = ConnectedProps; +type Props = OwnProps & PropsFromRedux; + +const StatefulTopNComponent: React.FC = ({ + activeTimelineEventType, + activeTimelineFilters, + activeTimelineFrom, + activeTimelineKqlQueryExpression, + activeTimelineTo, + browserFields, + dataProviders, + field, + globalFilters = EMPTY_FILTERS, + globalQuery = EMPTY_QUERY, + kqlMode, + onFilterAdded, + setAbsoluteRangeDatePicker, + toggleTopN, + value, +}) => { + const kibana = useKibana(); + + // Regarding data from useTimelineTypeContext: + // * `documentType` (e.g. 'signals') may only be populated in some views, + // e.g. the `Signals` view on the `Detections` page. + // * `id` (`timelineId`) may only be populated when we are rendered in the + // context of the active timeline. + // * `indexToAdd`, which enables the signals index to be appended to + // the `indexPattern` returned by `WithSource`, may only be populated when + // this component is rendered in the context of the active timeline. This + // behavior enables the 'All events' view by appending the signals index + // to the index pattern. + const { documentType, id: timelineId, indexToAdd } = useTimelineTypeContext(); + + const options = getOptions( + timelineId === ACTIVE_TIMELINE_REDUX_ID ? activeTimelineEventType : undefined + ); + + return ( + + {({ from, deleteQuery, setQuery, to }) => ( + + {({ indexPattern }) => ( + + )} + + )} + + ); +}; + +StatefulTopNComponent.displayName = 'StatefulTopNComponent'; + +export const StatefulTopN = connector(React.memo(StatefulTopNComponent)); diff --git a/x-pack/legacy/plugins/siem/public/components/top_n/top_n.test.tsx b/x-pack/legacy/plugins/siem/public/components/top_n/top_n.test.tsx new file mode 100644 index 0000000000000..13b77ea0ccd4c --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/top_n/top_n.test.tsx @@ -0,0 +1,261 @@ +/* + * 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 { mount, ReactWrapper } from 'enzyme'; +import React from 'react'; + +import { TestProviders, mockIndexPattern } from '../../mock'; +import { setAbsoluteRangeDatePicker } from '../../store/inputs/actions'; + +import { allEvents, defaultOptions } from './helpers'; +import { TopN } from './top_n'; + +jest.mock('../../lib/kibana'); + +jest.mock('uuid', () => { + return { + v1: jest.fn(() => 'uuid.v1()'), + v4: jest.fn(() => 'uuid.v4()'), + }; +}); + +const field = 'process.name'; +const value = 'nice'; +const combinedQueries = { + bool: { + must: [], + filter: [ + { + bool: { + filter: [ + { + bool: { + filter: [ + { + bool: { + should: [{ match_phrase: { 'network.transport': 'tcp' } }], + minimum_should_match: 1, + }, + }, + { + bool: { should: [{ exists: { field: 'host.name' } }], minimum_should_match: 1 }, + }, + ], + }, + }, + { + bool: { + filter: [ + { + bool: { + should: [{ range: { '@timestamp': { gte: 1586824450493 } } }], + minimum_should_match: 1, + }, + }, + { + bool: { + should: [{ range: { '@timestamp': { lte: 1586910850493 } } }], + minimum_should_match: 1, + }, + }, + ], + }, + }, + ], + }, + }, + { match_phrase: { 'source.port': { query: '30045' } } }, + ], + should: [], + must_not: [], + }, +}; + +describe('TopN', () => { + // Suppress warnings about "react-beautiful-dnd" + /* eslint-disable no-console */ + const originalError = console.error; + const originalWarn = console.warn; + beforeAll(() => { + console.warn = jest.fn(); + console.error = jest.fn(); + }); + afterAll(() => { + console.error = originalError; + console.warn = originalWarn; + }); + + const query = { query: '', language: 'kuery' }; + + describe('common functionality', () => { + let toggleTopN: () => void; + let wrapper: ReactWrapper; + + beforeEach(() => { + toggleTopN = jest.fn(); + wrapper = mount( + + + + ); + }); + + test('it invokes the toggleTopN function when the close button is clicked', () => { + wrapper + .find('[data-test-subj="close"]') + .first() + .simulate('click'); + wrapper.update(); + + expect(toggleTopN).toHaveBeenCalled(); + }); + + test('it enables the view select by default', () => { + expect( + wrapper + .find('[data-test-subj="view-select"]') + .first() + .props().disabled + ).toBe(false); + }); + }); + + describe('events view', () => { + let toggleTopN: () => void; + let wrapper: ReactWrapper; + + beforeEach(() => { + toggleTopN = jest.fn(); + wrapper = mount( + + + + ); + }); + + test(`it renders EventsByDataset when defaultView is 'raw'`, () => { + expect( + wrapper.find('[data-test-subj="eventsByDatasetOverview-uuid.v4()Panel"]').exists() + ).toBe(true); + }); + + test(`it does NOT render SignalsByCategory when defaultView is 'raw'`, () => { + expect(wrapper.find('[data-test-subj="signals-histogram-panel"]').exists()).toBe(false); + }); + }); + + describe('signals view', () => { + let toggleTopN: () => void; + let wrapper: ReactWrapper; + + beforeEach(() => { + toggleTopN = jest.fn(); + wrapper = mount( + + + + ); + }); + + test(`it renders SignalsByCategory when defaultView is 'signal'`, () => { + expect(wrapper.find('[data-test-subj="signals-histogram-panel"]').exists()).toBe(true); + }); + + test(`it does NOT render EventsByDataset when defaultView is 'signal'`, () => { + expect( + wrapper.find('[data-test-subj="eventsByDatasetOverview-uuid.v4()Panel"]').exists() + ).toBe(false); + }); + }); + + describe('All events, a view shown only when rendered in the context of the active timeline', () => { + let wrapper: ReactWrapper; + + beforeEach(() => { + wrapper = mount( + + + + ); + }); + + test(`it disables the view select when 'options' contains only one entry`, () => { + expect( + wrapper + .find('[data-test-subj="view-select"]') + .first() + .props().disabled + ).toBe(true); + }); + + test(`it renders EventsByDataset when defaultView is 'all'`, () => { + expect( + wrapper.find('[data-test-subj="eventsByDatasetOverview-uuid.v4()Panel"]').exists() + ).toBe(true); + }); + + test(`it does NOT render SignalsByCategory when defaultView is 'all'`, () => { + expect(wrapper.find('[data-test-subj="signals-histogram-panel"]').exists()).toBe(false); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/top_n/top_n.tsx b/x-pack/legacy/plugins/siem/public/components/top_n/top_n.tsx new file mode 100644 index 0000000000000..136252617e2a2 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/top_n/top_n.tsx @@ -0,0 +1,158 @@ +/* + * 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 { EuiButtonIcon, EuiSuperSelect } from '@elastic/eui'; +import React, { useCallback, useMemo, useState } from 'react'; +import styled from 'styled-components'; +import { ActionCreator } from 'typescript-fsa'; + +import { EventsByDataset } from '../../pages/overview/events_by_dataset'; +import { SignalsByCategory } from '../../pages/overview/signals_by_category'; +import { Filter, IIndexPattern, Query } from '../../../../../../../src/plugins/data/public'; +import { inputsModel } from '../../store'; +import { InputsModelId } from '../../store/inputs/constants'; +import { EventType } from '../../store/timeline/model'; + +import { TopNOption } from './helpers'; +import * as i18n from './translations'; + +const TopNContainer = styled.div` + width: 600px; +`; + +const CloseButton = styled(EuiButtonIcon)` + z-index: 999999; + position: absolute; + right: 4px; + top: 4px; +`; + +const ViewSelect = styled(EuiSuperSelect)` + z-index: 999999; + width: 155px; +`; + +const TopNContent = styled.div` + margin-top: 4px; + + .euiPanel { + border: none; + } +`; + +export interface Props { + combinedQueries?: string; + defaultView: EventType; + deleteQuery?: ({ id }: { id: string }) => void; + field: string; + filters: Filter[]; + from: number; + indexPattern: IIndexPattern; + indexToAdd?: string[] | null; + options: TopNOption[]; + query: Query; + setAbsoluteRangeDatePicker: ActionCreator<{ + id: InputsModelId; + from: number; + to: number; + }>; + setAbsoluteRangeDatePickerTarget: InputsModelId; + setQuery: (params: { + id: string; + inspect: inputsModel.InspectQuery | null; + loading: boolean; + refetch: inputsModel.Refetch; + }) => void; + to: number; + toggleTopN: () => void; + onFilterAdded?: () => void; + value?: string[] | string | null; +} + +const NO_FILTERS: Filter[] = []; +const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; + +const TopNComponent: React.FC = ({ + combinedQueries, + defaultView, + deleteQuery, + filters = NO_FILTERS, + field, + from, + indexPattern, + indexToAdd, + options, + query = DEFAULT_QUERY, + setAbsoluteRangeDatePicker, + setAbsoluteRangeDatePickerTarget, + setQuery, + to, + toggleTopN, +}) => { + const [view, setView] = useState(defaultView); + const onViewSelected = useCallback((value: string) => setView(value as EventType), [setView]); + + const headerChildren = useMemo( + () => ( + + ), + [onViewSelected, options, view] + ); + + return ( + + + + + {view === 'raw' || view === 'all' ? ( + + ) : ( + + )} + + + ); +}; + +TopNComponent.displayName = 'TopNComponent'; + +export const TopN = React.memo(TopNComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/top_n/translations.ts b/x-pack/legacy/plugins/siem/public/components/top_n/translations.ts new file mode 100644 index 0000000000000..7db55fa94d42e --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/top_n/translations.ts @@ -0,0 +1,23 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const CLOSE = i18n.translate('xpack.siem.topN.closeButtonLabel', { + defaultMessage: 'Close', +}); + +export const ALL_EVENTS = i18n.translate('xpack.siem.topN.allEventsSelectLabel', { + defaultMessage: 'All events', +}); + +export const RAW_EVENTS = i18n.translate('xpack.siem.topN.rawEventsSelectLabel', { + defaultMessage: 'Raw events', +}); + +export const SIGNAL_EVENTS = i18n.translate('xpack.siem.topN.signalEventsSelectLabel', { + defaultMessage: 'Signal events', +}); diff --git a/x-pack/legacy/plugins/siem/public/components/with_hover_actions/index.tsx b/x-pack/legacy/plugins/siem/public/components/with_hover_actions/index.tsx index 07ea165fcbb5c..86a9acc486b6d 100644 --- a/x-pack/legacy/plugins/siem/public/components/with_hover_actions/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/with_hover_actions/index.tsx @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useCallback } from 'react'; -import styled from 'styled-components'; +import { EuiPopover } from '@elastic/eui'; +import React, { useCallback, useMemo, useState } from 'react'; +import { IS_DRAGGING_CLASS_NAME } from '../drag_and_drop/helpers'; interface Props { /** @@ -26,34 +27,6 @@ interface Props { */ render: (showHoverContent: boolean) => JSX.Element; } - -const HoverActionsPanelContainer = styled.div` - color: ${({ theme }) => theme.eui.textColors.default}; - height: 100%; - position: relative; -`; - -HoverActionsPanelContainer.displayName = 'HoverActionsPanelContainer'; - -const HoverActionsPanel = React.memo<{ children: JSX.Element; show: boolean }>( - ({ children, show }) => ( - - {show ? children : null} - - ) -); - -HoverActionsPanel.displayName = 'HoverActionsPanel'; - -const WithHoverActionsContainer = styled.div` - display: flex; - flex-direction: row; - height: 100%; - padding-right: 5px; -`; - -WithHoverActionsContainer.displayName = 'WithHoverActionsContainer'; - /** * Decorates it's children with actions that are visible on hover. * This component does not enforce an opinion on the styling and @@ -68,20 +41,41 @@ export const WithHoverActions = React.memo( ({ alwaysShow = false, hoverContent, render }) => { const [showHoverContent, setShowHoverContent] = useState(false); const onMouseEnter = useCallback(() => { - setShowHoverContent(true); + // NOTE: the following read from the DOM is expensive, but not as + // expensive as the default behavior, which adds a div to the body, + // which-in turn performs a more expensive change to the layout + if (!document.body.classList.contains(IS_DRAGGING_CLASS_NAME)) { + setShowHoverContent(true); + } }, []); const onMouseLeave = useCallback(() => { setShowHoverContent(false); }, []); + const content = useMemo(() => <>{render(showHoverContent)}, [render, showHoverContent]); + + const isOpen = hoverContent != null && (showHoverContent || alwaysShow); + + const popover = useMemo(() => { + return ( + + {isOpen ? hoverContent : null} + + ); + }, [content, onMouseLeave, isOpen, alwaysShow, hoverContent]); + return ( - - <>{render(showHoverContent)} - - {hoverContent != null ? hoverContent : <>} - - +
+ {popover} +
); } ); diff --git a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.ts b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.ts index 0b369b4180fb8..83b3a8fdbb68c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.ts +++ b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/index.ts @@ -3,7 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { useEffect, useState, useRef } from 'react'; +import { isEmpty } from 'lodash/fp'; +import { useEffect, useMemo, useState, useRef } from 'react'; + import { MatrixHistogramQueryProps } from '../../components/matrix_histogram/types'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { errorToToaster, useStateToaster } from '../../components/toasters'; @@ -19,11 +21,19 @@ export const useQuery = ({ errorMessage, filterQuery, histogramType, + indexToAdd, isInspected, stackByField, startDate, }: MatrixHistogramQueryProps) => { - const [defaultIndex] = useUiSetting$(DEFAULT_INDEX_KEY); + const [configIndex] = useUiSetting$(DEFAULT_INDEX_KEY); + const defaultIndex = useMemo(() => { + if (indexToAdd != null && !isEmpty(indexToAdd)) { + return [...configIndex, ...indexToAdd]; + } + return configIndex; + }, [configIndex, indexToAdd]); + const [, dispatchToaster] = useStateToaster(); const refetch = useRef(); const [loading, setLoading] = useState(false); @@ -96,6 +106,7 @@ export const useQuery = ({ errorMessage, filterQuery, histogramType, + indexToAdd, isInspected, stackByField, startDate, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/helpers.tsx index 27ee552146092..5c89a7e25b7a4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/helpers.tsx @@ -5,6 +5,7 @@ */ import { HistogramData, SignalsAggregation, SignalsBucket, SignalsGroupBucket } from './types'; +import { showAllOthersBucket } from '../../../../../common/constants'; import { SignalSearchResponse } from '../../../../containers/detection_engine/signals/types'; import * as i18n from './translations'; @@ -34,48 +35,56 @@ export const getSignalsHistogramQuery = ( additionalFilters: Array<{ bool: { filter: unknown[]; should: unknown[]; must_not: unknown[]; must: unknown[] }; }> -) => ({ - aggs: { - signalsByGrouping: { - terms: { - field: stackByField, +) => { + const missing = showAllOthersBucket.includes(stackByField) + ? { missing: stackByField.endsWith('.ip') ? '0.0.0.0' : i18n.ALL_OTHERS, - order: { - _count: 'desc', + } + : {}; + + return { + aggs: { + signalsByGrouping: { + terms: { + field: stackByField, + ...missing, + order: { + _count: 'desc', + }, + size: 10, }, - size: 10, - }, - aggs: { - signals: { - date_histogram: { - field: '@timestamp', - fixed_interval: `${Math.floor((to - from) / 32)}ms`, - min_doc_count: 0, - extended_bounds: { - min: from, - max: to, + aggs: { + signals: { + date_histogram: { + field: '@timestamp', + fixed_interval: `${Math.floor((to - from) / 32)}ms`, + min_doc_count: 0, + extended_bounds: { + min: from, + max: to, + }, }, }, }, }, }, - }, - query: { - bool: { - filter: [ - ...additionalFilters, - { - range: { - '@timestamp': { - gte: from, - lte: to, + query: { + bool: { + filter: [ + ...additionalFilters, + { + range: { + '@timestamp': { + gte: from, + lte: to, + }, }, }, - }, - ], + ], + }, }, - }, -}); + }; +}; /** * Returns `true` when the signals histogram initial loading spinner should be shown diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx index e25442b31da4e..f2d722e5a66d7 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx @@ -9,16 +9,20 @@ import numeral from '@elastic/numeral'; import React, { memo, useCallback, useMemo, useState, useEffect } from 'react'; import styled from 'styled-components'; import { isEmpty } from 'lodash/fp'; +import uuid from 'uuid'; +import { LegendItem } from '../../../../components/charts/draggable_legend_item'; +import { escapeDataProviderId } from '../../../../components/drag_and_drop/helpers'; import { HeaderSection } from '../../../../components/header_section'; - import { Filter, esQuery, Query } from '../../../../../../../../../src/plugins/data/public'; import { DEFAULT_NUMBER_FORMAT } from '../../../../../common/constants'; import { useQuerySignals } from '../../../../containers/detection_engine/signals/use_query'; import { getDetectionEngineUrl } from '../../../../components/link_to'; +import { defaultLegendColors } from '../../../../components/matrix_histogram/utils'; import { InspectButtonContainer } from '../../../../components/inspect'; import { useGetUrlSearch } from '../../../../components/navigation/use_get_url_search'; import { MatrixLoader } from '../../../../components/matrix_histogram/matrix_loader'; +import { MatrixHistogramOption } from '../../../../components/matrix_histogram/types'; import { useKibana, useUiSetting$ } from '../../../../lib/kibana'; import { navTabs } from '../../../home/home_navigations'; import { signalsHistogramOptions } from './config'; @@ -53,6 +57,9 @@ interface SignalsHistogramPanelProps { deleteQuery?: ({ id }: { id: string }) => void; filters?: Filter[]; from: number; + headerChildren?: React.ReactNode; + /** Override all defaults, and only display this field */ + onlyField?: string; query?: Query; legendPosition?: Position; panelHeight?: number; @@ -66,12 +73,21 @@ interface SignalsHistogramPanelProps { updateDateRange: (min: number, max: number) => void; } +const getHistogramOption = (fieldName: string): MatrixHistogramOption => ({ + text: fieldName, + value: fieldName, +}); + +const NO_LEGEND_DATA: LegendItem[] = []; + export const SignalsHistogramPanel = memo( ({ chartHeight, defaultStackByOption = signalsHistogramOptions[0], deleteQuery, filters, + headerChildren, + onlyField, query, from, legendPosition = 'right', @@ -85,11 +101,13 @@ export const SignalsHistogramPanel = memo( title = i18n.HISTOGRAM_HEADER, updateDateRange, }) => { + // create a unique, but stable (across re-renders) query id + const uniqueQueryId = useMemo(() => `${DETECTIONS_HISTOGRAM_ID}-${uuid.v4()}`, []); const [isInitialLoading, setIsInitialLoading] = useState(true); const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); const [totalSignalsObj, setTotalSignalsObj] = useState(defaultTotalSignalsObj); const [selectedStackByOption, setSelectedStackByOption] = useState( - defaultStackByOption + onlyField == null ? defaultStackByOption : getHistogramOption(onlyField) ); const { loading: isLoadingSignals, @@ -123,6 +141,21 @@ export const SignalsHistogramPanel = memo( const formattedSignalsData = useMemo(() => formatSignalsData(signalsData), [signalsData]); + const legendItems: LegendItem[] = useMemo( + () => + signalsData?.aggregations?.signalsByGrouping?.buckets != null + ? signalsData.aggregations.signalsByGrouping.buckets.map((bucket, i) => ({ + color: i < defaultLegendColors.length ? defaultLegendColors[i] : undefined, + dataProviderId: escapeDataProviderId( + `draggable-legend-item-${uuid.v4()}-${selectedStackByOption.value}-${bucket.key}` + ), + field: selectedStackByOption.value, + value: bucket.key, + })) + : NO_LEGEND_DATA, + [signalsData, selectedStackByOption.value] + ); + useEffect(() => { let canceled = false; @@ -138,7 +171,7 @@ export const SignalsHistogramPanel = memo( useEffect(() => { return () => { if (deleteQuery) { - deleteQuery({ id: DETECTIONS_HISTOGRAM_ID }); + deleteQuery({ id: uniqueQueryId }); } }; }, []); @@ -146,7 +179,7 @@ export const SignalsHistogramPanel = memo( useEffect(() => { if (refetch != null && setQuery != null) { setQuery({ - id: DETECTIONS_HISTOGRAM_ID, + id: uniqueQueryId, inspect: { dsl: [request], response: [response], @@ -197,46 +230,49 @@ export const SignalsHistogramPanel = memo( } }, [showLinkToSignals, urlSearch]); + const titleText = useMemo(() => (onlyField == null ? title : i18n.TOP(onlyField)), [ + onlyField, + title, + ]); + return ( - + + + + + {stackByOptions && ( + + )} + {headerChildren != null && headerChildren} + + {linkButton} + + + {isInitialLoading ? ( - <> - - - + ) : ( - <> - - - - {stackByOptions && ( - - )} - - {linkButton} - - - - - + )} diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.test.tsx index 5eb9beaaaf76a..6a116efb8f2f8 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.test.tsx @@ -14,7 +14,14 @@ jest.mock('../../../../lib/kibana'); describe('SignalsHistogram', () => { it('renders correctly', () => { const wrapper = shallow( - + ); expect(wrapper.find('Chart')).toBeTruthy(); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx index 40e5b8abde072..4bb7e9f6e122f 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx @@ -12,11 +12,14 @@ import { Settings, ChartSizeArray, } from '@elastic/charts'; +import { EuiFlexGroup, EuiFlexItem, EuiProgress } from '@elastic/eui'; import React, { useMemo } from 'react'; -import { EuiProgress } from '@elastic/eui'; import { useTheme } from '../../../../components/charts/common'; import { histogramDateTimeFormatter } from '../../../../components/utils'; +import { DraggableLegend } from '../../../../components/charts/draggable_legend'; +import { LegendItem } from '../../../../components/charts/draggable_legend_item'; + import { HistogramData } from './types'; const DEFAULT_CHART_HEIGHT = 174; @@ -24,18 +27,19 @@ const DEFAULT_CHART_HEIGHT = 174; interface HistogramSignalsProps { chartHeight?: number; from: number; + legendItems: LegendItem[]; legendPosition?: Position; loading: boolean; to: number; data: HistogramData[]; updateDateRange: (min: number, max: number) => void; } - export const SignalsHistogram = React.memo( ({ chartHeight = DEFAULT_CHART_HEIGHT, data, from, + legendItems, legendPosition = 'right', loading, to, @@ -62,29 +66,38 @@ export const SignalsHistogram = React.memo( /> )} - - + + + + - + - + - - + + +
+ + {legendItems.length > 0 && ( + + )} + + ); } diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts index 8c88fa4a5dae6..e7b76a48c7592 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/translations.ts @@ -83,6 +83,12 @@ export const STACK_BY_USERS = i18n.translate( } ); +export const TOP = (fieldName: string) => + i18n.translate('xpack.siem.detectionEngine.signals.histogram.topNLabel', { + values: { fieldName }, + defaultMessage: `Top {fieldName}`, + }); + export const HISTOGRAM_HEADER = i18n.translate( 'xpack.siem.detectionEngine.signals.histogram.headerTitle', { diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/alerts_by_category/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/alerts_by_category/index.test.tsx index d838b936a2d65..bd9743bdccb4b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/alerts_by_category/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/alerts_by_category/index.test.tsx @@ -66,8 +66,8 @@ describe('Alerts by category', () => { ); }); - test('it does NOT render the subtitle', () => { - expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').exists()).toBe(false); + test('it renders the subtitle (to prevent layout thrashing)', () => { + expect(wrapper.find('[data-test-subj="header-panel-subtitle"]').exists()).toBe(true); }); test('it renders the expected filter fields', () => { diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/__mocks__/index.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/__mocks__/index.tsx new file mode 100644 index 0000000000000..dad1e0034b4e2 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/__mocks__/index.tsx @@ -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 const EventsByDataset = () => 'mock EventsByDataset'; diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx index cc1f9b1cc5681..485fec31db240 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx @@ -4,18 +4,26 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Position } from '@elastic/charts'; import { EuiButton } from '@elastic/eui'; import numeral from '@elastic/numeral'; import React, { useEffect, useMemo } from 'react'; +import uuid from 'uuid'; -import { Position } from '@elastic/charts'; +import { DEFAULT_NUMBER_FORMAT } from '../../../../common/constants'; import { SHOWING, UNIT } from '../../../components/events_viewer/translations'; -import { convertToBuildEsQuery } from '../../../lib/keury'; import { getTabsOnHostsUrl } from '../../../components/link_to/redirect_to_hosts'; -import { histogramConfigs } from '../../../pages/hosts/navigation/events_query_tab_body'; import { MatrixHistogramContainer } from '../../../components/matrix_histogram'; +import { + MatrixHisrogramConfigs, + MatrixHistogramOption, +} from '../../../components/matrix_histogram/types'; +import { useGetUrlSearch } from '../../../components/navigation/use_get_url_search'; +import { navTabs } from '../../home/home_navigations'; import { eventsStackByOptions } from '../../hosts/navigation'; +import { convertToBuildEsQuery } from '../../../lib/keury'; import { useKibana, useUiSetting$ } from '../../../lib/kibana'; +import { histogramConfigs } from '../../../pages/hosts/navigation/events_query_tab_body'; import { Filter, esQuery, @@ -24,12 +32,9 @@ import { } from '../../../../../../../../src/plugins/data/public'; import { inputsModel } from '../../../store'; import { HostsTableType, HostsType } from '../../../store/hosts/model'; -import { DEFAULT_NUMBER_FORMAT } from '../../../../common/constants'; +import { InputsModelId } from '../../../store/inputs/constants'; import * as i18n from '../translations'; -import { MatrixHisrogramConfigs } from '../../../components/matrix_histogram/types'; -import { useGetUrlSearch } from '../../../components/navigation/use_get_url_search'; -import { navTabs } from '../../home/home_navigations'; const NO_FILTERS: Filter[] = []; const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; @@ -38,36 +43,56 @@ const DEFAULT_STACK_BY = 'event.dataset'; const ID = 'eventsByDatasetOverview'; interface Props { + combinedQueries?: string; deleteQuery?: ({ id }: { id: string }) => void; filters?: Filter[]; from: number; + headerChildren?: React.ReactNode; indexPattern: IIndexPattern; + indexToAdd?: string[] | null; + onlyField?: string; query?: Query; + setAbsoluteRangeDatePickerTarget?: InputsModelId; setQuery: (params: { id: string; inspect: inputsModel.InspectQuery | null; loading: boolean; refetch: inputsModel.Refetch; }) => void; + showSpacer?: boolean; to: number; } +const getHistogramOption = (fieldName: string): MatrixHistogramOption => ({ + text: fieldName, + value: fieldName, +}); + const EventsByDatasetComponent: React.FC = ({ + combinedQueries, deleteQuery, filters = NO_FILTERS, from, + headerChildren, indexPattern, + indexToAdd, + onlyField, query = DEFAULT_QUERY, + setAbsoluteRangeDatePickerTarget, setQuery, + showSpacer = true, to, }) => { + // create a unique, but stable (across re-renders) query id + const uniqueQueryId = useMemo(() => `${ID}-${uuid.v4()}`, []); + useEffect(() => { return () => { if (deleteQuery) { - deleteQuery({ id: ID }); + deleteQuery({ id: uniqueQueryId }); } }; - }, [deleteQuery]); + }, [deleteQuery, uniqueQueryId]); const kibana = useKibana(); const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); @@ -84,38 +109,62 @@ const EventsByDatasetComponent: React.FC = ({ const filterQuery = useMemo( () => - convertToBuildEsQuery({ - config: esQuery.getEsQueryConfig(kibana.services.uiSettings), - indexPattern, - queries: [query], - filters, - }), - [kibana, indexPattern, query, filters] + combinedQueries == null + ? convertToBuildEsQuery({ + config: esQuery.getEsQueryConfig(kibana.services.uiSettings), + indexPattern, + queries: [query], + filters, + }) + : combinedQueries, + [combinedQueries, kibana, indexPattern, query, filters] ); const eventsByDatasetHistogramConfigs: MatrixHisrogramConfigs = useMemo( () => ({ ...histogramConfigs, + stackByOptions: + onlyField != null ? [getHistogramOption(onlyField)] : histogramConfigs.stackByOptions, defaultStackByOption: - eventsStackByOptions.find(o => o.text === DEFAULT_STACK_BY) ?? eventsStackByOptions[0], + onlyField != null + ? getHistogramOption(onlyField) + : eventsStackByOptions.find(o => o.text === DEFAULT_STACK_BY) ?? eventsStackByOptions[0], legendPosition: Position.Right, subtitle: (totalCount: number) => `${SHOWING}: ${numeral(totalCount).format(defaultNumberFormat)} ${UNIT(totalCount)}`, + titleSize: onlyField == null ? 'm' : 's', }), - [] + [onlyField, defaultNumberFormat] ); + const headerContent = useMemo(() => { + if (onlyField == null || headerChildren != null) { + return ( + <> + {headerChildren} + {onlyField == null && eventsCountViewEventsButton} + + ); + } else { + return null; + } + }, [onlyField, headerChildren, eventsCountViewEventsButton]); + return ( ); }; diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx index 2db49e60193fc..82f4444728902 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx @@ -63,7 +63,7 @@ const OverviewComponent: React.FC = ({ from={from} indexPattern={indexPattern} query={query} - setAbsoluteRangeDatePicker={setAbsoluteRangeDatePicker!} + setAbsoluteRangeDatePicker={setAbsoluteRangeDatePicker} setQuery={setQuery} to={to} /> diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/signals_by_category/index.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/signals_by_category/index.tsx index 5f78c4c10eb37..feba80539a11b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/signals_by_category/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/signals_by_category/index.tsx @@ -12,6 +12,7 @@ import { useSignalIndex } from '../../../containers/detection_engine/signals/use import { SetAbsoluteRangeDatePicker } from '../../network/types'; import { Filter, IIndexPattern, Query } from '../../../../../../../../src/plugins/data/public'; import { inputsModel } from '../../../store'; +import { InputsModelId } from '../../../store/inputs/constants'; import * as i18n from '../translations'; const DEFAULT_QUERY: Query = { query: '', language: 'kuery' }; @@ -22,9 +23,13 @@ interface Props { deleteQuery?: ({ id }: { id: string }) => void; filters?: Filter[]; from: number; + headerChildren?: React.ReactNode; indexPattern: IIndexPattern; + /** Override all defaults, and only display this field */ + onlyField?: string; query?: Query; setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker; + setAbsoluteRangeDatePickerTarget?: InputsModelId; setQuery: (params: { id: string; inspect: inputsModel.InspectQuery | null; @@ -38,15 +43,18 @@ const SignalsByCategoryComponent: React.FC = ({ deleteQuery, filters = NO_FILTERS, from, + headerChildren, + onlyField, query = DEFAULT_QUERY, setAbsoluteRangeDatePicker, + setAbsoluteRangeDatePickerTarget = 'global', setQuery, to, }) => { const { signalIndexName } = useSignalIndex(); const updateDateRangeCallback = useCallback( (min: number, max: number) => { - setAbsoluteRangeDatePicker!({ id: 'global', from: min, to: max }); + setAbsoluteRangeDatePicker({ id: setAbsoluteRangeDatePickerTarget, from: min, to: max }); }, [setAbsoluteRangeDatePicker] ); @@ -60,12 +68,14 @@ const SignalsByCategoryComponent: React.FC = ({ defaultStackByOption={defaultStackByOption} filters={filters} from={from} + headerChildren={headerChildren} + onlyField={onlyField} query={query} signalIndexName={signalIndexName} setQuery={setQuery} showTotalSignalsCount={true} - showLinkToSignals={true} - stackByOptions={signalsHistogramOptions} + showLinkToSignals={onlyField == null ? true : false} + stackByOptions={onlyField == null ? signalsHistogramOptions : undefined} legendPosition={'right'} to={to} title={i18n.SIGNAL_COUNT} diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/translations.ts b/x-pack/legacy/plugins/siem/public/pages/overview/translations.ts index 601a629d86e57..b7bee15e4c5bf 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/overview/translations.ts @@ -38,6 +38,12 @@ export const SIGNAL_COUNT = i18n.translate('xpack.siem.overview.signalCountTitle defaultMessage: 'Signal count', }); +export const TOP = (fieldName: string) => + i18n.translate('xpack.siem.overview.topNLabel', { + values: { fieldName }, + defaultMessage: `Top {fieldName}`, + }); + export const VIEW_ALERTS = i18n.translate('xpack.siem.overview.viewAlertsButtonLabel', { defaultMessage: 'View alerts', }); diff --git a/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.test.tsx b/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.test.tsx index 62399891c9606..ae95a1316a600 100644 --- a/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.test.tsx @@ -10,6 +10,8 @@ import { shallow, ShallowWrapper } from 'enzyme'; import React from 'react'; import ApolloClient from 'apollo-client'; +jest.mock('../../pages/overview/events_by_dataset'); + jest.mock('../../lib/kibana', () => { return { useKibana: jest.fn(), diff --git a/x-pack/legacy/plugins/siem/server/lib/matrix_histogram/query.events_over_time.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/matrix_histogram/query.events_over_time.dsl.ts index 3a4281b980cc4..63649a1064b02 100644 --- a/x-pack/legacy/plugins/siem/server/lib/matrix_histogram/query.events_over_time.dsl.ts +++ b/x-pack/legacy/plugins/siem/server/lib/matrix_histogram/query.events_over_time.dsl.ts @@ -3,9 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + +import { showAllOthersBucket } from '../../../common/constants'; import { createQueryFilterClauses, calculateTimeSeriesInterval } from '../../utils/build_query'; import { MatrixHistogramRequestOptions } from '../framework'; +import * as i18n from './translations'; + export const buildEventsOverTimeQuery = ({ filterQuery, timerange: { from, to }, @@ -41,11 +45,19 @@ export const buildEventsOverTimeQuery = ({ }, }, }; + + const missing = + stackByField != null && showAllOthersBucket.includes(stackByField) + ? { + missing: stackByField?.endsWith('.ip') ? '0.0.0.0' : i18n.ALL_OTHERS, + } + : {}; + return { eventActionGroup: { terms: { field: stackByField, - missing: 'All others', + ...missing, order: { _count: 'desc', }, diff --git a/x-pack/legacy/plugins/siem/server/lib/matrix_histogram/translations.ts b/x-pack/legacy/plugins/siem/server/lib/matrix_histogram/translations.ts new file mode 100644 index 0000000000000..413acaa2d4b0a --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/matrix_histogram/translations.ts @@ -0,0 +1,14 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const ALL_OTHERS = i18n.translate( + 'xpack.siem.detectionEngine.signals.histogram.allOthersGroupingLabel', + { + defaultMessage: 'All others', + } +); From b81f9269e5a29db75e56aaafa01d02ed860003fe Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 17 Apr 2020 10:04:38 +0300 Subject: [PATCH 04/22] Index pattern management UI -> TypeScript and New Platform Ready (create_index_pattern_wizard) (#63111) * Migrated create_index_pattern_wizard and its tests to typescript * Fixed types * Fixed some comments * Fixed comments * Fixed types * Fixed types * Fixed snapshot * Removed indexPatternCreationType from state. * Fixed comments Co-authored-by: Elastic Machine --- .../create_index_pattern_wizard.test.js.snap | 205 ------------ .../create_index_pattern_wizard.test.tsx.snap | 312 ++++++++++++++++++ .../step_index_pattern/step_index_pattern.tsx | 2 +- ...s => create_index_pattern_wizard.test.tsx} | 129 +++----- ...ard.js => create_index_pattern_wizard.tsx} | 133 +++++--- .../create_index_pattern_wizard/index.js | 4 +- 6 files changed, 443 insertions(+), 342 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.js.snap create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/{create_index_pattern_wizard.test.js => create_index_pattern_wizard.test.tsx} (55%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/{create_index_pattern_wizard.js => create_index_pattern_wizard.tsx} (63%) diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.js.snap deleted file mode 100644 index 59b275c7708a4..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.js.snap +++ /dev/null @@ -1,205 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CreateIndexPatternWizard defaults to the loading state 1`] = ` - -
-
- -
- -
-`; - -exports[`CreateIndexPatternWizard renders index pattern step when there are indices 1`] = ` - -
-
- -
- -
-`; - -exports[`CreateIndexPatternWizard renders the empty state when there are no indices 1`] = ` - -
-
- -
- -
-`; - -exports[`CreateIndexPatternWizard renders time field step when step is set to 2 1`] = ` - -
-
- -
- -
-`; - -exports[`CreateIndexPatternWizard renders when there are no indices but there are remote clusters 1`] = ` - -
-
- -
- -
-`; - -exports[`CreateIndexPatternWizard shows system indices even if there are no other indices if the include system indices is toggled 1`] = ` - -
-
- -
- -
-`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap new file mode 100644 index 0000000000000..09a06bd8827ce --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap @@ -0,0 +1,312 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CreateIndexPatternWizard defaults to the loading state 1`] = ` + +
+
+ +
+ +
+`; + +exports[`CreateIndexPatternWizard renders index pattern step when there are indices 1`] = ` + +
+
+ +
+ +
+`; + +exports[`CreateIndexPatternWizard renders the empty state when there are no indices 1`] = ` + +
+
+ +
+ +
+`; + +exports[`CreateIndexPatternWizard renders time field step when step is set to 2 1`] = ` + +
+
+ +
+ +
+`; + +exports[`CreateIndexPatternWizard renders when there are no indices but there are remote clusters 1`] = ` + +
+
+ +
+ +
+`; + +exports[`CreateIndexPatternWizard shows system indices even if there are no other indices if the include system indices is toggled 1`] = ` + +
+
+ +
+ +
+`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx index 648bf7f8f9738..d8f677b7f6089 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx @@ -48,7 +48,7 @@ interface StepIndexPatternProps { esService: DataPublicPluginStart['search']['__LEGACY']['esClient']; savedObjectsClient: SavedObjectsClient; indexPatternCreationType: IndexPatternCreationConfig; - goToNextStep: () => void; + goToNextStep: (query: string) => void; initialQuery?: string; uiSettings: IUiSettingsClient; } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx similarity index 55% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx index 941f87d4d9fd2..45af98661eda3 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx @@ -21,17 +21,12 @@ import React from 'react'; import { shallow } from 'enzyme'; import { CreateIndexPatternWizard } from './create_index_pattern_wizard'; -const mockIndexPatternCreationType = { - getIndexPatternType: () => 'default', - getIndexPatternName: () => 'name', - getIsBeta: () => false, - checkIndicesForErrors: () => false, - getShowSystemIndices: () => false, - renderPrompt: () => {}, - getIndexPatternMappings: () => { - return {}; - }, -}; +import { coreMock } from '../../../../../../../../core/public/mocks'; +import { dataPluginMock } from '../../../../../../../../plugins/data/public/mocks'; +import { IndexPatternCreationConfig } from '../../../../../../../../plugins/index_pattern_management/public'; +import { IndexPattern } from '../../../../../../../../plugins/data/public'; +import { SavedObjectsClient } from '../../../../../../../../core/public'; + jest.mock('./components/step_index_pattern', () => ({ StepIndexPattern: 'StepIndexPattern' })); jest.mock('./components/step_time_field', () => ({ StepTimeField: 'StepTimeField' })); jest.mock('./components/header', () => ({ Header: 'Header' })); @@ -46,39 +41,36 @@ jest.mock('ui/chrome', () => ({ addBasePath: () => {}, })); -const loadingDataDocUrl = ''; +const { savedObjects, overlays, uiSettings } = coreMock.createStart(); +const { indexPatterns, search } = dataPluginMock.createStartContract(); +const mockIndexPatternCreationType = new IndexPatternCreationConfig({ + type: 'default', + name: 'name', +}); + const initialQuery = ''; const services = { - es: {}, - indexPatterns: {}, - savedObjectsClient: {}, - config: {}, - changeUrl: () => {}, - scopeApply: () => {}, - + es: search.__LEGACY.esClient, + indexPatterns, + savedObjectsClient: savedObjects.client as SavedObjectsClient, + uiSettings, + changeUrl: jest.fn(), + openConfirm: overlays.openConfirm, indexPatternCreationType: mockIndexPatternCreationType, }; describe('CreateIndexPatternWizard', () => { - it(`defaults to the loading state`, async () => { + test(`defaults to the loading state`, () => { const component = shallow( - + ); expect(component).toMatchSnapshot(); }); - it('renders the empty state when there are no indices', async () => { + test('renders the empty state when there are no indices', async () => { const component = shallow( - + ); component.setState({ @@ -91,13 +83,9 @@ describe('CreateIndexPatternWizard', () => { expect(component).toMatchSnapshot(); }); - it('renders when there are no indices but there are remote clusters', async () => { + test('renders when there are no indices but there are remote clusters', async () => { const component = shallow( - + ); component.setState({ @@ -110,13 +98,9 @@ describe('CreateIndexPatternWizard', () => { expect(component).toMatchSnapshot(); }); - it('shows system indices even if there are no other indices if the include system indices is toggled', async () => { + test('shows system indices even if there are no other indices if the include system indices is toggled', async () => { const component = shallow( - + ); component.setState({ @@ -129,13 +113,9 @@ describe('CreateIndexPatternWizard', () => { expect(component).toMatchSnapshot(); }); - it('renders index pattern step when there are indices', async () => { + test('renders index pattern step when there are indices', async () => { const component = shallow( - + ); component.setState({ @@ -147,13 +127,9 @@ describe('CreateIndexPatternWizard', () => { expect(component).toMatchSnapshot(); }); - it('renders time field step when step is set to 2', async () => { + test('renders time field step when step is set to 2', async () => { const component = shallow( - + ); component.setState({ @@ -166,37 +142,30 @@ describe('CreateIndexPatternWizard', () => { expect(component).toMatchSnapshot(); }); - it('invokes the provided services when creating an index pattern', async () => { - const get = jest.fn(); - const set = jest.fn(); + test('invokes the provided services when creating an index pattern', async () => { const create = jest.fn().mockImplementation(() => 'id'); const clear = jest.fn(); - const changeUrl = jest.fn(); - - const component = shallow( - ({ - create, - }), - clearCache: clear, - }, - changeUrl, - indexPatternCreationType: mockIndexPatternCreationType, - }} - /> + services.indexPatterns.clearCache = clear; + const indexPattern = ({ + id: '1', + title: 'my-fake-index-pattern', + timeFieldName: 'timestamp', + fields: [], + create, + } as unknown) as IndexPattern; + services.indexPatterns.make = async () => { + return indexPattern; + }; + + const component = shallow( + ); component.setState({ indexPattern: 'foo' }); - await component.instance().createIndexPattern(null, 'id'); - expect(get).toBeCalled(); + await component.instance().createIndexPattern(undefined, 'id'); + expect(services.uiSettings.get).toBeCalled(); expect(create).toBeCalled(); expect(clear).toBeCalledWith('id'); - expect(changeUrl).toBeCalledWith(`/management/kibana/index_patterns/id`); + expect(services.changeUrl).toBeCalledWith(`/management/kibana/index_patterns/id`); }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.tsx similarity index 63% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.tsx index 1a93188edd6cc..4166d48349d35 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/create_index_pattern_wizard.tsx @@ -17,11 +17,11 @@ * under the License. */ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React, { ReactElement, Component } from 'react'; -import { EuiGlobalToastList } from '@elastic/eui'; +import { EuiGlobalToastList, EuiGlobalToastListToast } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; import { StepIndexPattern } from './components/step_index_pattern'; import { StepTimeField } from './components/step_time_field'; @@ -31,41 +31,61 @@ import { EmptyState } from './components/empty_state'; import { MAX_SEARCH_SIZE } from './constants'; import { ensureMinimumTime, getIndices } from './lib'; -import { i18n } from '@kbn/i18n'; - -export class CreateIndexPatternWizard extends Component { - static propTypes = { - initialQuery: PropTypes.string, - services: PropTypes.shape({ - es: PropTypes.object.isRequired, - indexPatterns: PropTypes.object.isRequired, - savedObjectsClient: PropTypes.object.isRequired, - indexPatternCreationType: PropTypes.object.isRequired, - config: PropTypes.object.isRequired, - changeUrl: PropTypes.func.isRequired, - openConfirm: PropTypes.func.isRequired, - }).isRequired, +import { + SavedObjectsClient, + IUiSettingsClient, + OverlayStart, +} from '../../../../../../../../core/public'; +import { DataPublicPluginStart } from '../../../../../../../../plugins/data/public'; +import { IndexPatternCreationConfig } from '../../../../../../../../plugins/index_pattern_management/public'; +import { MatchedIndex } from './types'; + +interface CreateIndexPatternWizardProps { + initialQuery: string; + services: { + indexPatternCreationType: IndexPatternCreationConfig; + es: DataPublicPluginStart['search']['__LEGACY']['esClient']; + indexPatterns: DataPublicPluginStart['indexPatterns']; + savedObjectsClient: SavedObjectsClient; + uiSettings: IUiSettingsClient; + changeUrl: (url: string) => void; + openConfirm: OverlayStart['openConfirm']; }; +} - constructor(props) { - super(props); - this.indexPatternCreationType = this.props.services.indexPatternCreationType; - this.state = { - step: 1, - indexPattern: '', - allIndices: [], - remoteClustersExist: false, - isInitiallyLoadingIndices: true, - isIncludingSystemIndices: false, - toasts: [], - }; - } +interface CreateIndexPatternWizardState { + step: number; + indexPattern: string; + allIndices: MatchedIndex[]; + remoteClustersExist: boolean; + isInitiallyLoadingIndices: boolean; + isIncludingSystemIndices: boolean; + toasts: EuiGlobalToastListToast[]; +} + +export class CreateIndexPatternWizard extends Component< + CreateIndexPatternWizardProps, + CreateIndexPatternWizardState +> { + state = { + step: 1, + indexPattern: '', + allIndices: [], + remoteClustersExist: false, + isInitiallyLoadingIndices: true, + isIncludingSystemIndices: false, + toasts: [], + }; async UNSAFE_componentWillMount() { this.fetchData(); } - catchAndWarn = async (asyncFn, errorValue, errorMsg) => { + catchAndWarn = async ( + asyncFn: Promise, + errorValue: [] | string[], + errorMsg: ReactElement + ) => { try { return await asyncFn; } catch (errors) { @@ -109,22 +129,26 @@ export class CreateIndexPatternWizard extends Component { // query local and remote indices, updating state independently ensureMinimumTime( this.catchAndWarn( - getIndices(services.es, this.indexPatternCreationType, `*`, MAX_SEARCH_SIZE), + getIndices(services.es, services.indexPatternCreationType, `*`, MAX_SEARCH_SIZE), [], indicesFailMsg ) - ).then(allIndices => this.setState({ allIndices, isInitiallyLoadingIndices: false })); + ).then((allIndices: MatchedIndex[]) => + this.setState({ allIndices, isInitiallyLoadingIndices: false }) + ); this.catchAndWarn( // if we get an error from remote cluster query, supply fallback value that allows user entry. // ['a'] is fallback value - getIndices(services.es, this.indexPatternCreationType, `*:*`, 1), + getIndices(services.es, services.indexPatternCreationType, `*:*`, 1), ['a'], clustersFailMsg - ).then(remoteIndices => this.setState({ remoteClustersExist: !!remoteIndices.length })); + ).then((remoteIndices: string[] | MatchedIndex[]) => + this.setState({ remoteClustersExist: !!remoteIndices.length }) + ); }; - createIndexPattern = async (timeFieldName, indexPatternId) => { + createIndexPattern = async (timeFieldName: string | undefined, indexPatternId: string) => { const { services } = this.props; const { indexPattern } = this.state; @@ -134,13 +158,13 @@ export class CreateIndexPatternWizard extends Component { id: indexPatternId, title: indexPattern, timeFieldName, - ...this.indexPatternCreationType.getIndexPatternMappings(), + ...services.indexPatternCreationType.getIndexPatternMappings(), }); const createdId = await emptyPattern.create(); if (!createdId) { const confirmMessage = i18n.translate('kbn.management.indexPattern.titleExistsLabel', { - values: { title: this.title }, + values: { title: emptyPattern.title }, defaultMessage: "An index pattern with the title '{title}' already exists.", }); @@ -157,15 +181,15 @@ export class CreateIndexPatternWizard extends Component { } } - if (!services.config.get('defaultIndex')) { - await services.config.set('defaultIndex', createdId); + if (!services.uiSettings.get('defaultIndex')) { + await services.uiSettings.set('defaultIndex', createdId); } services.indexPatterns.clearCache(createdId); services.changeUrl(`/management/kibana/index_patterns/${createdId}`); }; - goToTimeFieldStep = indexPattern => { + goToTimeFieldStep = (indexPattern: string) => { this.setState({ step: 2, indexPattern }); }; @@ -174,22 +198,23 @@ export class CreateIndexPatternWizard extends Component { }; onChangeIncludingSystemIndices = () => { - this.setState(state => ({ - isIncludingSystemIndices: !state.isIncludingSystemIndices, + this.setState(prevState => ({ + isIncludingSystemIndices: !prevState.isIncludingSystemIndices, })); }; renderHeader() { const { isIncludingSystemIndices } = this.state; + const { services } = this.props; return (
); } @@ -208,7 +233,7 @@ export class CreateIndexPatternWizard extends Component { return ; } - const hasDataIndices = allIndices.some(({ name }) => !name.startsWith('.')); + const hasDataIndices = allIndices.some(({ name }: MatchedIndex) => !name.startsWith('.')); if (!hasDataIndices && !isIncludingSystemIndices && !remoteClustersExist) { return ; } @@ -222,7 +247,7 @@ export class CreateIndexPatternWizard extends Component { isIncludingSystemIndices={isIncludingSystemIndices} esService={services.es} savedObjectsClient={services.savedObjectsClient} - indexPatternCreationType={this.indexPatternCreationType} + indexPatternCreationType={services.indexPatternCreationType} goToNextStep={this.goToTimeFieldStep} uiSettings={services.uiSettings} /> @@ -237,7 +262,7 @@ export class CreateIndexPatternWizard extends Component { indexPatternsService={services.indexPatterns} goToPreviousStep={this.goToIndexPatternStep} createIndexPattern={this.createIndexPattern} - indexPatternCreationType={this.indexPatternCreationType} + indexPatternCreationType={services.indexPatternCreationType} /> ); } @@ -245,9 +270,9 @@ export class CreateIndexPatternWizard extends Component { return null; } - removeToast = removedToast => { + removeToast = (id: string) => { this.setState(prevState => ({ - toasts: prevState.toasts.filter(toast => toast.id !== removedToast.id), + toasts: prevState.toasts.filter(toast => toast.id !== id), })); }; @@ -263,7 +288,9 @@ export class CreateIndexPatternWizard extends Component { { + this.removeToast(id); + }} toastLifeTimeMs={6000} /> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js index 47cb773258cb4..ed1fc026c560c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js @@ -36,17 +36,15 @@ uiRoutes.when('/management/kibana/index_pattern', { $routeParams.type ); const services = { - config: npStart.core.uiSettings, + uiSettings: npStart.core.uiSettings, es: npStart.plugins.data.search.__LEGACY.esClient, indexPatterns: npStart.plugins.data.indexPatterns, - $http: npStart.core.http, savedObjectsClient: npStart.core.savedObjects.client, indexPatternCreationType, changeUrl: url => { $scope.$evalAsync(() => kbnUrl.changePath(url)); }, openConfirm: npStart.core.overlays.openConfirm, - uiSettings: npStart.core.uiSettings, }; const initialQuery = $routeParams.id ? decodeURIComponent($routeParams.id) : undefined; From eefafa291920a04eda86ecb6d834b8ceca95990b Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Fri, 17 Apr 2020 10:18:01 +0200 Subject: [PATCH 05/22] Replacebad scope link with actual values (#63444) Co-authored-by: Elastic Machine --- .../json/overrides/cluster.put_settings.json | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json index 408b01c4cb8f5..0da2c130b47cf 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json +++ b/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json @@ -59,7 +59,61 @@ } }, "transient": { - "__scope_link": ".persistent" + "cluster": { + "routing": { + "allocation.enable": { + "__one_of": ["all", "primaries", "new_primaries", "none"] + }, + "allocation.disk.threshold_enabled": { "__one_of": [false, true] }, + "allocation.disk.watermark.low": "85%", + "allocation.disk.watermark.high": "90%", + "allocation.disk.reroute_interval": "60s", + "allocation.exclude": { + "_ip": "", + "_name": "", + "_host": "", + "_id": "" + }, + "allocation.include": { + "_ip": "", + "_name": "", + "_host": "", + "_id": "" + }, + "allocation.require": { + "_ip": "", + "_name": "", + "_host": "", + "_id": "" + }, + "allocation.awareness.attributes": [], + "allocation.awareness.force": { + "*": { + "values": [] + } + }, + "allocation.allow_rebalance": { + "__one_of": [ + "always", + "indices_primaries_active", + "indices_all_active" + ] + }, + "allocation.cluster_concurrent_rebalance": 2, + "allocation.node_initial_primaries_recoveries": 4, + "allocation.node_concurrent_recoveries": 2, + "allocation.same_shard.host": { "__one_of": [false, true] } + } + }, + "indices": { + "breaker": { + "total.limit": "70%", + "fielddata.limit": "60%", + "fielddata.overhead": 1.03, + "request.limit": "40%", + "request.overhead": 1.0 + } + } } } } From 4e56419ca4a45aca776ecea3562825d85fb6afbb Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 17 Apr 2020 10:42:27 +0200 Subject: [PATCH 06/22] Migrate timelion vis (#62819) --- .eslintignore | 4 +- .github/CODEOWNERS | 2 +- .i18nrc.json | 2 +- .../core_plugins/timelion/public/app.js | 5 +- .../directives/timelion_expression_input.js | 6 +-- .../public/panels/timechart/schema.ts | 14 ++++-- .../core_plugins/vis_type_timelion/index.ts | 44 ----------------- .../vis_type_timelion/package.json | 4 -- .../public/components/_index.scss | 2 - .../vis_type_timelion/public/legacy.ts | 35 -------------- .../public/legacy_imports.ts | 21 --------- .../ui/public/new_platform/new_platform.ts | 2 + src/plugins/timelion/kibana.json | 8 ---- src/plugins/timelion/public/index.ts | 30 ------------ .../vis_type_timelion/README.md | 0 .../common/chain.peg | 0 .../common/lib/calculate_interval.test.ts | 0 .../common/lib/calculate_interval.ts | 0 .../common/lib/index.ts | 0 .../common/lib/to_milliseconds.ts | 0 .../common/types.ts | 0 .../{timelion => vis_type_timelion}/config.ts | 0 src/plugins/vis_type_timelion/kibana.json | 8 ++++ .../public/_generated_/chain.js | 0 .../public/_timelion_editor.scss | 0 .../public/_timelion_vis.scss | 0 .../public/components/_index.scss | 2 + .../public/components/_panel.scss | 0 .../_timelion_expression_input.scss | 0 .../public/components/chart.tsx | 0 .../public/components/index.ts | 0 .../public/components/panel.tsx | 4 +- .../components/timelion_expression_input.tsx | 7 +-- .../timelion_expression_input_helpers.test.ts | 2 +- .../timelion_expression_input_helpers.ts | 5 +- .../public/components/timelion_interval.tsx | 4 +- .../public/components/timelion_vis.tsx | 2 +- .../vis_type_timelion/public/flot.js | 14 +++--- .../public/helpers/arg_value_suggestions.ts | 7 +-- .../public/helpers/get_timezone.ts | 0 .../public/helpers/panel_utils.ts | 2 +- .../public/helpers/plugin_services.ts | 2 +- .../public/helpers/tick_formatters.test.ts | 0 .../public/helpers/tick_formatters.ts | 0 .../public/helpers/tick_generator.test.ts | 0 .../public/helpers/tick_generator.ts | 0 .../helpers/timelion_request_handler.ts | 4 +- .../public/helpers/xaxis_formatter.ts | 0 .../vis_type_timelion/public/index.scss | 2 - .../vis_type_timelion/public/index.ts | 4 +- .../vis_type_timelion/public/plugin.ts | 47 +++++++++++++++---- .../public/timelion_options.tsx | 0 .../public/timelion_vis_fn.ts | 0 .../public/timelion_vis_type.tsx | 4 +- .../webpackShims/jquery.flot.axislabels.js | 0 .../webpackShims/jquery.flot.crosshair.js | 0 .../public/webpackShims/jquery.flot.js | 0 .../webpackShims/jquery.flot.selection.js | 0 .../public/webpackShims/jquery.flot.stack.js | 0 .../public/webpackShims/jquery.flot.symbol.js | 0 .../public/webpackShims/jquery.flot.time.js | 0 .../server/fit_functions/average.js | 0 .../server/fit_functions/average.test.js | 0 .../server/fit_functions/carry.js | 0 .../server/fit_functions/carry.test.js | 0 .../server/fit_functions/nearest.js | 0 .../server/fit_functions/none.js | 0 .../server/fit_functions/scale.js | 0 .../server/handlers/chain_runner.js | 0 .../server/handlers/lib/arg_type.js | 0 .../server/handlers/lib/index_arguments.js | 0 .../server/handlers/lib/parse_sheet.js | 0 .../server/handlers/lib/parse_sheet.test.js | 0 .../server/handlers/lib/preprocess_chain.js | 0 .../handlers/lib/reposition_arguments.js | 0 .../server/handlers/lib/tl_config.js | 0 .../server/handlers/lib/validate_arg.js | 0 .../server/handlers/lib/validate_time.js | 0 .../server/index.ts | 16 ++++--- .../server/lib/alter.js | 0 .../server/lib/as_sorted.js | 0 .../server/lib/build_target.js | 0 .../server/lib/classes/chainable.js | 0 .../server/lib/classes/datasource.js | 0 .../server/lib/classes/timelion_function.d.ts | 0 .../server/lib/classes/timelion_function.js | 0 .../server/lib/config_manager.ts | 0 .../server/lib/functions_md.js | 0 .../server/lib/get_namespaced_settings.js | 0 .../server/lib/load_functions.d.ts | 0 .../server/lib/load_functions.js | 0 .../server/lib/load_functions.test.js | 2 +- .../server/lib/offset_time.js | 0 .../server/lib/offset_time.test.js | 0 .../server/lib/process_function_definition.js | 0 .../server/lib/reduce.js | 0 .../server/lib/split_interval.js | 0 .../server/lib/unzip_pairs.js | 0 .../server/plugin.ts | 0 .../server/routes/functions.ts | 0 .../server/routes/run.ts | 0 .../server/routes/validate_es.ts | 0 .../server/series_functions/abs.js | 0 .../server/series_functions/abs.test.js | 0 .../aggregate/aggregate.test.js | 0 .../server/series_functions/aggregate/avg.js | 0 .../series_functions/aggregate/cardinality.js | 0 .../series_functions/aggregate/first.js | 0 .../series_functions/aggregate/index.js | 0 .../server/series_functions/aggregate/last.js | 0 .../server/series_functions/aggregate/max.js | 0 .../server/series_functions/aggregate/min.js | 0 .../server/series_functions/aggregate/sum.js | 0 .../server/series_functions/bars.js | 0 .../server/series_functions/bars.test.js | 0 .../server/series_functions/color.js | 0 .../server/series_functions/color.test.js | 0 .../server/series_functions/condition.js | 0 .../server/series_functions/condition.test.js | 0 .../server/series_functions/cusum.js | 0 .../server/series_functions/cusum.test.js | 0 .../server/series_functions/derivative.js | 0 .../series_functions/derivative.test.js | 0 .../server/series_functions/divide.js | 0 .../server/series_functions/divide.test.js | 0 .../server/series_functions/es/es.test.js | 0 .../server/series_functions/es/index.js | 0 .../series_functions/es/lib/agg_body.js | 0 .../es/lib/agg_response_to_series_list.js | 0 .../series_functions/es/lib/build_request.js | 0 .../es/lib/create_date_agg.js | 0 .../server/series_functions/first.js | 0 .../server/series_functions/first.test.js | 0 .../server/series_functions/fit.js | 0 .../server/series_functions/fit.test.js | 2 +- .../series_functions/fixtures/bucket_list.js | 0 .../series_functions/fixtures/es_response.js | 0 .../series_functions/fixtures/series_list.js | 0 .../series_functions/fixtures/tl_config.js | 0 .../server/series_functions/graphite.js | 0 .../server/series_functions/graphite.test.js | 0 .../series_functions/helpers/get_series.js | 0 .../helpers/get_series_list.js | 0 .../helpers/get_single_series_list.js | 0 .../helpers/invoke_series_fn.js | 0 .../server/series_functions/hide.js | 0 .../server/series_functions/hide.test.js | 0 .../server/series_functions/holt/index.js | 0 .../server/series_functions/holt/lib/des.js | 0 .../server/series_functions/holt/lib/ses.js | 0 .../server/series_functions/holt/lib/tes.js | 0 .../server/series_functions/label.js | 0 .../server/series_functions/label.test.js | 0 .../server/series_functions/legend.js | 0 .../server/series_functions/legend.test.js | 0 .../server/series_functions/lines.js | 0 .../server/series_functions/lines.test.js | 0 .../server/series_functions/log.js | 0 .../server/series_functions/log.test.js | 0 .../server/series_functions/max.js | 0 .../server/series_functions/max.test.js | 0 .../server/series_functions/min.js | 0 .../server/series_functions/min.test.js | 0 .../server/series_functions/movingaverage.js | 0 .../series_functions/movingaverage.test.js | 0 .../server/series_functions/movingstd.js | 0 .../server/series_functions/movingstd.test.js | 0 .../server/series_functions/multiply.js | 0 .../server/series_functions/multiply.test.js | 0 .../server/series_functions/points.js | 0 .../server/series_functions/points.test.js | 0 .../server/series_functions/precision.js | 0 .../server/series_functions/precision.test.js | 0 .../server/series_functions/props.js | 0 .../server/series_functions/quandl.js | 0 .../server/series_functions/quandl.test.js | 0 .../server/series_functions/range.js | 0 .../server/series_functions/range.test.js | 0 .../server/series_functions/scale_interval.js | 0 .../series_functions/scale_interval.test.js | 0 .../server/series_functions/static.js | 0 .../server/series_functions/static.test.js | 0 .../server/series_functions/subtract.js | 0 .../server/series_functions/subtract.test.js | 0 .../server/series_functions/sum.js | 0 .../server/series_functions/sum.test.js | 0 .../server/series_functions/title.js | 0 .../server/series_functions/title.test.js | 0 .../server/series_functions/trend/index.js | 0 .../series_functions/trend/lib/regress.js | 0 .../server/series_functions/trim.js | 0 .../server/series_functions/trim.test.js | 0 .../server/series_functions/worldbank.js | 0 .../series_functions/worldbank_indicators.js | 0 .../server/series_functions/yaxis.js | 0 .../server/series_functions/yaxis.test.js | 0 .../server/timelion.json | 0 .../server/types.ts | 0 tasks/config/peg.js | 4 +- .../kbn_tp_embeddable_explorer/tsconfig.json | 5 +- test/tsconfig.json | 3 +- x-pack/plugins/features/kibana.json | 2 +- x-pack/plugins/features/server/plugin.ts | 6 +-- x-pack/test/tsconfig.json | 3 +- x-pack/tsconfig.json | 3 +- 205 files changed, 123 insertions(+), 222 deletions(-) delete mode 100644 src/legacy/core_plugins/vis_type_timelion/index.ts delete mode 100644 src/legacy/core_plugins/vis_type_timelion/package.json delete mode 100644 src/legacy/core_plugins/vis_type_timelion/public/components/_index.scss delete mode 100644 src/legacy/core_plugins/vis_type_timelion/public/legacy.ts delete mode 100644 src/legacy/core_plugins/vis_type_timelion/public/legacy_imports.ts delete mode 100644 src/plugins/timelion/kibana.json delete mode 100644 src/plugins/timelion/public/index.ts rename src/{legacy/core_plugins => plugins}/vis_type_timelion/README.md (100%) rename src/plugins/{timelion => vis_type_timelion}/common/chain.peg (100%) rename src/plugins/{timelion => vis_type_timelion}/common/lib/calculate_interval.test.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/common/lib/calculate_interval.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/common/lib/index.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/common/lib/to_milliseconds.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/common/types.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/config.ts (100%) create mode 100644 src/plugins/vis_type_timelion/kibana.json rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/_generated_/chain.js (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/_timelion_editor.scss (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/_timelion_vis.scss (100%) create mode 100644 src/plugins/vis_type_timelion/public/components/_index.scss rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/_panel.scss (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/_timelion_expression_input.scss (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/chart.tsx (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/index.ts (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/panel.tsx (98%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/timelion_expression_input.tsx (96%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts (99%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/timelion_expression_input_helpers.ts (98%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/timelion_interval.tsx (96%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/components/timelion_vis.tsx (95%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/flot.js (72%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/arg_value_suggestions.ts (97%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/get_timezone.ts (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/panel_utils.ts (98%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/plugin_services.ts (93%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/tick_formatters.test.ts (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/tick_formatters.ts (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/tick_generator.test.ts (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/tick_generator.ts (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/timelion_request_handler.ts (95%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/helpers/xaxis_formatter.ts (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/index.scss (59%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/index.ts (90%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/plugin.ts (67%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/timelion_options.tsx (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/timelion_vis_fn.ts (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/timelion_vis_type.tsx (93%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/webpackShims/jquery.flot.axislabels.js (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/webpackShims/jquery.flot.crosshair.js (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/webpackShims/jquery.flot.js (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/webpackShims/jquery.flot.selection.js (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/webpackShims/jquery.flot.stack.js (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/webpackShims/jquery.flot.symbol.js (100%) rename src/{legacy/core_plugins => plugins}/vis_type_timelion/public/webpackShims/jquery.flot.time.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/fit_functions/average.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/fit_functions/average.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/fit_functions/carry.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/fit_functions/carry.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/fit_functions/nearest.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/fit_functions/none.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/fit_functions/scale.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/chain_runner.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/lib/arg_type.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/lib/index_arguments.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/lib/parse_sheet.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/lib/parse_sheet.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/lib/preprocess_chain.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/lib/reposition_arguments.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/lib/tl_config.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/lib/validate_arg.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/handlers/lib/validate_time.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/index.ts (64%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/alter.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/as_sorted.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/build_target.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/classes/chainable.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/classes/datasource.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/classes/timelion_function.d.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/classes/timelion_function.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/config_manager.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/functions_md.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/get_namespaced_settings.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/load_functions.d.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/load_functions.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/load_functions.test.js (94%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/offset_time.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/offset_time.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/process_function_definition.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/reduce.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/split_interval.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/lib/unzip_pairs.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/plugin.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/server/routes/functions.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/server/routes/run.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/server/routes/validate_es.ts (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/abs.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/abs.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/aggregate/aggregate.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/aggregate/avg.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/aggregate/cardinality.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/aggregate/first.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/aggregate/index.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/aggregate/last.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/aggregate/max.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/aggregate/min.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/aggregate/sum.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/bars.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/bars.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/color.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/color.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/condition.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/condition.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/cusum.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/cusum.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/derivative.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/derivative.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/divide.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/divide.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/es/es.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/es/index.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/es/lib/agg_body.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/es/lib/agg_response_to_series_list.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/es/lib/build_request.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/es/lib/create_date_agg.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/first.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/first.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/fit.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/fit.test.js (98%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/fixtures/bucket_list.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/fixtures/es_response.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/fixtures/series_list.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/fixtures/tl_config.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/graphite.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/graphite.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/helpers/get_series.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/helpers/get_series_list.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/helpers/get_single_series_list.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/helpers/invoke_series_fn.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/hide.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/hide.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/holt/index.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/holt/lib/des.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/holt/lib/ses.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/holt/lib/tes.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/label.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/label.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/legend.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/legend.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/lines.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/lines.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/log.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/log.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/max.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/max.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/min.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/min.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/movingaverage.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/movingaverage.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/movingstd.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/movingstd.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/multiply.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/multiply.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/points.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/points.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/precision.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/precision.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/props.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/quandl.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/quandl.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/range.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/range.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/scale_interval.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/scale_interval.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/static.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/static.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/subtract.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/subtract.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/sum.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/sum.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/title.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/title.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/trend/index.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/trend/lib/regress.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/trim.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/trim.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/worldbank.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/worldbank_indicators.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/yaxis.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/series_functions/yaxis.test.js (100%) rename src/plugins/{timelion => vis_type_timelion}/server/timelion.json (100%) rename src/plugins/{timelion => vis_type_timelion}/server/types.ts (100%) diff --git a/.eslintignore b/.eslintignore index 357d735e8044b..1f22b6074e76e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,14 +9,14 @@ bower_components /built_assets /html_docs /src/plugins/data/common/es_query/kuery/ast/_generated_/** -/src/legacy/core_plugins/vis_type_timelion/public/_generated_/** +/src/plugins/vis_type_timelion/public/_generated_/** src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data /src/legacy/ui/public/flot-charts /test/fixtures/scenarios /src/legacy/core_plugins/console/public/webpackShims /src/legacy/core_plugins/console/public/tests/webpackShims /src/legacy/ui/public/utils/decode_geo_hash.js -/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.* +/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.* /src/core/lib/kbn_internal_native_observable /packages/*/target /packages/eslint-config-kibana diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 985eb5c1342a0..ab05b32ab063e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -14,7 +14,7 @@ /src/legacy/core_plugins/vis_type_vislib/ @elastic/kibana-app /src/plugins/vis_type_xy/ @elastic/kibana-app /src/plugins/kibana_legacy/ @elastic/kibana-app -/src/plugins/timelion/ @elastic/kibana-app +/src/plugins/vis_type_timelion/ @elastic/kibana-app /src/plugins/dashboard/ @elastic/kibana-app /src/plugins/discover/ @elastic/kibana-app /src/plugins/visualize/ @elastic/kibana-app diff --git a/.i18nrc.json b/.i18nrc.json index 70277112136a9..4a516f23ebf05 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -43,7 +43,7 @@ "src/plugins/telemetry_management_section" ], "tileMap": "src/legacy/core_plugins/tile_map", - "timelion": ["src/legacy/core_plugins/timelion", "src/legacy/core_plugins/vis_type_timelion", "src/plugins/timelion"], + "timelion": ["src/legacy/core_plugins/timelion", "src/plugins/vis_type_timelion"], "uiActions": "src/plugins/ui_actions", "visDefaultEditor": "src/plugins/vis_default_editor", "visTypeMarkdown": "src/plugins/vis_type_markdown", diff --git a/src/legacy/core_plugins/timelion/public/app.js b/src/legacy/core_plugins/timelion/public/app.js index c15318d29e761..7f5c7d4664af8 100644 --- a/src/legacy/core_plugins/timelion/public/app.js +++ b/src/legacy/core_plugins/timelion/public/app.js @@ -27,10 +27,11 @@ import { fatalError, toastNotifications } from 'ui/notify'; import { timefilter } from 'ui/timefilter'; import { npStart } from 'ui/new_platform'; import { getSavedSheetBreadcrumbs, getCreateBreadcrumbs } from './breadcrumbs'; -import { getTimezone } from '../../vis_type_timelion/public'; +import { getTimezone } from '../../../../plugins/vis_type_timelion/public'; import 'uiExports/savedObjectTypes'; +require('ui/i18n'); require('ui/autoload/all'); // TODO: remove ui imports completely (move to plugins) @@ -57,7 +58,7 @@ require('plugins/timelion/directives/timelion_options_sheet'); document.title = 'Timelion - Kibana'; -const app = require('ui/modules').get('apps/timelion', []); +const app = require('ui/modules').get('apps/timelion', ['i18n', 'ngSanitize']); require('ui/routes').enable(); diff --git a/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js b/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js index 57262fda55e48..35ac883e5d99c 100644 --- a/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js +++ b/src/legacy/core_plugins/timelion/public/directives/timelion_expression_input.js @@ -43,7 +43,7 @@ import _ from 'lodash'; import $ from 'jquery'; import PEG from 'pegjs'; -import grammar from 'raw-loader!../../../../../plugins/timelion/common/chain.peg'; +import grammar from 'raw-loader!../../../../../plugins/vis_type_timelion/common/chain.peg'; import timelionExpressionInputTemplate from './timelion_expression_input.html'; import { SUGGESTION_TYPE, @@ -52,7 +52,7 @@ import { insertAtLocation, } from './timelion_expression_input_helpers'; import { comboBoxKeyCodes } from '@elastic/eui'; -import { getArgValueSuggestions } from '../../../vis_type_timelion/public/helpers/arg_value_suggestions'; +import { npStart } from 'ui/new_platform'; const Parser = PEG.generate(grammar); @@ -68,7 +68,7 @@ export function TimelionExpInput($http, $timeout) { replace: true, template: timelionExpressionInputTemplate, link: function(scope, elem) { - const argValueSuggestions = getArgValueSuggestions(); + const argValueSuggestions = npStart.plugins.visTypeTimelion.getArgValueSuggestions(); const expressionInput = elem.find('[data-expression-input]'); const functionReference = {}; let suggestibleFunctionLocation = {}; diff --git a/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts b/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts index cd40cbfa89ffe..34b389f5ff4ce 100644 --- a/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts +++ b/src/legacy/core_plugins/timelion/public/panels/timechart/schema.ts @@ -17,7 +17,8 @@ * under the License. */ -import '../../../../vis_type_timelion/public/flot'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import '../../../../../../plugins/vis_type_timelion/public/flot'; import _ from 'lodash'; import $ from 'jquery'; import moment from 'moment-timezone'; @@ -28,11 +29,14 @@ import { calculateInterval, DEFAULT_TIME_FORMAT, // @ts-ignore -} from '../../../../../../plugins/timelion/common/lib'; -import { tickFormatters } from '../../../../vis_type_timelion/public/helpers/tick_formatters'; +} from '../../../../../../plugins/vis_type_timelion/common/lib'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { tickFormatters } from '../../../../../../plugins/vis_type_timelion/public/helpers/tick_formatters'; import { TimelionVisualizationDependencies } from '../../plugin'; -import { xaxisFormatterProvider } from '../../../../vis_type_timelion/public/helpers/xaxis_formatter'; -import { generateTicksProvider } from '../../../../vis_type_timelion/public/helpers/tick_generator'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { xaxisFormatterProvider } from '../../../../../../plugins/vis_type_timelion/public/helpers/xaxis_formatter'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { generateTicksProvider } from '../../../../../../plugins/vis_type_timelion/public/helpers/tick_generator'; const DEBOUNCE_DELAY = 50; diff --git a/src/legacy/core_plugins/vis_type_timelion/index.ts b/src/legacy/core_plugins/vis_type_timelion/index.ts deleted file mode 100644 index 7bca5154c84fd..0000000000000 --- a/src/legacy/core_plugins/vis_type_timelion/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; -import { Legacy } from 'kibana'; - -import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy/types'; - -const timelionVisPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => - new Plugin({ - id: 'timelion_vis', - require: ['kibana', 'elasticsearch'], - publicDir: resolve(__dirname, 'public'), - uiExports: { - styleSheetPaths: resolve(__dirname, 'public/index.scss'), - hacks: [resolve(__dirname, 'public/legacy')], - injectDefaultVars: server => ({}), - }, - init: (server: Legacy.Server) => ({}), - config(Joi: any) { - return Joi.object({ - enabled: Joi.boolean().default(true), - }).default(); - }, - }); - -// eslint-disable-next-line import/no-default-export -export default timelionVisPluginInitializer; diff --git a/src/legacy/core_plugins/vis_type_timelion/package.json b/src/legacy/core_plugins/vis_type_timelion/package.json deleted file mode 100644 index 9b09f98ce6caf..0000000000000 --- a/src/legacy/core_plugins/vis_type_timelion/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "timelion_vis", - "version": "kibana" -} diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/_index.scss b/src/legacy/core_plugins/vis_type_timelion/public/components/_index.scss deleted file mode 100644 index 1d887f43ff9a1..0000000000000 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './panel'; -@import './timelion_expression_input'; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/legacy.ts b/src/legacy/core_plugins/vis_type_timelion/public/legacy.ts deleted file mode 100644 index f8de9f94dcedf..0000000000000 --- a/src/legacy/core_plugins/vis_type_timelion/public/legacy.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { PluginInitializerContext } from 'kibana/public'; - -import { npSetup, npStart } from './legacy_imports'; -import { TimelionVisSetupDependencies } from './plugin'; -import { plugin } from '.'; - -const setupPlugins: Readonly = { - expressions: npSetup.plugins.expressions, - data: npSetup.plugins.data, - visualizations: npSetup.plugins.visualizations, -}; - -const pluginInstance = plugin({} as PluginInitializerContext); - -export const setup = pluginInstance.setup(npSetup.core, setupPlugins); -export const start = pluginInstance.start(npStart.core, npStart.plugins); diff --git a/src/legacy/core_plugins/vis_type_timelion/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_timelion/public/legacy_imports.ts deleted file mode 100644 index e7612b288fb24..0000000000000 --- a/src/legacy/core_plugins/vis_type_timelion/public/legacy_imports.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { npSetup, npStart } from 'ui/new_platform'; -export { PluginsStart } from 'ui/new_platform/new_platform'; diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts index 80fb837258d4c..5ae2e2348aaa1 100644 --- a/src/legacy/ui/public/new_platform/new_platform.ts +++ b/src/legacy/ui/public/new_platform/new_platform.ts @@ -69,6 +69,7 @@ import { VisualizationsSetup, VisualizationsStart, } from '../../../../plugins/visualizations/public'; +import { VisTypeTimelionPluginStart } from '../../../../plugins/vis_type_timelion/public'; import { MapsLegacyPluginSetup } from '../../../../plugins/maps_legacy/public'; export interface PluginsSetup { @@ -116,6 +117,7 @@ export interface PluginsStart { telemetry?: TelemetryPluginStart; dashboard: DashboardStart; savedObjectsManagement: SavedObjectsManagementPluginStart; + visTypeTimelion: VisTypeTimelionPluginStart; indexPatternManagement: IndexPatternManagementStart; } diff --git a/src/plugins/timelion/kibana.json b/src/plugins/timelion/kibana.json deleted file mode 100644 index dddfd6c67e655..0000000000000 --- a/src/plugins/timelion/kibana.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "timelion", - "version": "8.0.0", - "kibanaVersion": "kibana", - "configPath": ["timelion"], - "server": true, - "ui": true -} diff --git a/src/plugins/timelion/public/index.ts b/src/plugins/timelion/public/index.ts deleted file mode 100644 index b05c4f8a30b22..0000000000000 --- a/src/plugins/timelion/public/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { CoreStart, PluginInitializerContext } from 'kibana/public'; -import { ConfigSchema } from '../config'; - -export const plugin = (initializerContext: PluginInitializerContext) => ({ - setup() {}, - start(core: CoreStart) { - if (initializerContext.config.get().ui.enabled === false) { - core.chrome.navLinks.update('timelion', { hidden: true }); - } - }, -}); diff --git a/src/legacy/core_plugins/vis_type_timelion/README.md b/src/plugins/vis_type_timelion/README.md similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/README.md rename to src/plugins/vis_type_timelion/README.md diff --git a/src/plugins/timelion/common/chain.peg b/src/plugins/vis_type_timelion/common/chain.peg similarity index 100% rename from src/plugins/timelion/common/chain.peg rename to src/plugins/vis_type_timelion/common/chain.peg diff --git a/src/plugins/timelion/common/lib/calculate_interval.test.ts b/src/plugins/vis_type_timelion/common/lib/calculate_interval.test.ts similarity index 100% rename from src/plugins/timelion/common/lib/calculate_interval.test.ts rename to src/plugins/vis_type_timelion/common/lib/calculate_interval.test.ts diff --git a/src/plugins/timelion/common/lib/calculate_interval.ts b/src/plugins/vis_type_timelion/common/lib/calculate_interval.ts similarity index 100% rename from src/plugins/timelion/common/lib/calculate_interval.ts rename to src/plugins/vis_type_timelion/common/lib/calculate_interval.ts diff --git a/src/plugins/timelion/common/lib/index.ts b/src/plugins/vis_type_timelion/common/lib/index.ts similarity index 100% rename from src/plugins/timelion/common/lib/index.ts rename to src/plugins/vis_type_timelion/common/lib/index.ts diff --git a/src/plugins/timelion/common/lib/to_milliseconds.ts b/src/plugins/vis_type_timelion/common/lib/to_milliseconds.ts similarity index 100% rename from src/plugins/timelion/common/lib/to_milliseconds.ts rename to src/plugins/vis_type_timelion/common/lib/to_milliseconds.ts diff --git a/src/plugins/timelion/common/types.ts b/src/plugins/vis_type_timelion/common/types.ts similarity index 100% rename from src/plugins/timelion/common/types.ts rename to src/plugins/vis_type_timelion/common/types.ts diff --git a/src/plugins/timelion/config.ts b/src/plugins/vis_type_timelion/config.ts similarity index 100% rename from src/plugins/timelion/config.ts rename to src/plugins/vis_type_timelion/config.ts diff --git a/src/plugins/vis_type_timelion/kibana.json b/src/plugins/vis_type_timelion/kibana.json new file mode 100644 index 0000000000000..85c282c51a2e7 --- /dev/null +++ b/src/plugins/vis_type_timelion/kibana.json @@ -0,0 +1,8 @@ +{ + "id": "visTypeTimelion", + "version": "8.0.0", + "kibanaVersion": "kibana", + "server": true, + "ui": true, + "requiredPlugins": ["visualizations", "data", "expressions"] +} diff --git a/src/legacy/core_plugins/vis_type_timelion/public/_generated_/chain.js b/src/plugins/vis_type_timelion/public/_generated_/chain.js similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/_generated_/chain.js rename to src/plugins/vis_type_timelion/public/_generated_/chain.js diff --git a/src/legacy/core_plugins/vis_type_timelion/public/_timelion_editor.scss b/src/plugins/vis_type_timelion/public/_timelion_editor.scss similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/_timelion_editor.scss rename to src/plugins/vis_type_timelion/public/_timelion_editor.scss diff --git a/src/legacy/core_plugins/vis_type_timelion/public/_timelion_vis.scss b/src/plugins/vis_type_timelion/public/_timelion_vis.scss similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/_timelion_vis.scss rename to src/plugins/vis_type_timelion/public/_timelion_vis.scss diff --git a/src/plugins/vis_type_timelion/public/components/_index.scss b/src/plugins/vis_type_timelion/public/components/_index.scss new file mode 100644 index 0000000000000..707c9dafebe2b --- /dev/null +++ b/src/plugins/vis_type_timelion/public/components/_index.scss @@ -0,0 +1,2 @@ +@import 'panel'; +@import 'timelion_expression_input'; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/_panel.scss b/src/plugins/vis_type_timelion/public/components/_panel.scss similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/components/_panel.scss rename to src/plugins/vis_type_timelion/public/components/_panel.scss diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/_timelion_expression_input.scss b/src/plugins/vis_type_timelion/public/components/_timelion_expression_input.scss similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/components/_timelion_expression_input.scss rename to src/plugins/vis_type_timelion/public/components/_timelion_expression_input.scss diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/chart.tsx b/src/plugins/vis_type_timelion/public/components/chart.tsx similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/components/chart.tsx rename to src/plugins/vis_type_timelion/public/components/chart.tsx diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/index.ts b/src/plugins/vis_type_timelion/public/components/index.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/components/index.ts rename to src/plugins/vis_type_timelion/public/components/index.ts diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx b/src/plugins/vis_type_timelion/public/components/panel.tsx similarity index 98% rename from src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx rename to src/plugins/vis_type_timelion/public/components/panel.tsx index 3b42fa7dfcbb8..8f796526e8520 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/panel.tsx +++ b/src/plugins/vis_type_timelion/public/components/panel.tsx @@ -22,9 +22,9 @@ import $ from 'jquery'; import moment from 'moment-timezone'; import { debounce, compact, get, each, cloneDeep, last, map } from 'lodash'; -import { useKibana } from '../../../../../plugins/kibana_react/public'; +import { useKibana } from '../../../kibana_react/public'; import '../flot'; -import { DEFAULT_TIME_FORMAT } from '../../../../../plugins/timelion/common/lib'; +import { DEFAULT_TIME_FORMAT } from '../../common/lib'; import { buildSeriesData, diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx b/src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx similarity index 96% rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx rename to src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx index c317451b8201e..999409ef35063 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input.tsx +++ b/src/plugins/vis_type_timelion/public/components/timelion_expression_input.tsx @@ -22,13 +22,10 @@ import { EuiFormLabel } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { monaco } from '@kbn/ui-shared-deps/monaco'; -import { CodeEditor, useKibana } from '../../../../../plugins/kibana_react/public'; +import { CodeEditor, useKibana } from '../../../kibana_react/public'; import { suggest, getSuggestion } from './timelion_expression_input_helpers'; import { getArgValueSuggestions } from '../helpers/arg_value_suggestions'; -import { - ITimelionFunction, - TimelionFunctionArgs, -} from '../../../../../plugins/timelion/common/types'; +import { ITimelionFunction, TimelionFunctionArgs } from '../../common/types'; const LANGUAGE_ID = 'timelion_expression'; monaco.languages.register({ id: LANGUAGE_ID }); diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts similarity index 99% rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts rename to src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts index 2f99256e2a192..2ff6809d1c83d 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts +++ b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.test.ts @@ -22,7 +22,7 @@ import { getArgValueSuggestions } from '../helpers/arg_value_suggestions'; import { setIndexPatterns, setSavedObjectsClient } from '../helpers/plugin_services'; import { IndexPatternsContract } from 'src/plugins/data/public'; import { SavedObjectsClient } from 'kibana/public'; -import { ITimelionFunction } from '../../../../../plugins/timelion/common/types'; +import { ITimelionFunction } from '../../common/types'; describe('Timelion expression suggestions', () => { setIndexPatterns({} as IndexPatternsContract); diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts similarity index 98% rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts rename to src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts index 6f23c864419eb..04cb54306c90e 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts +++ b/src/plugins/vis_type_timelion/public/components/timelion_expression_input_helpers.ts @@ -27,10 +27,7 @@ import { Parser } from 'pegjs'; import { parse } from '../_generated_/chain'; import { ArgValueSuggestions, FunctionArg, Location } from '../helpers/arg_value_suggestions'; -import { - ITimelionFunction, - TimelionFunctionArgs, -} from '../../../../../plugins/timelion/common/types'; +import { ITimelionFunction, TimelionFunctionArgs } from '../../common/types'; export enum SUGGESTION_TYPE { ARGUMENTS = 'arguments', diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_interval.tsx b/src/plugins/vis_type_timelion/public/components/timelion_interval.tsx similarity index 96% rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_interval.tsx rename to src/plugins/vis_type_timelion/public/components/timelion_interval.tsx index 8a8e1b22fb78d..985ecaeaf3e5a 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_interval.tsx +++ b/src/plugins/vis_type_timelion/public/components/timelion_interval.tsx @@ -21,9 +21,9 @@ import React, { useMemo, useCallback } from 'react'; import { EuiFormRow, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { search } from '../../../../../plugins/data/public'; +import { search } from '../../../data/public'; const { isValidEsInterval } = search.aggs; -import { useValidation } from '../../../../../plugins/vis_default_editor/public'; +import { useValidation } from '../../../vis_default_editor/public'; const intervalOptions = [ { diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx b/src/plugins/vis_type_timelion/public/components/timelion_vis.tsx similarity index 95% rename from src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx rename to src/plugins/vis_type_timelion/public/components/timelion_vis.tsx index 0fad0a164bf0b..4bb07fe74ee82 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx +++ b/src/plugins/vis_type_timelion/public/components/timelion_vis.tsx @@ -23,7 +23,7 @@ import { IUiSettingsClient } from 'kibana/public'; import { ChartComponent } from './chart'; import { VisParams } from '../timelion_vis_fn'; import { TimelionSuccessResponse } from '../helpers/timelion_request_handler'; -import { ExprVis } from '../../../../../plugins/visualizations/public'; +import { ExprVis } from '../../../visualizations/public'; export interface TimelionVisComponentProp { config: IUiSettingsClient; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/flot.js b/src/plugins/vis_type_timelion/public/flot.js similarity index 72% rename from src/legacy/core_plugins/vis_type_timelion/public/flot.js rename to src/plugins/vis_type_timelion/public/flot.js index d6ca6d96c34ef..1ccb40c93a3d6 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/flot.js +++ b/src/plugins/vis_type_timelion/public/flot.js @@ -17,10 +17,10 @@ * under the License. */ -require('jquery.flot'); -require('jquery.flot.time'); -require('jquery.flot.symbol'); -require('jquery.flot.crosshair'); -require('jquery.flot.selection'); -require('jquery.flot.stack'); -require('jquery.flot.axislabels'); +import './webpackShims/jquery.flot'; +import './webpackShims/jquery.flot.time'; +import './webpackShims/jquery.flot.symbol'; +import './webpackShims/jquery.flot.crosshair'; +import './webpackShims/jquery.flot.selection'; +import './webpackShims/jquery.flot.stack'; +import './webpackShims/jquery.flot.axislabels'; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts b/src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts similarity index 97% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts rename to src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts index ea9532964d6fe..76c25b9b9e8de 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts +++ b/src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts @@ -19,11 +19,8 @@ import { get } from 'lodash'; import { getIndexPatterns, getSavedObjectsClient } from './plugin_services'; -import { TimelionFunctionArgs } from '../../../../../plugins/timelion/common/types'; -import { - indexPatterns as indexPatternsUtils, - IndexPatternAttributes, -} from '../../../../../plugins/data/public'; +import { TimelionFunctionArgs } from '../../common/types'; +import { indexPatterns as indexPatternsUtils, IndexPatternAttributes } from '../../../data/public'; export interface Location { min: number; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/get_timezone.ts b/src/plugins/vis_type_timelion/public/helpers/get_timezone.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/get_timezone.ts rename to src/plugins/vis_type_timelion/public/helpers/get_timezone.ts diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts b/src/plugins/vis_type_timelion/public/helpers/panel_utils.ts similarity index 98% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts rename to src/plugins/vis_type_timelion/public/helpers/panel_utils.ts index f932e5ee4b2f4..db29d9112be8e 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/panel_utils.ts +++ b/src/plugins/vis_type_timelion/public/helpers/panel_utils.ts @@ -23,7 +23,7 @@ import moment, { Moment } from 'moment-timezone'; import { TimefilterContract } from 'src/plugins/data/public'; import { IUiSettingsClient } from 'kibana/public'; -import { calculateInterval } from '../../../../../plugins/timelion/common/lib'; +import { calculateInterval } from '../../common/lib'; import { xaxisFormatterProvider } from './xaxis_formatter'; import { Series } from './timelion_request_handler'; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/plugin_services.ts b/src/plugins/vis_type_timelion/public/helpers/plugin_services.ts similarity index 93% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/plugin_services.ts rename to src/plugins/vis_type_timelion/public/helpers/plugin_services.ts index 5ba4ee5e47983..b055626934eea 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/plugin_services.ts +++ b/src/plugins/vis_type_timelion/public/helpers/plugin_services.ts @@ -19,7 +19,7 @@ import { IndexPatternsContract } from 'src/plugins/data/public'; import { SavedObjectsClientContract } from 'kibana/public'; -import { createGetterSetter } from '../../../../../plugins/kibana_utils/public'; +import { createGetterSetter } from '../../../kibana_utils/public'; export const [getIndexPatterns, setIndexPatterns] = createGetterSetter( 'IndexPatterns' diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_formatters.test.ts b/src/plugins/vis_type_timelion/public/helpers/tick_formatters.test.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_formatters.test.ts rename to src/plugins/vis_type_timelion/public/helpers/tick_formatters.test.ts diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_formatters.ts b/src/plugins/vis_type_timelion/public/helpers/tick_formatters.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_formatters.ts rename to src/plugins/vis_type_timelion/public/helpers/tick_formatters.ts diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_generator.test.ts b/src/plugins/vis_type_timelion/public/helpers/tick_generator.test.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_generator.test.ts rename to src/plugins/vis_type_timelion/public/helpers/tick_generator.test.ts diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_generator.ts b/src/plugins/vis_type_timelion/public/helpers/tick_generator.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/tick_generator.ts rename to src/plugins/vis_type_timelion/public/helpers/tick_generator.ts diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts similarity index 95% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts rename to src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts index 61e31420f73ba..a654f7935af5f 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts +++ b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts @@ -19,8 +19,8 @@ import { i18n } from '@kbn/i18n'; import { KIBANA_CONTEXT_NAME } from 'src/plugins/expressions/public'; -import { VisParams } from '../../../../../plugins/visualizations/public'; -import { TimeRange, Filter, esQuery, Query } from '../../../../../plugins/data/public'; +import { VisParams } from '../../../visualizations/public'; +import { TimeRange, Filter, esQuery, Query } from '../../../data/public'; import { TimelionVisDependencies } from '../plugin'; import { getTimezone } from './get_timezone'; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/xaxis_formatter.ts b/src/plugins/vis_type_timelion/public/helpers/xaxis_formatter.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/helpers/xaxis_formatter.ts rename to src/plugins/vis_type_timelion/public/helpers/xaxis_formatter.ts diff --git a/src/legacy/core_plugins/vis_type_timelion/public/index.scss b/src/plugins/vis_type_timelion/public/index.scss similarity index 59% rename from src/legacy/core_plugins/vis_type_timelion/public/index.scss rename to src/plugins/vis_type_timelion/public/index.scss index 313f14a8acf69..00e9a88520961 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/index.scss +++ b/src/plugins/vis_type_timelion/public/index.scss @@ -1,5 +1,3 @@ -@import 'src/legacy/ui/public/styles/styling_constants'; - @import './timelion_vis'; @import './timelion_editor'; @import './components/index'; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/index.ts b/src/plugins/vis_type_timelion/public/index.ts similarity index 90% rename from src/legacy/core_plugins/vis_type_timelion/public/index.ts rename to src/plugins/vis_type_timelion/public/index.ts index 6292e2ad3eb08..0aa5f3a810033 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/index.ts +++ b/src/plugins/vis_type_timelion/public/index.ts @@ -17,7 +17,7 @@ * under the License. */ -import { PluginInitializerContext } from '../../../../core/public'; +import { PluginInitializerContext } from 'kibana/public'; import { TimelionVisPlugin as Plugin } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { @@ -25,3 +25,5 @@ export function plugin(initializerContext: PluginInitializerContext) { } export { getTimezone } from './helpers/get_timezone'; + +export { VisTypeTimelionPluginStart } from './plugin'; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/plugin.ts b/src/plugins/vis_type_timelion/public/plugin.ts similarity index 67% rename from src/legacy/core_plugins/vis_type_timelion/public/plugin.ts rename to src/plugins/vis_type_timelion/public/plugin.ts index b5aa64db19aa4..060fec04deb3f 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/plugin.ts +++ b/src/plugins/vis_type_timelion/public/plugin.ts @@ -26,16 +26,21 @@ import { HttpSetup, } from 'kibana/public'; import { Plugin as ExpressionsPlugin } from 'src/plugins/expressions/public'; -import { DataPublicPluginSetup, TimefilterContract } from 'src/plugins/data/public'; +import { + DataPublicPluginSetup, + DataPublicPluginStart, + TimefilterContract, +} from 'src/plugins/data/public'; -import { PluginsStart } from './legacy_imports'; -import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; +import { VisualizationsSetup } from '../../visualizations/public'; import { getTimelionVisualizationConfig } from './timelion_vis_fn'; import { getTimelionVisDefinition } from './timelion_vis_type'; import { setIndexPatterns, setSavedObjectsClient } from './helpers/plugin_services'; +import { ConfigSchema } from '../config'; -type TimelionVisCoreSetup = CoreSetup; +import './index.scss'; +import { getArgValueSuggestions } from './helpers/arg_value_suggestions'; /** @internal */ export interface TimelionVisDependencies extends Partial { @@ -52,11 +57,28 @@ export interface TimelionVisSetupDependencies { } /** @internal */ -export class TimelionVisPlugin implements Plugin { - constructor(public initializerContext: PluginInitializerContext) {} +export interface TimelionVisStartDependencies { + data: DataPublicPluginStart; +} + +/** @public */ +export interface VisTypeTimelionPluginStart { + getArgValueSuggestions: typeof getArgValueSuggestions; +} + +/** @internal */ +export class TimelionVisPlugin + implements + Plugin< + void, + VisTypeTimelionPluginStart, + TimelionVisSetupDependencies, + TimelionVisStartDependencies + > { + constructor(public initializerContext: PluginInitializerContext) {} - public async setup( - core: TimelionVisCoreSetup, + public setup( + core: CoreSetup, { expressions, visualizations, data }: TimelionVisSetupDependencies ) { const dependencies: TimelionVisDependencies = { @@ -69,8 +91,15 @@ export class TimelionVisPlugin implements Plugin { visualizations.createReactVisualization(getTimelionVisDefinition(dependencies)); } - public start(core: CoreStart, plugins: PluginsStart) { + public start(core: CoreStart, plugins: TimelionVisStartDependencies) { setIndexPatterns(plugins.data.indexPatterns); setSavedObjectsClient(core.savedObjects.client); + if (this.initializerContext.config.get().ui.enabled === false) { + core.chrome.navLinks.update('timelion', { hidden: true }); + } + + return { + getArgValueSuggestions, + }; } } diff --git a/src/legacy/core_plugins/vis_type_timelion/public/timelion_options.tsx b/src/plugins/vis_type_timelion/public/timelion_options.tsx similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/timelion_options.tsx rename to src/plugins/vis_type_timelion/public/timelion_options.tsx diff --git a/src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_fn.ts b/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_fn.ts rename to src/plugins/vis_type_timelion/public/timelion_vis_fn.ts diff --git a/src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_type.tsx b/src/plugins/vis_type_timelion/public/timelion_vis_type.tsx similarity index 93% rename from src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_type.tsx rename to src/plugins/vis_type_timelion/public/timelion_vis_type.tsx index 0900b7d898ede..52addb3c2d9d2 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/timelion_vis_type.tsx +++ b/src/plugins/vis_type_timelion/public/timelion_vis_type.tsx @@ -20,8 +20,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { KibanaContextProvider } from '../../../../plugins/kibana_react/public'; -import { DefaultEditorSize } from '../../../../plugins/vis_default_editor/public'; +import { KibanaContextProvider } from '../../kibana_react/public'; +import { DefaultEditorSize } from '../../vis_default_editor/public'; import { getTimelionRequestHandler } from './helpers/timelion_request_handler'; import { TimelionVisComponent, TimelionVisComponentProp } from './components'; import { TimelionOptions, TimelionOptionsProps } from './timelion_options'; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.axislabels.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.axislabels.js similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.axislabels.js rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.axislabels.js diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.crosshair.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.crosshair.js similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.crosshair.js rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.crosshair.js diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.js similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.js rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.js diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.selection.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.selection.js similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.selection.js rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.selection.js diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.stack.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.stack.js similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.stack.js rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.stack.js diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.symbol.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.symbol.js similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.symbol.js rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.symbol.js diff --git a/src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.time.js b/src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.time.js similarity index 100% rename from src/legacy/core_plugins/vis_type_timelion/public/webpackShims/jquery.flot.time.js rename to src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.time.js diff --git a/src/plugins/timelion/server/fit_functions/average.js b/src/plugins/vis_type_timelion/server/fit_functions/average.js similarity index 100% rename from src/plugins/timelion/server/fit_functions/average.js rename to src/plugins/vis_type_timelion/server/fit_functions/average.js diff --git a/src/plugins/timelion/server/fit_functions/average.test.js b/src/plugins/vis_type_timelion/server/fit_functions/average.test.js similarity index 100% rename from src/plugins/timelion/server/fit_functions/average.test.js rename to src/plugins/vis_type_timelion/server/fit_functions/average.test.js diff --git a/src/plugins/timelion/server/fit_functions/carry.js b/src/plugins/vis_type_timelion/server/fit_functions/carry.js similarity index 100% rename from src/plugins/timelion/server/fit_functions/carry.js rename to src/plugins/vis_type_timelion/server/fit_functions/carry.js diff --git a/src/plugins/timelion/server/fit_functions/carry.test.js b/src/plugins/vis_type_timelion/server/fit_functions/carry.test.js similarity index 100% rename from src/plugins/timelion/server/fit_functions/carry.test.js rename to src/plugins/vis_type_timelion/server/fit_functions/carry.test.js diff --git a/src/plugins/timelion/server/fit_functions/nearest.js b/src/plugins/vis_type_timelion/server/fit_functions/nearest.js similarity index 100% rename from src/plugins/timelion/server/fit_functions/nearest.js rename to src/plugins/vis_type_timelion/server/fit_functions/nearest.js diff --git a/src/plugins/timelion/server/fit_functions/none.js b/src/plugins/vis_type_timelion/server/fit_functions/none.js similarity index 100% rename from src/plugins/timelion/server/fit_functions/none.js rename to src/plugins/vis_type_timelion/server/fit_functions/none.js diff --git a/src/plugins/timelion/server/fit_functions/scale.js b/src/plugins/vis_type_timelion/server/fit_functions/scale.js similarity index 100% rename from src/plugins/timelion/server/fit_functions/scale.js rename to src/plugins/vis_type_timelion/server/fit_functions/scale.js diff --git a/src/plugins/timelion/server/handlers/chain_runner.js b/src/plugins/vis_type_timelion/server/handlers/chain_runner.js similarity index 100% rename from src/plugins/timelion/server/handlers/chain_runner.js rename to src/plugins/vis_type_timelion/server/handlers/chain_runner.js diff --git a/src/plugins/timelion/server/handlers/lib/arg_type.js b/src/plugins/vis_type_timelion/server/handlers/lib/arg_type.js similarity index 100% rename from src/plugins/timelion/server/handlers/lib/arg_type.js rename to src/plugins/vis_type_timelion/server/handlers/lib/arg_type.js diff --git a/src/plugins/timelion/server/handlers/lib/index_arguments.js b/src/plugins/vis_type_timelion/server/handlers/lib/index_arguments.js similarity index 100% rename from src/plugins/timelion/server/handlers/lib/index_arguments.js rename to src/plugins/vis_type_timelion/server/handlers/lib/index_arguments.js diff --git a/src/plugins/timelion/server/handlers/lib/parse_sheet.js b/src/plugins/vis_type_timelion/server/handlers/lib/parse_sheet.js similarity index 100% rename from src/plugins/timelion/server/handlers/lib/parse_sheet.js rename to src/plugins/vis_type_timelion/server/handlers/lib/parse_sheet.js diff --git a/src/plugins/timelion/server/handlers/lib/parse_sheet.test.js b/src/plugins/vis_type_timelion/server/handlers/lib/parse_sheet.test.js similarity index 100% rename from src/plugins/timelion/server/handlers/lib/parse_sheet.test.js rename to src/plugins/vis_type_timelion/server/handlers/lib/parse_sheet.test.js diff --git a/src/plugins/timelion/server/handlers/lib/preprocess_chain.js b/src/plugins/vis_type_timelion/server/handlers/lib/preprocess_chain.js similarity index 100% rename from src/plugins/timelion/server/handlers/lib/preprocess_chain.js rename to src/plugins/vis_type_timelion/server/handlers/lib/preprocess_chain.js diff --git a/src/plugins/timelion/server/handlers/lib/reposition_arguments.js b/src/plugins/vis_type_timelion/server/handlers/lib/reposition_arguments.js similarity index 100% rename from src/plugins/timelion/server/handlers/lib/reposition_arguments.js rename to src/plugins/vis_type_timelion/server/handlers/lib/reposition_arguments.js diff --git a/src/plugins/timelion/server/handlers/lib/tl_config.js b/src/plugins/vis_type_timelion/server/handlers/lib/tl_config.js similarity index 100% rename from src/plugins/timelion/server/handlers/lib/tl_config.js rename to src/plugins/vis_type_timelion/server/handlers/lib/tl_config.js diff --git a/src/plugins/timelion/server/handlers/lib/validate_arg.js b/src/plugins/vis_type_timelion/server/handlers/lib/validate_arg.js similarity index 100% rename from src/plugins/timelion/server/handlers/lib/validate_arg.js rename to src/plugins/vis_type_timelion/server/handlers/lib/validate_arg.js diff --git a/src/plugins/timelion/server/handlers/lib/validate_time.js b/src/plugins/vis_type_timelion/server/handlers/lib/validate_time.js similarity index 100% rename from src/plugins/timelion/server/handlers/lib/validate_time.js rename to src/plugins/vis_type_timelion/server/handlers/lib/validate_time.js diff --git a/src/plugins/timelion/server/index.ts b/src/plugins/vis_type_timelion/server/index.ts similarity index 64% rename from src/plugins/timelion/server/index.ts rename to src/plugins/vis_type_timelion/server/index.ts index 5d420327f961e..b40ab2af2b0d7 100644 --- a/src/plugins/timelion/server/index.ts +++ b/src/plugins/vis_type_timelion/server/index.ts @@ -17,19 +17,23 @@ * under the License. */ -import { PluginInitializerContext } from '../../../../src/core/server'; -import { configSchema } from '../config'; +import { PluginConfigDescriptor, PluginInitializerContext } from '../../../../src/core/server'; +import { configSchema, ConfigSchema } from '../config'; import { Plugin } from './plugin'; export { PluginSetupContract } from './plugin'; -export const config = { +export const config: PluginConfigDescriptor = { schema: configSchema, exposeToBrowser: { - ui: { - enabled: true, - }, + ui: true, }, + deprecations: ({ renameFromRoot }) => [ + renameFromRoot('timelion_vis.enabled', 'vis_type_timelion.enabled'), + renameFromRoot('timelion.enabled', 'vis_type_timelion.enabled'), + renameFromRoot('timelion.graphiteUrls', 'vis_type_timelion.graphiteUrls'), + renameFromRoot('timelion.ui.enabled', 'vis_type_timelion.ui.enabled'), + ], }; export const plugin = (initializerContext: PluginInitializerContext) => new Plugin(initializerContext); diff --git a/src/plugins/timelion/server/lib/alter.js b/src/plugins/vis_type_timelion/server/lib/alter.js similarity index 100% rename from src/plugins/timelion/server/lib/alter.js rename to src/plugins/vis_type_timelion/server/lib/alter.js diff --git a/src/plugins/timelion/server/lib/as_sorted.js b/src/plugins/vis_type_timelion/server/lib/as_sorted.js similarity index 100% rename from src/plugins/timelion/server/lib/as_sorted.js rename to src/plugins/vis_type_timelion/server/lib/as_sorted.js diff --git a/src/plugins/timelion/server/lib/build_target.js b/src/plugins/vis_type_timelion/server/lib/build_target.js similarity index 100% rename from src/plugins/timelion/server/lib/build_target.js rename to src/plugins/vis_type_timelion/server/lib/build_target.js diff --git a/src/plugins/timelion/server/lib/classes/chainable.js b/src/plugins/vis_type_timelion/server/lib/classes/chainable.js similarity index 100% rename from src/plugins/timelion/server/lib/classes/chainable.js rename to src/plugins/vis_type_timelion/server/lib/classes/chainable.js diff --git a/src/plugins/timelion/server/lib/classes/datasource.js b/src/plugins/vis_type_timelion/server/lib/classes/datasource.js similarity index 100% rename from src/plugins/timelion/server/lib/classes/datasource.js rename to src/plugins/vis_type_timelion/server/lib/classes/datasource.js diff --git a/src/plugins/timelion/server/lib/classes/timelion_function.d.ts b/src/plugins/vis_type_timelion/server/lib/classes/timelion_function.d.ts similarity index 100% rename from src/plugins/timelion/server/lib/classes/timelion_function.d.ts rename to src/plugins/vis_type_timelion/server/lib/classes/timelion_function.d.ts diff --git a/src/plugins/timelion/server/lib/classes/timelion_function.js b/src/plugins/vis_type_timelion/server/lib/classes/timelion_function.js similarity index 100% rename from src/plugins/timelion/server/lib/classes/timelion_function.js rename to src/plugins/vis_type_timelion/server/lib/classes/timelion_function.js diff --git a/src/plugins/timelion/server/lib/config_manager.ts b/src/plugins/vis_type_timelion/server/lib/config_manager.ts similarity index 100% rename from src/plugins/timelion/server/lib/config_manager.ts rename to src/plugins/vis_type_timelion/server/lib/config_manager.ts diff --git a/src/plugins/timelion/server/lib/functions_md.js b/src/plugins/vis_type_timelion/server/lib/functions_md.js similarity index 100% rename from src/plugins/timelion/server/lib/functions_md.js rename to src/plugins/vis_type_timelion/server/lib/functions_md.js diff --git a/src/plugins/timelion/server/lib/get_namespaced_settings.js b/src/plugins/vis_type_timelion/server/lib/get_namespaced_settings.js similarity index 100% rename from src/plugins/timelion/server/lib/get_namespaced_settings.js rename to src/plugins/vis_type_timelion/server/lib/get_namespaced_settings.js diff --git a/src/plugins/timelion/server/lib/load_functions.d.ts b/src/plugins/vis_type_timelion/server/lib/load_functions.d.ts similarity index 100% rename from src/plugins/timelion/server/lib/load_functions.d.ts rename to src/plugins/vis_type_timelion/server/lib/load_functions.d.ts diff --git a/src/plugins/timelion/server/lib/load_functions.js b/src/plugins/vis_type_timelion/server/lib/load_functions.js similarity index 100% rename from src/plugins/timelion/server/lib/load_functions.js rename to src/plugins/vis_type_timelion/server/lib/load_functions.js diff --git a/src/plugins/timelion/server/lib/load_functions.test.js b/src/plugins/vis_type_timelion/server/lib/load_functions.test.js similarity index 94% rename from src/plugins/timelion/server/lib/load_functions.test.js rename to src/plugins/vis_type_timelion/server/lib/load_functions.test.js index ebe1a04532e05..b4f83611a7773 100644 --- a/src/plugins/timelion/server/lib/load_functions.test.js +++ b/src/plugins/vis_type_timelion/server/lib/load_functions.test.js @@ -17,7 +17,7 @@ * under the License. */ -const fn = require(`src/plugins/timelion/server/lib/load_functions`); +const fn = require(`src/plugins/vis_type_timelion/server/lib/load_functions`); const expect = require('chai').expect; diff --git a/src/plugins/timelion/server/lib/offset_time.js b/src/plugins/vis_type_timelion/server/lib/offset_time.js similarity index 100% rename from src/plugins/timelion/server/lib/offset_time.js rename to src/plugins/vis_type_timelion/server/lib/offset_time.js diff --git a/src/plugins/timelion/server/lib/offset_time.test.js b/src/plugins/vis_type_timelion/server/lib/offset_time.test.js similarity index 100% rename from src/plugins/timelion/server/lib/offset_time.test.js rename to src/plugins/vis_type_timelion/server/lib/offset_time.test.js diff --git a/src/plugins/timelion/server/lib/process_function_definition.js b/src/plugins/vis_type_timelion/server/lib/process_function_definition.js similarity index 100% rename from src/plugins/timelion/server/lib/process_function_definition.js rename to src/plugins/vis_type_timelion/server/lib/process_function_definition.js diff --git a/src/plugins/timelion/server/lib/reduce.js b/src/plugins/vis_type_timelion/server/lib/reduce.js similarity index 100% rename from src/plugins/timelion/server/lib/reduce.js rename to src/plugins/vis_type_timelion/server/lib/reduce.js diff --git a/src/plugins/timelion/server/lib/split_interval.js b/src/plugins/vis_type_timelion/server/lib/split_interval.js similarity index 100% rename from src/plugins/timelion/server/lib/split_interval.js rename to src/plugins/vis_type_timelion/server/lib/split_interval.js diff --git a/src/plugins/timelion/server/lib/unzip_pairs.js b/src/plugins/vis_type_timelion/server/lib/unzip_pairs.js similarity index 100% rename from src/plugins/timelion/server/lib/unzip_pairs.js rename to src/plugins/vis_type_timelion/server/lib/unzip_pairs.js diff --git a/src/plugins/timelion/server/plugin.ts b/src/plugins/vis_type_timelion/server/plugin.ts similarity index 100% rename from src/plugins/timelion/server/plugin.ts rename to src/plugins/vis_type_timelion/server/plugin.ts diff --git a/src/plugins/timelion/server/routes/functions.ts b/src/plugins/vis_type_timelion/server/routes/functions.ts similarity index 100% rename from src/plugins/timelion/server/routes/functions.ts rename to src/plugins/vis_type_timelion/server/routes/functions.ts diff --git a/src/plugins/timelion/server/routes/run.ts b/src/plugins/vis_type_timelion/server/routes/run.ts similarity index 100% rename from src/plugins/timelion/server/routes/run.ts rename to src/plugins/vis_type_timelion/server/routes/run.ts diff --git a/src/plugins/timelion/server/routes/validate_es.ts b/src/plugins/vis_type_timelion/server/routes/validate_es.ts similarity index 100% rename from src/plugins/timelion/server/routes/validate_es.ts rename to src/plugins/vis_type_timelion/server/routes/validate_es.ts diff --git a/src/plugins/timelion/server/series_functions/abs.js b/src/plugins/vis_type_timelion/server/series_functions/abs.js similarity index 100% rename from src/plugins/timelion/server/series_functions/abs.js rename to src/plugins/vis_type_timelion/server/series_functions/abs.js diff --git a/src/plugins/timelion/server/series_functions/abs.test.js b/src/plugins/vis_type_timelion/server/series_functions/abs.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/abs.test.js rename to src/plugins/vis_type_timelion/server/series_functions/abs.test.js diff --git a/src/plugins/timelion/server/series_functions/aggregate/aggregate.test.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/aggregate.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/aggregate/aggregate.test.js rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/aggregate.test.js diff --git a/src/plugins/timelion/server/series_functions/aggregate/avg.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/avg.js similarity index 100% rename from src/plugins/timelion/server/series_functions/aggregate/avg.js rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/avg.js diff --git a/src/plugins/timelion/server/series_functions/aggregate/cardinality.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/cardinality.js similarity index 100% rename from src/plugins/timelion/server/series_functions/aggregate/cardinality.js rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/cardinality.js diff --git a/src/plugins/timelion/server/series_functions/aggregate/first.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/first.js similarity index 100% rename from src/plugins/timelion/server/series_functions/aggregate/first.js rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/first.js diff --git a/src/plugins/timelion/server/series_functions/aggregate/index.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/index.js similarity index 100% rename from src/plugins/timelion/server/series_functions/aggregate/index.js rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/index.js diff --git a/src/plugins/timelion/server/series_functions/aggregate/last.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/last.js similarity index 100% rename from src/plugins/timelion/server/series_functions/aggregate/last.js rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/last.js diff --git a/src/plugins/timelion/server/series_functions/aggregate/max.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/max.js similarity index 100% rename from src/plugins/timelion/server/series_functions/aggregate/max.js rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/max.js diff --git a/src/plugins/timelion/server/series_functions/aggregate/min.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/min.js similarity index 100% rename from src/plugins/timelion/server/series_functions/aggregate/min.js rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/min.js diff --git a/src/plugins/timelion/server/series_functions/aggregate/sum.js b/src/plugins/vis_type_timelion/server/series_functions/aggregate/sum.js similarity index 100% rename from src/plugins/timelion/server/series_functions/aggregate/sum.js rename to src/plugins/vis_type_timelion/server/series_functions/aggregate/sum.js diff --git a/src/plugins/timelion/server/series_functions/bars.js b/src/plugins/vis_type_timelion/server/series_functions/bars.js similarity index 100% rename from src/plugins/timelion/server/series_functions/bars.js rename to src/plugins/vis_type_timelion/server/series_functions/bars.js diff --git a/src/plugins/timelion/server/series_functions/bars.test.js b/src/plugins/vis_type_timelion/server/series_functions/bars.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/bars.test.js rename to src/plugins/vis_type_timelion/server/series_functions/bars.test.js diff --git a/src/plugins/timelion/server/series_functions/color.js b/src/plugins/vis_type_timelion/server/series_functions/color.js similarity index 100% rename from src/plugins/timelion/server/series_functions/color.js rename to src/plugins/vis_type_timelion/server/series_functions/color.js diff --git a/src/plugins/timelion/server/series_functions/color.test.js b/src/plugins/vis_type_timelion/server/series_functions/color.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/color.test.js rename to src/plugins/vis_type_timelion/server/series_functions/color.test.js diff --git a/src/plugins/timelion/server/series_functions/condition.js b/src/plugins/vis_type_timelion/server/series_functions/condition.js similarity index 100% rename from src/plugins/timelion/server/series_functions/condition.js rename to src/plugins/vis_type_timelion/server/series_functions/condition.js diff --git a/src/plugins/timelion/server/series_functions/condition.test.js b/src/plugins/vis_type_timelion/server/series_functions/condition.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/condition.test.js rename to src/plugins/vis_type_timelion/server/series_functions/condition.test.js diff --git a/src/plugins/timelion/server/series_functions/cusum.js b/src/plugins/vis_type_timelion/server/series_functions/cusum.js similarity index 100% rename from src/plugins/timelion/server/series_functions/cusum.js rename to src/plugins/vis_type_timelion/server/series_functions/cusum.js diff --git a/src/plugins/timelion/server/series_functions/cusum.test.js b/src/plugins/vis_type_timelion/server/series_functions/cusum.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/cusum.test.js rename to src/plugins/vis_type_timelion/server/series_functions/cusum.test.js diff --git a/src/plugins/timelion/server/series_functions/derivative.js b/src/plugins/vis_type_timelion/server/series_functions/derivative.js similarity index 100% rename from src/plugins/timelion/server/series_functions/derivative.js rename to src/plugins/vis_type_timelion/server/series_functions/derivative.js diff --git a/src/plugins/timelion/server/series_functions/derivative.test.js b/src/plugins/vis_type_timelion/server/series_functions/derivative.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/derivative.test.js rename to src/plugins/vis_type_timelion/server/series_functions/derivative.test.js diff --git a/src/plugins/timelion/server/series_functions/divide.js b/src/plugins/vis_type_timelion/server/series_functions/divide.js similarity index 100% rename from src/plugins/timelion/server/series_functions/divide.js rename to src/plugins/vis_type_timelion/server/series_functions/divide.js diff --git a/src/plugins/timelion/server/series_functions/divide.test.js b/src/plugins/vis_type_timelion/server/series_functions/divide.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/divide.test.js rename to src/plugins/vis_type_timelion/server/series_functions/divide.test.js diff --git a/src/plugins/timelion/server/series_functions/es/es.test.js b/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/es/es.test.js rename to src/plugins/vis_type_timelion/server/series_functions/es/es.test.js diff --git a/src/plugins/timelion/server/series_functions/es/index.js b/src/plugins/vis_type_timelion/server/series_functions/es/index.js similarity index 100% rename from src/plugins/timelion/server/series_functions/es/index.js rename to src/plugins/vis_type_timelion/server/series_functions/es/index.js diff --git a/src/plugins/timelion/server/series_functions/es/lib/agg_body.js b/src/plugins/vis_type_timelion/server/series_functions/es/lib/agg_body.js similarity index 100% rename from src/plugins/timelion/server/series_functions/es/lib/agg_body.js rename to src/plugins/vis_type_timelion/server/series_functions/es/lib/agg_body.js diff --git a/src/plugins/timelion/server/series_functions/es/lib/agg_response_to_series_list.js b/src/plugins/vis_type_timelion/server/series_functions/es/lib/agg_response_to_series_list.js similarity index 100% rename from src/plugins/timelion/server/series_functions/es/lib/agg_response_to_series_list.js rename to src/plugins/vis_type_timelion/server/series_functions/es/lib/agg_response_to_series_list.js diff --git a/src/plugins/timelion/server/series_functions/es/lib/build_request.js b/src/plugins/vis_type_timelion/server/series_functions/es/lib/build_request.js similarity index 100% rename from src/plugins/timelion/server/series_functions/es/lib/build_request.js rename to src/plugins/vis_type_timelion/server/series_functions/es/lib/build_request.js diff --git a/src/plugins/timelion/server/series_functions/es/lib/create_date_agg.js b/src/plugins/vis_type_timelion/server/series_functions/es/lib/create_date_agg.js similarity index 100% rename from src/plugins/timelion/server/series_functions/es/lib/create_date_agg.js rename to src/plugins/vis_type_timelion/server/series_functions/es/lib/create_date_agg.js diff --git a/src/plugins/timelion/server/series_functions/first.js b/src/plugins/vis_type_timelion/server/series_functions/first.js similarity index 100% rename from src/plugins/timelion/server/series_functions/first.js rename to src/plugins/vis_type_timelion/server/series_functions/first.js diff --git a/src/plugins/timelion/server/series_functions/first.test.js b/src/plugins/vis_type_timelion/server/series_functions/first.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/first.test.js rename to src/plugins/vis_type_timelion/server/series_functions/first.test.js diff --git a/src/plugins/timelion/server/series_functions/fit.js b/src/plugins/vis_type_timelion/server/series_functions/fit.js similarity index 100% rename from src/plugins/timelion/server/series_functions/fit.js rename to src/plugins/vis_type_timelion/server/series_functions/fit.js diff --git a/src/plugins/timelion/server/series_functions/fit.test.js b/src/plugins/vis_type_timelion/server/series_functions/fit.test.js similarity index 98% rename from src/plugins/timelion/server/series_functions/fit.test.js rename to src/plugins/vis_type_timelion/server/series_functions/fit.test.js index 75eaa2a50ea72..6622259a1fd87 100644 --- a/src/plugins/timelion/server/series_functions/fit.test.js +++ b/src/plugins/vis_type_timelion/server/series_functions/fit.test.js @@ -17,7 +17,7 @@ * under the License. */ -const fn = require(`src/plugins/timelion/server/series_functions/fit`); +const fn = require(`src/plugins/vis_type_timelion/server/series_functions/fit`); import moment from 'moment'; const expect = require('chai').expect; import invoke from './helpers/invoke_series_fn.js'; diff --git a/src/plugins/timelion/server/series_functions/fixtures/bucket_list.js b/src/plugins/vis_type_timelion/server/series_functions/fixtures/bucket_list.js similarity index 100% rename from src/plugins/timelion/server/series_functions/fixtures/bucket_list.js rename to src/plugins/vis_type_timelion/server/series_functions/fixtures/bucket_list.js diff --git a/src/plugins/timelion/server/series_functions/fixtures/es_response.js b/src/plugins/vis_type_timelion/server/series_functions/fixtures/es_response.js similarity index 100% rename from src/plugins/timelion/server/series_functions/fixtures/es_response.js rename to src/plugins/vis_type_timelion/server/series_functions/fixtures/es_response.js diff --git a/src/plugins/timelion/server/series_functions/fixtures/series_list.js b/src/plugins/vis_type_timelion/server/series_functions/fixtures/series_list.js similarity index 100% rename from src/plugins/timelion/server/series_functions/fixtures/series_list.js rename to src/plugins/vis_type_timelion/server/series_functions/fixtures/series_list.js diff --git a/src/plugins/timelion/server/series_functions/fixtures/tl_config.js b/src/plugins/vis_type_timelion/server/series_functions/fixtures/tl_config.js similarity index 100% rename from src/plugins/timelion/server/series_functions/fixtures/tl_config.js rename to src/plugins/vis_type_timelion/server/series_functions/fixtures/tl_config.js diff --git a/src/plugins/timelion/server/series_functions/graphite.js b/src/plugins/vis_type_timelion/server/series_functions/graphite.js similarity index 100% rename from src/plugins/timelion/server/series_functions/graphite.js rename to src/plugins/vis_type_timelion/server/series_functions/graphite.js diff --git a/src/plugins/timelion/server/series_functions/graphite.test.js b/src/plugins/vis_type_timelion/server/series_functions/graphite.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/graphite.test.js rename to src/plugins/vis_type_timelion/server/series_functions/graphite.test.js diff --git a/src/plugins/timelion/server/series_functions/helpers/get_series.js b/src/plugins/vis_type_timelion/server/series_functions/helpers/get_series.js similarity index 100% rename from src/plugins/timelion/server/series_functions/helpers/get_series.js rename to src/plugins/vis_type_timelion/server/series_functions/helpers/get_series.js diff --git a/src/plugins/timelion/server/series_functions/helpers/get_series_list.js b/src/plugins/vis_type_timelion/server/series_functions/helpers/get_series_list.js similarity index 100% rename from src/plugins/timelion/server/series_functions/helpers/get_series_list.js rename to src/plugins/vis_type_timelion/server/series_functions/helpers/get_series_list.js diff --git a/src/plugins/timelion/server/series_functions/helpers/get_single_series_list.js b/src/plugins/vis_type_timelion/server/series_functions/helpers/get_single_series_list.js similarity index 100% rename from src/plugins/timelion/server/series_functions/helpers/get_single_series_list.js rename to src/plugins/vis_type_timelion/server/series_functions/helpers/get_single_series_list.js diff --git a/src/plugins/timelion/server/series_functions/helpers/invoke_series_fn.js b/src/plugins/vis_type_timelion/server/series_functions/helpers/invoke_series_fn.js similarity index 100% rename from src/plugins/timelion/server/series_functions/helpers/invoke_series_fn.js rename to src/plugins/vis_type_timelion/server/series_functions/helpers/invoke_series_fn.js diff --git a/src/plugins/timelion/server/series_functions/hide.js b/src/plugins/vis_type_timelion/server/series_functions/hide.js similarity index 100% rename from src/plugins/timelion/server/series_functions/hide.js rename to src/plugins/vis_type_timelion/server/series_functions/hide.js diff --git a/src/plugins/timelion/server/series_functions/hide.test.js b/src/plugins/vis_type_timelion/server/series_functions/hide.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/hide.test.js rename to src/plugins/vis_type_timelion/server/series_functions/hide.test.js diff --git a/src/plugins/timelion/server/series_functions/holt/index.js b/src/plugins/vis_type_timelion/server/series_functions/holt/index.js similarity index 100% rename from src/plugins/timelion/server/series_functions/holt/index.js rename to src/plugins/vis_type_timelion/server/series_functions/holt/index.js diff --git a/src/plugins/timelion/server/series_functions/holt/lib/des.js b/src/plugins/vis_type_timelion/server/series_functions/holt/lib/des.js similarity index 100% rename from src/plugins/timelion/server/series_functions/holt/lib/des.js rename to src/plugins/vis_type_timelion/server/series_functions/holt/lib/des.js diff --git a/src/plugins/timelion/server/series_functions/holt/lib/ses.js b/src/plugins/vis_type_timelion/server/series_functions/holt/lib/ses.js similarity index 100% rename from src/plugins/timelion/server/series_functions/holt/lib/ses.js rename to src/plugins/vis_type_timelion/server/series_functions/holt/lib/ses.js diff --git a/src/plugins/timelion/server/series_functions/holt/lib/tes.js b/src/plugins/vis_type_timelion/server/series_functions/holt/lib/tes.js similarity index 100% rename from src/plugins/timelion/server/series_functions/holt/lib/tes.js rename to src/plugins/vis_type_timelion/server/series_functions/holt/lib/tes.js diff --git a/src/plugins/timelion/server/series_functions/label.js b/src/plugins/vis_type_timelion/server/series_functions/label.js similarity index 100% rename from src/plugins/timelion/server/series_functions/label.js rename to src/plugins/vis_type_timelion/server/series_functions/label.js diff --git a/src/plugins/timelion/server/series_functions/label.test.js b/src/plugins/vis_type_timelion/server/series_functions/label.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/label.test.js rename to src/plugins/vis_type_timelion/server/series_functions/label.test.js diff --git a/src/plugins/timelion/server/series_functions/legend.js b/src/plugins/vis_type_timelion/server/series_functions/legend.js similarity index 100% rename from src/plugins/timelion/server/series_functions/legend.js rename to src/plugins/vis_type_timelion/server/series_functions/legend.js diff --git a/src/plugins/timelion/server/series_functions/legend.test.js b/src/plugins/vis_type_timelion/server/series_functions/legend.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/legend.test.js rename to src/plugins/vis_type_timelion/server/series_functions/legend.test.js diff --git a/src/plugins/timelion/server/series_functions/lines.js b/src/plugins/vis_type_timelion/server/series_functions/lines.js similarity index 100% rename from src/plugins/timelion/server/series_functions/lines.js rename to src/plugins/vis_type_timelion/server/series_functions/lines.js diff --git a/src/plugins/timelion/server/series_functions/lines.test.js b/src/plugins/vis_type_timelion/server/series_functions/lines.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/lines.test.js rename to src/plugins/vis_type_timelion/server/series_functions/lines.test.js diff --git a/src/plugins/timelion/server/series_functions/log.js b/src/plugins/vis_type_timelion/server/series_functions/log.js similarity index 100% rename from src/plugins/timelion/server/series_functions/log.js rename to src/plugins/vis_type_timelion/server/series_functions/log.js diff --git a/src/plugins/timelion/server/series_functions/log.test.js b/src/plugins/vis_type_timelion/server/series_functions/log.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/log.test.js rename to src/plugins/vis_type_timelion/server/series_functions/log.test.js diff --git a/src/plugins/timelion/server/series_functions/max.js b/src/plugins/vis_type_timelion/server/series_functions/max.js similarity index 100% rename from src/plugins/timelion/server/series_functions/max.js rename to src/plugins/vis_type_timelion/server/series_functions/max.js diff --git a/src/plugins/timelion/server/series_functions/max.test.js b/src/plugins/vis_type_timelion/server/series_functions/max.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/max.test.js rename to src/plugins/vis_type_timelion/server/series_functions/max.test.js diff --git a/src/plugins/timelion/server/series_functions/min.js b/src/plugins/vis_type_timelion/server/series_functions/min.js similarity index 100% rename from src/plugins/timelion/server/series_functions/min.js rename to src/plugins/vis_type_timelion/server/series_functions/min.js diff --git a/src/plugins/timelion/server/series_functions/min.test.js b/src/plugins/vis_type_timelion/server/series_functions/min.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/min.test.js rename to src/plugins/vis_type_timelion/server/series_functions/min.test.js diff --git a/src/plugins/timelion/server/series_functions/movingaverage.js b/src/plugins/vis_type_timelion/server/series_functions/movingaverage.js similarity index 100% rename from src/plugins/timelion/server/series_functions/movingaverage.js rename to src/plugins/vis_type_timelion/server/series_functions/movingaverage.js diff --git a/src/plugins/timelion/server/series_functions/movingaverage.test.js b/src/plugins/vis_type_timelion/server/series_functions/movingaverage.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/movingaverage.test.js rename to src/plugins/vis_type_timelion/server/series_functions/movingaverage.test.js diff --git a/src/plugins/timelion/server/series_functions/movingstd.js b/src/plugins/vis_type_timelion/server/series_functions/movingstd.js similarity index 100% rename from src/plugins/timelion/server/series_functions/movingstd.js rename to src/plugins/vis_type_timelion/server/series_functions/movingstd.js diff --git a/src/plugins/timelion/server/series_functions/movingstd.test.js b/src/plugins/vis_type_timelion/server/series_functions/movingstd.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/movingstd.test.js rename to src/plugins/vis_type_timelion/server/series_functions/movingstd.test.js diff --git a/src/plugins/timelion/server/series_functions/multiply.js b/src/plugins/vis_type_timelion/server/series_functions/multiply.js similarity index 100% rename from src/plugins/timelion/server/series_functions/multiply.js rename to src/plugins/vis_type_timelion/server/series_functions/multiply.js diff --git a/src/plugins/timelion/server/series_functions/multiply.test.js b/src/plugins/vis_type_timelion/server/series_functions/multiply.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/multiply.test.js rename to src/plugins/vis_type_timelion/server/series_functions/multiply.test.js diff --git a/src/plugins/timelion/server/series_functions/points.js b/src/plugins/vis_type_timelion/server/series_functions/points.js similarity index 100% rename from src/plugins/timelion/server/series_functions/points.js rename to src/plugins/vis_type_timelion/server/series_functions/points.js diff --git a/src/plugins/timelion/server/series_functions/points.test.js b/src/plugins/vis_type_timelion/server/series_functions/points.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/points.test.js rename to src/plugins/vis_type_timelion/server/series_functions/points.test.js diff --git a/src/plugins/timelion/server/series_functions/precision.js b/src/plugins/vis_type_timelion/server/series_functions/precision.js similarity index 100% rename from src/plugins/timelion/server/series_functions/precision.js rename to src/plugins/vis_type_timelion/server/series_functions/precision.js diff --git a/src/plugins/timelion/server/series_functions/precision.test.js b/src/plugins/vis_type_timelion/server/series_functions/precision.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/precision.test.js rename to src/plugins/vis_type_timelion/server/series_functions/precision.test.js diff --git a/src/plugins/timelion/server/series_functions/props.js b/src/plugins/vis_type_timelion/server/series_functions/props.js similarity index 100% rename from src/plugins/timelion/server/series_functions/props.js rename to src/plugins/vis_type_timelion/server/series_functions/props.js diff --git a/src/plugins/timelion/server/series_functions/quandl.js b/src/plugins/vis_type_timelion/server/series_functions/quandl.js similarity index 100% rename from src/plugins/timelion/server/series_functions/quandl.js rename to src/plugins/vis_type_timelion/server/series_functions/quandl.js diff --git a/src/plugins/timelion/server/series_functions/quandl.test.js b/src/plugins/vis_type_timelion/server/series_functions/quandl.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/quandl.test.js rename to src/plugins/vis_type_timelion/server/series_functions/quandl.test.js diff --git a/src/plugins/timelion/server/series_functions/range.js b/src/plugins/vis_type_timelion/server/series_functions/range.js similarity index 100% rename from src/plugins/timelion/server/series_functions/range.js rename to src/plugins/vis_type_timelion/server/series_functions/range.js diff --git a/src/plugins/timelion/server/series_functions/range.test.js b/src/plugins/vis_type_timelion/server/series_functions/range.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/range.test.js rename to src/plugins/vis_type_timelion/server/series_functions/range.test.js diff --git a/src/plugins/timelion/server/series_functions/scale_interval.js b/src/plugins/vis_type_timelion/server/series_functions/scale_interval.js similarity index 100% rename from src/plugins/timelion/server/series_functions/scale_interval.js rename to src/plugins/vis_type_timelion/server/series_functions/scale_interval.js diff --git a/src/plugins/timelion/server/series_functions/scale_interval.test.js b/src/plugins/vis_type_timelion/server/series_functions/scale_interval.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/scale_interval.test.js rename to src/plugins/vis_type_timelion/server/series_functions/scale_interval.test.js diff --git a/src/plugins/timelion/server/series_functions/static.js b/src/plugins/vis_type_timelion/server/series_functions/static.js similarity index 100% rename from src/plugins/timelion/server/series_functions/static.js rename to src/plugins/vis_type_timelion/server/series_functions/static.js diff --git a/src/plugins/timelion/server/series_functions/static.test.js b/src/plugins/vis_type_timelion/server/series_functions/static.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/static.test.js rename to src/plugins/vis_type_timelion/server/series_functions/static.test.js diff --git a/src/plugins/timelion/server/series_functions/subtract.js b/src/plugins/vis_type_timelion/server/series_functions/subtract.js similarity index 100% rename from src/plugins/timelion/server/series_functions/subtract.js rename to src/plugins/vis_type_timelion/server/series_functions/subtract.js diff --git a/src/plugins/timelion/server/series_functions/subtract.test.js b/src/plugins/vis_type_timelion/server/series_functions/subtract.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/subtract.test.js rename to src/plugins/vis_type_timelion/server/series_functions/subtract.test.js diff --git a/src/plugins/timelion/server/series_functions/sum.js b/src/plugins/vis_type_timelion/server/series_functions/sum.js similarity index 100% rename from src/plugins/timelion/server/series_functions/sum.js rename to src/plugins/vis_type_timelion/server/series_functions/sum.js diff --git a/src/plugins/timelion/server/series_functions/sum.test.js b/src/plugins/vis_type_timelion/server/series_functions/sum.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/sum.test.js rename to src/plugins/vis_type_timelion/server/series_functions/sum.test.js diff --git a/src/plugins/timelion/server/series_functions/title.js b/src/plugins/vis_type_timelion/server/series_functions/title.js similarity index 100% rename from src/plugins/timelion/server/series_functions/title.js rename to src/plugins/vis_type_timelion/server/series_functions/title.js diff --git a/src/plugins/timelion/server/series_functions/title.test.js b/src/plugins/vis_type_timelion/server/series_functions/title.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/title.test.js rename to src/plugins/vis_type_timelion/server/series_functions/title.test.js diff --git a/src/plugins/timelion/server/series_functions/trend/index.js b/src/plugins/vis_type_timelion/server/series_functions/trend/index.js similarity index 100% rename from src/plugins/timelion/server/series_functions/trend/index.js rename to src/plugins/vis_type_timelion/server/series_functions/trend/index.js diff --git a/src/plugins/timelion/server/series_functions/trend/lib/regress.js b/src/plugins/vis_type_timelion/server/series_functions/trend/lib/regress.js similarity index 100% rename from src/plugins/timelion/server/series_functions/trend/lib/regress.js rename to src/plugins/vis_type_timelion/server/series_functions/trend/lib/regress.js diff --git a/src/plugins/timelion/server/series_functions/trim.js b/src/plugins/vis_type_timelion/server/series_functions/trim.js similarity index 100% rename from src/plugins/timelion/server/series_functions/trim.js rename to src/plugins/vis_type_timelion/server/series_functions/trim.js diff --git a/src/plugins/timelion/server/series_functions/trim.test.js b/src/plugins/vis_type_timelion/server/series_functions/trim.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/trim.test.js rename to src/plugins/vis_type_timelion/server/series_functions/trim.test.js diff --git a/src/plugins/timelion/server/series_functions/worldbank.js b/src/plugins/vis_type_timelion/server/series_functions/worldbank.js similarity index 100% rename from src/plugins/timelion/server/series_functions/worldbank.js rename to src/plugins/vis_type_timelion/server/series_functions/worldbank.js diff --git a/src/plugins/timelion/server/series_functions/worldbank_indicators.js b/src/plugins/vis_type_timelion/server/series_functions/worldbank_indicators.js similarity index 100% rename from src/plugins/timelion/server/series_functions/worldbank_indicators.js rename to src/plugins/vis_type_timelion/server/series_functions/worldbank_indicators.js diff --git a/src/plugins/timelion/server/series_functions/yaxis.js b/src/plugins/vis_type_timelion/server/series_functions/yaxis.js similarity index 100% rename from src/plugins/timelion/server/series_functions/yaxis.js rename to src/plugins/vis_type_timelion/server/series_functions/yaxis.js diff --git a/src/plugins/timelion/server/series_functions/yaxis.test.js b/src/plugins/vis_type_timelion/server/series_functions/yaxis.test.js similarity index 100% rename from src/plugins/timelion/server/series_functions/yaxis.test.js rename to src/plugins/vis_type_timelion/server/series_functions/yaxis.test.js diff --git a/src/plugins/timelion/server/timelion.json b/src/plugins/vis_type_timelion/server/timelion.json similarity index 100% rename from src/plugins/timelion/server/timelion.json rename to src/plugins/vis_type_timelion/server/timelion.json diff --git a/src/plugins/timelion/server/types.ts b/src/plugins/vis_type_timelion/server/types.ts similarity index 100% rename from src/plugins/timelion/server/types.ts rename to src/plugins/vis_type_timelion/server/types.ts diff --git a/tasks/config/peg.js b/tasks/config/peg.js index 1d8667840faba..2de6ff4b5cff9 100644 --- a/tasks/config/peg.js +++ b/tasks/config/peg.js @@ -26,7 +26,7 @@ module.exports = { }, }, timelion_chain: { - src: 'src/legacy/core_plugins/vis_type_timelion/public/chain.peg', - dest: 'src/legacy/core_plugins/vis_type_timelion/public/_generated_/chain.js', + src: 'src/plugins/vis_type_timelion/public/chain.peg', + dest: 'src/plugins/vis_type_timelion/public/_generated_/chain.js', }, }; diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/tsconfig.json index d8096d9aab27a..544c27241f5cb 100644 --- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/tsconfig.json +++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/tsconfig.json @@ -6,7 +6,8 @@ "types": [ "node", "jest", - "react" + "react", + "flot" ] }, "include": [ @@ -16,4 +17,4 @@ "../../../../typings/**/*", ], "exclude": [] -} \ No newline at end of file +} diff --git a/test/tsconfig.json b/test/tsconfig.json index 285d3db64a874..5a3716e620fed 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "types": [ "node", - "mocha" + "mocha", + "flot" ], "lib": [ "esnext", diff --git a/x-pack/plugins/features/kibana.json b/x-pack/plugins/features/kibana.json index 325e5a0407493..6e51f3b650710 100644 --- a/x-pack/plugins/features/kibana.json +++ b/x-pack/plugins/features/kibana.json @@ -2,7 +2,7 @@ "id": "features", "version": "8.0.0", "kibanaVersion": "kibana", - "optionalPlugins": ["timelion"], + "optionalPlugins": ["visTypeTimelion"], "configPath": ["xpack", "features"], "server": true, "ui": true diff --git a/x-pack/plugins/features/server/plugin.ts b/x-pack/plugins/features/server/plugin.ts index cebf67243fb28..83cc9e1eb7cc8 100644 --- a/x-pack/plugins/features/server/plugin.ts +++ b/x-pack/plugins/features/server/plugin.ts @@ -13,7 +13,7 @@ import { import { Capabilities as UICapabilities } from '../../../../src/core/server'; import { deepFreeze } from '../../../../src/core/utils'; import { XPackInfo } from '../../../legacy/plugins/xpack_main/server/lib/xpack_info'; -import { PluginSetupContract as TimelionSetupContract } from '../../../../src/plugins/timelion/server'; +import { PluginSetupContract as TimelionSetupContract } from '../../../../src/plugins/vis_type_timelion/server'; import { FeatureRegistry } from './feature_registry'; import { Feature, FeatureConfig } from '../common/feature'; import { uiCapabilitiesForFeatures } from './ui_capabilities_for_features'; @@ -65,7 +65,7 @@ export class Plugin { public async setup( core: CoreSetup, - { timelion }: { timelion?: TimelionSetupContract } + { visTypeTimelion }: { visTypeTimelion?: TimelionSetupContract } ): Promise> { defineRoutes({ router: core.http.createRouter(), @@ -84,7 +84,7 @@ export class Plugin { // Register OSS features. for (const feature of buildOSSFeatures({ savedObjectTypes: this.legacyAPI.savedObjectTypes, - includeTimelion: timelion !== undefined && timelion.uiEnabled, + includeTimelion: visTypeTimelion !== undefined && visTypeTimelion.uiEnabled, })) { this.featureRegistry.register(feature); } diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index e9aab9b47535f..df1d7e789507b 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "types": [ "mocha", - "node" + "node", + "flot" ] }, "include": [ diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index a6c94ff74620e..55f697fb4f5ec 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -40,7 +40,8 @@ }, "types": [ "node", - "jest" + "jest", + "flot" ] } } From abbb51ba11feb2c24e61e07969773ea73e56eadd Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Fri, 17 Apr 2020 11:04:58 +0200 Subject: [PATCH 07/22] add deprecation warning for legacy 3rd party plugins (#62401) * add warnings for legacy 3rd party plugins * use published doc page for 8.0 breaking changes * update message to remove fixed 8.0 version reference * fix generated doc --- .../legacy/legacy_service.test.mocks.ts | 7 +- src/core/server/legacy/legacy_service.test.ts | 37 +++++++- src/core/server/legacy/legacy_service.ts | 7 +- src/core/server/legacy/plugins/index.ts | 1 + .../log_legacy_plugins_warning.test.ts | 90 +++++++++++++++++++ .../plugins/log_legacy_plugins_warning.ts | 52 +++++++++++ src/core/server/legacy/types.ts | 1 + src/core/server/server.api.md | 10 +-- 8 files changed, 197 insertions(+), 8 deletions(-) create mode 100644 src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts create mode 100644 src/core/server/legacy/plugins/log_legacy_plugins_warning.ts diff --git a/src/core/server/legacy/legacy_service.test.mocks.ts b/src/core/server/legacy/legacy_service.test.mocks.ts index 451a75ced7ae2..9ad554d63add0 100644 --- a/src/core/server/legacy/legacy_service.test.mocks.ts +++ b/src/core/server/legacy/legacy_service.test.mocks.ts @@ -30,6 +30,11 @@ export const findLegacyPluginSpecsMock = jest.fn().mockImplementation((settings: uiExports: {}, navLinks: [], })); -jest.doMock('./plugins/find_legacy_plugin_specs.ts', () => ({ +jest.doMock('./plugins/find_legacy_plugin_specs', () => ({ findLegacyPluginSpecs: findLegacyPluginSpecsMock, })); + +export const logLegacyThirdPartyPluginDeprecationWarningMock = jest.fn(); +jest.doMock('./plugins/log_legacy_plugins_warning', () => ({ + logLegacyThirdPartyPluginDeprecationWarning: logLegacyThirdPartyPluginDeprecationWarningMock, +})); diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index 0c4e58f6a8da1..a75f7dda302c2 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -22,7 +22,10 @@ jest.mock('../../../cli/cluster/cluster_manager'); jest.mock('./config/legacy_deprecation_adapters', () => ({ convertLegacyDeprecationProvider: (provider: any) => Promise.resolve(provider), })); -import { findLegacyPluginSpecsMock } from './legacy_service.test.mocks'; +import { + findLegacyPluginSpecsMock, + logLegacyThirdPartyPluginDeprecationWarningMock, +} from './legacy_service.test.mocks'; import { BehaviorSubject, throwError } from 'rxjs'; @@ -476,6 +479,38 @@ describe('#discoverPlugins()', () => { expect(configService.addDeprecationProvider).toHaveBeenCalledWith('', 'providerA'); expect(configService.addDeprecationProvider).toHaveBeenCalledWith('', 'providerB'); }); + + it(`logs deprecations for legacy third party plugins`, async () => { + const pluginSpecs = [ + { getId: () => 'pluginA', getDeprecationsProvider: () => undefined }, + { getId: () => 'pluginB', getDeprecationsProvider: () => undefined }, + ]; + findLegacyPluginSpecsMock.mockImplementation( + settings => + Promise.resolve({ + pluginSpecs, + pluginExtendedConfig: settings, + disabledPluginSpecs: [], + uiExports: {}, + navLinks: [], + }) as any + ); + + const legacyService = new LegacyService({ + coreId, + env, + logger, + configService: configService as any, + }); + + await legacyService.discoverPlugins(); + + expect(logLegacyThirdPartyPluginDeprecationWarningMock).toHaveBeenCalledTimes(1); + expect(logLegacyThirdPartyPluginDeprecationWarningMock).toHaveBeenCalledWith({ + specs: pluginSpecs, + log: expect.any(Object), + }); + }); }); test('Sets the server.uuid property on the legacy configuration', async () => { diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index fd3ebfe120599..b95362e1ea26e 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -28,7 +28,7 @@ import { DevConfig, DevConfigType, config as devConfig } from '../dev'; import { BasePathProxyServer, HttpConfig, HttpConfigType, config as httpConfig } from '../http'; import { Logger } from '../logging'; import { PathConfigType } from '../path'; -import { findLegacyPluginSpecs } from './plugins'; +import { findLegacyPluginSpecs, logLegacyThirdPartyPluginDeprecationWarning } from './plugins'; import { convertLegacyDeprecationProvider } from './config'; import { ILegacyInternals, @@ -133,6 +133,11 @@ export class LegacyService implements CoreService { this.coreContext.env.packageInfo ); + logLegacyThirdPartyPluginDeprecationWarning({ + specs: pluginSpecs, + log: this.log, + }); + this.legacyPlugins = { pluginSpecs, disabledPluginSpecs, diff --git a/src/core/server/legacy/plugins/index.ts b/src/core/server/legacy/plugins/index.ts index a6d55e1da7839..7ec5dbc1983ab 100644 --- a/src/core/server/legacy/plugins/index.ts +++ b/src/core/server/legacy/plugins/index.ts @@ -18,3 +18,4 @@ */ export { findLegacyPluginSpecs } from './find_legacy_plugin_specs'; +export { logLegacyThirdPartyPluginDeprecationWarning } from './log_legacy_plugins_warning'; diff --git a/src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts b/src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts new file mode 100644 index 0000000000000..1790b096a71ae --- /dev/null +++ b/src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts @@ -0,0 +1,90 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { loggerMock } from '../../logging/logger.mock'; +import { logLegacyThirdPartyPluginDeprecationWarning } from './log_legacy_plugins_warning'; +import { LegacyPluginSpec } from '../types'; + +const createPluginSpec = ({ id, path }: { id: string; path: string }): LegacyPluginSpec => { + return { + getId: () => id, + getExpectedKibanaVersion: () => 'kibana', + getConfigPrefix: () => 'plugin.config', + getDeprecationsProvider: () => undefined, + getPack: () => ({ + getPath: () => path, + }), + }; +}; + +describe('logLegacyThirdPartyPluginDeprecationWarning', () => { + let log: ReturnType; + + beforeEach(() => { + log = loggerMock.create(); + }); + + it('logs warning for third party plugins', () => { + logLegacyThirdPartyPluginDeprecationWarning({ + specs: [createPluginSpec({ id: 'plugin', path: '/some-external-path' })], + log, + }); + expect(log.warn).toHaveBeenCalledTimes(1); + expect(log.warn.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "Some installed third party plugin(s) [plugin] are using the legacy plugin format and will no longer work in a future Kibana release. Please refer to https://www.elastic.co/guide/en/kibana/master/breaking-changes-8.0.html for a list of breaking changes and https://github.com/elastic/kibana/blob/master/src/core/MIGRATION.md for documentation on how to migrate legacy plugins.", + ] + `); + }); + + it('lists all the deprecated plugins and only log once', () => { + logLegacyThirdPartyPluginDeprecationWarning({ + specs: [ + createPluginSpec({ id: 'pluginA', path: '/abs/path/to/pluginA' }), + createPluginSpec({ id: 'pluginB', path: '/abs/path/to/pluginB' }), + createPluginSpec({ id: 'pluginC', path: '/abs/path/to/pluginC' }), + ], + log, + }); + expect(log.warn).toHaveBeenCalledTimes(1); + expect(log.warn.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "Some installed third party plugin(s) [pluginA, pluginB, pluginC] are using the legacy plugin format and will no longer work in a future Kibana release. Please refer to https://www.elastic.co/guide/en/kibana/master/breaking-changes-8.0.html for a list of breaking changes and https://github.com/elastic/kibana/blob/master/src/core/MIGRATION.md for documentation on how to migrate legacy plugins.", + ] + `); + }); + + it('does not log warning for internal legacy plugins', () => { + logLegacyThirdPartyPluginDeprecationWarning({ + specs: [ + createPluginSpec({ + id: 'plugin', + path: '/absolute/path/to/kibana/src/legacy/core_plugins', + }), + createPluginSpec({ + id: 'plugin', + path: '/absolute/path/to/kibana/x-pack', + }), + ], + log, + }); + + expect(log.warn).not.toHaveBeenCalled(); + }); +}); diff --git a/src/core/server/legacy/plugins/log_legacy_plugins_warning.ts b/src/core/server/legacy/plugins/log_legacy_plugins_warning.ts new file mode 100644 index 0000000000000..f9c3dcbf554cb --- /dev/null +++ b/src/core/server/legacy/plugins/log_legacy_plugins_warning.ts @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Logger } from '../../logging'; +import { LegacyPluginSpec } from '../types'; + +const internalPaths = ['/src/legacy/core_plugins', '/x-pack']; + +const breakingChangesUrl = + 'https://www.elastic.co/guide/en/kibana/master/breaking-changes-8.0.html'; +const migrationGuideUrl = 'https://github.com/elastic/kibana/blob/master/src/core/MIGRATION.md'; + +export const logLegacyThirdPartyPluginDeprecationWarning = ({ + specs, + log, +}: { + specs: LegacyPluginSpec[]; + log: Logger; +}) => { + const thirdPartySpecs = specs.filter(isThirdPartyPluginSpec); + if (thirdPartySpecs.length > 0) { + const pluginIds = thirdPartySpecs.map(spec => spec.getId()); + log.warn( + `Some installed third party plugin(s) [${pluginIds.join( + ', ' + )}] are using the legacy plugin format and will no longer work in a future Kibana release. ` + + `Please refer to ${breakingChangesUrl} for a list of breaking changes ` + + `and ${migrationGuideUrl} for documentation on how to migrate legacy plugins.` + ); + } +}; + +const isThirdPartyPluginSpec = (spec: LegacyPluginSpec): boolean => { + const pluginPath = spec.getPack().getPath(); + return !internalPaths.some(internalPath => pluginPath.indexOf(internalPath) > -1); +}; diff --git a/src/core/server/legacy/types.ts b/src/core/server/legacy/types.ts index 38cb9e6835ce9..2567ca790e04f 100644 --- a/src/core/server/legacy/types.ts +++ b/src/core/server/legacy/types.ts @@ -98,6 +98,7 @@ export interface LegacyPluginSpec { getExpectedKibanaVersion: () => string; getConfigPrefix: () => string; getDeprecationsProvider: () => LegacyConfigDeprecationProvider | undefined; + getPack: () => LegacyPluginPack; } /** diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index dd08df06c73d2..7ca5c75f19e8f 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2468,11 +2468,11 @@ export const validBodyOutput: readonly ["data", "stream"]; // Warnings were encountered during analysis: // // src/core/server/http/router/response.ts:316:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts -// src/core/server/legacy/types.ts:162:3 - (ae-forgotten-export) The symbol "VarsProvider" needs to be exported by the entry point index.d.ts -// src/core/server/legacy/types.ts:163:3 - (ae-forgotten-export) The symbol "VarsReplacer" needs to be exported by the entry point index.d.ts -// src/core/server/legacy/types.ts:164:3 - (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts -// src/core/server/legacy/types.ts:165:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts -// src/core/server/legacy/types.ts:166:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts +// src/core/server/legacy/types.ts:163:3 - (ae-forgotten-export) The symbol "VarsProvider" needs to be exported by the entry point index.d.ts +// src/core/server/legacy/types.ts:164:3 - (ae-forgotten-export) The symbol "VarsReplacer" needs to be exported by the entry point index.d.ts +// src/core/server/legacy/types.ts:165:3 - (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts +// src/core/server/legacy/types.ts:166:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts +// src/core/server/legacy/types.ts:167:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:232:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts From 90f5ce0ef34885373d43bd613ac382a5ab9aee15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Fri, 17 Apr 2020 10:15:28 +0100 Subject: [PATCH 08/22] [APM]Upgrade apm-rum agent to latest version to fix full page reload (#63723) --- package.json | 2 +- x-pack/package.json | 2 +- yarn.lock | 45 ++++++++++++++++++++++----------------------- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 8a45ea27d3168..21e9f67e6206a 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "dependencies": { "@babel/core": "^7.9.0", "@babel/register": "^7.9.0", - "@elastic/apm-rum": "^4.6.0", + "@elastic/apm-rum": "^5.1.1", "@elastic/charts": "18.3.0", "@elastic/datemath": "5.0.3", "@elastic/ems-client": "7.8.0", diff --git a/x-pack/package.json b/x-pack/package.json index b2ec4c3dc3f6f..a4fdb17f52fe5 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -179,7 +179,7 @@ "@babel/core": "^7.9.0", "@babel/register": "^7.9.0", "@babel/runtime": "^7.9.2", - "@elastic/apm-rum-react": "^0.3.2", + "@elastic/apm-rum-react": "^1.1.1", "@elastic/datemath": "5.0.3", "@elastic/ems-client": "7.8.0", "@elastic/eui": "21.0.1", diff --git a/yarn.lock b/yarn.lock index 34ee6f393f25a..45540cd2675b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1220,30 +1220,29 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@elastic/apm-rum-core@^4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@elastic/apm-rum-core/-/apm-rum-core-4.7.0.tgz#b00b58bf7380f2e36652e5333e3ca97608986e40" - integrity sha512-/lTZWfA3ces3qoKCx72Sc+w43lZkyktaQlbYoYO86h3tNX7tScc/7YBBHI9oxKMcXweqkKOcpnwNZFy71bb86w== +"@elastic/apm-rum-core@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@elastic/apm-rum-core/-/apm-rum-core-5.2.0.tgz#2ed30dc226c9b5779532ab2e6065a155587bcea4" + integrity sha512-3ti2dhrqfxjHFXgArQI/sVAG2AgZH0kB1nx+2WjLpuAh8gGS4R772M5VXcWcGQb8UW9jrANwwbW2hT2GKv+uOA== dependencies: error-stack-parser "^1.3.5" - es6-promise "^4.2.8" opentracing "^0.14.3" - uuid "^3.1.0" + promise-polyfill "^8.1.3" -"@elastic/apm-rum-react@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@elastic/apm-rum-react/-/apm-rum-react-0.3.2.tgz#134634643e15ebcf97b6f17b2c74a50afdbe1c64" - integrity sha512-hU1srW9noygppyrLmipulu30c+LWEie8V/dQjEqLYMx2mRZRwNIue3midYgWa6qrWqgYZhwpAtWrWcXc+AWk2Q== +"@elastic/apm-rum-react@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@elastic/apm-rum-react/-/apm-rum-react-1.1.1.tgz#3a2ba91efc9260da55ef6c31cce642a476eba828" + integrity sha512-ZMixw+82VbZIDBnz0dj5Fo4PZ7pnXlLjAA7XTi3AtSIEjpsZa7YIuCFzJdrgb/nOq7MOFkODkFPTiIYAM/yCqg== dependencies: - "@elastic/apm-rum" "^4.6.0" + "@elastic/apm-rum" "^5.1.1" hoist-non-react-statics "^3.3.0" -"@elastic/apm-rum@^4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@elastic/apm-rum/-/apm-rum-4.6.0.tgz#e2ac560dd4a4761c0e9b08c301418b1d4063bdd2" - integrity sha512-hsqvyTm5rT6lKgV06wvm8ID9aMsuJyw8wIOPjRwKmvzlTjayabxKTcr50lJJV8jY9OWfDkqymIqpHyCEChQAHQ== +"@elastic/apm-rum@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@elastic/apm-rum/-/apm-rum-5.1.1.tgz#02d29fa606e66f9a3a88f629d468b02457b1b183" + integrity sha512-A0O/0ZffcHm1taLuXyFoUmV2+aARr+9+xbmsEDIExLV0yKaNlaLl3UaZrodSOZ1ijlCEsRRS+y2i0md93YKQTA== dependencies: - "@elastic/apm-rum-core" "^4.7.0" + "@elastic/apm-rum-core" "^5.2.0" "@elastic/charts@18.3.0": version "18.3.0" @@ -12279,11 +12278,6 @@ es6-promise@^4.2.5: resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f" integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q== -es6-promise@^4.2.8: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - es6-promisify@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" @@ -23577,6 +23571,11 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= +promise-polyfill@^8.1.3: + version "8.1.3" + resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.1.3.tgz#8c99b3cf53f3a91c68226ffde7bde81d7f904116" + integrity sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g== + promise.prototype.finally@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.0.tgz#66f161b1643636e50e7cf201dc1b84a857f3864e" @@ -30861,7 +30860,7 @@ utils-regex-from-string@^1.0.0: regex-regex "^1.0.0" validate.io-string-primitive "^1.0.0" -uuid@3.3.2, uuid@^3.0.1, uuid@^3.1.0, uuid@^3.3.2: +uuid@3.3.2, uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== @@ -30876,7 +30875,7 @@ uuid@^3.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g== -uuid@^3.3.3: +uuid@^3.1.0, uuid@^3.3.3: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== From f91c795e30b7221cdce36e235470a4cda82f70b2 Mon Sep 17 00:00:00 2001 From: Sonja Krause-Harder Date: Fri, 17 Apr 2020 13:23:30 +0200 Subject: [PATCH 09/22] [EPM] Handle multi fields in index template generation (#63112) * Add unit test stub for multi fields. * Add multi field handling to mapping generation. * Start documenting index template generation. * Add unit tests. * Remove stub for fields.yml documentation Co-authored-by: Elastic Machine --- docs/ingest_manager/index-templates.asciidoc | 7 + docs/ingest_manager/index.asciidoc | 7 + .../__snapshots__/template.test.ts.snap | 176 +++++++++--------- .../elasticsearch/template/template.test.ts | 98 ++++++++++ .../epm/elasticsearch/template/template.ts | 69 +++++-- 5 files changed, 256 insertions(+), 101 deletions(-) create mode 100644 docs/ingest_manager/index-templates.asciidoc diff --git a/docs/ingest_manager/index-templates.asciidoc b/docs/ingest_manager/index-templates.asciidoc new file mode 100644 index 0000000000000..e19af63c3116f --- /dev/null +++ b/docs/ingest_manager/index-templates.asciidoc @@ -0,0 +1,7 @@ +# Elasticsearch Index Templates + +## Generation + +* Index templates are generated from `YAML` files contained in the package. +* There is one index template per dataset. +* For the generation of an index template, all `yml` files contained in the package subdirectory `dataset/DATASET_NAME/fields/` are used. diff --git a/docs/ingest_manager/index.asciidoc b/docs/ingest_manager/index.asciidoc index 22afa88c919e4..866935d1fa580 100644 --- a/docs/ingest_manager/index.asciidoc +++ b/docs/ingest_manager/index.asciidoc @@ -199,3 +199,10 @@ The new ingest pipeline is expected to still work with the data coming from olde In case of a breaking change in the data structure, the new ingest pipeline is also expected to deal with this change. In case there are breaking changes which cannot be dealt with in an ingest pipeline, a new package has to be created. Each package lists its minimal required agent version. In case there are agents enrolled with an older version, the user is notified to upgrade these agents as otherwise the new configs cannot be rolled out. + +=== Generated assets + +When a package is installed or upgraded, certain Kibana and Elasticsearch assets are generated from . These follow the naming conventions explained above (see "indexing strategy") and contain configuration for the elastic stack that makes ingesting and displaying data work with as little user interaction as possible. + +* link:index-templates.asciidoc[Elasticsearch Index Templates] +* Kibana Index Patterns diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap index 0e239c24dd9cf..166983fbccc35 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap @@ -47,12 +47,12 @@ exports[`tests loading base.yml: base.yml 1`] = ` "user": { "properties": { "auid": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "euid": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" } } }, @@ -73,12 +73,12 @@ exports[`tests loading base.yml: base.yml 1`] = ` "nested": { "properties": { "bar": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "baz": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" } } }, @@ -142,8 +142,8 @@ exports[`tests loading coredns.logs.yml: coredns.logs.yml 1`] = ` "coredns": { "properties": { "id": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "query": { "properties": { @@ -151,28 +151,28 @@ exports[`tests loading coredns.logs.yml: coredns.logs.yml 1`] = ` "type": "long" }, "class": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "name": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "type": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" } } }, "response": { "properties": { "code": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "flags": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "size": { "type": "long" @@ -509,12 +509,12 @@ exports[`tests loading system.yml: system.yml 1`] = ` "diskio": { "properties": { "name": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "serial_number": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "read": { "properties": { @@ -643,16 +643,16 @@ exports[`tests loading system.yml: system.yml 1`] = ` "type": "long" }, "device_name": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "type": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "mount_point": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "files": { "type": "long" @@ -867,8 +867,8 @@ exports[`tests loading system.yml: system.yml 1`] = ` "network": { "properties": { "name": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "out": { "properties": { @@ -946,12 +946,12 @@ exports[`tests loading system.yml: system.yml 1`] = ` "process": { "properties": { "state": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "cmdline": { - "type": "keyword", - "ignore_above": 2048 + "ignore_above": 2048, + "type": "keyword" }, "env": { "type": "object" @@ -1040,22 +1040,22 @@ exports[`tests loading system.yml: system.yml 1`] = ` "cgroup": { "properties": { "id": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "path": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "cpu": { "properties": { "id": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "path": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "cfs": { "properties": { @@ -1118,12 +1118,12 @@ exports[`tests loading system.yml: system.yml 1`] = ` "cpuacct": { "properties": { "id": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "path": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "total": { "properties": { @@ -1158,12 +1158,12 @@ exports[`tests loading system.yml: system.yml 1`] = ` "memory": { "properties": { "id": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "path": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "mem": { "properties": { @@ -1382,12 +1382,12 @@ exports[`tests loading system.yml: system.yml 1`] = ` "blkio": { "properties": { "id": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "path": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "total": { "properties": { @@ -1436,20 +1436,20 @@ exports[`tests loading system.yml: system.yml 1`] = ` "raid": { "properties": { "name": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "status": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "level": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "sync_action": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "disks": { "properties": { @@ -1507,24 +1507,24 @@ exports[`tests loading system.yml: system.yml 1`] = ` "type": "long" }, "host": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "etld_plus_one": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "host_error": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" } } }, "process": { "properties": { "cmdline": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" } } }, @@ -1622,42 +1622,42 @@ exports[`tests loading system.yml: system.yml 1`] = ` "users": { "properties": { "id": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "seat": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "path": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "type": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "service": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "remote": { "type": "boolean" }, "state": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "scope": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" }, "leader": { "type": "long" }, "remote_host": { - "type": "keyword", - "ignore_above": 1024 + "ignore_above": 1024, + "type": "keyword" } } } diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts index f4e13748641ed..cde2e5b420f3b 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts @@ -63,3 +63,101 @@ test('tests loading system.yml', () => { expect(template).toMatchSnapshot(path.basename(ymlPath)); }); + +test('tests processing text field with multi fields', () => { + const textWithMultiFieldsLiteralYml = ` +- name: textWithMultiFields + type: text + multi_fields: + - name: raw + type: keyword + - name: indexed + type: text +`; + const textWithMultiFieldsMapping = { + properties: { + textWithMultiFields: { + type: 'text', + fields: { + raw: { + ignore_above: 1024, + type: 'keyword', + }, + indexed: { + type: 'text', + }, + }, + }, + }, + }; + const fields: Field[] = safeLoad(textWithMultiFieldsLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(JSON.stringify(mappings)).toEqual(JSON.stringify(textWithMultiFieldsMapping)); +}); + +test('tests processing keyword field with multi fields', () => { + const keywordWithMultiFieldsLiteralYml = ` +- name: keywordWithMultiFields + type: keyword + multi_fields: + - name: raw + type: keyword + - name: indexed + type: text +`; + + const keywordWithMultiFieldsMapping = { + properties: { + keywordWithMultiFields: { + ignore_above: 1024, + type: 'keyword', + fields: { + raw: { + ignore_above: 1024, + type: 'keyword', + }, + indexed: { + type: 'text', + }, + }, + }, + }, + }; + const fields: Field[] = safeLoad(keywordWithMultiFieldsLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(JSON.stringify(mappings)).toEqual(JSON.stringify(keywordWithMultiFieldsMapping)); +}); + +test('tests processing keyword field with multi fields with analyzed text field', () => { + const keywordWithAnalyzedMultiFieldsLiteralYml = ` + - name: keywordWithAnalyzedMultiField + type: keyword + multi_fields: + - name: analyzed + type: text + analyzer: autocomplete + search_analyzer: standard + `; + + const keywordWithAnalyzedMultiFieldsMapping = { + properties: { + keywordWithAnalyzedMultiField: { + ignore_above: 1024, + type: 'keyword', + fields: { + analyzed: { + analyzer: 'autocomplete', + search_analyzer: 'standard', + type: 'text', + }, + }, + }, + }, + }; + const fields: Field[] = safeLoad(keywordWithAnalyzedMultiFieldsLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(JSON.stringify(mappings)).toEqual(JSON.stringify(keywordWithAnalyzedMultiFieldsMapping)); +}); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts index 832e4772beb0d..e876c8a2efb4f 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Field } from '../../fields/field'; +import { Field, Fields } from '../../fields/field'; import { Dataset, IndexTemplate } from '../../../../types'; import { getDatasetAssetBaseName } from '../index'; @@ -15,6 +15,14 @@ interface Mappings { properties: any; } +interface Mapping { + [key: string]: any; +} + +interface MultiFields { + [key: string]: object; +} + const DEFAULT_SCALING_FACTOR = 1000; const DEFAULT_IGNORE_ABOVE = 1024; @@ -67,23 +75,19 @@ export function generateMappings(fields: Field[]): Mappings { fieldProps.scaling_factor = field.scaling_factor || DEFAULT_SCALING_FACTOR; break; case 'text': - fieldProps.type = 'text'; - if (field.analyzer) { - fieldProps.analyzer = field.analyzer; - } - if (field.search_analyzer) { - fieldProps.search_analyzer = field.search_analyzer; + const textMapping = generateTextMapping(field); + fieldProps = { ...fieldProps, ...textMapping, type: 'text' }; + if (field.multi_fields) { + fieldProps.fields = generateMultiFields(field.multi_fields); } break; case 'keyword': - fieldProps.type = 'keyword'; - if (field.ignore_above) { - fieldProps.ignore_above = field.ignore_above; - } else { - fieldProps.ignore_above = DEFAULT_IGNORE_ABOVE; + const keywordMapping = generateKeywordMapping(field); + fieldProps = { ...fieldProps, ...keywordMapping, type: 'keyword' }; + if (field.multi_fields) { + fieldProps.fields = generateMultiFields(field.multi_fields); } break; - // TODO move handling of multi_fields here? case 'object': // TODO improve fieldProps.type = 'object'; @@ -113,6 +117,45 @@ export function generateMappings(fields: Field[]): Mappings { return { properties: props }; } +function generateMultiFields(fields: Fields): MultiFields { + const multiFields: MultiFields = {}; + if (fields) { + fields.forEach((f: Field) => { + const type = f.type; + switch (type) { + case 'text': + multiFields[f.name] = { ...generateTextMapping(f), type: f.type }; + break; + case 'keyword': + multiFields[f.name] = { ...generateKeywordMapping(f), type: f.type }; + break; + } + }); + } + return multiFields; +} + +function generateKeywordMapping(field: Field): Mapping { + const mapping: Mapping = { + ignore_above: DEFAULT_IGNORE_ABOVE, + }; + if (field.ignore_above) { + mapping.ignore_above = field.ignore_above; + } + return mapping; +} + +function generateTextMapping(field: Field): Mapping { + const mapping: Mapping = {}; + if (field.analyzer) { + mapping.analyzer = field.analyzer; + } + if (field.search_analyzer) { + mapping.search_analyzer = field.search_analyzer; + } + return mapping; +} + function getDefaultProperties(field: Field): Properties { const properties: Properties = {}; From 1385cce3b7e4b06da95ede4ae454fb0b08ca60e4 Mon Sep 17 00:00:00 2001 From: Sonja Krause-Harder Date: Fri, 17 Apr 2020 15:16:20 +0200 Subject: [PATCH 10/22] [EPM] Improve object handling in index template mappings (#63688) * Unit-test current mapping for object types * Handle 'enabled' attribute for object fields * Handle 'dynamic' attribute for object fields Co-authored-by: Elastic Machine --- .../elasticsearch/template/template.test.ts | 98 +++++++++++++++++++ .../epm/elasticsearch/template/template.ts | 7 +- .../server/services/epm/fields/field.ts | 1 + 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts index cde2e5b420f3b..1a73c9581a2de 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts @@ -161,3 +161,101 @@ test('tests processing keyword field with multi fields with analyzed text field' const mappings = generateMappings(processedFields); expect(JSON.stringify(mappings)).toEqual(JSON.stringify(keywordWithAnalyzedMultiFieldsMapping)); }); + +test('tests processing object field with no other attributes', () => { + const objectFieldLiteralYml = ` +- name: objectField + type: object +`; + const objectFieldMapping = { + properties: { + objectField: { + type: 'object', + }, + }, + }; + const fields: Field[] = safeLoad(objectFieldLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(JSON.stringify(mappings)).toEqual(JSON.stringify(objectFieldMapping)); +}); + +test('tests processing object field with enabled set to false', () => { + const objectFieldEnabledFalseLiteralYml = ` +- name: objectField + type: object + enabled: false +`; + const objectFieldEnabledFalseMapping = { + properties: { + objectField: { + type: 'object', + enabled: false, + }, + }, + }; + const fields: Field[] = safeLoad(objectFieldEnabledFalseLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(JSON.stringify(mappings)).toEqual(JSON.stringify(objectFieldEnabledFalseMapping)); +}); + +test('tests processing object field with dynamic set to false', () => { + const objectFieldDynamicFalseLiteralYml = ` +- name: objectField + type: object + dynamic: false +`; + const objectFieldDynamicFalseMapping = { + properties: { + objectField: { + type: 'object', + dynamic: false, + }, + }, + }; + const fields: Field[] = safeLoad(objectFieldDynamicFalseLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(JSON.stringify(mappings)).toEqual(JSON.stringify(objectFieldDynamicFalseMapping)); +}); + +test('tests processing object field with dynamic set to true', () => { + const objectFieldDynamicTrueLiteralYml = ` +- name: objectField + type: object + dynamic: true +`; + const objectFieldDynamicTrueMapping = { + properties: { + objectField: { + type: 'object', + dynamic: true, + }, + }, + }; + const fields: Field[] = safeLoad(objectFieldDynamicTrueLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(JSON.stringify(mappings)).toEqual(JSON.stringify(objectFieldDynamicTrueMapping)); +}); + +test('tests processing object field with dynamic set to strict', () => { + const objectFieldDynamicStrictLiteralYml = ` +- name: objectField + type: object + dynamic: strict +`; + const objectFieldDynamicStrictMapping = { + properties: { + objectField: { + type: 'object', + dynamic: 'strict', + }, + }, + }; + const fields: Field[] = safeLoad(objectFieldDynamicStrictLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(JSON.stringify(mappings)).toEqual(JSON.stringify(objectFieldDynamicStrictMapping)); +}); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts index e876c8a2efb4f..22a61d2bdfb7c 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts @@ -89,8 +89,13 @@ export function generateMappings(fields: Field[]): Mappings { } break; case 'object': - // TODO improve fieldProps.type = 'object'; + if (field.hasOwnProperty('enabled')) { + fieldProps.enabled = field.enabled; + } + if (field.hasOwnProperty('dynamic')) { + fieldProps.dynamic = field.dynamic; + } break; case 'array': // this assumes array fields were validated in an earlier step diff --git a/x-pack/plugins/ingest_manager/server/services/epm/fields/field.ts b/x-pack/plugins/ingest_manager/server/services/epm/fields/field.ts index 810896bb50389..9c9843e0454ab 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/fields/field.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/fields/field.ts @@ -27,6 +27,7 @@ export interface Field { ignore_above?: number; object_type?: string; scaling_factor?: number; + dynamic?: 'strict' | boolean; // Kibana specific analyzed?: boolean; From 954dda1662de39e678213d288e7110536d1d4f06 Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Fri, 17 Apr 2020 10:04:48 -0400 Subject: [PATCH 11/22] [SIEM][Detections] - Update KQL/Lucene search to include lists exceptions (#63264) [SIEM][Detections] - Update KQL/Lucene search to include lists exceptions (#63264) ### Summary This PR adds logic to include the lists values in search so we can now filter off of lists. - does work with KQL search - does work with Lucene search - does NOT yet filter off of large lists (will be separate PR) - does NOT yet work on ML search (will be separate PR) --- .../schemas/create_rules_schema.test.ts | 4 +- .../routes/schemas/patch_rules_schema.test.ts | 4 +- .../schemas/types/lists_default_array.ts | 10 +- .../schemas/update_rules_schema.test.ts | 4 +- .../rules/queries/lists/query_with_and.json | 35 + .../queries/lists/query_with_excluded.json | 23 + .../queries/lists/query_with_exists.json | 18 + .../rules/queries/lists/query_with_list.json | 54 + .../rules/queries/lists/query_with_match.json | 23 + .../queries/lists/query_with_match_all.json | 26 + .../rules/queries/lists/query_with_or.json | 32 + .../rules/queries/query_with_list.json | 41 - .../signals/build_exceptions_query.test.ts | 1318 +++++++++++++++++ .../signals/build_exceptions_query.ts | 203 +++ .../signals/get_filter.test.ts | 198 ++- .../detection_engine/signals/get_filter.ts | 24 +- .../signals/signal_rule_alert_type.ts | 2 + .../siem/server/lib/detection_engine/types.ts | 6 +- 18 files changed, 1959 insertions(+), 66 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_and.json create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_excluded.json create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_exists.json create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_list.json create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_match.json create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_match_all.json create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_or.json delete mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_list.json create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_exceptions_query.test.ts create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_exceptions_query.ts diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.test.ts index e56e8e5fe34d3..82d355d37e7bb 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/create_rules_schema.test.ts @@ -556,7 +556,9 @@ describe('create rules schema', () => { test('language does not validate with something made up', () => { expect( - createRulesSchema.validate>({ + createRulesSchema.validate< + Partial & { language: string }> + >({ rule_id: 'rule-1', output_index: '.siem-signals', risk_score: 50, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/patch_rules_schema.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/patch_rules_schema.test.ts index e01a8f40fcea4..9e23e4e3bad55 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/patch_rules_schema.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/patch_rules_schema.test.ts @@ -572,7 +572,9 @@ describe('patch rules schema', () => { test('language does not validate with something made up', () => { expect( - patchRulesSchema.validate>({ + patchRulesSchema.validate< + Partial & { language: string }> + >({ id: 'rule-1', description: 'some description', from: 'now-5m', diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/types/lists_default_array.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/types/lists_default_array.ts index 85a38e296494a..743914ad070a2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/types/lists_default_array.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/types/lists_default_array.ts @@ -7,10 +7,16 @@ import * as t from 'io-ts'; import { Either } from 'fp-ts/lib/Either'; -import { list_and as listAnd } from '../response/schemas'; +import { + list_and as listAnd, + list_values as listValues, + list_values_operator as listOperator, +} from '../response/schemas'; export type ListsDefaultArrayC = t.Type; -type List = t.TypeOf; +export type List = t.TypeOf; +export type ListValues = t.TypeOf; +export type ListOperator = t.TypeOf; /** * Types the ListsDefaultArray as: diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.test.ts index e8f9aad620ca0..be2f06590e81d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/schemas/update_rules_schema.test.ts @@ -575,7 +575,9 @@ describe('create rules schema', () => { test('language does not validate with something made up', () => { expect( - updateRulesSchema.validate>({ + updateRulesSchema.validate< + Partial & { language: string }> + >({ rule_id: 'rule-1', output_index: '.siem-signals', risk_score: 50, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_and.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_and.json new file mode 100644 index 0000000000000..33ae8df87e3c8 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_and.json @@ -0,0 +1,35 @@ +{ + "name": "List - and", + "description": "Query with a list that includes and. This rule should only produce signals when host.name exists and when both event.module is endgame and event.category is anything other than file", + "rule_id": "query-with-list-and", + "risk_score": 1, + "severity": "high", + "type": "query", + "query": "host.name: *", + "interval": "30s", + "language": "kuery", + "lists": [ + { + "field": "event.module", + "values_operator": "excluded", + "values_type": "match", + "values": [ + { + "name": "endgame" + } + ], + "and": [ + { + "field": "event.category", + "values_operator": "included", + "values_type": "match", + "values": [ + { + "name": "file" + } + ] + } + ] + } + ] +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_excluded.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_excluded.json new file mode 100644 index 0000000000000..8ce9440fce219 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_excluded.json @@ -0,0 +1,23 @@ +{ + "name": "List - excluded", + "description": "Query with a list of values_operator excluded. This rule should only produce signals when host.name exists and event.module is suricata", + "rule_id": "query-with-list-excluded", + "risk_score": 1, + "severity": "high", + "type": "query", + "query": "host.name: *", + "interval": "30s", + "language": "kuery", + "lists": [ + { + "field": "event.module", + "values_operator": "excluded", + "values_type": "match", + "values": [ + { + "name": "suricata" + } + ] + } + ] +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_exists.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_exists.json new file mode 100644 index 0000000000000..4ec014422a61b --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_exists.json @@ -0,0 +1,18 @@ +{ + "name": "List - exists", + "description": "Query with a list that includes exists. This rule should only produce signals when host.name exists and event.action does not exist", + "rule_id": "query-with-list-exists", + "risk_score": 1, + "severity": "high", + "type": "query", + "query": "host.name: *", + "interval": "30s", + "language": "kuery", + "lists": [ + { + "field": "event.action", + "values_operator": "included", + "values_type": "exists" + } + ] +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_list.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_list.json new file mode 100644 index 0000000000000..ce4bf80b0a722 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_list.json @@ -0,0 +1,54 @@ +{ + "name": "Query with a list", + "description": "Query with a list. This rule should only produce signals when either host.name exists and event.module is system and user.name is zeek or gdm OR when host.name exists and event.module is not endgame or zeek or system.", + "rule_id": "query-with-list", + "risk_score": 2, + "severity": "high", + "type": "query", + "query": "host.name: *", + "interval": "30s", + "language": "kuery", + "lists": [ + { + "field": "event.module", + "values_operator": "excluded", + "values_type": "match", + "values": [ + { + "name": "system" + } + ], + "and": [ + { + "field": "user.name", + "values_operator": "excluded", + "values_type": "match_all", + "values": [ + { + "name": "zeek" + }, + { + "name": "gdm" + } + ] + } + ] + }, + { + "field": "event.module", + "values_operator": "included", + "values_type": "match_all", + "values": [ + { + "name": "endgame" + }, + { + "name": "zeek" + }, + { + "name": "system" + } + ] + } + ] +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_match.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_match.json new file mode 100644 index 0000000000000..e1abac19b51e5 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_match.json @@ -0,0 +1,23 @@ +{ + "name": "List - match", + "description": "Query with a list that includes match. This rule should only produce signals when host.name exists and event.module is not suricata", + "rule_id": "query-with-list-match", + "risk_score": 1, + "severity": "high", + "type": "query", + "query": "host.name: *", + "interval": "30s", + "language": "kuery", + "lists": [ + { + "field": "event.module", + "values_operator": "included", + "values_type": "match", + "values": [ + { + "name": "suricata" + } + ] + } + ] +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_match_all.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_match_all.json new file mode 100644 index 0000000000000..1afbb1fee4785 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_match_all.json @@ -0,0 +1,26 @@ +{ + "name": "List - match_all", + "description": "Query with a list that includes match_all. This rule should only produce signals when host.name exists and event.module is not suricata or auditd", + "rule_id": "query-with-list-match-all", + "risk_score": 1, + "severity": "high", + "type": "query", + "query": "host.name: *", + "interval": "30s", + "language": "kuery", + "lists": [ + { + "field": "event.module", + "values_operator": "included", + "values_type": "match_all", + "values": [ + { + "name": "suricata" + }, + { + "name": "auditd" + } + ] + } + ] +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_or.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_or.json new file mode 100644 index 0000000000000..08e38e9ffa53d --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/lists/query_with_or.json @@ -0,0 +1,32 @@ +{ + "name": "List - or", + "description": "Query with a list that includes or. This rule should only produce signals when host.name exists and event.module is suricata OR when host.name exists and event.category is file", + "rule_id": "query-with-list-or", + "risk_score": 1, + "severity": "high", + "type": "query", + "query": "host.name: *", + "interval": "30s", + "lists": [ + { + "field": "event.module", + "values_operator": "excluded", + "values_type": "match", + "values": [ + { + "name": "suricata" + } + ] + }, + { + "field": "event.category", + "values_operator": "excluded", + "values_type": "match", + "values": [ + { + "name": "file" + } + ] + } + ] +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_list.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_list.json deleted file mode 100644 index 997d03369a699..0000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/scripts/rules/queries/query_with_list.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "Query with a list", - "description": "Query with a list", - "rule_id": "query-with-list", - "risk_score": 1, - "severity": "high", - "type": "query", - "query": "user.name: root or user.name: admin", - "lists": [ - { - "field": "source.ip", - "values_operator": "included", - "values_type": "exists" - }, - { - "field": "host.name", - "values_operator": "excluded", - "values_type": "match", - "values": [ - { - "name": "rock01" - } - ], - "and": [ - { - "field": "host.id", - "values_operator": "included", - "values_type": "match_all", - "values": [ - { - "name": "123" - }, - { - "name": "678" - } - ] - } - ] - } - ] -} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_exceptions_query.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_exceptions_query.test.ts new file mode 100644 index 0000000000000..ec8db77dac725 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_exceptions_query.test.ts @@ -0,0 +1,1318 @@ +/* + * 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 { + buildQueryExceptions, + buildExceptions, + operatorBuilder, + buildExists, + buildMatch, + buildMatchAll, + evaluateValues, + formatQuery, + getLanguageBooleanOperator, +} from './build_exceptions_query'; +import { List } from '../routes/schemas/types/lists_default_array'; + +describe('build_exceptions_query', () => { + describe('getLanguageBooleanOperator', () => { + test('it returns value as uppercase if language is "lucene"', () => { + const result = getLanguageBooleanOperator({ language: 'lucene', value: 'not' }); + + expect(result).toEqual('NOT'); + }); + + test('it returns value as is if language is "kuery"', () => { + const result = getLanguageBooleanOperator({ language: 'kuery', value: 'not' }); + + expect(result).toEqual('not'); + }); + }); + + describe('operatorBuilder', () => { + describe('kuery', () => { + test('it returns "not " when operator is "excluded"', () => { + const operator = operatorBuilder({ operator: 'excluded', language: 'kuery' }); + + expect(operator).toEqual(' and '); + }); + + test('it returns empty string when operator is "included"', () => { + const operator = operatorBuilder({ operator: 'included', language: 'kuery' }); + + expect(operator).toEqual(' and not '); + }); + }); + + describe('lucene', () => { + test('it returns "NOT " when operator is "excluded"', () => { + const operator = operatorBuilder({ operator: 'excluded', language: 'lucene' }); + + expect(operator).toEqual(' AND '); + }); + + test('it returns empty string when operator is "included"', () => { + const operator = operatorBuilder({ operator: 'included', language: 'lucene' }); + + expect(operator).toEqual(' AND NOT '); + }); + }); + }); + + describe('buildExists', () => { + describe('kuery', () => { + test('it returns formatted wildcard string when operator is "excluded"', () => { + const query = buildExists({ operator: 'excluded', field: 'host.name', language: 'kuery' }); + + expect(query).toEqual(' and host.name:*'); + }); + + test('it returns formatted wildcard string when operator is "included"', () => { + const query = buildExists({ operator: 'included', field: 'host.name', language: 'kuery' }); + + expect(query).toEqual(' and not host.name:*'); + }); + }); + + describe('lucene', () => { + test('it returns formatted wildcard string when operator is "excluded"', () => { + const query = buildExists({ operator: 'excluded', field: 'host.name', language: 'lucene' }); + + expect(query).toEqual(' AND _exists_host.name'); + }); + + test('it returns formatted wildcard string when operator is "included"', () => { + const query = buildExists({ operator: 'included', field: 'host.name', language: 'lucene' }); + + expect(query).toEqual(' AND NOT _exists_host.name'); + }); + }); + }); + + describe('buildMatch', () => { + describe('kuery', () => { + test('it returns empty string if no items in "values"', () => { + const query = buildMatch({ + operator: 'included', + field: 'host.name', + values: [], + language: 'kuery', + }); + + expect(query).toEqual(''); + }); + + test('it returns formatted string when operator is "included"', () => { + const values = [ + { + name: 'suricata', + }, + ]; + const query = buildMatch({ + operator: 'included', + field: 'host.name', + values, + language: 'kuery', + }); + + expect(query).toEqual(' and not host.name:suricata'); + }); + + test('it returns formatted string when operator is "excluded"', () => { + const values = [ + { + name: 'suricata', + }, + ]; + const query = buildMatch({ + operator: 'excluded', + field: 'host.name', + values, + language: 'kuery', + }); + + expect(query).toEqual(' and host.name:suricata'); + }); + + // TODO: need to clean up types and maybe restrict values to one if type is 'match' + test('it returns formatted string when "values" includes more than one item', () => { + const values = [ + { + name: 'suricata', + }, + { + name: 'auditd', + }, + ]; + const query = buildMatch({ + operator: 'included', + field: 'host.name', + values, + language: 'kuery', + }); + + expect(query).toEqual(' and not host.name:suricata'); + }); + }); + + describe('lucene', () => { + test('it returns formatted string when operator is "included"', () => { + const values = [ + { + name: 'suricata', + }, + ]; + const query = buildMatch({ + operator: 'included', + field: 'host.name', + values, + language: 'lucene', + }); + + expect(query).toEqual(' AND NOT host.name:suricata'); + }); + + test('it returns formatted string when operator is "excluded"', () => { + const values = [ + { + name: 'suricata', + }, + ]; + const query = buildMatch({ + operator: 'excluded', + field: 'host.name', + values, + language: 'lucene', + }); + + expect(query).toEqual(' AND host.name:suricata'); + }); + + // TODO: need to clean up types and maybe restrict values to one if type is 'match' + test('it returns formatted string when "values" includes more than one item', () => { + const values = [ + { + name: 'suricata', + }, + { + name: 'auditd', + }, + ]; + const query = buildMatch({ + operator: 'included', + field: 'host.name', + values, + language: 'lucene', + }); + + expect(query).toEqual(' AND NOT host.name:suricata'); + }); + }); + }); + + describe('buildMatchAll', () => { + describe('kuery', () => { + test('it returns empty string if given an empty array for "values"', () => { + const exceptionSegment = buildMatchAll({ + operator: 'included', + field: 'host.name', + values: [], + language: 'kuery', + }); + + expect(exceptionSegment).toEqual(''); + }); + + test('it returns formatted string when "values" includes only one item', () => { + const values = [ + { + name: 'suricata', + }, + ]; + const exceptionSegment = buildMatchAll({ + operator: 'included', + field: 'host.name', + values, + language: 'kuery', + }); + + expect(exceptionSegment).toEqual(' and not host.name:suricata'); + }); + + test('it returns formatted string when operator is "included"', () => { + const values = [ + { + name: 'suricata', + }, + { + name: 'auditd', + }, + ]; + const exceptionSegment = buildMatchAll({ + operator: 'included', + field: 'host.name', + values, + language: 'kuery', + }); + + expect(exceptionSegment).toEqual(' and not host.name:(suricata or auditd)'); + }); + + test('it returns formatted string when operator is "excluded"', () => { + const values = [ + { + name: 'suricata', + }, + { + name: 'auditd', + }, + ]; + const exceptionSegment = buildMatchAll({ + operator: 'excluded', + field: 'host.name', + values, + language: 'kuery', + }); + + expect(exceptionSegment).toEqual(' and host.name:(suricata or auditd)'); + }); + }); + + describe('lucene', () => { + test('it returns formatted string when operator is "included"', () => { + const values = [ + { + name: 'suricata', + }, + { + name: 'auditd', + }, + ]; + const exceptionSegment = buildMatchAll({ + operator: 'included', + field: 'host.name', + values, + language: 'lucene', + }); + + expect(exceptionSegment).toEqual(' AND NOT host.name:(suricata OR auditd)'); + }); + + test('it returns formatted string when operator is "excluded"', () => { + const values = [ + { + name: 'suricata', + }, + { + name: 'auditd', + }, + ]; + const exceptionSegment = buildMatchAll({ + operator: 'excluded', + field: 'host.name', + values, + language: 'lucene', + }); + + expect(exceptionSegment).toEqual(' AND host.name:(suricata OR auditd)'); + }); + + test('it returns formatted string when "values" includes only one item', () => { + const values = [ + { + name: 'suricata', + }, + ]; + const exceptionSegment = buildMatchAll({ + operator: 'included', + field: 'host.name', + values, + language: 'lucene', + }); + + expect(exceptionSegment).toEqual(' AND NOT host.name:suricata'); + }); + }); + }); + + describe('evaluateValues', () => { + describe('kuery', () => { + test('it returns formatted wildcard string when "type" is "exists"', () => { + const list: List = { + values_operator: 'included', + values_type: 'exists', + field: 'host.name', + }; + const result = evaluateValues({ + list, + language: 'kuery', + }); + + expect(result).toEqual(' and not host.name:*'); + }); + + test('it returns formatted string when "type" is "match"', () => { + const list: List = { + values_operator: 'included', + values_type: 'match', + field: 'host.name', + values: [{ name: 'suricata' }], + }; + const result = evaluateValues({ + list, + language: 'kuery', + }); + + expect(result).toEqual(' and not host.name:suricata'); + }); + + test('it returns formatted string when "type" is "match_all"', () => { + const list: List = { + values_operator: 'included', + values_type: 'match_all', + field: 'host.name', + values: [ + { + name: 'suricata', + }, + { + name: 'auditd', + }, + ], + }; + + const result = evaluateValues({ + list, + language: 'kuery', + }); + + expect(result).toEqual(' and not host.name:(suricata or auditd)'); + }); + }); + + describe('lucene', () => { + describe('kuery', () => { + test('it returns formatted wildcard string when "type" is "exists"', () => { + const list: List = { + values_operator: 'included', + values_type: 'exists', + field: 'host.name', + }; + const result = evaluateValues({ + list, + language: 'lucene', + }); + + expect(result).toEqual(' AND NOT _exists_host.name'); + }); + + test('it returns formatted string when "type" is "match"', () => { + const list: List = { + values_operator: 'included', + values_type: 'match', + field: 'host.name', + values: [{ name: 'suricata' }], + }; + const result = evaluateValues({ + list, + language: 'lucene', + }); + + expect(result).toEqual(' AND NOT host.name:suricata'); + }); + + test('it returns formatted string when "type" is "match_all"', () => { + const list: List = { + values_operator: 'included', + values_type: 'match_all', + field: 'host.name', + values: [ + { + name: 'suricata', + }, + { + name: 'auditd', + }, + ], + }; + + const result = evaluateValues({ + list, + language: 'lucene', + }); + + expect(result).toEqual(' AND NOT host.name:(suricata OR auditd)'); + }); + }); + }); + }); + + describe('formatQuery', () => { + test('it returns query if "exceptions" is empty array', () => { + const formattedQuery = formatQuery({ exceptions: [], query: 'a:*', language: 'kuery' }); + + expect(formattedQuery).toEqual('a:*'); + }); + + test('it returns expected query string when single exception in array', () => { + const formattedQuery = formatQuery({ + exceptions: [' and b:(value-1 or value-2) and not c:*'], + query: 'a:*', + language: 'kuery', + }); + + expect(formattedQuery).toEqual('(a:* and b:(value-1 or value-2) and not c:*)'); + }); + + test('it returns expected query string when multiple exceptions in array', () => { + const formattedQuery = formatQuery({ + exceptions: [' and b:(value-1 or value-2) and not c:*', ' and not d:*'], + query: 'a:*', + language: 'kuery', + }); + + expect(formattedQuery).toEqual( + '(a:* and b:(value-1 or value-2) and not c:*) or (a:* and not d:*)' + ); + }); + }); + + describe('buildExceptions', () => { + test('it returns empty array if empty lists array passed in', () => { + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists: [], + }); + + expect(query).toEqual([]); + }); + + test('it returns expected query when more than one item in list', () => { + // Equal to query && !(b && !c) -> (query AND NOT b) OR (query AND c) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value-1', + }, + { + name: 'value-2', + }, + ], + }, + { + field: 'c', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'value-3', + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and not b:(value-1 or value-2)', ' and c:value-3']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list item includes nested "and" value', () => { + // Equal to query && !(b || !c) -> (query AND NOT b AND c) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value-1', + }, + { + name: 'value-2', + }, + ], + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'value-3', + }, + ], + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and not b:(value-1 or value-2) and c:value-3']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list item includes nested "and" value of empty array', () => { + // Equal to query && !(b || !c) -> (query AND NOT b AND c) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value-1', + }, + { + name: 'value-2', + }, + ], + and: [], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and not b:(value-1 or value-2)']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list item includes nested "and" value of null', () => { + // Equal to query && !(b || !c) -> (query AND NOT b AND c) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value-1', + }, + { + name: 'value-2', + }, + ], + and: undefined, + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and not b:(value-1 or value-2)']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes multiple items and nested "and" values', () => { + // Equal to query && !((b || !c) && d) -> (query AND NOT b AND c) OR (query AND NOT d) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value-1', + }, + { + name: 'value-2', + }, + ], + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'value-3', + }, + ], + }, + ], + }, + { + field: 'd', + values_operator: 'included', + values_type: 'exists', + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and not b:(value-1 or value-2) and c:value-3', ' and not d:*']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when language is "lucene"', () => { + // Equal to query && !((b || !c) && !d) -> (query AND NOT b AND c) OR (query AND d) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value-1', + }, + { + name: 'value-2', + }, + ], + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'value-3', + }, + ], + }, + ], + }, + { + field: 'e', + values_operator: 'excluded', + values_type: 'exists', + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'lucene', + lists, + }); + const expectedQuery = [' AND NOT b:(value-1 OR value-2) AND c:value-3', ' AND _exists_e']; + + expect(query).toEqual(expectedQuery); + }); + + describe('exists', () => { + test('it returns expected query when list includes single list item with values_operator of "included"', () => { + // Equal to query && !(b) -> (query AND NOT b) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'exists', + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and not b:*']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes single list item with values_operator of "excluded"', () => { + // Equal to query && !(!b) -> (query AND b) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'excluded', + values_type: 'exists', + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and b:*']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes list item with "and" values', () => { + // Equal to query && !(!b || !c) -> (query AND b AND c) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'excluded', + values_type: 'exists', + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'exists', + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and b:* and c:*']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes multiple items', () => { + // Equal to query && !((b || !c || d) && e) -> (query AND NOT b AND c AND NOT d) OR (query AND NOT e) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'exists', + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'exists', + }, + { + field: 'd', + values_operator: 'included', + values_type: 'exists', + }, + ], + }, + { + field: 'e', + values_operator: 'included', + values_type: 'exists', + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and not b:* and c:* and not d:*', ' and not e:*']; + + expect(query).toEqual(expectedQuery); + }); + }); + + describe('match', () => { + test('it returns expected query when list includes single list item with values_operator of "included"', () => { + // Equal to query && !(b) -> (query AND NOT b) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match', + values: [ + { + name: 'value', + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and not b:value']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes single list item with values_operator of "excluded"', () => { + // Equal to query && !(!b) -> (query AND b) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'value', + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and b:value']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes list item with "and" values', () => { + // Equal to query && !(!b || !c) -> (query AND b AND c) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'value', + }, + ], + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'valueC', + }, + ], + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and b:value and c:valueC']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes multiple items', () => { + // Equal to query && !((b || !c || d) && e) -> (query AND NOT b AND c AND NOT d) OR (query AND NOT e) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match', + values: [ + { + name: 'value', + }, + ], + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'valueC', + }, + ], + }, + { + field: 'd', + values_operator: 'included', + values_type: 'match', + values: [ + { + name: 'valueC', + }, + ], + }, + ], + }, + { + field: 'e', + values_operator: 'included', + values_type: 'match', + values: [ + { + name: 'valueC', + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [ + ' and not b:value and c:valueC and not d:valueC', + ' and not e:valueC', + ]; + + expect(query).toEqual(expectedQuery); + }); + }); + + describe('match_all', () => { + test('it returns expected query when list includes single list item with values_operator of "included"', () => { + // Equal to query && !(b) -> (query AND NOT b) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value', + }, + { + name: 'value-1', + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and not b:(value or value-1)']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes single list item with values_operator of "excluded"', () => { + // Equal to query && !(!b) -> (query AND b) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'excluded', + values_type: 'match_all', + values: [ + { + name: 'value', + }, + { + name: 'value-1', + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and b:(value or value-1)']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes list item with "and" values', () => { + // Equal to query && !(!b || c) -> (query AND b AND NOT c) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'excluded', + values_type: 'match_all', + values: [ + { + name: 'value', + }, + { + name: 'value-1', + }, + ], + and: [ + { + field: 'c', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'valueC', + }, + { + name: 'value-2', + }, + ], + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [' and b:(value or value-1) and not c:(valueC or value-2)']; + + expect(query).toEqual(expectedQuery); + }); + + test('it returns expected query when list includes multiple items', () => { + // Equal to query && !((b || !c || d) && e) -> ((query AND NOT b AND c AND NOT d) OR (query AND NOT e) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value', + }, + { + name: 'value-1', + }, + ], + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'match_all', + values: [ + { + name: 'valueC', + }, + { + name: 'value-2', + }, + ], + }, + { + field: 'd', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'valueD', + }, + { + name: 'value-3', + }, + ], + }, + ], + }, + { + field: 'e', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'valueE', + }, + { + name: 'value-4', + }, + ], + }, + ]; + const query = buildExceptions({ + query: 'a:*', + language: 'kuery', + lists, + }); + const expectedQuery = [ + ' and not b:(value or value-1) and c:(valueC or value-2) and not d:(valueD or value-3)', + ' and not e:(valueE or value-4)', + ]; + + expect(query).toEqual(expectedQuery); + }); + }); + }); + + describe('buildQueryExceptions', () => { + test('it returns original query if no lists exist', () => { + const query = buildQueryExceptions({ + query: 'host.name: *', + language: 'kuery', + lists: undefined, + }); + const expectedQuery = 'host.name: *'; + + expect(query).toEqual([{ query: expectedQuery, language: 'kuery' }]); + }); + + test('it returns original query if lists is empty array', () => { + const query = buildQueryExceptions({ query: 'host.name: *', language: 'kuery', lists: [] }); + const expectedQuery = 'host.name: *'; + + expect(query).toEqual([{ query: expectedQuery, language: 'kuery' }]); + }); + + test('it returns original query if lists is null', () => { + const query = buildQueryExceptions({ query: 'host.name: *', language: 'kuery', lists: null }); + const expectedQuery = 'host.name: *'; + + expect(query).toEqual([{ query: expectedQuery, language: 'kuery' }]); + }); + + test('it returns original query if lists is undefined', () => { + const query = buildQueryExceptions({ + query: 'host.name: *', + language: 'kuery', + lists: undefined, + }); + const expectedQuery = 'host.name: *'; + + expect(query).toEqual([{ query: expectedQuery, language: 'kuery' }]); + }); + + test('it returns expected query when lists exist and language is "kuery"', () => { + // Equal to query && !((b || !c || d) && e) -> ((query AND NOT b AND c AND NOT d) OR (query AND NOT e) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value', + }, + { + name: 'value-1', + }, + ], + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'match_all', + values: [ + { + name: 'valueC', + }, + { + name: 'value-2', + }, + ], + }, + { + field: 'd', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'valueD', + }, + { + name: 'value-3', + }, + ], + }, + ], + }, + { + field: 'e', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'valueE', + }, + { + name: 'value-4', + }, + ], + }, + ]; + const query = buildQueryExceptions({ query: 'a:*', language: 'kuery', lists }); + const expectedQuery = + '(a:* and not b:(value or value-1) and c:(valueC or value-2) and not d:(valueD or value-3)) or (a:* and not e:(valueE or value-4))'; + + expect(query).toEqual([{ query: expectedQuery, language: 'kuery' }]); + }); + + test('it returns expected query when lists exist and language is "lucene"', () => { + // Equal to query && !((b || !c || d) && e) -> ((query AND NOT b AND c AND NOT d) OR (query AND NOT e) + // https://www.dcode.fr/boolean-expressions-calculator + const lists: List[] = [ + { + field: 'b', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'value', + }, + { + name: 'value-1', + }, + ], + and: [ + { + field: 'c', + values_operator: 'excluded', + values_type: 'match_all', + values: [ + { + name: 'valueC', + }, + { + name: 'value-2', + }, + ], + }, + { + field: 'd', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'valueD', + }, + { + name: 'value-3', + }, + ], + }, + ], + }, + { + field: 'e', + values_operator: 'included', + values_type: 'match_all', + values: [ + { + name: 'valueE', + }, + { + name: 'value-4', + }, + ], + }, + ]; + const query = buildQueryExceptions({ query: 'a:*', language: 'lucene', lists }); + const expectedQuery = + '(a:* AND NOT b:(value OR value-1) AND c:(valueC OR value-2) AND NOT d:(valueD OR value-3)) OR (a:* AND NOT e:(valueE OR value-4))'; + + expect(query).toEqual([{ query: expectedQuery, language: 'lucene' }]); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_exceptions_query.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_exceptions_query.ts new file mode 100644 index 0000000000000..21d1524796649 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/build_exceptions_query.ts @@ -0,0 +1,203 @@ +/* + * 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 { Query } from '../../../../../../../../src/plugins/data/server'; +import { List, ListOperator, ListValues } from '../routes/schemas/types/lists_default_array'; +import { RuleAlertParams, Language } from '../types'; + +type Operators = 'and' | 'or' | 'not'; +type LuceneOperators = 'AND' | 'OR' | 'NOT'; + +export const getLanguageBooleanOperator = ({ + language, + value, +}: { + language: Language; + value: Operators; +}): Operators | LuceneOperators => { + switch (language) { + case 'lucene': + const luceneValues: Record = { and: 'AND', or: 'OR', not: 'NOT' }; + + return luceneValues[value]; + case 'kuery': + return value; + default: + return value; + } +}; + +export const operatorBuilder = ({ + operator, + language, +}: { + operator: ListOperator; + language: Language; +}): string => { + const and = getLanguageBooleanOperator({ + language, + value: 'and', + }); + const or = getLanguageBooleanOperator({ + language, + value: 'not', + }); + + switch (operator) { + case 'excluded': + return ` ${and} `; + case 'included': + return ` ${and} ${or} `; + default: + return ''; + } +}; + +export const buildExists = ({ + operator, + field, + language, +}: { + operator: ListOperator; + field: string; + language: Language; +}): string => { + const exceptionOperator = operatorBuilder({ operator, language }); + + switch (language) { + case 'kuery': + return `${exceptionOperator}${field}:*`; + case 'lucene': + return `${exceptionOperator}_exists_${field}`; + default: + return ''; + } +}; + +export const buildMatch = ({ + operator, + field, + values, + language, +}: { + operator: ListOperator; + field: string; + values: ListValues[]; + language: Language; +}): string => { + if (values.length > 0) { + const exceptionOperator = operatorBuilder({ operator, language }); + const [exception] = values; + + return `${exceptionOperator}${field}:${exception.name}`; + } else { + return ''; + } +}; + +export const buildMatchAll = ({ + operator, + field, + values, + language, +}: { + operator: ListOperator; + field: string; + values: ListValues[]; + language: Language; +}): string => { + switch (values.length) { + case 0: + return ''; + case 1: + return buildMatch({ operator, field, values, language }); + default: + const or = getLanguageBooleanOperator({ language, value: 'or' }); + const exceptionOperator = operatorBuilder({ operator, language }); + const matchAllValues = values.map(value => { + return value.name; + }); + + return `${exceptionOperator}${field}:(${matchAllValues.join(` ${or} `)})`; + } +}; + +export const evaluateValues = ({ list, language }: { list: List; language: Language }): string => { + const { values_operator: operator, values_type: type, field, values } = list; + switch (type) { + case 'exists': + return buildExists({ operator, field, language }); + case 'match': + return buildMatch({ operator, field, values: values ?? [], language }); + case 'match_all': + return buildMatchAll({ operator, field, values: values ?? [], language }); + default: + return ''; + } +}; + +export const formatQuery = ({ + exceptions, + query, + language, +}: { + exceptions: string[]; + query: string; + language: Language; +}): string => { + if (exceptions.length > 0) { + const or = getLanguageBooleanOperator({ language, value: 'or' }); + const formattedExceptions = exceptions.map(exception => { + return `(${query}${exception})`; + }); + + return formattedExceptions.join(` ${or} `); + } else { + return query; + } +}; + +export const buildExceptions = ({ + query, + lists, + language, +}: { + query: string; + lists: List[]; + language: Language; +}): string[] => { + return lists.reduce((accum, listItem) => { + const { and, ...exceptionDetails } = { ...listItem }; + const andExceptionsSegments = and ? buildExceptions({ query, lists: and, language }) : []; + const exceptionSegment = evaluateValues({ list: exceptionDetails, language }); + const exception = [...exceptionSegment, ...andExceptionsSegments]; + + return [...accum, exception.join('')]; + }, []); +}; + +export const buildQueryExceptions = ({ + query, + language, + lists, +}: { + query: string; + language: Language; + lists: RuleAlertParams['lists']; +}): Query[] => { + if (lists && lists !== null) { + const exceptions = buildExceptions({ lists, language, query }); + const formattedQuery = formatQuery({ exceptions, language, query }); + + return [ + { + query: formattedQuery, + language, + }, + ]; + } else { + return [{ query, language }]; + } +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_filter.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_filter.test.ts index 510667b211d25..c34a0010574af 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_filter.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_filter.test.ts @@ -35,7 +35,7 @@ describe('get_filter', () => { describe('getQueryFilter', () => { test('it should work with an empty filter as kuery', () => { - const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*']); + const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], []); expect(esQuery).toEqual({ bool: { must: [], @@ -60,7 +60,7 @@ describe('get_filter', () => { }); test('it should work with an empty filter as lucene', () => { - const esQuery = getQueryFilter('host.name: linux', 'lucene', [], ['auditbeat-*']); + const esQuery = getQueryFilter('host.name: linux', 'lucene', [], ['auditbeat-*'], []); expect(esQuery).toEqual({ bool: { must: [ @@ -102,7 +102,8 @@ describe('get_filter', () => { }, }, ], - ['auditbeat-*'] + ['auditbeat-*'], + [] ); expect(esQuery).toEqual({ bool: { @@ -145,7 +146,8 @@ describe('get_filter', () => { }, }, ], - ['auditbeat-*'] + ['auditbeat-*'], + [] ); expect(esQuery).toEqual({ bool: { @@ -194,7 +196,8 @@ describe('get_filter', () => { 'host.name: windows', 'kuery', [query, exists], - ['auditbeat-*'] + ['auditbeat-*'], + [] ); expect(esQuery).toEqual({ bool: { @@ -252,7 +255,8 @@ describe('get_filter', () => { }, }, ], - ['auditbeat-*'] + ['auditbeat-*'], + [] ); expect(esQuery).toEqual({ bool: { @@ -300,7 +304,8 @@ describe('get_filter', () => { }, }, ], - ['auditbeat-*'] + ['auditbeat-*'], + [] ); expect(esQuery).toEqual({ bool: { @@ -349,7 +354,8 @@ describe('get_filter', () => { }, }, ], - ['auditbeat-*'] + ['auditbeat-*'], + [] ); expect(esQuery).toEqual({ bool: { @@ -368,6 +374,108 @@ describe('get_filter', () => { }, }); }); + + test('it should work with a list', () => { + const esQuery = getQueryFilter( + 'host.name: linux', + 'kuery', + [], + ['auditbeat-*'], + [ + { + field: 'event.module', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'suricata', + }, + ], + }, + ] + ); + expect(esQuery).toEqual({ + bool: { + filter: [ + { + bool: { + filter: [ + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'host.name': 'linux', + }, + }, + ], + }, + }, + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'event.module': 'suricata', + }, + }, + ], + }, + }, + ], + }, + }, + ], + must: [], + must_not: [], + should: [], + }, + }); + }); + + test('it should work with an empty list', () => { + const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], []); + expect(esQuery).toEqual({ + bool: { + filter: [ + { bool: { minimum_should_match: 1, should: [{ match: { 'host.name': 'linux' } }] } }, + ], + must: [], + must_not: [], + should: [], + }, + }); + }); + + test('it should work when lists has value null', () => { + const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], null); + expect(esQuery).toEqual({ + bool: { + filter: [ + { bool: { minimum_should_match: 1, should: [{ match: { 'host.name': 'linux' } }] } }, + ], + must: [], + must_not: [], + should: [], + }, + }); + }); + + test('it should work when lists has value undefined', () => { + const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], undefined); + expect(esQuery).toEqual({ + bool: { + filter: [ + { bool: { minimum_should_match: 1, should: [{ match: { 'host.name': 'linux' } }] } }, + ], + must: [], + must_not: [], + should: [], + }, + }); + }); }); describe('getFilter', () => { @@ -380,6 +488,7 @@ describe('get_filter', () => { savedId: undefined, services: servicesMock, index: ['auditbeat-*'], + lists: undefined, }); expect(filter).toEqual({ bool: { @@ -414,6 +523,7 @@ describe('get_filter', () => { savedId: undefined, services: servicesMock, index: ['auditbeat-*'], + lists: undefined, }) ).rejects.toThrow('query, filters, and index parameter should be defined'); }); @@ -428,6 +538,7 @@ describe('get_filter', () => { savedId: undefined, services: servicesMock, index: ['auditbeat-*'], + lists: undefined, }) ).rejects.toThrow('query, filters, and index parameter should be defined'); }); @@ -442,6 +553,7 @@ describe('get_filter', () => { savedId: undefined, services: servicesMock, index: undefined, + lists: undefined, }) ).rejects.toThrow('query, filters, and index parameter should be defined'); }); @@ -455,6 +567,7 @@ describe('get_filter', () => { savedId: 'some-id', services: servicesMock, index: ['auditbeat-*'], + lists: undefined, }); expect(filter).toEqual({ bool: { @@ -478,6 +591,7 @@ describe('get_filter', () => { savedId: undefined, services: servicesMock, index: ['auditbeat-*'], + lists: undefined, }) ).rejects.toThrow('savedId parameter should be defined'); }); @@ -492,6 +606,7 @@ describe('get_filter', () => { savedId: 'some-id', services: servicesMock, index: undefined, + lists: undefined, }) ).rejects.toThrow('savedId parameter should be defined'); }); @@ -506,6 +621,7 @@ describe('get_filter', () => { savedId: 'some-id', services: servicesMock, index: undefined, + lists: undefined, }) ).rejects.toThrow('Unsupported Rule of type "machine_learning" supplied to getFilter'); }); @@ -515,7 +631,8 @@ describe('get_filter', () => { '(event.module:suricata and event.kind:alert) and suricata.eve.alert.signature_id: (2610182 or 2610183 or 2610184 or 2610185 or 2610186 or 2610187)', 'kuery', [], - ['my custom index'] + ['my custom index'], + [] ); expect(esQuery).toEqual({ bool: { @@ -644,5 +761,68 @@ describe('get_filter', () => { }, }); }); + + test('returns a query when given a list', async () => { + const filter = await getFilter({ + type: 'query', + filters: undefined, + language: 'kuery', + query: 'host.name: siem', + savedId: undefined, + services: servicesMock, + index: ['auditbeat-*'], + lists: [ + { + field: 'event.module', + values_operator: 'excluded', + values_type: 'match', + values: [ + { + name: 'suricata', + }, + ], + }, + ], + }); + expect(filter).toEqual({ + bool: { + filter: [ + { + bool: { + filter: [ + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'host.name': 'siem', + }, + }, + ], + }, + }, + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'event.module': 'suricata', + }, + }, + ], + }, + }, + ], + }, + }, + ], + must: [], + must_not: [], + should: [], + }, + }); + }); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_filter.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_filter.ts index 82a50222dc351..e900f78609e1e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_filter.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_filter.ts @@ -13,21 +13,24 @@ import { esFilters, IIndexPattern, } from '../../../../../../../../src/plugins/data/server'; -import { PartialFilter, RuleAlertParams } from '../types'; +import { PartialFilter, RuleAlertParams, Language } from '../types'; import { BadRequestError } from '../errors/bad_request_error'; +import { buildQueryExceptions } from './build_exceptions_query'; export const getQueryFilter = ( query: string, - language: string, + language: Language, filters: PartialFilter[], - index: string[] + index: string[], + lists: RuleAlertParams['lists'] ) => { const indexPattern = { fields: [], title: index.join(), } as IIndexPattern; - const queries: Query[] = [{ query, language }]; + const queries: Query[] = buildQueryExceptions({ query, language, lists }); + const config = { allowLeadingWildcards: true, queryStringOptions: { analyze_wildcard: true }, @@ -45,18 +48,19 @@ export const getQueryFilter = ( interface GetFilterArgs { type: RuleAlertParams['type']; filters: PartialFilter[] | undefined | null; - language: string | undefined | null; + language: Language | undefined | null; query: string | undefined | null; savedId: string | undefined | null; services: AlertServices; index: string[] | undefined | null; + lists: RuleAlertParams['lists']; } interface QueryAttributes { // NOTE: doesn't match Query interface query: { query: string; - language: string; + language: Language; }; filters: PartialFilter[]; } @@ -69,11 +73,12 @@ export const getFilter = async ({ services, type, query, + lists, }: GetFilterArgs): Promise => { switch (type) { case 'query': { if (query != null && language != null && index != null) { - return getQueryFilter(query, language, filters || [], index); + return getQueryFilter(query, language, filters || [], index, lists); } else { throw new BadRequestError('query, filters, and index parameter should be defined'); } @@ -90,13 +95,14 @@ export const getFilter = async ({ savedObject.attributes.query.query, savedObject.attributes.query.language, savedObject.attributes.filters, - index + index, + lists ); } catch (err) { // saved object does not exist, so try and fall back if the user pushed // any additional language, query, filters, etc... if (query != null && language != null && index != null) { - return getQueryFilter(query, language, filters || [], index); + return getQueryFilter(query, language, filters || [], index, lists); } else { // user did not give any additional fall back mechanism for generating a rule // rethrow error for activity monitoring diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 0357f906f8035..efb1338fd480e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -66,6 +66,7 @@ export const signalRulesAlertType = ({ query, to, type, + lists, } = params; const searchAfterSize = Math.min(maxSignals, DEFAULT_SEARCH_AFTER_PAGE_SIZE); let hasError: boolean = false; @@ -200,6 +201,7 @@ export const signalRulesAlertType = ({ savedId, services, index: inputIndex, + lists, }); const noReIndex = buildEventsSearchQuery({ diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/types.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/types.ts index 035f1b10ff8b2..d87c226bf957a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/types.ts @@ -24,7 +24,7 @@ export interface ThreatParams { technique: IMitreAttack[]; } -// Notice below we are using lists: ListsDefaultArraySchema[]; which is coming directly from the response output section. +// Notice below we are using lists: ListsAndArraySchema[]; which is coming directly from the response output section. // TODO: Eventually this whole RuleAlertParams will be replaced with io-ts. For now we can slowly strangle it out and reduce duplicate types // We don't have the input types defined through io-ts just yet but as we being introducing types from there we will more and more remove // types and share them between input and output schema but have an input Rule Schema and an output Rule Schema. @@ -34,6 +34,8 @@ export interface Meta { kibana_siem_app_url?: string | undefined; } +export type Language = 'kuery' | 'lucene'; + export interface RuleAlertParams { actions: RuleAlertAction[]; anomalyThreshold: number | undefined; @@ -47,7 +49,7 @@ export interface RuleAlertParams { index: string[] | undefined | null; interval: string; ruleId: string | undefined | null; - language: string | undefined | null; + language: Language | undefined | null; maxSignals: number; machineLearningJobId: string | undefined; riskScore: number; From c57121ba79cd30f632b7a40d66d1bbc92c1300f5 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Fri, 17 Apr 2020 16:05:46 +0200 Subject: [PATCH 12/22] Relax error requirement of ECONNREFUSED (#63835) Also added a test for the different errors that could occur at a lower network level. --- .../proxy_route/proxy_fallback.test.ts | 64 +++++++++++++++++++ .../api/console/proxy/create_handler.ts | 5 +- 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 src/plugins/console/server/__tests__/proxy_route/proxy_fallback.test.ts diff --git a/src/plugins/console/server/__tests__/proxy_route/proxy_fallback.test.ts b/src/plugins/console/server/__tests__/proxy_route/proxy_fallback.test.ts new file mode 100644 index 0000000000000..b226bad11a01a --- /dev/null +++ b/src/plugins/console/server/__tests__/proxy_route/proxy_fallback.test.ts @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { duration } from 'moment'; +import { getProxyRouteHandlerDeps } from './mocks'; + +import { kibanaResponseFactory } from '../../../../../core/server'; +import { createHandler } from '../../routes/api/console/proxy/create_handler'; +import * as requestModule from '../../lib/proxy_request'; + +describe('Console Proxy Route', () => { + afterEach(async () => { + jest.resetAllMocks(); + }); + + describe('fallback behaviour', () => { + it('falls back to all configured endpoints regardless of error', async () => { + // Describe a situation where all three configured nodes reject + (requestModule.proxyRequest as jest.Mock).mockRejectedValueOnce(new Error('ECONNREFUSED')); + (requestModule.proxyRequest as jest.Mock).mockRejectedValueOnce(new Error('EHOSTUNREACH')); + (requestModule.proxyRequest as jest.Mock).mockRejectedValueOnce(new Error('ESOCKETTIMEDOUT')); + + const handler = createHandler( + getProxyRouteHandlerDeps({ + readLegacyESConfig: () => ({ + requestTimeout: duration(30000), + customHeaders: {}, + requestHeadersWhitelist: [], + hosts: ['http://localhost:9201', 'http://localhost:9202', 'http://localhost:9203'], + }), + }) + ); + + const response = await handler( + {} as any, + { + headers: {}, + query: { method: 'get', path: 'test' }, + } as any, + kibanaResponseFactory + ); + + expect(response.status).toBe(502); + // Return the message from the ES node we attempted last. + expect(response.payload.message).toBe('ESOCKETTIMEDOUT'); + }); + }); +}); diff --git a/src/plugins/console/server/routes/api/console/proxy/create_handler.ts b/src/plugins/console/server/routes/api/console/proxy/create_handler.ts index 50a9fcf03c209..9446289ff03ea 100644 --- a/src/plugins/console/server/routes/api/console/proxy/create_handler.ts +++ b/src/plugins/console/server/routes/api/console/proxy/create_handler.ts @@ -175,10 +175,9 @@ export const createHandler = ({ break; } catch (e) { + // If we reached here it means we hit a lower level network issue than just, for e.g., a 500. + // We try contacting another node in that case. log.error(e); - if (e.code !== 'ECONNREFUSED') { - return response.internalError(e); - } if (idx === hosts.length - 1) { log.warn(`Could not connect to any configured ES node [${hosts.join(', ')}]`); return response.customError({ From 7e7884e01fdb3922a324ca9faa77a6b6899b6e5f Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 17 Apr 2020 07:37:50 -0700 Subject: [PATCH 13/22] Add body validation to update follower index API endpoint. (#63653) --- .../public/np_ready/app/services/api.js | 28 ++++++++++- .../np_ready/routes/api/follower_index.ts | 12 +++++ .../follower_indices.helpers.js | 48 ++++++++++++++++++- .../follower_indices.js | 26 ++++++++++ 4 files changed, 112 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js index b50c36aa8df9f..24bc7e17356e2 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js @@ -145,9 +145,35 @@ export const updateFollowerIndex = (id, followerIndex) => { if (isUsingAdvancedSettings) { uiMetrics.push(UIM_FOLLOWER_INDEX_USE_ADVANCED_OPTIONS); } + + const { + maxReadRequestOperationCount, + maxOutstandingReadRequests, + maxReadRequestSize, + maxWriteRequestOperationCount, + maxWriteRequestSize, + maxOutstandingWriteRequests, + maxWriteBufferCount, + maxWriteBufferSize, + maxRetryDelay, + readPollTimeout, + } = followerIndex; + const request = httpClient.put(`${API_BASE_PATH}/follower_indices/${encodeURIComponent(id)}`, { - body: JSON.stringify(followerIndex), + body: JSON.stringify({ + maxReadRequestOperationCount, + maxOutstandingReadRequests, + maxReadRequestSize, + maxWriteRequestOperationCount, + maxWriteRequestSize, + maxOutstandingWriteRequests, + maxWriteBufferCount, + maxWriteBufferSize, + maxRetryDelay, + readPollTimeout, + }), }); + return trackUserRequest(request, uiMetrics); }; diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts index 3896e1c02c915..1d7dacf4a8688 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts +++ b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts @@ -164,6 +164,18 @@ export const registerFollowerIndexRoutes = ({ router, __LEGACY }: RouteDependenc path: `${API_BASE_PATH}/follower_indices/{id}`, validate: { params: schema.object({ id: schema.string() }), + body: schema.object({ + maxReadRequestOperationCount: schema.maybe(schema.number()), + maxOutstandingReadRequests: schema.maybe(schema.number()), + maxReadRequestSize: schema.maybe(schema.string()), // byte value + maxWriteRequestOperationCount: schema.maybe(schema.number()), + maxWriteRequestSize: schema.maybe(schema.string()), // byte value + maxOutstandingWriteRequests: schema.maybe(schema.number()), + maxWriteBufferCount: schema.maybe(schema.number()), + maxWriteBufferSize: schema.maybe(schema.string()), // byte value + maxRetryDelay: schema.maybe(schema.string()), // time value + readPollTimeout: schema.maybe(schema.string()), // time value + }), }, }, licensePreRoutingFactory({ diff --git a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.helpers.js b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.helpers.js index dbcb6bf819749..294db29f6dce4 100644 --- a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.helpers.js +++ b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.helpers.js @@ -13,7 +13,45 @@ export const registerHelpers = supertest => { const loadFollowerIndices = () => supertest.get(`${API_BASE_PATH}/follower_indices`); - const getFollowerIndex = name => supertest.get(`${API_BASE_PATH}/follower_indices/${name}`); + const getFollowerIndex = (name, waitUntilIsActive = false) => { + const maxRetries = 10; + const delayBetweenRetries = 500; + let retryCount = 0; + + const proceed = async () => { + const response = await supertest.get(`${API_BASE_PATH}/follower_indices/${name}`); + + if (waitUntilIsActive && response.body.status !== 'active') { + retryCount += 1; + + if (retryCount > maxRetries) { + throw new Error('Error waiting for follower index to be active.'); + } + + return new Promise(resolve => setTimeout(resolve, delayBetweenRetries)).then(proceed); + } + + return response; + }; + + return { + expect: status => + new Promise((resolve, reject) => + proceed() + .then(response => { + if (status !== response.status) { + reject(new Error(`Expected status ${status} but got ${response.status}`)); + } + return resolve(response); + }) + .catch(reject) + ), + then: (resolve, reject) => + proceed() + .then(resolve) + .catch(reject), + }; + }; const createFollowerIndex = (name = getRandomString(), payload = getFollowerIndexPayload()) => { followerIndicesCreated.push(name); @@ -24,6 +62,13 @@ export const registerHelpers = supertest => { .send({ ...payload, name }); }; + const updateFollowerIndex = (name, payload) => { + return supertest + .put(`${API_BASE_PATH}/follower_indices/${name}`) + .set('kbn-xsrf', 'xxx') + .send(payload); + }; + const unfollowLeaderIndex = followerIndex => { const followerIndices = Array.isArray(followerIndex) ? followerIndex : [followerIndex]; const followerIndicesToEncodedString = followerIndices @@ -51,6 +96,7 @@ export const registerHelpers = supertest => { loadFollowerIndices, getFollowerIndex, createFollowerIndex, + updateFollowerIndex, unfollowAll, }; }; diff --git a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js index 5f9ebbd2a0a3f..eabf474120f2b 100644 --- a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js +++ b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js @@ -21,6 +21,7 @@ export default function({ getService }) { loadFollowerIndices, getFollowerIndex, createFollowerIndex, + updateFollowerIndex, unfollowAll, } = registerFollowerIndicesnHelpers(supertest); @@ -92,6 +93,31 @@ export default function({ getService }) { }); }); + describe('update()', () => { + it('should update a follower index advanced settings', async () => { + // Create a follower index + const leaderIndex = await createIndex(); + const followerIndex = getRandomString(); + const initialValue = 1234; + const payload = getFollowerIndexPayload(leaderIndex, undefined, { + maxReadRequestOperationCount: initialValue, + }); + await createFollowerIndex(followerIndex, payload); + + // Verify that its advanced settings are correctly set + const { body } = await getFollowerIndex(followerIndex, true); + expect(body.maxReadRequestOperationCount).to.be(initialValue); + + // Update the follower index + const updatedValue = 7777; + await updateFollowerIndex(followerIndex, { maxReadRequestOperationCount: updatedValue }); + + // Verify that the advanced settings are updated + const { body: updatedBody } = await getFollowerIndex(followerIndex, true); + expect(updatedBody.maxReadRequestOperationCount).to.be(updatedValue); + }); + }); + describe('Advanced settings', () => { it('hard-coded values should match Elasticsearch default values', async () => { /** From cf7da3cdb710ba7a0c133f93809ae78135d79e86 Mon Sep 17 00:00:00 2001 From: Radu Gheorghe Date: Fri, 17 Apr 2020 18:01:30 +0300 Subject: [PATCH 14/22] Add headers to the sample curl (#63548) * Add headers to the sample curl At least in 7.x it doesn't work without the kbn-xsrf and json headers. * More headers to curl commands Co-authored-by: Elastic Machine --- docs/api/saved-objects/create.asciidoc | 4 ++-- docs/api/saved-objects/export.asciidoc | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/api/saved-objects/create.asciidoc b/docs/api/saved-objects/create.asciidoc index dc010c80fd012..571b57a5ef9c2 100644 --- a/docs/api/saved-objects/create.asciidoc +++ b/docs/api/saved-objects/create.asciidoc @@ -57,12 +57,12 @@ any data that you send to the API is properly formed. [source,sh] -------------------------------------------------- -$ curl -X POST "localhost:5601/api/saved_objects/index-pattern/my-pattern" +$ curl -X POST "localhost:5601/api/saved_objects/index-pattern/my-pattern" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d ' { "attributes": { "title": "my-pattern-*" } -} +}' -------------------------------------------------- // KIBANA diff --git a/docs/api/saved-objects/export.asciidoc b/docs/api/saved-objects/export.asciidoc index e8c762b9543a1..a992d13ed9b9c 100644 --- a/docs/api/saved-objects/export.asciidoc +++ b/docs/api/saved-objects/export.asciidoc @@ -68,10 +68,10 @@ Export all index pattern saved objects: [source,sh] -------------------------------------------------- -$ curl -X POST "localhost:5601/api/saved_objects/_export" +$ curl -X POST "localhost:5601/api/saved_objects/_export" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d ' { "type": "index-pattern" -} +}' -------------------------------------------------- // KIBANA @@ -79,11 +79,11 @@ Export all index pattern saved objects and exclude the export summary from the s [source,sh] -------------------------------------------------- -$ curl -X POST "localhost:5601/api/saved_objects/_export" +$ curl -X POST "localhost:5601/api/saved_objects/_export" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d ' { "type": "index-pattern", "excludeExportDetails": true -} +}' -------------------------------------------------- // KIBANA @@ -91,7 +91,7 @@ Export a specific saved object: [source,sh] -------------------------------------------------- -$ curl -X POST "localhost:5601/api/saved_objects/_export" +$ curl -X POST "localhost:5601/api/saved_objects/_export" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d ' { "objects": [ { @@ -99,7 +99,7 @@ $ curl -X POST "localhost:5601/api/saved_objects/_export" "id": "be3733a0-9efe-11e7-acb3-3dab96693fab" } ] -} +}' -------------------------------------------------- // KIBANA @@ -107,7 +107,7 @@ Export a specific saved object and it's related objects : [source,sh] -------------------------------------------------- -$ curl -X POST "localhost:5601/api/saved_objects/_export" +$ curl -X POST "localhost:5601/api/saved_objects/_export" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d ' { "objects": [ { @@ -116,6 +116,6 @@ $ curl -X POST "localhost:5601/api/saved_objects/_export" } ], "includeReferencesDeep": true -} +}' -------------------------------------------------- // KIBANA From 3f98f0f8496f55f80f6ee4ed9a5d720d1aecf08a Mon Sep 17 00:00:00 2001 From: Devon Thomson Date: Fri, 17 Apr 2020 11:35:27 -0400 Subject: [PATCH 15/22] Duplicate panel feature (#61367) Added a new cloning feature for panels on a dashboard. --- .../actions/clone_panel_action.test.tsx | 155 ++++++++++++++++ .../actions/clone_panel_action.tsx | 158 +++++++++++++++++ .../public/application/actions/index.ts | 5 + .../embeddable/dashboard_container.tsx | 60 ++++++- .../panel/create_panel_state.test.ts | 14 +- .../embeddable/panel/create_panel_state.ts | 113 ++++-------- .../panel/dashboard_panel_placement.ts | 167 ++++++++++++++++++ .../embeddable/placeholder/index.ts | 21 +++ .../placeholder/placeholder_embeddable.tsx | 52 ++++++ .../placeholder_embeddable_factory.ts | 45 +++++ src/plugins/dashboard/public/plugin.tsx | 13 ++ .../apps/dashboard/panel_controls.js | 48 +++++ .../services/dashboard/panel_actions.js | 25 ++- 13 files changed, 783 insertions(+), 93 deletions(-) create mode 100644 src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx create mode 100644 src/plugins/dashboard/public/application/actions/clone_panel_action.tsx create mode 100644 src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts create mode 100644 src/plugins/dashboard/public/application/embeddable/placeholder/index.ts create mode 100644 src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable.tsx create mode 100644 src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable_factory.ts diff --git a/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx b/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx new file mode 100644 index 0000000000000..17943333d25b0 --- /dev/null +++ b/src/plugins/dashboard/public/application/actions/clone_panel_action.test.tsx @@ -0,0 +1,155 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { isErrorEmbeddable, IContainer } from '../../embeddable_plugin'; +import { DashboardContainer, DashboardPanelState } from '../embeddable'; +import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helpers'; +import { + CONTACT_CARD_EMBEDDABLE, + ContactCardEmbeddableFactory, + ContactCardEmbeddable, + ContactCardEmbeddableInput, + ContactCardEmbeddableOutput, +} from '../../embeddable_plugin_test_samples'; +import { coreMock } from '../../../../../core/public/mocks'; +import { CoreStart } from 'kibana/public'; +import { ClonePanelAction } from '.'; + +// eslint-disable-next-line +import { embeddablePluginMock } from 'src/plugins/embeddable/public/mocks'; + +const { setup, doStart } = embeddablePluginMock.createInstance(); +setup.registerEmbeddableFactory( + CONTACT_CARD_EMBEDDABLE, + new ContactCardEmbeddableFactory((() => null) as any, {} as any) +); +const start = doStart(); + +let container: DashboardContainer; +let embeddable: ContactCardEmbeddable; +let coreStart: CoreStart; +beforeEach(async () => { + coreStart = coreMock.createStart(); + coreStart.savedObjects.client = { + ...coreStart.savedObjects.client, + get: jest.fn().mockImplementation(() => ({ attributes: { title: 'Holy moly' } })), + find: jest.fn().mockImplementation(() => ({ total: 15 })), + create: jest.fn().mockImplementation(() => ({ id: 'brandNewSavedObject' })), + }; + + const options = { + ExitFullScreenButton: () => null, + SavedObjectFinder: () => null, + application: {} as any, + embeddable: start, + inspector: {} as any, + notifications: {} as any, + overlays: coreStart.overlays, + savedObjectMetaData: {} as any, + uiActions: {} as any, + }; + const input = getSampleDashboardInput({ + panels: { + '123': getSampleDashboardPanel({ + explicitInput: { firstName: 'Kibanana', id: '123' }, + type: CONTACT_CARD_EMBEDDABLE, + }), + }, + }); + container = new DashboardContainer(input, options); + + const contactCardEmbeddable = await container.addNewEmbeddable< + ContactCardEmbeddableInput, + ContactCardEmbeddableOutput, + ContactCardEmbeddable + >(CONTACT_CARD_EMBEDDABLE, { + firstName: 'Kibana', + }); + + if (isErrorEmbeddable(contactCardEmbeddable)) { + throw new Error('Failed to create embeddable'); + } else { + embeddable = contactCardEmbeddable; + } +}); + +test('Clone adds a new embeddable', async () => { + const dashboard = embeddable.getRoot() as IContainer; + const originalPanelCount = Object.keys(dashboard.getInput().panels).length; + const originalPanelKeySet = new Set(Object.keys(dashboard.getInput().panels)); + const action = new ClonePanelAction(coreStart); + await action.execute({ embeddable }); + expect(Object.keys(container.getInput().panels).length).toEqual(originalPanelCount + 1); + const newPanelId = Object.keys(container.getInput().panels).find( + key => !originalPanelKeySet.has(key) + ); + expect(newPanelId).toBeDefined(); + const newPanel = container.getInput().panels[newPanelId!]; + expect(newPanel.type).toEqual(embeddable.type); +}); + +test('Clones an embeddable without a saved object ID', async () => { + const dashboard = embeddable.getRoot() as IContainer; + const panel = dashboard.getInput().panels[embeddable.id] as DashboardPanelState; + const action = new ClonePanelAction(coreStart); + // @ts-ignore + const newPanel = await action.cloneEmbeddable(panel, embeddable.type); + expect(newPanel.type).toEqual(embeddable.type); +}); + +test('Clones an embeddable with a saved object ID', async () => { + const dashboard = embeddable.getRoot() as IContainer; + const panel = dashboard.getInput().panels[embeddable.id] as DashboardPanelState; + panel.explicitInput.savedObjectId = 'holySavedObjectBatman'; + const action = new ClonePanelAction(coreStart); + // @ts-ignore + const newPanel = await action.cloneEmbeddable(panel, embeddable.type); + expect(coreStart.savedObjects.client.get).toHaveBeenCalledTimes(1); + expect(coreStart.savedObjects.client.find).toHaveBeenCalledTimes(1); + expect(coreStart.savedObjects.client.create).toHaveBeenCalledTimes(1); + expect(newPanel.type).toEqual(embeddable.type); +}); + +test('Gets a unique title ', async () => { + coreStart.savedObjects.client.find = jest.fn().mockImplementation(({ search }) => { + if (search === '"testFirstTitle"') return { total: 1 }; + else if (search === '"testSecondTitle"') return { total: 41 }; + else if (search === '"testThirdTitle"') return { total: 90 }; + }); + const action = new ClonePanelAction(coreStart); + // @ts-ignore + expect(await action.getUniqueTitle('testFirstTitle', embeddable.type)).toEqual( + 'testFirstTitle (copy)' + ); + // @ts-ignore + expect(await action.getUniqueTitle('testSecondTitle (copy 39)', embeddable.type)).toEqual( + 'testSecondTitle (copy 40)' + ); + // @ts-ignore + expect(await action.getUniqueTitle('testSecondTitle (copy 20)', embeddable.type)).toEqual( + 'testSecondTitle (copy 40)' + ); + // @ts-ignore + expect(await action.getUniqueTitle('testThirdTitle', embeddable.type)).toEqual( + 'testThirdTitle (copy 89)' + ); + // @ts-ignore + expect(await action.getUniqueTitle('testThirdTitle (copy 10000)', embeddable.type)).toEqual( + 'testThirdTitle (copy 89)' + ); +}); diff --git a/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx b/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx new file mode 100644 index 0000000000000..4d15e7e899fa8 --- /dev/null +++ b/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx @@ -0,0 +1,158 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { CoreStart } from 'src/core/public'; +import uuid from 'uuid'; +import { ActionByType, IncompatibleActionError } from '../../ui_actions_plugin'; +import { ViewMode, PanelState, IEmbeddable } from '../../embeddable_plugin'; +import { SavedObject } from '../../../../saved_objects/public'; +import { PanelNotFoundError, EmbeddableInput } from '../../../../embeddable/public'; +import { + placePanelBeside, + IPanelPlacementBesideArgs, +} from '../embeddable/panel/dashboard_panel_placement'; +import { DashboardPanelState, DASHBOARD_CONTAINER_TYPE, DashboardContainer } from '..'; + +export const ACTION_CLONE_PANEL = 'clonePanel'; + +export interface ClonePanelActionContext { + embeddable: IEmbeddable; +} + +export class ClonePanelAction implements ActionByType { + public readonly type = ACTION_CLONE_PANEL; + public readonly id = ACTION_CLONE_PANEL; + public order = 11; + + constructor(private core: CoreStart) {} + + public getDisplayName({ embeddable }: ClonePanelActionContext) { + if (!embeddable.getRoot() || !embeddable.getRoot().isContainer) { + throw new IncompatibleActionError(); + } + return i18n.translate('dashboard.panel.clonePanel', { + defaultMessage: 'Clone panel', + }); + } + + public getIconType({ embeddable }: ClonePanelActionContext) { + if (!embeddable.getRoot() || !embeddable.getRoot().isContainer) { + throw new IncompatibleActionError(); + } + return 'copy'; + } + + public async isCompatible({ embeddable }: ClonePanelActionContext) { + return Boolean( + embeddable.getInput()?.viewMode !== ViewMode.VIEW && + embeddable.getRoot() && + embeddable.getRoot().isContainer && + embeddable.getRoot().type === DASHBOARD_CONTAINER_TYPE + ); + } + + public async execute({ embeddable }: ClonePanelActionContext) { + if (!embeddable.getRoot() || !embeddable.getRoot().isContainer) { + throw new IncompatibleActionError(); + } + + const dashboard = embeddable.getRoot() as DashboardContainer; + const panelToClone = dashboard.getInput().panels[embeddable.id] as DashboardPanelState; + if (!panelToClone) { + throw new PanelNotFoundError(); + } + + dashboard.showPlaceholderUntil( + this.cloneEmbeddable(panelToClone, embeddable.type), + placePanelBeside, + { + width: panelToClone.gridData.w, + height: panelToClone.gridData.h, + currentPanels: dashboard.getInput().panels, + placeBesideId: panelToClone.explicitInput.id, + } as IPanelPlacementBesideArgs + ); + } + + private async getUniqueTitle(rawTitle: string, embeddableType: string): Promise { + const clonedTag = i18n.translate('dashboard.panel.title.clonedTag', { + defaultMessage: 'copy', + }); + const cloneRegex = new RegExp(`\\(${clonedTag}\\)`, 'g'); + const cloneNumberRegex = new RegExp(`\\(${clonedTag} [0-9]+\\)`, 'g'); + const baseTitle = rawTitle + .replace(cloneNumberRegex, '') + .replace(cloneRegex, '') + .trim(); + + const similarSavedObjects = await this.core.savedObjects.client.find({ + type: embeddableType, + perPage: 0, + fields: ['title'], + searchFields: ['title'], + search: `"${baseTitle}"`, + }); + const similarBaseTitlesCount: number = similarSavedObjects.total - 1; + + return similarBaseTitlesCount <= 0 + ? baseTitle + ` (${clonedTag})` + : baseTitle + ` (${clonedTag} ${similarBaseTitlesCount})`; + } + + private async cloneEmbeddable( + panelToClone: DashboardPanelState, + embeddableType: string + ): Promise> { + const panelState: PanelState = { + type: embeddableType, + explicitInput: { + ...panelToClone.explicitInput, + id: uuid.v4(), + }, + }; + let newTitle: string = ''; + if (panelToClone.explicitInput.savedObjectId) { + // Fetch existing saved object + const savedObjectToClone = await this.core.savedObjects.client.get( + embeddableType, + panelToClone.explicitInput.savedObjectId + ); + + // Clone the saved object + newTitle = await this.getUniqueTitle(savedObjectToClone.attributes.title, embeddableType); + const clonedSavedObject = await this.core.savedObjects.client.create( + embeddableType, + { + ..._.cloneDeep(savedObjectToClone.attributes), + title: newTitle, + }, + { references: _.cloneDeep(savedObjectToClone.references) } + ); + panelState.explicitInput.savedObjectId = clonedSavedObject.id; + } + this.core.notifications.toasts.addSuccess({ + title: i18n.translate('dashboard.panel.clonedToast', { + defaultMessage: 'Cloned panel', + }), + 'data-test-subj': 'addObjectToContainerSuccess', + }); + return panelState; + } +} diff --git a/src/plugins/dashboard/public/application/actions/index.ts b/src/plugins/dashboard/public/application/actions/index.ts index 23c26dbd280f8..d7a84fb79f6af 100644 --- a/src/plugins/dashboard/public/application/actions/index.ts +++ b/src/plugins/dashboard/public/application/actions/index.ts @@ -27,3 +27,8 @@ export { ReplacePanelActionContext, ACTION_REPLACE_PANEL, } from './replace_panel_action'; +export { + ClonePanelAction, + ClonePanelActionContext, + ACTION_CLONE_PANEL, +} from './clone_panel_action'; diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx index 50089f1f061f4..8346fd900caef 100644 --- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx @@ -23,6 +23,7 @@ import { I18nProvider } from '@kbn/i18n/react'; import { RefreshInterval, TimeRange, Query, Filter } from 'src/plugins/data/public'; import { CoreStart } from 'src/core/public'; import { Start as InspectorStartContract } from 'src/plugins/inspector/public'; +import uuid from 'uuid'; import { UiActionsStart } from '../../ui_actions_plugin'; import { Container, @@ -32,6 +33,7 @@ import { EmbeddableFactory, IEmbeddable, EmbeddableStart, + PanelState, } from '../../embeddable_plugin'; import { DASHBOARD_CONTAINER_TYPE } from './dashboard_constants'; import { createPanelState } from './panel'; @@ -42,6 +44,8 @@ import { KibanaReactContext, KibanaReactContextValue, } from '../../../../kibana_react/public'; +import { PLACEHOLDER_EMBEDDABLE } from './placeholder'; +import { PanelPlacementMethod, IPanelPlacementArgs } from './panel/dashboard_panel_placement'; export interface DashboardContainerInput extends ContainerInput { viewMode: ViewMode; @@ -120,7 +124,61 @@ export class DashboardContainer extends Container = {} ): DashboardPanelState { const panelState = super.createNewPanelState(factory, partial); - return createPanelState(panelState, Object.values(this.input.panels)); + return createPanelState(panelState, this.input.panels); + } + + public showPlaceholderUntil( + newStateComplete: Promise>, + placementMethod?: PanelPlacementMethod, + placementArgs?: TPlacementMethodArgs + ): void { + const originalPanelState = { + type: PLACEHOLDER_EMBEDDABLE, + explicitInput: { + id: uuid.v4(), + disabledActions: [ + 'ACTION_CUSTOMIZE_PANEL', + 'CUSTOM_TIME_RANGE', + 'clonePanel', + 'replacePanel', + 'togglePanel', + ], + }, + } as PanelState; + const placeholderPanelState = createPanelState( + originalPanelState, + this.input.panels, + placementMethod, + placementArgs + ); + this.updateInput({ + panels: { + ...this.input.panels, + [placeholderPanelState.explicitInput.id]: placeholderPanelState, + }, + }); + newStateComplete.then((newPanelState: Partial) => { + const finalPanels = { ...this.input.panels }; + delete finalPanels[placeholderPanelState.explicitInput.id]; + const newPanelId = newPanelState.explicitInput?.id + ? newPanelState.explicitInput.id + : uuid.v4(); + finalPanels[newPanelId] = { + ...placeholderPanelState, + ...newPanelState, + gridData: { + ...placeholderPanelState.gridData, + i: newPanelId, + }, + explicitInput: { + ...newPanelState.explicitInput, + id: newPanelId, + }, + }; + this.updateInput({ + panels: finalPanels, + }); + }); } public render(dom: HTMLElement) { diff --git a/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.test.ts b/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.test.ts index 409cae8b49a53..7c11ac8a5031b 100644 --- a/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.test.ts +++ b/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.test.ts @@ -26,7 +26,7 @@ import { CONTACT_CARD_EMBEDDABLE } from '../../../embeddable_plugin_test_samples interface TestInput extends EmbeddableInput { test: string; } -const panels: DashboardPanelState[] = []; +const panels: { [key: string]: DashboardPanelState } = {}; test('createPanelState adds a new panel state in 0,0 position', () => { const panelState = createPanelState( @@ -34,7 +34,7 @@ test('createPanelState adds a new panel state in 0,0 position', () => { type: CONTACT_CARD_EMBEDDABLE, explicitInput: { test: 'hi', id: '123' }, }, - [] + panels ); expect(panelState.explicitInput.test).toBe('hi'); expect(panelState.type).toBe(CONTACT_CARD_EMBEDDABLE); @@ -44,7 +44,7 @@ test('createPanelState adds a new panel state in 0,0 position', () => { expect(panelState.gridData.h).toBe(DEFAULT_PANEL_HEIGHT); expect(panelState.gridData.w).toBe(DEFAULT_PANEL_WIDTH); - panels.push(panelState); + panels[panelState.explicitInput.id] = panelState; }); test('createPanelState adds a second new panel state', () => { @@ -58,7 +58,7 @@ test('createPanelState adds a second new panel state', () => { expect(panelState.gridData.h).toBe(DEFAULT_PANEL_HEIGHT); expect(panelState.gridData.w).toBe(DEFAULT_PANEL_WIDTH); - panels.push(panelState); + panels[panelState.explicitInput.id] = panelState; }); test('createPanelState adds a third new panel state', () => { @@ -74,17 +74,17 @@ test('createPanelState adds a third new panel state', () => { expect(panelState.gridData.h).toBe(DEFAULT_PANEL_HEIGHT); expect(panelState.gridData.w).toBe(DEFAULT_PANEL_WIDTH); - panels.push(panelState); + panels[panelState.explicitInput.id] = panelState; }); test('createPanelState adds a new panel state in the top most position', () => { - const panelsWithEmptySpace = panels.filter(panel => panel.gridData.x === 0); + delete panels['456']; const panelState = createPanelState( { type: CONTACT_CARD_EMBEDDABLE, explicitInput: { test: 'bye', id: '987' }, }, - panelsWithEmptySpace + panels ); expect(panelState.gridData.x).toBe(DEFAULT_PANEL_WIDTH); expect(panelState.gridData.y).toBe(0); diff --git a/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.ts b/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.ts index f3a48368fe1b3..79116a57869d3 100644 --- a/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.ts +++ b/src/plugins/dashboard/public/application/embeddable/panel/create_panel_state.ts @@ -19,98 +19,45 @@ import _ from 'lodash'; import { PanelState, EmbeddableInput } from '../../../embeddable_plugin'; -import { - DASHBOARD_GRID_COLUMN_COUNT, - DEFAULT_PANEL_HEIGHT, - DEFAULT_PANEL_WIDTH, -} from '../dashboard_constants'; +import { DEFAULT_PANEL_HEIGHT, DEFAULT_PANEL_WIDTH } from '../dashboard_constants'; import { DashboardPanelState } from '../types'; - -// Look for the smallest y and x value where the default panel will fit. -function findTopLeftMostOpenSpace( - width: number, - height: number, - currentPanels: DashboardPanelState[] -) { - let maxY = -1; - - currentPanels.forEach(panel => { - maxY = Math.max(panel.gridData.y + panel.gridData.h, maxY); - }); - - // Handle case of empty grid. - if (maxY < 0) { - return { x: 0, y: 0 }; - } - - const grid = new Array(maxY); - for (let y = 0; y < maxY; y++) { - grid[y] = new Array(DASHBOARD_GRID_COLUMN_COUNT).fill(0); - } - - currentPanels.forEach(panel => { - for (let x = panel.gridData.x; x < panel.gridData.x + panel.gridData.w; x++) { - for (let y = panel.gridData.y; y < panel.gridData.y + panel.gridData.h; y++) { - const row = grid[y]; - if (row === undefined) { - throw new Error( - `Attempted to access a row that doesn't exist at ${y} for panel ${JSON.stringify( - panel - )}` - ); - } - grid[y][x] = 1; - } - } - }); - - for (let y = 0; y < maxY; y++) { - for (let x = 0; x < DASHBOARD_GRID_COLUMN_COUNT; x++) { - if (grid[y][x] === 1) { - // Space is filled - continue; - } else { - for (let h = y; h < Math.min(y + height, maxY); h++) { - for (let w = x; w < Math.min(x + width, DASHBOARD_GRID_COLUMN_COUNT); w++) { - const spaceIsEmpty = grid[h][w] === 0; - const fitsPanelWidth = w === x + width - 1; - // If the panel is taller than any other panel in the current grid, it can still fit in the space, hence - // we check the minimum of maxY and the panel height. - const fitsPanelHeight = h === Math.min(y + height - 1, maxY - 1); - - if (spaceIsEmpty && fitsPanelWidth && fitsPanelHeight) { - // Found space - return { x, y }; - } else if (grid[h][w] === 1) { - // x, y spot doesn't work, break. - break; - } - } - } - } - } - } - return { x: 0, y: maxY }; -} +import { + IPanelPlacementArgs, + findTopLeftMostOpenSpace, + PanelPlacementMethod, +} from './dashboard_panel_placement'; /** * Creates and initializes a basic panel state. */ -export function createPanelState( +export function createPanelState< + TEmbeddableInput extends EmbeddableInput, + TPlacementMethodArgs extends IPanelPlacementArgs = IPanelPlacementArgs +>( panelState: PanelState, - currentPanels: DashboardPanelState[] + currentPanels: { [key: string]: DashboardPanelState }, + placementMethod?: PanelPlacementMethod, + placementArgs?: TPlacementMethodArgs ): DashboardPanelState { - const { x, y } = findTopLeftMostOpenSpace( - DEFAULT_PANEL_WIDTH, - DEFAULT_PANEL_HEIGHT, - currentPanels - ); + const defaultPlacementArgs = { + width: DEFAULT_PANEL_WIDTH, + height: DEFAULT_PANEL_HEIGHT, + currentPanels, + }; + const finalPlacementArgs = placementArgs + ? { + ...defaultPlacementArgs, + ...placementArgs, + } + : defaultPlacementArgs; + + const gridDataLocation = placementMethod + ? placementMethod(finalPlacementArgs as TPlacementMethodArgs) + : findTopLeftMostOpenSpace(defaultPlacementArgs); + return { gridData: { - w: DEFAULT_PANEL_WIDTH, - h: DEFAULT_PANEL_HEIGHT, - x, - y, + ...gridDataLocation, i: panelState.explicitInput.id, }, ...panelState, diff --git a/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts b/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts new file mode 100644 index 0000000000000..70a6c83418587 --- /dev/null +++ b/src/plugins/dashboard/public/application/embeddable/panel/dashboard_panel_placement.ts @@ -0,0 +1,167 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PanelNotFoundError } from '../../../embeddable_plugin'; +import { DashboardPanelState, GridData, DASHBOARD_GRID_COLUMN_COUNT } from '..'; + +export type PanelPlacementMethod = ( + args: PlacementArgs +) => Omit; + +export interface IPanelPlacementArgs { + width: number; + height: number; + currentPanels: { [key: string]: DashboardPanelState }; +} + +export interface IPanelPlacementBesideArgs extends IPanelPlacementArgs { + placeBesideId: string; +} + +// Look for the smallest y and x value where the default panel will fit. +export function findTopLeftMostOpenSpace({ + width, + height, + currentPanels, +}: IPanelPlacementArgs): Omit { + let maxY = -1; + + const currentPanelsArray = Object.values(currentPanels); + currentPanelsArray.forEach(panel => { + maxY = Math.max(panel.gridData.y + panel.gridData.h, maxY); + }); + + // Handle case of empty grid. + if (maxY < 0) { + return { x: 0, y: 0, w: width, h: height }; + } + + const grid = new Array(maxY); + for (let y = 0; y < maxY; y++) { + grid[y] = new Array(DASHBOARD_GRID_COLUMN_COUNT).fill(0); + } + + currentPanelsArray.forEach(panel => { + for (let x = panel.gridData.x; x < panel.gridData.x + panel.gridData.w; x++) { + for (let y = panel.gridData.y; y < panel.gridData.y + panel.gridData.h; y++) { + const row = grid[y]; + if (row === undefined) { + throw new Error( + `Attempted to access a row that doesn't exist at ${y} for panel ${JSON.stringify( + panel + )}` + ); + } + grid[y][x] = 1; + } + } + }); + + for (let y = 0; y < maxY; y++) { + for (let x = 0; x < DASHBOARD_GRID_COLUMN_COUNT; x++) { + if (grid[y][x] === 1) { + // Space is filled + continue; + } else { + for (let h = y; h < Math.min(y + height, maxY); h++) { + for (let w = x; w < Math.min(x + width, DASHBOARD_GRID_COLUMN_COUNT); w++) { + const spaceIsEmpty = grid[h][w] === 0; + const fitsPanelWidth = w === x + width - 1; + // If the panel is taller than any other panel in the current grid, it can still fit in the space, hence + // we check the minimum of maxY and the panel height. + const fitsPanelHeight = h === Math.min(y + height - 1, maxY - 1); + + if (spaceIsEmpty && fitsPanelWidth && fitsPanelHeight) { + // Found space + return { x, y, w: width, h: height }; + } else if (grid[h][w] === 1) { + // x, y spot doesn't work, break. + break; + } + } + } + } + } + } + return { x: 0, y: maxY, w: width, h: height }; +} + +interface IplacementDirection { + grid: Omit; + fits: boolean; +} + +export function placePanelBeside({ + width, + height, + currentPanels, + placeBesideId, +}: IPanelPlacementBesideArgs): Omit { + // const clonedPanels = _.cloneDeep(currentPanels); + if (!placeBesideId) { + throw new Error('Place beside method called without placeBesideId'); + } + const panelToPlaceBeside = currentPanels[placeBesideId]; + if (!panelToPlaceBeside) { + throw new PanelNotFoundError(); + } + const beside = panelToPlaceBeside.gridData; + const otherPanels: GridData[] = []; + _.forOwn(currentPanels, (panel: DashboardPanelState, key: string | undefined) => { + otherPanels.push(panel.gridData); + }); + + const possiblePlacementDirections: IplacementDirection[] = [ + { grid: { x: beside.x + beside.w, y: beside.y, w: width, h: height }, fits: true }, // right + { grid: { x: beside.x - width, y: beside.y, w: width, h: height }, fits: true }, // left + { grid: { x: beside.x, y: beside.y + beside.h, w: width, h: height }, fits: true }, // bottom + ]; + + for (const direction of possiblePlacementDirections) { + if ( + direction.grid.x >= 0 && + direction.grid.x + direction.grid.w <= DASHBOARD_GRID_COLUMN_COUNT && + direction.grid.y >= 0 + ) { + const intersection = otherPanels.some((currentPanelGrid: GridData) => { + return ( + direction.grid.x + direction.grid.w > currentPanelGrid.x && + direction.grid.x < currentPanelGrid.x + currentPanelGrid.w && + direction.grid.y < currentPanelGrid.y + currentPanelGrid.h && + direction.grid.y + direction.grid.h > currentPanelGrid.y + ); + }); + if (!intersection) { + return direction.grid; + } + } else { + direction.fits = false; + } + } + // if we get here that means there is no blank space around the panel we are placing beside. This means it's time to mess up the dashboard's groove. Fun! + const [, , bottomPlacement] = possiblePlacementDirections; + for (const currentPanelGrid of otherPanels) { + if (bottomPlacement.grid.y <= currentPanelGrid.y) { + const movedPanel = _.cloneDeep(currentPanels[currentPanelGrid.i]); + movedPanel.gridData.y = movedPanel.gridData.y + bottomPlacement.grid.h; + currentPanels[currentPanelGrid.i] = movedPanel; + } + } + return bottomPlacement.grid; +} diff --git a/src/plugins/dashboard/public/application/embeddable/placeholder/index.ts b/src/plugins/dashboard/public/application/embeddable/placeholder/index.ts new file mode 100644 index 0000000000000..7c65d50ce3fea --- /dev/null +++ b/src/plugins/dashboard/public/application/embeddable/placeholder/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './placeholder_embeddable'; +export * from './placeholder_embeddable_factory'; diff --git a/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable.tsx b/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable.tsx new file mode 100644 index 0000000000000..1a5c3386bdeda --- /dev/null +++ b/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable.tsx @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { EuiLoadingChart } from '@elastic/eui'; +import classNames from 'classnames'; +import { Embeddable, EmbeddableInput, IContainer } from '../../../embeddable_plugin'; + +export const PLACEHOLDER_EMBEDDABLE = 'placeholder'; + +export class PlaceholderEmbeddable extends Embeddable { + public readonly type = PLACEHOLDER_EMBEDDABLE; + private node?: HTMLElement; + + constructor(initialInput: EmbeddableInput, parent?: IContainer) { + super(initialInput, {}, parent); + this.input = initialInput; + } + public render(node: HTMLElement) { + if (this.node) { + ReactDOM.unmountComponentAtNode(this.node); + } + this.node = node; + + const classes = classNames('embPanel', 'embPanel-isLoading'); + ReactDOM.render( +
+ +
, + node + ); + } + + public reload() {} +} diff --git a/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable_factory.ts b/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable_factory.ts new file mode 100644 index 0000000000000..30a93989649a7 --- /dev/null +++ b/src/plugins/dashboard/public/application/embeddable/placeholder/placeholder_embeddable_factory.ts @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +import { + EmbeddableFactoryDefinition, + EmbeddableInput, + IContainer, +} from '../../../embeddable_plugin'; +import { PlaceholderEmbeddable, PLACEHOLDER_EMBEDDABLE } from './placeholder_embeddable'; + +export class PlaceholderEmbeddableFactory implements EmbeddableFactoryDefinition { + public readonly type = PLACEHOLDER_EMBEDDABLE; + + public async isEditable() { + return false; + } + + public async create(initialInput: EmbeddableInput, parent?: IContainer) { + return new PlaceholderEmbeddable(initialInput, parent); + } + + public getDisplayName() { + return i18n.translate('dashboard.placeholder.factory.displayName', { + defaultMessage: 'placeholder', + }); + } +} diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 322d734d9f39f..203c784d9df4e 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -67,9 +67,12 @@ import { ExpandPanelActionContext, ReplacePanelAction, ReplacePanelActionContext, + ClonePanelAction, + ClonePanelActionContext, ACTION_EXPAND_PANEL, ACTION_REPLACE_PANEL, RenderDeps, + ACTION_CLONE_PANEL, } from './application'; import { DashboardAppLinkGeneratorState, @@ -78,6 +81,7 @@ import { } from './url_generator'; import { createSavedDashboardLoader } from './saved_dashboards'; import { DashboardConstants } from './dashboard_constants'; +import { PlaceholderEmbeddableFactory } from './application/embeddable/placeholder'; declare module '../../share/public' { export interface UrlGeneratorStateMapping { @@ -115,6 +119,7 @@ declare module '../../../plugins/ui_actions/public' { export interface ActionContextMapping { [ACTION_EXPAND_PANEL]: ExpandPanelActionContext; [ACTION_REPLACE_PANEL]: ReplacePanelActionContext; + [ACTION_CLONE_PANEL]: ClonePanelActionContext; } } @@ -173,6 +178,9 @@ export class DashboardPlugin const factory = new DashboardContainerFactory(getStartServices); embeddable.registerEmbeddableFactory(factory.type, factory); + const placeholderFactory = new PlaceholderEmbeddableFactory(); + embeddable.registerEmbeddableFactory(placeholderFactory.type, placeholderFactory); + const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({ baseUrl: core.http.basePath.prepend('/app/kibana'), defaultSubUrl: `#${DashboardConstants.LANDING_PAGE_PATH}`, @@ -297,6 +305,11 @@ export class DashboardPlugin ); uiActions.registerAction(changeViewAction); uiActions.attachAction(CONTEXT_MENU_TRIGGER, changeViewAction); + + const clonePanelAction = new ClonePanelAction(core); + uiActions.registerAction(clonePanelAction); + uiActions.attachAction(CONTEXT_MENU_TRIGGER, clonePanelAction); + const savedDashboardLoader = createSavedDashboardLoader({ savedObjectsClient: core.savedObjects.client, indexPatterns, diff --git a/test/functional/apps/dashboard/panel_controls.js b/test/functional/apps/dashboard/panel_controls.js index 52c4a11360355..6e24b9f3570a3 100644 --- a/test/functional/apps/dashboard/panel_controls.js +++ b/test/functional/apps/dashboard/panel_controls.js @@ -113,6 +113,50 @@ export default function({ getService, getPageObjects }) { }); }); + describe('panel cloning', function() { + before(async () => { + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.timePicker.setHistoricalDataRange(); + await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); + }); + + after(async function() { + await PageObjects.dashboard.gotoDashboardLandingPage(); + }); + + it('clones a panel', async () => { + const initialPanelTitles = await PageObjects.dashboard.getPanelTitles(); + await dashboardPanelActions.clonePanelByTitle(PIE_CHART_VIS_NAME); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + const postPanelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(postPanelTitles.length).to.equal(initialPanelTitles.length + 1); + }); + + it('appends a clone title tag', async () => { + const panelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(panelTitles[1]).to.equal(PIE_CHART_VIS_NAME + ' (copy)'); + }); + + it('retains original panel dimensions', async () => { + const panelDimensions = await PageObjects.dashboard.getPanelDimensions(); + expect(panelDimensions[0]).to.eql(panelDimensions[1]); + }); + + it('gives a correct title to the clone of a clone', async () => { + const initialPanelTitles = await PageObjects.dashboard.getPanelTitles(); + const clonedPanelName = initialPanelTitles[initialPanelTitles.length - 1]; + await dashboardPanelActions.clonePanelByTitle(clonedPanelName); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + const postPanelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(postPanelTitles.length).to.equal(initialPanelTitles.length + 1); + expect(postPanelTitles[postPanelTitles.length - 1]).to.equal( + PIE_CHART_VIS_NAME + ' (copy 1)' + ); + }); + }); + describe('panel edit controls', function() { before(async () => { await PageObjects.dashboard.clickNewDashboard(); @@ -137,6 +181,7 @@ export default function({ getService, getPageObjects }) { await dashboardPanelActions.expectExistsEditPanelAction(); await dashboardPanelActions.expectExistsReplacePanelAction(); + await dashboardPanelActions.expectExistsDuplicatePanelAction(); await dashboardPanelActions.expectExistsRemovePanelAction(); }); @@ -151,6 +196,7 @@ export default function({ getService, getPageObjects }) { await dashboardPanelActions.openContextMenu(); await dashboardPanelActions.expectExistsEditPanelAction(); await dashboardPanelActions.expectExistsReplacePanelAction(); + await dashboardPanelActions.expectExistsDuplicatePanelAction(); await dashboardPanelActions.expectExistsRemovePanelAction(); // Get rid of the timestamp in the url. @@ -166,6 +212,7 @@ export default function({ getService, getPageObjects }) { await dashboardPanelActions.openContextMenu(); await dashboardPanelActions.expectMissingEditPanelAction(); await dashboardPanelActions.expectMissingReplacePanelAction(); + await dashboardPanelActions.expectMissingDuplicatePanelAction(); await dashboardPanelActions.expectMissingRemovePanelAction(); }); @@ -174,6 +221,7 @@ export default function({ getService, getPageObjects }) { await dashboardPanelActions.openContextMenu(); await dashboardPanelActions.expectExistsEditPanelAction(); await dashboardPanelActions.expectExistsReplacePanelAction(); + await dashboardPanelActions.expectExistsDuplicatePanelAction(); await dashboardPanelActions.expectMissingRemovePanelAction(); await dashboardPanelActions.clickExpandPanelToggle(); }); diff --git a/test/functional/services/dashboard/panel_actions.js b/test/functional/services/dashboard/panel_actions.js index baea2a52208c1..b155d747f3b93 100644 --- a/test/functional/services/dashboard/panel_actions.js +++ b/test/functional/services/dashboard/panel_actions.js @@ -20,6 +20,7 @@ const REMOVE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-deletePanel'; const EDIT_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-editPanel'; const REPLACE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-replacePanel'; +const CLONE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-clonePanel'; const TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-togglePanel'; const CUSTOMIZE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-ACTION_CUSTOMIZE_PANEL'; const OPEN_CONTEXT_MENU_ICON_DATA_TEST_SUBJ = 'embeddablePanelToggleMenuIcon'; @@ -97,6 +98,16 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) { await testSubjects.click(REPLACE_PANEL_DATA_TEST_SUBJ); } + async clonePanelByTitle(title) { + log.debug(`clonePanel(${title})`); + let panelOptions = null; + if (title) { + panelOptions = await this.getPanelHeading(title); + } + await this.openContextMenu(panelOptions); + await testSubjects.click(CLONE_PANEL_DATA_TEST_SUBJ); + } + async openInspectorByTitle(title) { const header = await this.getPanelHeading(title); await this.openInspector(header); @@ -123,7 +134,12 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) { } async expectExistsReplacePanelAction() { - log.debug('expectExistsEditPanelAction'); + log.debug('expectExistsReplacePanelAction'); + await testSubjects.existOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); + } + + async expectExistsDuplicatePanelAction() { + log.debug('expectExistsDuplicatePanelAction'); await testSubjects.existOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); } @@ -133,7 +149,12 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) { } async expectMissingReplacePanelAction() { - log.debug('expectMissingEditPanelAction'); + log.debug('expectMissingReplacePanelAction'); + await testSubjects.missingOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); + } + + async expectMissingDuplicatePanelAction() { + log.debug('expectMissingDuplicatePanelAction'); await testSubjects.missingOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); } From c4ddd00540d838add7bdea9faf741ad4f288cca6 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Fri, 17 Apr 2020 17:39:06 +0200 Subject: [PATCH 16/22] Add isConfigSchema typeguard and stop using `instanceof Type` checks in core (#63821) * add isConfigSchema type guard * replace instanceof checks with isConfigSchema * add dummy test plugin using a route with validation schema * remove `?.` prop access * remove test plugin * fix test description --- packages/kbn-config-schema/src/index.ts | 1 + .../kbn-config-schema/src/typeguards/index.ts | 20 +++++++ .../src/typeguards/is_config_schema.test.ts | 56 +++++++++++++++++++ .../src/typeguards/is_config_schema.ts | 24 ++++++++ packages/kbn-config-schema/src/types/type.ts | 3 + src/core/server/http/router/router.ts | 4 +- .../server/http/router/validator/validator.ts | 4 +- src/core/server/plugins/plugin.ts | 4 +- 8 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 packages/kbn-config-schema/src/typeguards/index.ts create mode 100644 packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts create mode 100644 packages/kbn-config-schema/src/typeguards/is_config_schema.ts diff --git a/packages/kbn-config-schema/src/index.ts b/packages/kbn-config-schema/src/index.ts index fc3e3c541846a..5d387f327e58f 100644 --- a/packages/kbn-config-schema/src/index.ts +++ b/packages/kbn-config-schema/src/index.ts @@ -60,6 +60,7 @@ import { export { ObjectType, TypeOf, Type }; export { ByteSizeValue } from './byte_size_value'; export { SchemaTypeError, ValidationError } from './errors'; +export { isConfigSchema } from './typeguards'; function any(options?: TypeOptions) { return new AnyType(options); diff --git a/packages/kbn-config-schema/src/typeguards/index.ts b/packages/kbn-config-schema/src/typeguards/index.ts new file mode 100644 index 0000000000000..e724878eb33e9 --- /dev/null +++ b/packages/kbn-config-schema/src/typeguards/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { isConfigSchema } from './is_config_schema'; diff --git a/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts b/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts new file mode 100644 index 0000000000000..e0ef3835ca0a3 --- /dev/null +++ b/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { schema } from '..'; +import { isConfigSchema } from './is_config_schema'; + +describe('isConfigSchema', () => { + it('returns true for every sub classes of `Type`', () => { + expect(isConfigSchema(schema.any())).toBe(true); + expect(isConfigSchema(schema.arrayOf(schema.string()))).toBe(true); + expect(isConfigSchema(schema.boolean())).toBe(true); + expect(isConfigSchema(schema.buffer())).toBe(true); + expect(isConfigSchema(schema.byteSize())).toBe(true); + expect(isConfigSchema(schema.duration())).toBe(true); + expect(isConfigSchema(schema.literal(''))).toBe(true); + expect(isConfigSchema(schema.mapOf(schema.string(), schema.number()))).toBe(true); + expect(isConfigSchema(schema.nullable(schema.string()))).toBe(true); + expect(isConfigSchema(schema.number())).toBe(true); + expect(isConfigSchema(schema.object({}))).toBe(true); + expect(isConfigSchema(schema.oneOf([schema.string()]))).toBe(true); + expect(isConfigSchema(schema.recordOf(schema.string(), schema.object({})))).toBe(true); + expect(isConfigSchema(schema.string())).toBe(true); + expect(isConfigSchema(schema.stream())).toBe(true); + }); + + it('returns false for every javascript data type', () => { + expect(isConfigSchema('foo')).toBe(false); + expect(isConfigSchema(42)).toBe(false); + expect(isConfigSchema(new Date())).toBe(false); + expect(isConfigSchema(null)).toBe(false); + expect(isConfigSchema(undefined)).toBe(false); + expect(isConfigSchema([1, 2, 3])).toBe(false); + expect(isConfigSchema({ foo: 'bar' })).toBe(false); + expect(isConfigSchema(function() {})).toBe(false); + }); + + it('returns true as long as `__isKbnConfigSchemaType` is true', () => { + expect(isConfigSchema({ __isKbnConfigSchemaType: true })).toBe(true); + }); +}); diff --git a/packages/kbn-config-schema/src/typeguards/is_config_schema.ts b/packages/kbn-config-schema/src/typeguards/is_config_schema.ts new file mode 100644 index 0000000000000..20e68ab2ead25 --- /dev/null +++ b/packages/kbn-config-schema/src/typeguards/is_config_schema.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Type } from '../types'; + +export function isConfigSchema(obj: any): obj is Type { + return obj ? obj.__isKbnConfigSchemaType === true : false; +} diff --git a/packages/kbn-config-schema/src/types/type.ts b/packages/kbn-config-schema/src/types/type.ts index 6d5ddf6b24afb..5ca16c61399e7 100644 --- a/packages/kbn-config-schema/src/types/type.ts +++ b/packages/kbn-config-schema/src/types/type.ts @@ -32,6 +32,9 @@ export abstract class Type { // sets the value to `null` while still keeping the type. public readonly type: V = null! as V; + // used for the `isConfigSchema` typeguard + public readonly __isKbnConfigSchemaType = true; + /** * Internal "schema" backed by Joi. * @type {Schema} diff --git a/src/core/server/http/router/router.ts b/src/core/server/http/router/router.ts index b4e7fc2a989b6..69402a74eda5f 100644 --- a/src/core/server/http/router/router.ts +++ b/src/core/server/http/router/router.ts @@ -20,7 +20,7 @@ import { Request, ResponseObject, ResponseToolkit } from 'hapi'; import Boom from 'boom'; -import { Type } from '@kbn/config-schema'; +import { isConfigSchema } from '@kbn/config-schema'; import { Logger } from '../../logging'; import { KibanaRequest } from './request'; import { KibanaResponseFactory, kibanaResponseFactory, IKibanaResponse } from './response'; @@ -139,7 +139,7 @@ function routeSchemasFromRouteConfig( if (route.validate !== false) { Object.entries(route.validate).forEach(([key, schema]) => { - if (!(schema instanceof Type || typeof schema === 'function')) { + if (!(isConfigSchema(schema) || typeof schema === 'function')) { throw new Error( `Expected a valid validation logic declared with '@kbn/config-schema' package or a RouteValidationFunction at key: [${key}].` ); diff --git a/src/core/server/http/router/validator/validator.ts b/src/core/server/http/router/validator/validator.ts index 97dd2bc894f81..6c766e69f0f37 100644 --- a/src/core/server/http/router/validator/validator.ts +++ b/src/core/server/http/router/validator/validator.ts @@ -17,7 +17,7 @@ * under the License. */ -import { ValidationError, Type, schema, ObjectType } from '@kbn/config-schema'; +import { ValidationError, Type, schema, ObjectType, isConfigSchema } from '@kbn/config-schema'; import { Stream } from 'stream'; import { RouteValidationError } from './validator_error'; @@ -236,7 +236,7 @@ export class RouteValidator

{ data?: unknown, namespace?: string ): RouteValidationResultType { - if (validationRule instanceof Type) { + if (isConfigSchema(validationRule)) { return validationRule.validate(data, {}, namespace); } else if (typeof validationRule === 'function') { return this.validateFunction(validationRule, data, namespace); diff --git a/src/core/server/plugins/plugin.ts b/src/core/server/plugins/plugin.ts index 7c67ab7a48df1..d7cfaa14d2343 100644 --- a/src/core/server/plugins/plugin.ts +++ b/src/core/server/plugins/plugin.ts @@ -21,7 +21,7 @@ import { join } from 'path'; import typeDetect from 'type-detect'; import { Subject } from 'rxjs'; import { first } from 'rxjs/operators'; -import { Type } from '@kbn/config-schema'; +import { isConfigSchema } from '@kbn/config-schema'; import { Logger } from '../logging'; import { @@ -150,7 +150,7 @@ export class PluginWrapper< } const configDescriptor = pluginDefinition.config; - if (!(configDescriptor.schema instanceof Type)) { + if (!isConfigSchema(configDescriptor.schema)) { throw new Error('Configuration schema expected to be an instance of Type'); } return configDescriptor; From 7efe7e88d31d3ccaf503ee2f864610b25c63165c Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 17 Apr 2020 11:50:20 -0400 Subject: [PATCH 17/22] [Uptime] Remove monitor states graphql (#62853) * WIP replacing GQL with redux/rest. * Finish implementing migration. * Introduce new connected component for ping list. * Replace GraphQL type with io-ts. * Update some broken tests. * Add test for new helper function. * Write test snapshots. * Migrate api tests from graphql to rest. * Update fixtures that rely on pings. * Move ping types to runtime_types folder with rest of io-ts files. * Update Ping type location and imports, type checking. * Remove reliance on fixtures for ping functional API tests. * Fix broken unit tests. * Fix broken types. * Remove local state storage from parent components. * Add functional test to cover Ping List functionality. * Fix monitor page functional test that was broken by merge conflicts. * Fix broken tests. * Fix broken API test. * Replace a test with a describe block that will pre-navigate all tests. * Delete unused reducer keys. * Re-introduce loading to ping list reducer. * Inroduce code that will cause PingList to re-fetch when refresh button is pressed. * Update expanded rows to support multiple concurrent expanded rows. * Modify pingList reducer to have singular optional error field. * Delete unnecessary helper code. * Delete unused interface. * Add runtime_type to parse getPings params, fix pagination index. * Add dedicated monitor type to runtime_types. * Fix broken tests. * Fix broken tests. * Rename '@timestamp' property to 'timestamp' on Ping type. * Fix broken type and key pings list table on document ID instead of timestamp. * Fix broken unit tests. * Fix broken tests and types. * Fix broken functional test. * Add REST endpoint for monitor states. * Add REST route to constants file. * Introduce io-ts typing for monitor states. * Remove remaining GraphQL types. * Update monitor states types to use io-ts types. * Add state management for monitor states. * Introduce connected monitor list component. * Fixup runtime types for monitor states. * Remove all remaining references to apollo graphql. * Update URL generator function tests to use inline snapshots instead of snapshot files. * Fix missing imports and small type issues. * Prefer inline snapshot to object literal comparison. * Add type check and console log to API response. * Update README to remove graphql references. * Fix type error. * Make monitor list refresh when global refresh button is pressed. * Fix broken types. * Rename `@timestamp` field to `timestamp`. * Change spelling of var. * Add timestamp map for `@timestamp` field in monitor states fetcher. * Remove need for `monito_states` fixture. * Write test code that allows for deletion of the `monitor_states_id_filtered` fixture. * Rewrite pagination tests to no longer rely on monitor states page fixtures. * Skip test that is causing other functional tests to fail. * Remove unused translations. * Fix broken test snapshots. * Fix stale error reporting errors. * Remove runtime validation from REST handler. Co-authored-by: Elastic Machine --- x-pack/legacy/plugins/uptime/README.md | 17 +- .../common/constants/context_defaults.ts | 2 +- .../uptime/common/constants/rest_api.ts | 1 + .../plugins/uptime/common/graphql/types.ts | 232 --- .../common/runtime_types/monitor/index.ts | 1 + .../common/runtime_types/monitor/state.ts | 145 ++ .../public/components/connected/index.ts | 1 + .../monitor/list_drawer_container.tsx | 3 +- .../connected/monitor/monitor_list.tsx | 31 + .../monitor_bar_series.test.tsx.snap | 1 - .../__tests__/monitor_bar_series.test.tsx | 13 +- .../functional/charts/monitor_bar_series.tsx | 18 +- .../public/components/functional/index.ts | 2 +- .../__snapshots__/monitor_list.test.tsx.snap | 909 +++++++--- .../monitor_list_pagination.test.tsx.snap | 307 ---- .../__tests__/monitor_list.test.tsx | 217 ++- .../monitor_list_pagination.test.tsx | 126 -- .../monitor_list_status_column.test.tsx | 47 +- .../functional/monitor_list/index.ts | 2 +- .../functional/monitor_list/monitor_list.tsx | 206 ++- .../monitor_list_drawer.test.tsx.snap | 8 +- .../__tests__/integration_group.test.tsx | 3 +- .../__tests__/monitor_list_drawer.test.tsx | 11 +- .../__tests__/monitor_status_list.test.tsx | 52 +- .../monitor_list_drawer/integration_group.tsx | 2 +- .../monitor_list_actions_popover.tsx | 2 +- .../monitor_list_drawer.tsx | 3 +- .../monitor_status_list.tsx | 2 +- .../monitor_list_status_column.tsx | 2 +- .../public/components/higher_order/index.ts | 1 - .../higher_order/uptime_graphql_query.tsx | 89 - .../framework/apollo_client_adapter.ts | 16 - .../framework/framework_adapter_types.ts | 12 - .../framework/new_platform_adapter.tsx | 2 - .../format_error_string.test.ts.snap | 7 - .../__tests__/format_error_string.test.ts | 41 - .../public/lib/helper/format_error_list.ts | 20 - .../__snapshots__/get_apm_href.test.ts.snap | 5 - .../__snapshots__/get_infra_href.test.ts.snap | 19 - .../get_logging_href.test.ts.snap | 13 - .../__tests__/get_apm_href.test.ts | 12 +- .../__tests__/get_infra_href.test.ts | 57 +- .../__tests__/get_logging_href.test.ts | 35 +- .../observability_integration/build_href.ts | 2 +- .../observability_integration/get_apm_href.ts | 2 +- .../get_infra_href.ts | 2 +- .../get_logging_href.ts | 2 +- .../lib/helper/series_has_down_values.ts | 4 +- .../legacy/plugins/uptime/public/lib/lib.ts | 8 +- .../plugins/uptime/public/pages/overview.tsx | 60 +- .../public/queries/monitor_states_query.ts | 110 -- .../uptime/public/state/actions/index.ts | 1 + .../public/state/actions/monitor_list.ts | 12 + .../public/state/actions/monitor_status.ts | 1 + .../plugins/uptime/public/state/api/index.ts | 1 + .../uptime/public/state/api/monitor_list.ts | 19 + .../uptime/public/state/effects/index.ts | 2 + .../public/state/effects/monitor_list.ts | 17 + .../uptime/public/state/reducers/index.ts | 2 + .../public/state/reducers/monitor_duration.ts | 4 +- .../public/state/reducers/monitor_list.ts | 51 + .../state/selectors/__tests__/index.test.ts | 9 + .../uptime/public/state/selectors/index.ts | 5 + .../plugins/uptime/public/uptime_app.tsx | 41 +- .../plugins/uptime/scripts/gql_gen.json | 11 - .../uptime/scripts/infer_graphql_types.js | 45 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../uptime/server/graphql/constants.ts | 7 - x-pack/plugins/uptime/server/graphql/index.ts | 17 - .../server/graphql/monitor_states/index.ts | 8 - .../graphql/monitor_states/resolvers.ts | 76 - .../graphql/monitor_states/schema.gql.ts | 183 -- .../uptime/server/graphql/pings/index.ts | 7 - .../uptime/server/graphql/pings/schema.gql.ts | 264 --- x-pack/plugins/uptime/server/graphql/types.ts | 23 - .../__tests__/parse_literal.test.ts | 42 - .../__tests__/parse_value.test.ts | 19 - .../__tests__/serialize.test.ts | 24 - .../graphql/unsigned_int_scalar/index.ts | 8 - .../graphql/unsigned_int_scalar/resolvers.ts | 51 - .../graphql/unsigned_int_scalar/schema.gql.ts | 11 - .../lib/adapters/framework/adapter_types.ts | 2 - .../framework/kibana_framework_adapter.ts | 70 - .../lib/requests/get_monitor_details.ts | 4 +- .../server/lib/requests/get_monitor_states.ts | 5 +- .../search/__tests__/fetch_page.test.ts | 51 +- .../search/__tests__/query_context.test.ts | 2 +- .../requests/search/__tests__/test_helpers.ts | 2 +- .../requests/search/enrich_monitor_groups.ts | 15 +- .../server/lib/requests/search/fetch_page.ts | 2 +- .../requests/search/find_potential_matches.ts | 2 +- .../requests/search/monitor_group_iterator.ts | 2 +- .../search/refine_potential_matches.ts | 2 +- .../server/lib/requests/search/types.ts | 2 +- .../plugins/uptime/server/rest_api/index.ts | 2 + .../uptime/server/rest_api/monitors/index.ts | 1 + .../server/rest_api/monitors/monitor_list.ts | 69 + x-pack/plugins/uptime/server/uptime_server.ts | 8 - .../apis/uptime/feature_controls.ts | 26 - .../graphql/fixtures/monitor_states.json | 1609 ----------------- .../fixtures/monitor_states_id_filtered.json | 169 -- .../fixtures/monitor_states_page_1.json | 1609 ----------------- .../fixtures/monitor_states_page_10.json | 1609 ----------------- .../monitor_states_page_10_previous.json | 1609 ----------------- .../fixtures/monitor_states_page_2.json | 1609 ----------------- .../monitor_states_page_2_previous.json | 1609 ----------------- .../fixtures/monitor_states_page_3.json | 1609 ----------------- .../monitor_states_page_3_previous.json | 1609 ----------------- .../fixtures/monitor_states_page_4.json | 1609 ----------------- .../monitor_states_page_4_previous.json | 1609 ----------------- .../fixtures/monitor_states_page_5.json | 1609 ----------------- .../monitor_states_page_5_previous.json | 1609 ----------------- .../fixtures/monitor_states_page_6.json | 1609 ----------------- .../monitor_states_page_6_previous.json | 1609 ----------------- .../fixtures/monitor_states_page_7.json | 1609 ----------------- .../monitor_states_page_7_previous.json | 1609 ----------------- .../fixtures/monitor_states_page_8.json | 1609 ----------------- .../monitor_states_page_8_previous.json | 1609 ----------------- .../fixtures/monitor_states_page_9.json | 1609 ----------------- .../monitor_states_page_9_previous.json | 1609 ----------------- .../apis/uptime/graphql/index.ts | 17 - .../apis/uptime/graphql/monitor_states.ts | 245 --- .../test/api_integration/apis/uptime/index.ts | 1 - .../apis/uptime/rest/doc_count.ts | 2 +- .../apis/uptime/rest/filters.ts | 2 +- .../{graphql => rest}/fixtures/filters.json | 0 .../fixtures/monitor_status.json | 0 .../fixtures/monitor_status_all.json | 0 .../fixtures/monitors_with_location.json | 0 .../{graphql => rest}/fixtures/snapshot.json | 0 .../fixtures/snapshot_empty.json | 0 .../fixtures/snapshot_filtered_by_down.json | 0 .../fixtures/snapshot_filtered_by_up.json | 0 .../helper}/expect_fixture_eql.ts | 6 +- .../helpers => rest/helper}/make_checks.ts | 0 .../api_integration/apis/uptime/rest/index.ts | 2 + .../apis/uptime/rest/monitor_duration.ts | 2 +- .../apis/uptime/rest/monitor_latest_status.ts | 2 +- .../uptime/rest/monitor_states_generated.ts | 193 ++ .../uptime/rest/monitor_states_real_data.ts | 525 ++++++ .../apis/uptime/rest/ping_histogram.ts | 2 +- .../apis/uptime/rest/snapshot.ts | 4 +- .../apis/uptime/rest/telemetry_collectors.ts | 2 +- .../test/functional/apps/uptime/locations.ts | 2 +- .../test/functional/apps/uptime/settings.ts | 2 +- 146 files changed, 2261 insertions(+), 35212 deletions(-) delete mode 100644 x-pack/legacy/plugins/uptime/common/graphql/types.ts create mode 100644 x-pack/legacy/plugins/uptime/common/runtime_types/monitor/state.ts create mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/monitor/monitor_list.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_pagination.test.tsx.snap delete mode 100644 x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_pagination.test.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/adapters/framework/apollo_client_adapter.ts delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/adapters/framework/framework_adapter_types.ts delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/__snapshots__/format_error_string.test.ts.snap delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/format_error_string.test.ts delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/helper/format_error_list.ts delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_apm_href.test.ts.snap delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_infra_href.test.ts.snap delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_logging_href.test.ts.snap delete mode 100644 x-pack/legacy/plugins/uptime/public/queries/monitor_states_query.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/actions/monitor_list.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/api/monitor_list.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/effects/monitor_list.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/reducers/monitor_list.ts delete mode 100644 x-pack/legacy/plugins/uptime/scripts/gql_gen.json delete mode 100644 x-pack/legacy/plugins/uptime/scripts/infer_graphql_types.js delete mode 100644 x-pack/plugins/uptime/server/graphql/constants.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/index.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/monitor_states/index.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/monitor_states/resolvers.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/pings/index.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/types.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_literal.test.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_value.test.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/serialize.test.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/index.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/resolvers.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/schema.gql.ts create mode 100644 x-pack/plugins/uptime/server/rest_api/monitors/monitor_list.ts delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_id_filtered.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_1.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_10.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_10_previous.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_2.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_2_previous.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_3.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_3_previous.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_4.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_4_previous.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_5.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_5_previous.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_6.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_6_previous.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_7.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_7_previous.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_8.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_8_previous.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_9.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_9_previous.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/index.ts delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts rename x-pack/test/api_integration/apis/uptime/{graphql => rest}/fixtures/filters.json (100%) rename x-pack/test/api_integration/apis/uptime/{graphql => rest}/fixtures/monitor_status.json (100%) rename x-pack/test/api_integration/apis/uptime/{graphql => rest}/fixtures/monitor_status_all.json (100%) rename x-pack/test/api_integration/apis/uptime/{graphql => rest}/fixtures/monitors_with_location.json (100%) rename x-pack/test/api_integration/apis/uptime/{graphql => rest}/fixtures/snapshot.json (100%) rename x-pack/test/api_integration/apis/uptime/{graphql => rest}/fixtures/snapshot_empty.json (100%) rename x-pack/test/api_integration/apis/uptime/{graphql => rest}/fixtures/snapshot_filtered_by_down.json (100%) rename x-pack/test/api_integration/apis/uptime/{graphql => rest}/fixtures/snapshot_filtered_by_up.json (100%) rename x-pack/test/api_integration/apis/uptime/{graphql/helpers => rest/helper}/expect_fixture_eql.ts (87%) rename x-pack/test/api_integration/apis/uptime/{graphql/helpers => rest/helper}/make_checks.ts (100%) create mode 100644 x-pack/test/api_integration/apis/uptime/rest/monitor_states_generated.ts create mode 100644 x-pack/test/api_integration/apis/uptime/rest/monitor_states_real_data.ts diff --git a/x-pack/legacy/plugins/uptime/README.md b/x-pack/legacy/plugins/uptime/README.md index 2ed0e2fc77cbc..92162341ff426 100644 --- a/x-pack/legacy/plugins/uptime/README.md +++ b/x-pack/legacy/plugins/uptime/README.md @@ -3,7 +3,7 @@ ## Purpose The purpose of this plugin is to provide users of Heartbeat more visibility of what's happening -in their infrastructure. It's primarily built using React and Apollo's GraphQL tools. +in their infrastructure. ## Layout @@ -11,13 +11,15 @@ There are three sections to the app, `common`, `public`, and `server`. ### common -Contains GraphQL types, constants and a few other files. +Contains runtime types types, constants and a few other files. + +Notably, we use `io-ts`/`fp-ts` functions and types to help provide +additional runtime safety for our API requests/responses. ### public -Components come in two main types, queries and functional. Queries are extended from Apollo's queries -type which abstracts a lot of the GraphQL connectivity away. Functional are dumb components that -don't store any state. +We use Redux and associated tools for managing our app state. Components come in the usual `connect`ed and +presentational varieties. The `lib` directory controls bootstrapping code and adapter types. @@ -27,12 +29,13 @@ The principal structure of the app is stored in `uptime_app.tsx`. ### server -There is a `graphql` directory which contains the resolvers, schema files, and constants. - The `lib` directory contains `adapters`, which are connections to external resources like Kibana Server, Elasticsearch, etc. In addition, it contains domains, which are libraries that provide functionality via adapters. +The `requests` directory contains functions responsible for querying Elasticsearch and parsing its +responses. + There's also a `rest_api` folder that defines the structure of the RESTful API endpoints. ## Testing diff --git a/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts b/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts index 540e60a28b066..c6b79afd9043b 100644 --- a/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts +++ b/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SortOrder, CursorDirection } from '../graphql/types'; +import { CursorDirection, SortOrder } from '../runtime_types'; /** * The Uptime UI utilizes a settings context, the defaults for which are stored here. diff --git a/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts b/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts index dffa131870db1..9721d396625fc 100644 --- a/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts +++ b/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts @@ -7,6 +7,7 @@ export enum API_URLS { INDEX_PATTERN = `/api/uptime/index_pattern`, INDEX_STATUS = '/api/uptime/index_status', + MONITOR_LIST = `/api/uptime/monitor/list`, MONITOR_LOCATIONS = `/api/uptime/monitor/locations`, MONITOR_DURATION = `/api/uptime/monitor/duration`, MONITOR_DETAILS = `/api/uptime/monitor/details`, diff --git a/x-pack/legacy/plugins/uptime/common/graphql/types.ts b/x-pack/legacy/plugins/uptime/common/graphql/types.ts deleted file mode 100644 index 506966ec6b5c9..0000000000000 --- a/x-pack/legacy/plugins/uptime/common/graphql/types.ts +++ /dev/null @@ -1,232 +0,0 @@ -/* tslint:disable */ - -// ==================================================== -// START: Typescript template -// ==================================================== - -// ==================================================== -// Scalars -// ==================================================== - -export type UnsignedInteger = any; - -// ==================================================== -// Types -// ==================================================== - -export interface Query { - /** Fetches the current state of Uptime monitors for the given parameters. */ - getMonitorStates?: MonitorSummaryResult | null; -} - -/** The monitor's status for a ping */ -export interface Duration { - us?: UnsignedInteger | null; -} - -export interface Rtt { - connect?: Duration | null; - - handshake?: Duration | null; - - validate?: Duration | null; -} - -export interface Summary { - up?: number | null; - - down?: number | null; - - geo?: CheckGeo | null; -} - -export interface CheckGeo { - name?: string | null; - - location?: Location | null; -} - -export interface Location { - lat?: number | null; - - lon?: number | null; -} - -export interface DocCount { - count: UnsignedInteger; -} - -/** The primary object returned for monitor states. */ -export interface MonitorSummaryResult { - /** Used to go to the next page of results */ - prevPagePagination?: string | null; - /** Used to go to the previous page of results */ - nextPagePagination?: string | null; - /** The objects representing the state of a series of heartbeat monitors. */ - summaries?: MonitorSummary[] | null; - /** The number of summaries. */ - totalSummaryCount: number; -} -/** Represents the current state and associated data for an Uptime monitor. */ -export interface MonitorSummary { - /** The ID assigned by the config or generated by the user. */ - monitor_id: string; - /** The state of the monitor and its associated details. */ - state: State; - - histogram?: SummaryHistogram | null; -} -/** Unifies the subsequent data for an uptime monitor. */ -export interface State { - /** The agent processing the monitor. */ - agent?: Agent | null; - /** There is a check object for each instance of the monitoring agent. */ - checks?: Check[] | null; - - geo?: StateGeo | null; - - observer?: StateObserver | null; - - monitor?: MonitorState | null; - - summary: Summary; - - timestamp: UnsignedInteger; - /** Transport encryption information. */ - tls?: (StateTls | null)[] | null; - - url?: StateUrl | null; -} - -export interface Agent { - id: string; -} - -export interface Check { - agent?: Agent | null; - - container?: StateContainer | null; - - kubernetes?: StateKubernetes | null; - - monitor: CheckMonitor; - - observer?: CheckObserver | null; - - timestamp: string; -} - -export interface StateContainer { - id?: string | null; -} - -export interface StateKubernetes { - pod?: StatePod | null; -} - -export interface StatePod { - uid?: string | null; -} - -export interface CheckMonitor { - ip?: string | null; - - name?: string | null; - - status: string; -} - -export interface CheckObserver { - geo?: CheckGeo | null; -} - -export interface StateGeo { - name?: (string | null)[] | null; - - location?: Location | null; -} - -export interface StateObserver { - geo?: StateGeo | null; -} - -export interface MonitorState { - status?: string | null; - - name?: string | null; - - id?: string | null; - - type?: string | null; -} -/** Contains monitor transmission encryption information. */ -export interface StateTls { - /** The date and time after which the certificate is invalid. */ - certificate_not_valid_after?: string | null; - - certificate_not_valid_before?: string | null; - - certificates?: string | null; - - rtt?: Rtt | null; -} - -export interface StateUrl { - domain?: string | null; - - full?: string | null; - - path?: string | null; - - port?: number | null; - - scheme?: string | null; -} -/** Monitor status data over time. */ -export interface SummaryHistogram { - /** The number of documents used to assemble the histogram. */ - count: number; - /** The individual histogram data points. */ - points: SummaryHistogramPoint[]; -} -/** Represents a monitor's statuses for a period of time. */ -export interface SummaryHistogramPoint { - /** The time at which these data were collected. */ - timestamp: UnsignedInteger; - /** The number of _up_ documents. */ - up: number; - /** The number of _down_ documents. */ - down: number; -} - -export interface GetMonitorStatesQueryArgs { - dateRangeStart: string; - - dateRangeEnd: string; - - pagination?: string | null; - - filters?: string | null; - - statusFilter?: string | null; - - pageSize: number; -} - -// ==================================================== -// Enums -// ==================================================== - -export enum CursorDirection { - AFTER = 'AFTER', - BEFORE = 'BEFORE', -} - -export enum SortOrder { - ASC = 'ASC', - DESC = 'DESC', -} - -// ==================================================== -// END: Typescript template -// ==================================================== diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/index.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/index.ts index 80b48d09dc5b8..46b19d8442a94 100644 --- a/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/index.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/index.ts @@ -6,3 +6,4 @@ export * from './details'; export * from './locations'; +export * from './state'; diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/state.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/state.ts new file mode 100644 index 0000000000000..90aa692f89a42 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/monitor/state.ts @@ -0,0 +1,145 @@ +/* + * 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 * as t from 'io-ts'; + +export const CheckMonitorType = t.intersection([ + t.partial({ + name: t.string, + ip: t.union([t.array(t.string), t.string]), + }), + t.type({ + status: t.string, + }), +]); + +export const CheckType = t.intersection([ + t.partial({ + agent: t.partial({ + id: t.string, + }), + container: t.type({ + id: t.string, + }), + kubernetes: t.type({ + pod: t.type({ + uid: t.string, + }), + }), + observer: t.type({ + geo: t.partial({ + name: t.string, + location: t.partial({ + lat: t.number, + lon: t.number, + }), + }), + }), + }), + t.type({ + monitor: CheckMonitorType, + timestamp: t.number, + }), +]); + +export type Check = t.TypeOf; + +export const StateType = t.intersection([ + t.partial({ + checks: t.array(CheckType), + observer: t.partial({ + geo: t.partial({ + name: t.array(t.string), + }), + }), + summary: t.partial({ + up: t.number, + down: t.number, + geo: t.partial({ + name: t.string, + location: t.partial({ + lat: t.number, + lon: t.number, + }), + }), + }), + }), + t.type({ + timestamp: t.string, + url: t.partial({ + domain: t.string, + full: t.string, + path: t.string, + port: t.number, + scheme: t.string, + }), + }), +]); + +export const HistogramPointType = t.type({ + timestamp: t.number, + up: t.number, + down: t.number, +}); + +export type HistogramPoint = t.TypeOf; + +export const HistogramType = t.type({ + count: t.number, + points: t.array(HistogramPointType), +}); + +export type Histogram = t.TypeOf; + +export const MonitorSummaryType = t.intersection([ + t.type({ + monitor_id: t.string, + state: StateType, + }), + t.partial({ + histogram: HistogramType, + }), +]); + +export type MonitorSummary = t.TypeOf; + +export const MonitorSummaryResultType = t.intersection([ + t.partial({ + summaries: t.array(MonitorSummaryType), + }), + t.type({ + prevPagePagination: t.union([t.string, t.null]), + nextPagePagination: t.union([t.string, t.null]), + totalSummaryCount: t.number, + }), +]); + +export type MonitorSummaryResult = t.TypeOf; + +export const FetchMonitorStatesQueryArgsType = t.intersection([ + t.partial({ + pagination: t.string, + filters: t.string, + statusFilter: t.string, + }), + t.type({ + dateRangeStart: t.string, + dateRangeEnd: t.string, + pageSize: t.number, + }), +]); + +export type FetchMonitorStatesQueryArgs = t.TypeOf; + +export enum CursorDirection { + AFTER = 'AFTER', + BEFORE = 'BEFORE', +} + +export enum SortOrder { + ASC = 'ASC', + DESC = 'DESC', +} diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/index.ts b/x-pack/legacy/plugins/uptime/public/components/connected/index.ts index be3cc5b65aa0e..94e2529a46a00 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/connected/index.ts @@ -11,6 +11,7 @@ export { KueryBar } from './kuerybar/kuery_bar_container'; export { FilterGroup } from './filter_group/filter_group_container'; export { MonitorStatusDetails } from './monitor/status_details_container'; export { MonitorStatusBar } from './monitor/status_bar_container'; +export { MonitorList } from './monitor/monitor_list'; export { MonitorListDrawer } from './monitor/list_drawer_container'; export { MonitorListActionsPopover } from './monitor/drawer_popover_container'; export { PingList, PingListProps } from './pings'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx index 70da62d5833af..37a96ba0396aa 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx @@ -12,8 +12,7 @@ import { MonitorDetailsActionPayload } from '../../../state/actions/types'; import { getMonitorDetailsAction } from '../../../state/actions/monitor'; import { MonitorListDrawerComponent } from '../../functional/monitor_list/monitor_list_drawer/monitor_list_drawer'; import { useGetUrlParams } from '../../../hooks'; -import { MonitorSummary } from '../../../../common/graphql/types'; -import { MonitorDetails } from '../../../../common/runtime_types/monitor'; +import { MonitorDetails, MonitorSummary } from '../../../../common/runtime_types'; interface ContainerProps { summary: MonitorSummary; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/monitor_list.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/monitor_list.tsx new file mode 100644 index 0000000000000..c9457664566b7 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/monitor_list.tsx @@ -0,0 +1,31 @@ +/* + * 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, { useCallback } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import { getMonitorList } from '../../../state/actions'; +import { FetchMonitorStatesQueryArgs } from '../../../../common/runtime_types'; +import { monitorListSelector } from '../../../state/selectors'; +import { MonitorListComponent } from '../../functional/monitor_list'; + +export interface MonitorListProps { + filters?: string; + linkParameters?: string; +} + +export const MonitorList: React.FC = props => { + const dispatch = useDispatch(); + const dispatchCallback = useCallback( + (params: FetchMonitorStatesQueryArgs) => { + dispatch(getMonitorList(params)); + }, + [dispatch] + ); + const monitorListState = useSelector(monitorListSelector); + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/monitor_bar_series.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/monitor_bar_series.test.tsx.snap index 8ca73879cab8c..b389139d71dbf 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/monitor_bar_series.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/monitor_bar_series.test.tsx.snap @@ -82,7 +82,6 @@ exports[`MonitorBarSeries component shallow renders a series when there are down } > { let props: MonitorBarSeriesProps; - let histogramSeries: SummaryHistogramPoint[]; + let histogramSeries: HistogramPoint[]; beforeEach(() => { props = { - dangerColor: 'A danger color', histogramSeries: [ { timestamp: 124, @@ -193,16 +192,12 @@ describe('MonitorBarSeries component', () => { }); it('shallow renders nothing if the data series is null', () => { - const component = shallowWithRouter( - - ); + const component = shallowWithRouter(); expect(component).toEqual({}); }); it('renders if the data series is present', () => { - const component = renderWithRouter( - - ); + const component = renderWithRouter(); expect(component).toMatchSnapshot(); }); }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/monitor_bar_series.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/monitor_bar_series.tsx index 6a1e255d308d7..5e11685e36140 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/monitor_bar_series.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/monitor_bar_series.tsx @@ -14,23 +14,20 @@ import { timeFormatter, } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; -import React from 'react'; +import React, { useContext } from 'react'; import moment from 'moment'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiText, EuiToolTip } from '@elastic/eui'; -import { SummaryHistogramPoint } from '../../../../common/graphql/types'; +import { HistogramPoint } from '../../../../common/runtime_types'; import { getChartDateLabel, seriesHasDownValues } from '../../../lib/helper'; import { useUrlParams } from '../../../hooks'; +import { UptimeThemeContext } from '../../../contexts'; export interface MonitorBarSeriesProps { - /** - * The color to use for the display of down states. - */ - dangerColor: string; /** * The timeseries data to display. */ - histogramSeries: SummaryHistogramPoint[] | null; + histogramSeries: HistogramPoint[] | null; } /** @@ -38,7 +35,10 @@ export interface MonitorBarSeriesProps { * so we will only render the series component if there are down counts for the selected monitor. * @param props - the values for the monitor this chart visualizes */ -export const MonitorBarSeries = ({ dangerColor, histogramSeries }: MonitorBarSeriesProps) => { +export const MonitorBarSeries = ({ histogramSeries }: MonitorBarSeriesProps) => { + const { + colors: { danger }, + } = useContext(UptimeThemeContext); const [getUrlParams, updateUrlParams] = useUrlParams(); const { absoluteDateRangeStart, absoluteDateRangeEnd } = getUrlParams(); @@ -68,7 +68,7 @@ export const MonitorBarSeries = ({ dangerColor, histogramSeries }: MonitorBarSer /> [timestamp, down])} name={i18n.translate('xpack.uptime.monitorList.downLineSeries.downLabel', { defaultMessage: 'Down checks', 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 d82912a6216e8..07809561c31b7 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/functional/index.ts @@ -13,7 +13,7 @@ export * from './alerts'; export { DonutChart } from './charts/donut_chart'; export { KueryBarComponent } from './kuery_bar/kuery_bar'; export { MonitorCharts } from './monitor_charts'; -export { MonitorList } from './monitor_list'; +export { MonitorListComponent } from './monitor_list'; export { OverviewPageParsingErrorCallout } from './overview_page_parsing_error_callout'; export { PingListComponent } from './ping_list'; export { PingHistogramComponent } from './charts'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap index 2b8bc0bb06ddf..ed5602323d254 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap @@ -1,125 +1,535 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`MonitorList component renders a no items message when no data is provided 1`] = ` - - - -

- -
- - - + + +`; + +exports[`MonitorList component MonitorListPagination component renders the pagination 1`] = ` + + + +`; + +exports[`MonitorList component renders a no items message when no data is provided 1`] = ` + + + +`; + +exports[`MonitorList component renders error list 1`] = ` + + + +`; + +exports[`MonitorList component renders loading state 1`] = ` + + - - - - - - - - - - - - - - - - - - + } + /> + `; exports[`MonitorList component renders the monitor list 1`] = ` @@ -672,185 +1082,132 @@ exports[`MonitorList component renders the monitor list 1`] = ` `; exports[`MonitorList component shallow renders the monitor list 1`] = ` - - - -
- -
-
- - + - - - - - - - - - - - - - - - - -
-
+ } + /> + `; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_pagination.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_pagination.test.tsx.snap deleted file mode 100644 index db5bfa72deb36..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_pagination.test.tsx.snap +++ /dev/null @@ -1,307 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`MonitorListPagination component renders a no items message when no data is provided 1`] = ` - - - -
- -
-
- - - - - - - - - - - - - - - - - - -
-
-`; - -exports[`MonitorListPagination component renders the monitor list 1`] = ` - - - -
- -
-
- - - - - - - - - - - - - - - - - - -
-
-`; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list.test.tsx index d2030155d0092..9b1d799a23e37 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list.test.tsx @@ -4,17 +4,30 @@ * you may not use this file except in compliance with the Elastic License. */ -import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; -import { MonitorSummaryResult } from '../../../../../common/graphql/types'; +import { + MonitorSummaryResult, + CursorDirection, + SortOrder, +} from '../../../../../common/runtime_types'; import { MonitorListComponent } from '../monitor_list'; -import { renderWithRouter } from '../../../../lib'; +import { renderWithRouter, shallowWithRouter } from '../../../../lib'; describe('MonitorList component', () => { let result: MonitorSummaryResult; + let localStorageMock: any; beforeEach(() => { + localStorageMock = { + getItem: jest.fn().mockImplementation(() => '25'), + setItem: jest.fn(), + }; + + // @ts-ignore replacing a call to localStorage we use for monitor list size + global.localStorage = localStorageMock; result = { + nextPagePagination: null, + prevPagePagination: null, summaries: [ { monitor_id: 'foo', @@ -25,21 +38,21 @@ describe('MonitorList component', () => { ip: '127.0.0.1', status: 'up', }, - timestamp: '124', + timestamp: 124, }, { monitor: { ip: '127.0.0.2', status: 'down', }, - timestamp: '125', + timestamp: 125, }, { monitor: { ip: '127.0.0.3', status: 'down', }, - timestamp: '126', + timestamp: 126, }, ], summary: { @@ -47,6 +60,7 @@ describe('MonitorList component', () => { down: 2, }, timestamp: '123', + url: {}, }, }, { @@ -58,14 +72,14 @@ describe('MonitorList component', () => { ip: '127.0.0.1', status: 'up', }, - timestamp: '125', + timestamp: 125, }, { monitor: { ip: '127.0.0.2', status: 'up', }, - timestamp: '126', + timestamp: 126, }, ], summary: { @@ -73,6 +87,7 @@ describe('MonitorList component', () => { down: 0, }, timestamp: '125', + url: {}, }, }, ], @@ -81,15 +96,11 @@ describe('MonitorList component', () => { }); it('shallow renders the monitor list', () => { - const component = shallowWithIntl( + const component = shallowWithRouter( ); @@ -97,15 +108,19 @@ describe('MonitorList component', () => { }); it('renders a no items message when no data is provided', () => { - const component = shallowWithIntl( + const component = shallowWithRouter( ); expect(component).toMatchSnapshot(); @@ -114,16 +129,156 @@ describe('MonitorList component', () => { it('renders the monitor list', () => { const component = renderWithRouter( + ); + + expect(component).toMatchSnapshot(); + }); + + it('renders error list', () => { + const component = shallowWithRouter( + ); expect(component).toMatchSnapshot(); }); + + it('renders loading state', () => { + const component = shallowWithRouter( + + ); + + expect(component).toMatchSnapshot(); + }); + + describe('MonitorListPagination component', () => { + let paginationResult: MonitorSummaryResult; + + beforeEach(() => { + paginationResult = { + prevPagePagination: JSON.stringify({ + cursorKey: { monitor_id: 123 }, + cursorDirection: CursorDirection.BEFORE, + sortOrder: SortOrder.ASC, + }), + nextPagePagination: JSON.stringify({ + cursorKey: { monitor_id: 456 }, + cursorDirection: CursorDirection.AFTER, + sortOrder: SortOrder.ASC, + }), + summaries: [ + { + monitor_id: 'foo', + state: { + checks: [ + { + monitor: { + ip: '127.0.0.1', + status: 'up', + }, + timestamp: 124, + }, + { + monitor: { + ip: '127.0.0.2', + status: 'down', + }, + timestamp: 125, + }, + { + monitor: { + ip: '127.0.0.3', + status: 'down', + }, + timestamp: 126, + }, + ], + summary: { + up: 1, + down: 2, + }, + timestamp: '123', + url: {}, + }, + }, + { + monitor_id: 'bar', + state: { + checks: [ + { + monitor: { + ip: '127.0.0.1', + status: 'up', + }, + timestamp: 125, + }, + { + monitor: { + ip: '127.0.0.2', + status: 'up', + }, + timestamp: 126, + }, + ], + summary: { + up: 2, + down: 0, + }, + timestamp: '125', + url: {}, + }, + }, + ], + totalSummaryCount: 2, + }; + }); + + it('renders the pagination', () => { + const component = shallowWithRouter( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('renders a no items message when no data is provided', () => { + const component = shallowWithRouter( + + ); + + expect(component).toMatchSnapshot(); + }); + }); }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_pagination.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_pagination.test.tsx deleted file mode 100644 index b08b8b3fabc3e..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_pagination.test.tsx +++ /dev/null @@ -1,126 +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 { shallowWithIntl } from 'test_utils/enzyme_helpers'; -import React from 'react'; -import { - CursorDirection, - MonitorSummaryResult, - SortOrder, -} from '../../../../../common/graphql/types'; -import { MonitorListComponent } from '../monitor_list'; - -describe('MonitorListPagination component', () => { - let result: MonitorSummaryResult; - - beforeEach(() => { - result = { - prevPagePagination: JSON.stringify({ - cursorKey: { monitor_id: 123 }, - cursorDirection: CursorDirection.BEFORE, - sortOrder: SortOrder.ASC, - }), - nextPagePagination: JSON.stringify({ - cursorKey: { monitor_id: 456 }, - cursorDirection: CursorDirection.AFTER, - sortOrder: SortOrder.ASC, - }), - summaries: [ - { - monitor_id: 'foo', - state: { - checks: [ - { - monitor: { - ip: '127.0.0.1', - status: 'up', - }, - timestamp: '124', - }, - { - monitor: { - ip: '127.0.0.2', - status: 'down', - }, - timestamp: '125', - }, - { - monitor: { - ip: '127.0.0.3', - status: 'down', - }, - timestamp: '126', - }, - ], - summary: { - up: 1, - down: 2, - }, - timestamp: '123', - }, - }, - { - monitor_id: 'bar', - state: { - checks: [ - { - monitor: { - ip: '127.0.0.1', - status: 'up', - }, - timestamp: '125', - }, - { - monitor: { - ip: '127.0.0.2', - status: 'up', - }, - timestamp: '126', - }, - ], - summary: { - up: 2, - down: 0, - }, - timestamp: '125', - }, - }, - ], - totalSummaryCount: 2, - }; - }); - - it('renders the monitor list', () => { - const component = shallowWithIntl( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('renders a no items message when no data is provided', () => { - const component = shallowWithIntl( - - ); - expect(component).toMatchSnapshot(); - }); -}); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_status_column.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_status_column.test.tsx index 406e18535f34c..d765c0b33ea4b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_status_column.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_status_column.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import moment from 'moment'; import { renderWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import { getLocationStatus, MonitorListStatusColumn } from '../monitor_list_status_column'; -import { Check } from '../../../../../common/graphql/types'; +import { Check } from '../../../../../common/runtime_types'; import { STATUS } from '../../../../../common/constants'; describe('MonitorListStatusColumn', () => { @@ -29,9 +29,6 @@ describe('MonitorListStatusColumn', () => { beforeEach(() => { upChecks = [ { - agent: { id: '6a2f2a1c-e346-49ed-8418-6d48af8841d6' }, - container: null, - kubernetes: null, monitor: { ip: '104.86.46.103', name: '', @@ -46,12 +43,9 @@ describe('MonitorListStatusColumn', () => { }, }, }, - timestamp: '1579794631464', + timestamp: 1579794631464, }, { - agent: { id: '1117fd01-bc1a-4aa5-bfab-40ab455eadf9' }, - container: null, - kubernetes: null, monitor: { ip: '104.86.46.103', name: '', @@ -66,12 +60,9 @@ describe('MonitorListStatusColumn', () => { }, }, }, - timestamp: '1579794634220', + timestamp: 1579794634220, }, { - agent: { id: 'eda59510-45e8-4dfe-b0f8-959c449e3565' }, - container: null, - kubernetes: null, monitor: { ip: '104.86.46.103', name: '', @@ -86,15 +77,12 @@ describe('MonitorListStatusColumn', () => { }, }, }, - timestamp: '1579794628368', + timestamp: 1579794628368, }, ]; downChecks = [ { - agent: { id: '6a2f2a1c-e346-49ed-8418-6d48af8841d6' }, - container: null, - kubernetes: null, monitor: { ip: '104.86.46.103', name: '', @@ -109,12 +97,9 @@ describe('MonitorListStatusColumn', () => { }, }, }, - timestamp: '1579794631464', + timestamp: 1579794631464, }, { - agent: { id: '1117fd01-bc1a-4aa5-bfab-40ab455eadf9' }, - container: null, - kubernetes: null, monitor: { ip: '104.86.46.103', name: '', @@ -129,12 +114,9 @@ describe('MonitorListStatusColumn', () => { }, }, }, - timestamp: '1579794634220', + timestamp: 1579794634220, }, { - agent: { id: 'eda59510-45e8-4dfe-b0f8-959c449e3565' }, - container: null, - kubernetes: null, monitor: { ip: '104.86.46.103', name: '', @@ -149,15 +131,12 @@ describe('MonitorListStatusColumn', () => { }, }, }, - timestamp: '1579794628368', + timestamp: 1579794628368, }, ]; checks = [ { - agent: { id: '6a2f2a1c-e346-49ed-8418-6d48af8841d6' }, - container: null, - kubernetes: null, monitor: { ip: '104.86.46.103', name: '', @@ -172,12 +151,9 @@ describe('MonitorListStatusColumn', () => { }, }, }, - timestamp: '1579794631464', + timestamp: 1579794631464, }, { - agent: { id: '1117fd01-bc1a-4aa5-bfab-40ab455eadf9' }, - container: null, - kubernetes: null, monitor: { ip: '104.86.46.103', name: '', @@ -192,12 +168,9 @@ describe('MonitorListStatusColumn', () => { }, }, }, - timestamp: '1579794634220', + timestamp: 1579794634220, }, { - agent: { id: 'eda59510-45e8-4dfe-b0f8-959c449e3565' }, - container: null, - kubernetes: null, monitor: { ip: '104.86.46.103', name: '', @@ -212,7 +185,7 @@ describe('MonitorListStatusColumn', () => { }, }, }, - timestamp: '1579794628368', + timestamp: 1579794628368, }, ]; }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/index.ts b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/index.ts index a83330a7a3a0b..2dc43050f9515 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/index.ts @@ -4,6 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -export { MonitorList } from './monitor_list'; +export { MonitorListComponent } from './monitor_list'; export { Criteria, Pagination } from './types'; export { LocationLink } from './monitor_list_drawer'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx index a9fb1ce2f4be1..6705101ccd572 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx @@ -16,17 +16,11 @@ import { EuiTitle, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; -import { withUptimeGraphQL, UptimeGraphQLQueryProps } from '../../higher_order'; -import { monitorStatesQuery } from '../../../queries/monitor_states_query'; -import { - MonitorSummary, - MonitorSummaryResult, - SummaryHistogramPoint, -} from '../../../../common/graphql/types'; +import { HistogramPoint, FetchMonitorStatesQueryArgs } from '../../../../common/runtime_types'; +import { MonitorSummary } from '../../../../common/runtime_types'; import { MonitorListStatusColumn } from './monitor_list_status_column'; -import { formatUptimeGraphQLErrorList } from '../../../lib/helper/format_error_list'; import { ExpandedRowMap } from './types'; import { MonitorBarSeries } from '../charts'; import { MonitorPageLink } from './monitor_page_link'; @@ -34,36 +28,69 @@ import { OverviewPageLink } from './overview_page_link'; import * as labels from './translations'; import { MonitorListDrawer } from '../../connected'; import { MonitorListPageSizeSelect } from './monitor_list_page_size_select'; +import { MonitorListProps } from '../../connected/monitor/monitor_list'; +import { MonitorList } from '../../../state/reducers/monitor_list'; +import { useUrlParams } from '../../../hooks'; -interface MonitorListQueryResult { - monitorStates?: MonitorSummaryResult; -} - -interface MonitorListProps { - dangerColor: string; - hasActiveFilters: boolean; - successColor: string; - linkParameters?: string; - pageSize: number; - setPageSize: (size: number) => void; +interface Props extends MonitorListProps { + lastRefresh: number; + monitorList: MonitorList; + getMonitorList: (params: FetchMonitorStatesQueryArgs) => void; } -type Props = UptimeGraphQLQueryProps & MonitorListProps; - const TruncatedEuiLink = styled(EuiLink)` white-space: nowrap; overflow: hidden; text-overflow: ellipsis; `; -export const MonitorListComponent = (props: Props) => { - const { dangerColor, data, errors, hasActiveFilters, linkParameters, loading } = props; +const DEFAULT_PAGE_SIZE = 10; +const LOCAL_STORAGE_KEY = 'xpack.uptime.monitorList.pageSize'; +const getPageSizeValue = () => { + const value = parseInt(localStorage.getItem(LOCAL_STORAGE_KEY) ?? '', 10); + if (isNaN(value)) { + return DEFAULT_PAGE_SIZE; + } + return value; +}; + +export const MonitorListComponent: React.FC = ({ + filters, + getMonitorList, + lastRefresh, + monitorList: { list, error, loading }, + linkParameters, +}) => { + const [pageSize, setPageSize] = useState(getPageSizeValue()); const [drawerIds, updateDrawerIds] = useState([]); - const items = data?.monitorStates?.summaries ?? []; + const [getUrlValues] = useUrlParams(); + const { dateRangeStart, dateRangeEnd, pagination, statusFilter } = getUrlValues(); + + useEffect(() => { + getMonitorList({ + dateRangeStart, + dateRangeEnd, + filters, + pageSize, + pagination, + statusFilter, + }); + }, [ + getMonitorList, + dateRangeStart, + dateRangeEnd, + filters, + lastRefresh, + pageSize, + pagination, + statusFilter, + ]); + + const items = list.summaries ?? []; - const nextPagePagination = data?.monitorStates?.nextPagePagination ?? ''; - const prevPagePagination = data?.monitorStates?.prevPagePagination ?? ''; + const nextPagePagination = list.nextPagePagination ?? ''; + const prevPagePagination = list.prevPagePagination ?? ''; const getExpandedRowMap = () => { return drawerIds.reduce((map: ExpandedRowMap, id: string) => { @@ -123,8 +150,8 @@ export const MonitorListComponent = (props: Props) => { mobileOptions: { show: false, }, - render: (histogramSeries: SummaryHistogramPoint[] | null) => ( - + render: (histogramSeries: HistogramPoint[] | null) => ( + ), }, { @@ -153,70 +180,61 @@ export const MonitorListComponent = (props: Props) => { ]; return ( - <> - - -
- -
-
- - - - - - - - - - - - - - - - - - -
- + + +
+ +
+
+ + + + + + + + + + + + + + + + + + +
); }; - -export const MonitorList = withUptimeGraphQL( - MonitorListComponent, - monitorStatesQuery -); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap index cf754581b1a33..4520b760be379 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap @@ -71,21 +71,21 @@ exports[`MonitorListDrawer component renders a MonitorListDrawer when there are "ip": "127.0.0.1", "status": "up", }, - "timestamp": "121", + "timestamp": 121, }, Object { "monitor": Object { "ip": "127.0.0.2", "status": "down", }, - "timestamp": "123", + "timestamp": 123, }, Object { "monitor": Object { "ip": "127.0.0.3", "status": "up", }, - "timestamp": "125", + "timestamp": 125, }, ], "summary": Object { @@ -175,7 +175,7 @@ exports[`MonitorListDrawer component renders a MonitorListDrawer when there is o "ip": "127.0.0.1", "status": "up", }, - "timestamp": "121", + "timestamp": 121, }, ], "summary": Object { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx index 723f8f9f4430a..48fa2c9766681 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import { MonitorSummary } from '../../../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../../../common/runtime_types'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import { IntegrationGroup } from '../integration_group'; @@ -19,6 +19,7 @@ describe('IntegrationGroup', () => { summary: {}, checks: [], timestamp: '123', + url: {}, }, }; }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_list_drawer.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_list_drawer.test.tsx index d870acefaaea6..4bc0c3f0a40ba 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_list_drawer.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_list_drawer.test.tsx @@ -4,10 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ import 'jest'; -import { MonitorSummary, Check } from '../../../../../../common/graphql/types'; import React from 'react'; import { MonitorListDrawerComponent } from '../monitor_list_drawer'; -import { MonitorDetails } from '../../../../../../common/runtime_types'; +import { Check, MonitorDetails, MonitorSummary } from '../../../../../../common/runtime_types'; import { shallowWithRouter } from '../../../../../lib'; describe('MonitorListDrawer component', () => { @@ -24,7 +23,7 @@ describe('MonitorListDrawer component', () => { ip: '127.0.0.1', status: 'up', }, - timestamp: '121', + timestamp: 121, }, ], summary: { @@ -77,21 +76,21 @@ describe('MonitorListDrawer component', () => { ip: '127.0.0.1', status: 'up', }, - timestamp: '121', + timestamp: 121, }, { monitor: { ip: '127.0.0.2', status: 'down', }, - timestamp: '123', + timestamp: 123, }, { monitor: { ip: '127.0.0.3', status: 'up', }, - timestamp: '125', + timestamp: 125, }, ]; summary.state.checks = checks; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_status_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_status_list.test.tsx index 8c07d0b1a7d22..c7f3aef4075e1 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_status_list.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_status_list.test.tsx @@ -8,7 +8,7 @@ import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import moment from 'moment'; import { MonitorStatusList } from '../monitor_status_list'; -import { Check } from '../../../../../../common/graphql/types'; +import { Check } from '../../../../../../common/runtime_types'; describe('MonitorStatusList component', () => { let checks: Check[]; @@ -21,110 +21,92 @@ describe('MonitorStatusList component', () => { beforeEach(() => { checks = [ { - agent: { id: '8f9a37fb-573a-4fdc-9895-440a5b39c250' }, monitor: { ip: '151.101.130.217', name: 'elastic', status: 'up', }, observer: { - geo: { name: null, location: null }, + geo: {}, }, - timestamp: '1570538236414', + timestamp: 1570538236414, }, { - agent: { id: '8f9a37fb-573a-4fdc-9895-440a5b39c250' }, monitor: { ip: '151.101.194.217', name: 'elastic', status: 'up', }, observer: { - geo: { name: null, location: null }, + geo: {}, }, - timestamp: '1570538236414', + timestamp: 1570538236414, }, { - agent: { id: '8f9a37fb-573a-4fdc-9895-440a5b39c250' }, monitor: { ip: '151.101.2.217', name: 'elastic', status: 'up', }, observer: { - geo: { name: null, location: null }, + geo: {}, }, - timestamp: '1570538236414', + timestamp: 1570538236414, }, { - agent: { id: '8f9a37fb-573a-4fdc-9895-440a5b39c250' }, - container: null, - kubernetes: null, monitor: { ip: '151.101.66.217', name: 'elastic', status: 'up', }, observer: { - geo: { name: null, location: null }, + geo: {}, }, - timestamp: '1570538236414', + timestamp: 1570538236414, }, { - agent: { id: '8f9a37fb-573a-4fdc-9895-440a5b39c250' }, - container: null, - kubernetes: null, monitor: { ip: '2a04:4e42:200::729', name: 'elastic', status: 'down', }, observer: { - geo: { name: null, location: null }, + geo: {}, }, - timestamp: '1570538236414', + timestamp: 1570538236414, }, { - agent: { id: '8f9a37fb-573a-4fdc-9895-440a5b39c250' }, - container: null, - kubernetes: null, monitor: { ip: '2a04:4e42:400::729', name: 'elastic', status: 'down', }, observer: { - geo: { name: null, location: null }, + geo: {}, }, - timestamp: '1570538236414', + timestamp: 1570538236414, }, { - agent: { id: '8f9a37fb-573a-4fdc-9895-440a5b39c250' }, - container: null, - kubernetes: null, monitor: { ip: '2a04:4e42:600::729', name: 'elastic', status: 'down', }, observer: { - geo: { name: null, location: null }, + geo: {}, }, - timestamp: '1570538236414', + timestamp: 1570538236414, }, { - agent: { id: '8f9a37fb-573a-4fdc-9895-440a5b39c250' }, - container: null, - kubernetes: null, monitor: { ip: '2a04:4e42::729', name: 'elastic', status: 'down', }, observer: { - geo: { name: null, location: null }, + geo: {}, }, - timestamp: '1570538236414', + timestamp: 1570538236414, }, ]; }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/integration_group.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/integration_group.tsx index 34bff58a3e2d9..cc06b9a2306c7 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/integration_group.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/integration_group.tsx @@ -19,7 +19,7 @@ import { getLoggingIpHref, getLoggingKubernetesHref, } from '../../../../lib/helper'; -import { MonitorSummary } from '../../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../../common/runtime_types'; import { UptimeSettingsContext } from '../../../../contexts'; interface IntegrationGroupProps { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_actions_popover.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_actions_popover.tsx index 6b946baa8d403..c57ecbaa4d3ed 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_actions_popover.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_actions_popover.tsx @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { EuiPopover, EuiButton } from '@elastic/eui'; import { IntegrationGroup } from './integration_group'; -import { MonitorSummary } from '../../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../../common/runtime_types'; import { toggleIntegrationsPopover, PopoverState } from '../../../../state/actions'; interface MonitorListActionsPopoverProps { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx index 8383596ccc346..6dc9ebbef1287 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx @@ -7,10 +7,9 @@ import React from 'react'; import styled from 'styled-components'; import { EuiLink, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText } from '@elastic/eui'; -import { MonitorSummary } from '../../../../../common/graphql/types'; import { MostRecentError } from './most_recent_error'; import { MonitorStatusList } from './monitor_status_list'; -import { MonitorDetails } from '../../../../../common/runtime_types'; +import { MonitorDetails, MonitorSummary } from '../../../../../common/runtime_types'; import { MonitorListActionsPopover } from '../../../connected'; const ContainerDiv = styled.div` diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_status_list.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_status_list.tsx index a2042e379dd80..8a46167dcd3bc 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_status_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_status_list.tsx @@ -8,9 +8,9 @@ import React from 'react'; import { get, capitalize } from 'lodash'; import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Check } from '../../../../../common/graphql/types'; import { LocationLink } from './location_link'; import { MonitorStatusRow } from './monitor_status_row'; +import { Check } from '../../../../../common/runtime_types'; import { STATUS, UNNAMED_LOCATION } from '../../../../../common/constants'; interface MonitorStatusListProps { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_status_column.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_status_column.tsx index 7e23be572a6f9..8076fe66cc208 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_status_column.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_status_column.tsx @@ -11,7 +11,7 @@ import { capitalize } from 'lodash'; import styled from 'styled-components'; import { EuiHealth, EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip } from '@elastic/eui'; import { parseTimestamp } from './parse_timestamp'; -import { Check } from '../../../../common/graphql/types'; +import { Check } from '../../../../common/runtime_types'; import { STATUS, SHORT_TIMESPAN_LOCALE, diff --git a/x-pack/legacy/plugins/uptime/public/components/higher_order/index.ts b/x-pack/legacy/plugins/uptime/public/components/higher_order/index.ts index e0e14456cfc68..0682f6d0478f3 100644 --- a/x-pack/legacy/plugins/uptime/public/components/higher_order/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/higher_order/index.ts @@ -4,5 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { UptimeGraphQLQueryProps, withUptimeGraphQL } from './uptime_graphql_query'; export { ResponsiveWrapperProps, withResponsiveWrapper } from './responsive_wrapper'; diff --git a/x-pack/legacy/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx b/x-pack/legacy/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx deleted file mode 100644 index 6839050cec7a8..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/higher_order/uptime_graphql_query.tsx +++ /dev/null @@ -1,89 +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 { OperationVariables } from 'apollo-client'; -import { GraphQLError } from 'graphql'; -import React, { Fragment, useContext, useEffect, useState } from 'react'; -import { withApollo, WithApolloClient } from 'react-apollo'; -import { formatUptimeGraphQLErrorList } from '../../lib/helper/format_error_list'; -import { UptimeRefreshContext } from '../../contexts'; - -export interface UptimeGraphQLQueryProps { - loading: boolean; - data?: T; - errors?: GraphQLError[]; -} - -interface UptimeGraphQLProps { - implementsCustomErrorState?: boolean; - variables: OperationVariables; -} - -/** - * This HOC abstracts the task of querying our GraphQL endpoint, - * which eliminates the need for a lot of boilerplate code in the other components. - * - * @type T - the expected result's type - * @type P - any props the wrapped component will require - * @param WrappedComponent - the consuming component - * @param query - the graphQL query - */ -export function withUptimeGraphQL(WrappedComponent: any, query: any) { - type Props = UptimeGraphQLProps & WithApolloClient & P; - - return withApollo((props: Props) => { - const { lastRefresh } = useContext(UptimeRefreshContext); - const [loading, setLoading] = useState(true); - const [data, setData] = useState(undefined); - const [errors, setErrors] = useState(undefined); - let updateState = ( - loadingVal: boolean, - dataVal: T | undefined, - errorsVal: GraphQLError[] | undefined - ) => { - setLoading(loadingVal); - setData(dataVal); - setErrors(errorsVal); - }; - const { client, implementsCustomErrorState, variables } = props; - const fetch = () => { - setLoading(true); - client - .query({ fetchPolicy: 'network-only', query, variables }) - .then( - (result: any) => { - updateState(result.loading, result.data, result.errors); - }, - (result: any) => { - updateState(false, undefined, result.graphQLErrors); - } - ); - }; - useEffect(() => { - fetch(); - - /** - * If the `then` handler in `fetch`'s promise is fired after - * this component has unmounted, it will try to set state on an - * unmounted component, which indicates a memory leak and will trigger - * React warnings. - * - * We counteract this side effect by providing a cleanup function that will - * reassign the update function to do nothing with the returned values. - */ - return () => { - // this component is planned to be deprecated, for the time being - // we will want to preserve this for the reason above. - // eslint-disable-next-line react-hooks/exhaustive-deps - updateState = () => {}; - }; - }, [variables, lastRefresh]); - if (!implementsCustomErrorState && errors && errors.length > 0) { - return {formatUptimeGraphQLErrorList(errors)}; - } - return ; - }); -} diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/apollo_client_adapter.ts b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/apollo_client_adapter.ts deleted file mode 100644 index 2cec0d5fc8c64..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/apollo_client_adapter.ts +++ /dev/null @@ -1,16 +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 { InMemoryCache } from 'apollo-cache-inmemory'; -import { ApolloClient } from 'apollo-client'; -import { HttpLink } from 'apollo-link-http'; -import { CreateGraphQLClient } from './framework_adapter_types'; - -export const createApolloClient: CreateGraphQLClient = (uri: string, xsrfHeader: string) => - new ApolloClient({ - link: new HttpLink({ uri, credentials: 'same-origin', headers: { 'kbn-xsrf': xsrfHeader } }), - cache: new InMemoryCache({ dataIdFromObject: () => undefined }), - }); diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/framework_adapter_types.ts b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/framework_adapter_types.ts deleted file mode 100644 index 34cf48514c932..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/framework_adapter_types.ts +++ /dev/null @@ -1,12 +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 { NormalizedCacheObject } from 'apollo-cache-inmemory'; -import { ApolloClient } from 'apollo-client'; - -export type GraphQLClient = ApolloClient; - -export type CreateGraphQLClient = (url: string, xsrfHeader: string) => GraphQLClient; diff --git a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx index a2f3328b98612..71c73bf5ba5d4 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx +++ b/x-pack/legacy/plugins/uptime/public/lib/adapters/framework/new_platform_adapter.tsx @@ -20,7 +20,6 @@ import { DEFAULT_TIMEPICKER_QUICK_RANGES, } from '../../../../common/constants'; import { UMFrameworkAdapter } from '../../lib'; -import { createApolloClient } from './apollo_client_adapter'; export const getKibanaFrameworkAdapter = ( core: CoreStart, @@ -60,7 +59,6 @@ export const getKibanaFrameworkAdapter = ( const props: UptimeAppProps = { basePath: basePath.get(), canSave, - client: createApolloClient(`${basePath.get()}/api/uptime/graphql`, 'true'), core, darkMode: core.uiSettings.get(DEFAULT_DARK_MODE), commonlyUsedRanges: core.uiSettings.get(DEFAULT_TIMEPICKER_QUICK_RANGES), diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/__snapshots__/format_error_string.test.ts.snap b/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/__snapshots__/format_error_string.test.ts.snap deleted file mode 100644 index 8519157e4039e..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/__snapshots__/format_error_string.test.ts.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`formatErrorString returns a formatted string containing each error 1`] = ` -"Error: foo is bar -Error: bar is not foo -" -`; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/format_error_string.test.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/format_error_string.test.ts deleted file mode 100644 index ba437c05cbe2b..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/__tests__/format_error_string.test.ts +++ /dev/null @@ -1,41 +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 { formatUptimeGraphQLErrorList } from '../format_error_list'; - -describe('formatErrorString', () => { - it('returns an empty string for empty array', () => { - const result = formatUptimeGraphQLErrorList([]); - expect(result).toEqual(''); - }); - it('returns a formatted string containing each error', () => { - const result = formatUptimeGraphQLErrorList([ - { - message: 'foo is bar', - locations: undefined, - path: undefined, - nodes: undefined, - source: undefined, - positions: undefined, - originalError: undefined, - extensions: undefined, - name: 'test error', - }, - { - message: 'bar is not foo', - locations: undefined, - path: undefined, - nodes: undefined, - source: undefined, - positions: undefined, - originalError: undefined, - extensions: undefined, - name: 'test error', - }, - ]); - expect(result).toMatchSnapshot(); - }); -}); diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/format_error_list.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/format_error_list.ts deleted file mode 100644 index a23122c5eead5..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/format_error_list.ts +++ /dev/null @@ -1,20 +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 { i18n } from '@kbn/i18n'; -import { GraphQLError } from 'graphql'; - -export const formatUptimeGraphQLErrorList = (errors: GraphQLError[]) => - errors.reduce( - (errorString, error) => - errorString.concat( - `${i18n.translate('xpack.uptime.errorMessage', { - values: { message: error.message }, - defaultMessage: 'Error: {message}', - })}\n` - ), - '' - ); diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_apm_href.test.ts.snap b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_apm_href.test.ts.snap deleted file mode 100644 index 53d336b52bd24..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_apm_href.test.ts.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`getApmHref creates href with base path when present 1`] = `"foo/app/apm#/services?kuery=url.domain:%20%22www.elastic.co%22&rangeFrom=now-15m&rangeTo=now"`; - -exports[`getApmHref does not add a base path or extra slash when base path is empty string 1`] = `"/app/apm#/services?kuery=url.domain:%20%22www.elastic.co%22&rangeFrom=now-15m&rangeTo=now"`; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_infra_href.test.ts.snap b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_infra_href.test.ts.snap deleted file mode 100644 index e79eb50d384a8..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_infra_href.test.ts.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`getInfraHref getInfraContainerHref creates a link for valid parameters 1`] = `"foo/app/metrics/link-to/container-detail/test-container-id"`; - -exports[`getInfraHref getInfraContainerHref does not specify a base path when none is available 1`] = `"/app/metrics/link-to/container-detail/test-container-id"`; - -exports[`getInfraHref getInfraContainerHref returns the first item when multiple container ids are supplied 1`] = `"bar/app/metrics/link-to/container-detail/test-container-id"`; - -exports[`getInfraHref getInfraIpHref creates a link for valid parameters 1`] = `"bar/app/metrics/inventory?waffleFilter=(expression:'host.ip%20%3A%20151.101.202.217',kind:kuery)"`; - -exports[`getInfraHref getInfraIpHref does not specify a base path when none is available 1`] = `"/app/metrics/inventory?waffleFilter=(expression:'host.ip%20%3A%20151.101.202.217',kind:kuery)"`; - -exports[`getInfraHref getInfraIpHref returns a url for ors between multiple ips 1`] = `"foo/app/metrics/inventory?waffleFilter=(expression:'host.ip%20%3A%20152.151.23.192%20or%20host.ip%20%3A%20151.101.202.217',kind:kuery)"`; - -exports[`getInfraHref getInfraKubernetesHref creates a link for valid parameters 1`] = `"foo/app/metrics/link-to/pod-detail/test-pod-uid"`; - -exports[`getInfraHref getInfraKubernetesHref does not specify a base path when none is available 1`] = `"/app/metrics/link-to/pod-detail/test-pod-uid"`; - -exports[`getInfraHref getInfraKubernetesHref selects the first pod uid when there are multiple 1`] = `"/app/metrics/link-to/pod-detail/test-pod-uid"`; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_logging_href.test.ts.snap b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_logging_href.test.ts.snap deleted file mode 100644 index cfac6ce133c8a..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/__snapshots__/get_logging_href.test.ts.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`getLoggingHref creates a container href with base path when present 1`] = `"bar/app/logs?logFilter=(expression:'container.id%20:%20test-container-id',kind:kuery)"`; - -exports[`getLoggingHref creates a container href without a base path if it's an empty string 1`] = `"/app/logs?logFilter=(expression:'container.id%20:%20test-container-id',kind:kuery)"`; - -exports[`getLoggingHref creates a pod href with base path when present 1`] = `"bar/app/logs?logFilter=(expression:'pod.uid%20:%20test-pod-id',kind:kuery)"`; - -exports[`getLoggingHref creates a pod href without a base path when it's an empty string 1`] = `"/app/logs?logFilter=(expression:'pod.uid%20:%20test-pod-id',kind:kuery)"`; - -exports[`getLoggingHref creates an ip href with base path when present 1`] = `"bar/app/logs?logFilter=(expression:'pod.uid%20:%20test-pod-id',kind:kuery)"`; - -exports[`getLoggingHref creates an ip href without a base path when it's an empty string 1`] = `"/app/logs?logFilter=(expression:'host.ip%20%3A%20151.101.202.217',kind:kuery)"`; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_apm_href.test.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_apm_href.test.ts index db49e95896ac1..f27ed78d593ac 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_apm_href.test.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_apm_href.test.ts @@ -5,7 +5,7 @@ */ import { getApmHref } from '../get_apm_href'; -import { MonitorSummary } from '../../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../../common/runtime_types'; describe('getApmHref', () => { let summary: MonitorSummary; @@ -29,7 +29,7 @@ describe('getApmHref', () => { uid: 'test-pod-id', }, }, - timestamp: '123', + timestamp: 123, }, ], timestamp: '123', @@ -43,11 +43,15 @@ describe('getApmHref', () => { it('creates href with base path when present', () => { const result = getApmHref(summary, 'foo', 'now-15m', 'now'); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"foo/app/apm#/services?kuery=url.domain:%20%22www.elastic.co%22&rangeFrom=now-15m&rangeTo=now"` + ); }); it('does not add a base path or extra slash when base path is empty string', () => { const result = getApmHref(summary, '', 'now-15m', 'now'); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"/app/apm#/services?kuery=url.domain:%20%22www.elastic.co%22&rangeFrom=now-15m&rangeTo=now"` + ); }); }); diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_infra_href.test.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_infra_href.test.ts index c2360c321da8f..ee5db74af22c2 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_infra_href.test.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_infra_href.test.ts @@ -5,7 +5,7 @@ */ import { getInfraContainerHref, getInfraKubernetesHref, getInfraIpHref } from '../get_infra_href'; -import { MonitorSummary } from '../../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../../common/runtime_types'; describe('getInfraHref', () => { let summary: MonitorSummary; @@ -13,7 +13,6 @@ describe('getInfraHref', () => { summary = { monitor_id: 'foo', state: { - summary: {}, checks: [ { monitor: { @@ -28,9 +27,11 @@ describe('getInfraHref', () => { uid: 'test-pod-uid', }, }, - timestamp: '123', + timestamp: 123, }, ], + summary: {}, + url: {}, timestamp: '123', }, }; @@ -38,11 +39,15 @@ describe('getInfraHref', () => { it('getInfraContainerHref creates a link for valid parameters', () => { const result = getInfraContainerHref(summary, 'foo'); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"foo/app/metrics/link-to/container-detail/test-container-id"` + ); }); it('getInfraContainerHref does not specify a base path when none is available', () => { - expect(getInfraContainerHref(summary, '')).toMatchSnapshot(); + expect(getInfraContainerHref(summary, '')).toMatchInlineSnapshot( + `"/app/metrics/link-to/container-detail/test-container-id"` + ); }); it('getInfraContainerHref returns undefined when no container id is present', () => { @@ -65,7 +70,7 @@ describe('getInfraHref', () => { uid: 'test-pod-uid', }, }, - timestamp: '123', + timestamp: 123, }, { monitor: { @@ -80,10 +85,12 @@ describe('getInfraHref', () => { uid: 'test-pod-uid-bar', }, }, - timestamp: '123', + timestamp: 123, }, ]; - expect(getInfraContainerHref(summary, 'bar')).toMatchSnapshot(); + expect(getInfraContainerHref(summary, 'bar')).toMatchInlineSnapshot( + `"bar/app/metrics/link-to/container-detail/test-container-id"` + ); }); it('getInfraContainerHref returns undefined when checks are undefined', () => { @@ -94,11 +101,13 @@ describe('getInfraHref', () => { it('getInfraKubernetesHref creates a link for valid parameters', () => { const result = getInfraKubernetesHref(summary, 'foo'); expect(result).not.toBeUndefined(); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot(`"foo/app/metrics/link-to/pod-detail/test-pod-uid"`); }); it('getInfraKubernetesHref does not specify a base path when none is available', () => { - expect(getInfraKubernetesHref(summary, '')).toMatchSnapshot(); + expect(getInfraKubernetesHref(summary, '')).toMatchInlineSnapshot( + `"/app/metrics/link-to/pod-detail/test-pod-uid"` + ); }); it('getInfraKubernetesHref returns undefined when no pod data is present', () => { @@ -121,7 +130,7 @@ describe('getInfraHref', () => { uid: 'test-pod-uid', }, }, - timestamp: '123', + timestamp: 123, }, { monitor: { @@ -136,10 +145,12 @@ describe('getInfraHref', () => { uid: 'test-pod-uid-bar', }, }, - timestamp: '123', + timestamp: 123, }, ]; - expect(getInfraKubernetesHref(summary, '')).toMatchSnapshot(); + expect(getInfraKubernetesHref(summary, '')).toMatchInlineSnapshot( + `"/app/metrics/link-to/pod-detail/test-pod-uid"` + ); }); it('getInfraKubernetesHref returns undefined when checks are undefined', () => { @@ -148,17 +159,21 @@ describe('getInfraHref', () => { }); it('getInfraKubernetesHref returns undefined when checks are null', () => { - summary.state.checks![0]!.kubernetes!.pod!.uid = null; + delete summary.state.checks![0]!.kubernetes!.pod!.uid; expect(getInfraKubernetesHref(summary, '')).toBeUndefined(); }); it('getInfraIpHref creates a link for valid parameters', () => { const result = getInfraIpHref(summary, 'bar'); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"bar/app/metrics/inventory?waffleFilter=(expression:'host.ip%20%3A%20151.101.202.217',kind:kuery)"` + ); }); it('getInfraIpHref does not specify a base path when none is available', () => { - expect(getInfraIpHref(summary, '')).toMatchSnapshot(); + expect(getInfraIpHref(summary, '')).toMatchInlineSnapshot( + `"/app/metrics/inventory?waffleFilter=(expression:'host.ip%20%3A%20151.101.202.217',kind:kuery)"` + ); }); it('getInfraIpHref returns undefined when ip is undefined', () => { @@ -167,14 +182,14 @@ describe('getInfraHref', () => { }); it('getInfraIpHref returns undefined when ip is null', () => { - summary.state.checks![0].monitor.ip = null; + delete summary.state.checks![0].monitor.ip; expect(getInfraIpHref(summary, 'foo')).toBeUndefined(); }); it('getInfraIpHref returns a url for ors between multiple ips', () => { summary.state.checks = [ { - timestamp: '123', + timestamp: 123, monitor: { ip: '152.151.23.192', status: 'up', @@ -193,10 +208,12 @@ describe('getInfraHref', () => { uid: 'test-pod-uid', }, }, - timestamp: '123', + timestamp: 123, }, ]; - expect(getInfraIpHref(summary, 'foo')).toMatchSnapshot(); + expect(getInfraIpHref(summary, 'foo')).toMatchInlineSnapshot( + `"foo/app/metrics/inventory?waffleFilter=(expression:'host.ip%20%3A%20152.151.23.192%20or%20host.ip%20%3A%20151.101.202.217',kind:kuery)"` + ); }); it('getInfraIpHref returns undefined if checks are undefined', () => { diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_logging_href.test.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_logging_href.test.ts index 1117fa1429962..b188a8d1b8ef6 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_logging_href.test.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/__tests__/get_logging_href.test.ts @@ -9,7 +9,7 @@ import { getLoggingKubernetesHref, getLoggingIpHref, } from '../get_logging_href'; -import { MonitorSummary } from '../../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../../common/runtime_types'; describe('getLoggingHref', () => { let summary: MonitorSummary; @@ -33,10 +33,11 @@ describe('getLoggingHref', () => { uid: 'test-pod-id', }, }, - timestamp: '123', + timestamp: 123, }, ], timestamp: '123', + url: {}, }, }; }); @@ -44,37 +45,49 @@ describe('getLoggingHref', () => { it('creates a container href with base path when present', () => { const result = getLoggingContainerHref(summary, 'bar'); expect(result).not.toBeUndefined(); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"bar/app/logs?logFilter=(expression:'container.id%20:%20test-container-id',kind:kuery)"` + ); }); it(`creates a container href without a base path if it's an empty string`, () => { const result = getLoggingContainerHref(summary, ''); expect(result).not.toBeUndefined(); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"/app/logs?logFilter=(expression:'container.id%20:%20test-container-id',kind:kuery)"` + ); }); it(`creates an ip href with base path when present`, () => { const result = getLoggingKubernetesHref(summary, 'bar'); expect(result).not.toBeUndefined(); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"bar/app/logs?logFilter=(expression:'pod.uid%20:%20test-pod-id',kind:kuery)"` + ); }); it('creates a pod href with base path when present', () => { const result = getLoggingKubernetesHref(summary, 'bar'); expect(result).not.toBeUndefined(); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"bar/app/logs?logFilter=(expression:'pod.uid%20:%20test-pod-id',kind:kuery)"` + ); }); it(`creates a pod href without a base path when it's an empty string`, () => { const result = getLoggingKubernetesHref(summary, ''); expect(result).not.toBeUndefined(); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"/app/logs?logFilter=(expression:'pod.uid%20:%20test-pod-id',kind:kuery)"` + ); }); it(`creates an ip href without a base path when it's an empty string`, () => { const result = getLoggingIpHref(summary, ''); expect(result).not.toBeUndefined(); - expect(result).toMatchSnapshot(); + expect(result).toMatchInlineSnapshot( + `"/app/logs?logFilter=(expression:'host.ip%20%3A%20151.101.202.217',kind:kuery)"` + ); }); it('returns undefined if necessary container is not present', () => { @@ -83,7 +96,7 @@ describe('getLoggingHref', () => { }); it('returns undefined if necessary container is null', () => { - summary.state.checks![0].container!.id = null; + delete summary.state.checks![0].container!.id; expect(getLoggingContainerHref(summary, '')).toBeUndefined(); }); @@ -93,7 +106,7 @@ describe('getLoggingHref', () => { }); it('returns undefined if necessary pod is null', () => { - summary.state.checks![0].kubernetes!.pod!.uid = null; + delete summary.state.checks![0].kubernetes!.pod!.uid; expect(getLoggingKubernetesHref(summary, '')).toBeUndefined(); }); @@ -103,7 +116,7 @@ describe('getLoggingHref', () => { }); it('returns undefined ip href if ip is null', () => { - summary.state.checks![0].monitor.ip = null; + delete summary.state.checks![0].monitor.ip; expect(getLoggingIpHref(summary, '')).toBeUndefined(); }); }); diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/build_href.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/build_href.ts index 19e437651090b..0f830435be89d 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/build_href.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/build_href.ts @@ -5,7 +5,7 @@ */ import { get } from 'lodash'; -import { Check } from '../../../../common/graphql/types'; +import { Check } from '../../../../common/runtime_types'; /** * Builds URLs to the designated features by extracting values from the provided diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.ts index aaa57acee6c6a..0ff5a8acb3367 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.ts @@ -6,7 +6,7 @@ import { get } from 'lodash'; import { addBasePath } from './add_base_path'; -import { MonitorSummary } from '../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../common/runtime_types'; export const getApmHref = ( summary: MonitorSummary, diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_infra_href.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_infra_href.ts index 73065be395c76..384067e4b033b 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_infra_href.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_infra_href.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { MonitorSummary } from '../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../common/runtime_types'; import { addBasePath } from './add_base_path'; import { buildHref } from './build_href'; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_logging_href.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_logging_href.ts index b97b5a34855fb..222c7b57c9272 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_logging_href.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/observability_integration/get_logging_href.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { MonitorSummary } from '../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../common/runtime_types'; import { addBasePath } from './add_base_path'; import { buildHref } from './build_href'; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/series_has_down_values.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/series_has_down_values.ts index 13079b912a147..4ebeb350ed892 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/series_has_down_values.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/series_has_down_values.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SummaryHistogramPoint } from '../../../common/graphql/types'; +import { HistogramPoint } from '../../../common/runtime_types'; -export const seriesHasDownValues = (series: SummaryHistogramPoint[] | null): boolean => { +export const seriesHasDownValues = (series: HistogramPoint[] | null): boolean => { return series ? series.some(point => !!point.down) : false; }; diff --git a/x-pack/legacy/plugins/uptime/public/lib/lib.ts b/x-pack/legacy/plugins/uptime/public/lib/lib.ts index aba151bf5aab3..6b6191441c931 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/lib.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/lib.ts @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { NormalizedCacheObject } from 'apollo-cache-inmemory'; -import ApolloClient from 'apollo-client'; -import React from 'react'; +import { ReactElement } from 'react'; import { ChromeBreadcrumb } from 'src/core/public'; import { UMBadge } from '../badge'; import { UptimeAppProps } from '../uptime_app'; @@ -19,9 +17,7 @@ export type UMUpdateBreadcrumbs = (breadcrumbs: ChromeBreadcrumb[]) => void; export type UMUpdateBadge = (badge: UMBadge) => void; -export type UMGraphQLClient = ApolloClient; // | OtherClientType - -export type BootstrapUptimeApp = (props: UptimeAppProps) => React.ReactElement; +export type BootstrapUptimeApp = (props: UptimeAppProps) => ReactElement; export interface UMFrameworkAdapter { render(element: any): void; diff --git a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx index 5550facaf42e9..5b51a208a4c37 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx @@ -5,20 +5,15 @@ */ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import React, { useContext, useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; -import { - MonitorList, - OverviewPageParsingErrorCallout, - StatusPanel, -} from '../components/functional'; +import { OverviewPageParsingErrorCallout, StatusPanel } from '../components/functional'; import { useUptimeTelemetry, UptimePage, useGetUrlParams } from '../hooks'; import { stringifyUrlParams } from '../lib/helper/stringify_url_params'; import { useTrackPageview } from '../../../../../plugins/observability/public'; import { DataPublicPluginSetup, IIndexPattern } from '../../../../../../src/plugins/data/public'; -import { UptimeThemeContext } from '../contexts'; -import { EmptyState, FilterGroup, KueryBar } from '../components/connected'; +import { EmptyState, FilterGroup, KueryBar, MonitorList } from '../components/connected'; import { useUpdateKueryString } from '../hooks'; import { PageHeader } from './page_header'; import { useBreadcrumbs } from '../hooks/use_breadcrumbs'; @@ -40,34 +35,9 @@ const EuiFlexItemStyled = styled(EuiFlexItem)` } `; -// TODO: these values belong deeper down in the monitor -// list pagination control, but are here temporarily until we -// are done removing GraphQL -const DEFAULT_PAGE_SIZE = 10; -const LOCAL_STORAGE_KEY = 'xpack.uptime.monitorList.pageSize'; -const getMonitorListPageSizeValue = () => { - const value = parseInt(localStorage.getItem(LOCAL_STORAGE_KEY) ?? '', 10); - if (isNaN(value)) { - return DEFAULT_PAGE_SIZE; - } - return value; -}; - export const OverviewPageComponent = ({ autocomplete, indexPattern, setEsKueryFilters }: Props) => { - const { colors } = useContext(UptimeThemeContext); - // TODO: this is temporary until we migrate the monitor list to our Redux implementation - const [monitorListPageSize, setMonitorListPageSize] = useState( - getMonitorListPageSizeValue() - ); const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = useGetUrlParams(); - const { - dateRangeStart, - dateRangeEnd, - pagination, - statusFilter, - search, - filters: urlFilters, - } = params; + const { search, filters: urlFilters } = params; useUptimeTelemetry(UptimePage.Overview); @@ -80,13 +50,6 @@ export const OverviewPageComponent = ({ autocomplete, indexPattern, setEsKueryFi setEsKueryFilters(esFilters ?? ''); }, [esFilters, setEsKueryFilters]); - const sharedProps = { - dateRangeStart, - dateRangeEnd, - statusFilter, - filters: esFilters, - }; - const linkParameters = stringifyUrlParams(params, true); const heading = i18n.translate('xpack.uptime.overviewPage.headerText', { @@ -117,20 +80,7 @@ export const OverviewPageComponent = ({ autocomplete, indexPattern, setEsKueryFi - +
); diff --git a/x-pack/legacy/plugins/uptime/public/queries/monitor_states_query.ts b/x-pack/legacy/plugins/uptime/public/queries/monitor_states_query.ts deleted file mode 100644 index 676e638c239de..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/queries/monitor_states_query.ts +++ /dev/null @@ -1,110 +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 monitorStatesQueryString = ` -query MonitorStates($dateRangeStart: String!, $dateRangeEnd: String!, $pagination: String, $filters: String, $statusFilter: String, $pageSize: Int) { - monitorStates: getMonitorStates( - dateRangeStart: $dateRangeStart - dateRangeEnd: $dateRangeEnd - pagination: $pagination - filters: $filters - statusFilter: $statusFilter - pageSize: $pageSize - ) { - prevPagePagination - nextPagePagination - totalSummaryCount - summaries { - monitor_id - histogram { - count - points { - timestamp - up - down - } - } - state { - agent { - id - } - checks { - agent { - id - } - container { - id - } - kubernetes { - pod { - uid - } - } - monitor { - ip - name - status - } - observer { - geo { - name - location { - lat - lon - } - } - } - timestamp - } - geo { - name - location { - lat - lon - } - } - observer { - geo { - name - location { - lat - lon - } - } - } - monitor { - id - name - status - type - } - summary { - up - down - geo { - name - location { - lat - lon - } - } - } - url { - full - domain - } - timestamp - } - } - } -} -`; - -export const monitorStatesQuery = gql` - ${monitorStatesQueryString} -`; diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/index.ts b/x-pack/legacy/plugins/uptime/public/state/actions/index.ts index 4563e6bfc4f0e..0dc6baa0b2e50 100644 --- a/x-pack/legacy/plugins/uptime/public/state/actions/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/actions/index.ts @@ -7,6 +7,7 @@ export * from './overview_filters'; export * from './snapshot'; export * from './ui'; +export * from './monitor_list'; export * from './monitor_status'; export * from './index_patternts'; export * from './ping'; diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/monitor_list.ts b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_list.ts new file mode 100644 index 0000000000000..ee2267a9058af --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_list.ts @@ -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 { FetchMonitorStatesQueryArgs, MonitorSummaryResult } from '../../../common/runtime_types'; + +export const getMonitorList = createAction('GET_MONITOR_LIST'); +export const getMonitorListSuccess = createAction('GET_MONITOR_LIST_SUCCESS'); +export const getMonitorListFailure = createAction('GET_MONITOR_LIST_FAIL'); diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts index e8c862e209739..3d480e66c9e0b 100644 --- a/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts +++ b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts @@ -3,6 +3,7 @@ * 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 { QueryParams } from './types'; import { Ping } from '../../../common/runtime_types'; 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 793762c0f4a10..a50afb3f866de 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/index.ts @@ -5,6 +5,7 @@ */ export * from './monitor'; +export * from './monitor_list'; export * from './overview_filters'; export * from './snapshot'; export * from './monitor_status'; diff --git a/x-pack/legacy/plugins/uptime/public/state/api/monitor_list.ts b/x-pack/legacy/plugins/uptime/public/state/api/monitor_list.ts new file mode 100644 index 0000000000000..084bcb4bd2a91 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/api/monitor_list.ts @@ -0,0 +1,19 @@ +/* + * 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 { API_URLS } from '../../../common/constants'; +import { apiService } from './utils'; +import { + FetchMonitorStatesQueryArgs, + MonitorSummaryResult, + MonitorSummaryResultType, +} from '../../../common/runtime_types'; + +export const fetchMonitorList = async ( + params: FetchMonitorStatesQueryArgs +): Promise => { + return await apiService.get(API_URLS.MONITOR_LIST, params, MonitorSummaryResultType); +}; 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 8df11312b6455..739179c5bbeae 100644 --- a/x-pack/legacy/plugins/uptime/public/state/effects/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/effects/index.ts @@ -8,6 +8,7 @@ import { fork } from 'redux-saga/effects'; import { fetchMonitorDetailsEffect } from './monitor'; import { fetchOverviewFiltersEffect } from './overview_filters'; import { fetchSnapshotCountEffect } from './snapshot'; +import { fetchMonitorListEffect } from './monitor_list'; import { fetchMonitorStatusEffect } from './monitor_status'; import { fetchDynamicSettingsEffect, setDynamicSettingsEffect } from './dynamic_settings'; import { fetchIndexPatternEffect } from './index_pattern'; @@ -20,6 +21,7 @@ export function* rootEffect() { yield fork(fetchMonitorDetailsEffect); yield fork(fetchSnapshotCountEffect); yield fork(fetchOverviewFiltersEffect); + yield fork(fetchMonitorListEffect); yield fork(fetchMonitorStatusEffect); yield fork(fetchDynamicSettingsEffect); yield fork(setDynamicSettingsEffect); diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/monitor_list.ts b/x-pack/legacy/plugins/uptime/public/state/effects/monitor_list.ts new file mode 100644 index 0000000000000..b607641ecd7d0 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/effects/monitor_list.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 { getMonitorList, getMonitorListSuccess, getMonitorListFailure } from '../actions'; +import { fetchMonitorList } from '../api'; +import { fetchEffectFactory } from './fetch_effect'; + +export function* fetchMonitorListEffect() { + yield takeLatest( + getMonitorList, + fetchEffectFactory(fetchMonitorList, getMonitorListSuccess, getMonitorListFailure) + ); +} 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 0a3ff35df0599..294bde2f277ec 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 { monitorListReducer } from './monitor_list'; import { dynamicSettingsReducer } from './dynamic_settings'; import { indexPatternReducer } from './index_pattern'; import { pingReducer } from './ping'; @@ -23,6 +24,7 @@ export const rootReducer = combineReducers({ overviewFilters: overviewFiltersReducer, snapshot: snapshotReducer, ui: uiReducer, + monitorList: monitorListReducer, monitorStatus: monitorStatusReducer, dynamicSettings: dynamicSettingsReducer, indexPattern: indexPatternReducer, diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_duration.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_duration.ts index 0e1771c393e50..ec6b374c1057c 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_duration.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_duration.ts @@ -24,9 +24,9 @@ const initialState: MonitorDuration = { errors: [], }; -type PayLoad = MonitorDurationResult & Error; +type Payload = MonitorDurationResult & Error; -export const monitorDurationReducer = handleActions( +export const monitorDurationReducer = handleActions( { [String(getMonitorDurationAction)]: (state: MonitorDuration) => ({ ...state, diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_list.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_list.ts new file mode 100644 index 0000000000000..cf895aebeb755 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_list.ts @@ -0,0 +1,51 @@ +/* + * 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 { getMonitorList, getMonitorListSuccess, getMonitorListFailure } from '../actions'; +import { MonitorSummaryResult } from '../../../common/runtime_types'; + +export interface MonitorList { + list: MonitorSummaryResult; + error?: Error; + loading: boolean; +} + +export const initialState: MonitorList = { + list: { + nextPagePagination: null, + prevPagePagination: null, + summaries: [], + totalSummaryCount: 0, + }, + loading: false, +}; + +type Payload = MonitorSummaryResult & Error; + +export const monitorListReducer = handleActions( + { + [String(getMonitorList)]: (state: MonitorList) => ({ + ...state, + loading: true, + }), + [String(getMonitorListSuccess)]: ( + state: MonitorList, + action: Action + ) => ({ + ...state, + loading: false, + error: undefined, + list: { ...action.payload }, + }), + [String(getMonitorListFailure)]: (state: MonitorList, action: Action) => ({ + ...state, + error: 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 77902f347f6f9..2b7c04178e9b4 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 @@ -71,6 +71,15 @@ describe('state selectors', () => { loading: false, errors: [], }, + monitorList: { + list: { + prevPagePagination: null, + nextPagePagination: null, + summaries: [], + totalSummaryCount: 0, + }, + loading: false, + }, ml: { mlJob: { data: null, 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 37695e4274306..dc5df3f93804d 100644 --- a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts @@ -92,3 +92,8 @@ export const selectMonitorStatusAlert = ({ indexPattern, overviewFilters, ui }: export const indexStatusSelector = ({ indexStatus }: AppState) => { return indexStatus.indexStatus; }; + +export const monitorListSelector = ({ monitorList, ui: { lastRefresh } }: AppState) => ({ + monitorList, + lastRefresh, +}); diff --git a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx index dafb20dc9c323..556e5b9bf299e 100644 --- a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx +++ b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx @@ -7,13 +7,12 @@ import { EuiPage, EuiErrorBoundary } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useEffect } from 'react'; -import { ApolloProvider } from 'react-apollo'; import { Provider as ReduxProvider } from 'react-redux'; import { BrowserRouter as Router } from 'react-router-dom'; import { I18nStart, ChromeBreadcrumb, CoreStart } from 'src/core/public'; import { PluginsSetup } from 'ui/new_platform/new_platform'; import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; -import { UMGraphQLClient, UMUpdateBadge } from './lib/lib'; +import { UMUpdateBadge } from './lib/lib'; import { UptimeRefreshContextProvider, UptimeSettingsContextProvider, @@ -39,7 +38,6 @@ export interface UptimeAppColors { export interface UptimeAppProps { basePath: string; canSave: boolean; - client: UMGraphQLClient; core: CoreStart; darkMode: boolean; i18n: I18nStart; @@ -59,7 +57,6 @@ const Application = (props: UptimeAppProps) => { const { basePath, canSave, - client, core, darkMode, i18n: i18nCore, @@ -97,25 +94,23 @@ const Application = (props: UptimeAppProps) => { - - - - - - -
- - -
-
-
-
-
-
-
+ + + + + +
+ + +
+
+
+
+
+
diff --git a/x-pack/legacy/plugins/uptime/scripts/gql_gen.json b/x-pack/legacy/plugins/uptime/scripts/gql_gen.json deleted file mode 100644 index 87b8233dd1eeb..0000000000000 --- a/x-pack/legacy/plugins/uptime/scripts/gql_gen.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "flattenTypes": true, - "generatorConfig": {}, - "primitives": { - "String": "string", - "Int": "number", - "Float": "number", - "Boolean": "boolean", - "ID": "string" - } -} diff --git a/x-pack/legacy/plugins/uptime/scripts/infer_graphql_types.js b/x-pack/legacy/plugins/uptime/scripts/infer_graphql_types.js deleted file mode 100644 index 2499e15bf4e23..0000000000000 --- a/x-pack/legacy/plugins/uptime/scripts/infer_graphql_types.js +++ /dev/null @@ -1,45 +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. - */ - -require('../../../../../src/setup_node_env'); - -const { resolve } = require('path'); -// eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved -const { generate } = require('graphql-code-generator'); - -const CONFIG_PATH = resolve(__dirname, 'gql_gen.json'); -const OUTPUT_INTROSPECTION_PATH = resolve('common', 'graphql', 'introspection.json'); -const OUTPUT_TYPES_PATH = resolve('common', 'graphql', 'types.ts'); -const SCHEMA_PATH = resolve(__dirname, 'graphql_schemas.ts'); - -async function main() { - await generate( - { - args: [], - config: CONFIG_PATH, - out: OUTPUT_INTROSPECTION_PATH, - overwrite: true, - schema: SCHEMA_PATH, - template: 'graphql-codegen-introspection-template', - }, - true - ); - await generate( - { - args: [], - config: CONFIG_PATH, - out: OUTPUT_TYPES_PATH, - overwrite: true, - schema: SCHEMA_PATH, - template: 'graphql-codegen-typescript-template', - }, - true - ); -} - -if (require.main === module) { - main(); -} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 72b55121bbec0..2f05088c4a62b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -16241,7 +16241,6 @@ "xpack.uptime.emptyStateError.notAuthorized": "アップタイムデータの表示が承認されていません。システム管理者にお問い合わせください。", "xpack.uptime.emptyStateError.notFoundPage": "ページが見つかりません", "xpack.uptime.emptyStateError.title": "エラー", - "xpack.uptime.errorMessage": "エラー: {message}", "xpack.uptime.featureCatalogueDescription": "エンドポイントヘルスチェックとアップタイム監視を行います。", "xpack.uptime.featureRegistry.uptimeFeatureName": "アップタイム", "xpack.uptime.filterBar.ariaLabel": "概要ページのインプットフィルター基準", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c1b4663da91e7..620aa6c7f225c 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -16246,7 +16246,6 @@ "xpack.uptime.emptyStateError.notAuthorized": "您无权查看 Uptime 数据,请联系系统管理员。", "xpack.uptime.emptyStateError.notFoundPage": "未找到页面", "xpack.uptime.emptyStateError.title": "错误", - "xpack.uptime.errorMessage": "错误:{message}", "xpack.uptime.featureCatalogueDescription": "执行终端节点运行状况检查和运行时间监测。", "xpack.uptime.featureRegistry.uptimeFeatureName": "运行时间", "xpack.uptime.filterBar.ariaLabel": "概览页面的输入筛选条件", diff --git a/x-pack/plugins/uptime/server/graphql/constants.ts b/x-pack/plugins/uptime/server/graphql/constants.ts deleted file mode 100644 index aba58f5c6c4a5..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/constants.ts +++ /dev/null @@ -1,7 +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. - */ - -export const DEFAULT_GRAPHQL_PATH = '/api/uptime/graphql'; diff --git a/x-pack/plugins/uptime/server/graphql/index.ts b/x-pack/plugins/uptime/server/graphql/index.ts deleted file mode 100644 index a88afd7ac769c..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/index.ts +++ /dev/null @@ -1,17 +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 { createMonitorStatesResolvers, monitorStatesSchema } from './monitor_states'; -import { pingsSchema } from './pings'; -import { CreateUMGraphQLResolvers } from './types'; -import { unsignedIntegerResolverFunctions, unsignedIntegerSchema } from './unsigned_int_scalar'; - -export { DEFAULT_GRAPHQL_PATH } from './constants'; -export const resolvers: CreateUMGraphQLResolvers[] = [ - createMonitorStatesResolvers, - unsignedIntegerResolverFunctions, -]; -export const typeDefs: any[] = [pingsSchema, unsignedIntegerSchema, monitorStatesSchema]; diff --git a/x-pack/plugins/uptime/server/graphql/monitor_states/index.ts b/x-pack/plugins/uptime/server/graphql/monitor_states/index.ts deleted file mode 100644 index fb0893dbc4dbf..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/monitor_states/index.ts +++ /dev/null @@ -1,8 +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. - */ - -export { createMonitorStatesResolvers } from './resolvers'; -export { monitorStatesSchema } from './schema.gql'; diff --git a/x-pack/plugins/uptime/server/graphql/monitor_states/resolvers.ts b/x-pack/plugins/uptime/server/graphql/monitor_states/resolvers.ts deleted file mode 100644 index 479c06234ca66..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/monitor_states/resolvers.ts +++ /dev/null @@ -1,76 +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 { CreateUMGraphQLResolvers, UMContext } from '../types'; -import { UMServerLibs } from '../../lib/lib'; -import { UMResolver } from '../../../../../legacy/plugins/uptime/common/graphql/resolver_types'; -import { - GetMonitorStatesQueryArgs, - MonitorSummaryResult, -} from '../../../../../legacy/plugins/uptime/common/graphql/types'; -import { CONTEXT_DEFAULTS } from '../../../../../legacy/plugins/uptime/common/constants'; -import { savedObjectsAdapter } from '../../lib/saved_objects'; - -export type UMGetMonitorStatesResolver = UMResolver< - MonitorSummaryResult | Promise, - any, - GetMonitorStatesQueryArgs, - UMContext ->; - -export const createMonitorStatesResolvers: CreateUMGraphQLResolvers = ( - libs: UMServerLibs -): { - Query: { - getMonitorStates: UMGetMonitorStatesResolver; - }; -} => { - return { - Query: { - async getMonitorStates( - _resolver, - { dateRangeStart, dateRangeEnd, filters, pagination, statusFilter, pageSize }, - { APICaller, savedObjectsClient } - ): Promise { - const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings( - savedObjectsClient - ); - - const decodedPagination = pagination - ? JSON.parse(decodeURIComponent(pagination)) - : CONTEXT_DEFAULTS.CURSOR_PAGINATION; - const [ - indexStatus, - { summaries, nextPagePagination, prevPagePagination }, - ] = await Promise.all([ - libs.requests.getIndexStatus({ callES: APICaller, dynamicSettings }), - libs.requests.getMonitorStates({ - callES: APICaller, - dynamicSettings, - dateRangeStart, - dateRangeEnd, - pagination: decodedPagination, - pageSize, - filters, - // this is added to make typescript happy, - // this sort of reassignment used to be further downstream but I've moved it here - // because this code is going to be decomissioned soon - statusFilter: statusFilter || undefined, - }), - ]); - - const totalSummaryCount = indexStatus?.docCount ?? 0; - - return { - summaries, - nextPagePagination, - prevPagePagination, - totalSummaryCount, - }; - }, - }, - }; -}; diff --git a/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts deleted file mode 100644 index 040ad99ac0c64..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts +++ /dev/null @@ -1,183 +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 monitorStatesSchema = gql` - "Represents a monitor's statuses for a period of time." - type SummaryHistogramPoint { - "The time at which these data were collected." - timestamp: UnsignedInteger! - "The number of _up_ documents." - up: Int! - "The number of _down_ documents." - down: Int! - } - - "Monitor status data over time." - type SummaryHistogram { - "The number of documents used to assemble the histogram." - count: Int! - "The individual histogram data points." - points: [SummaryHistogramPoint!]! - } - - type Agent { - id: String! - } - - type Check { - agent: Agent - container: StateContainer - kubernetes: StateKubernetes - monitor: CheckMonitor! - observer: CheckObserver - timestamp: String! - } - - type StateContainer { - id: String - } - - type StateKubernetes { - pod: StatePod - } - - type StatePod { - uid: String - } - - type CheckMonitor { - ip: String - name: String - status: String! - } - - type Location { - lat: Float - lon: Float - } - - type CheckGeo { - name: String - location: Location - } - - type CheckObserver { - geo: CheckGeo - } - - type StateGeo { - name: [String] - location: Location - } - - type StateObserver { - geo: StateGeo - } - - type MonitorState { - status: String - name: String - id: String - type: String - } - - type Summary { - up: Int - down: Int - geo: CheckGeo - } - - type MonitorSummaryUrl { - domain: String - fragment: String - full: String - original: String - password: String - path: String - port: Int - query: String - scheme: String - username: String - } - - type StateUrl { - domain: String - full: String - path: String - port: Int - scheme: String - } - - "Contains monitor transmission encryption information." - type StateTLS { - "The date and time after which the certificate is invalid." - certificate_not_valid_after: String - certificate_not_valid_before: String - certificates: String - rtt: RTT - } - - "Unifies the subsequent data for an uptime monitor." - type State { - "The agent processing the monitor." - agent: Agent - "There is a check object for each instance of the monitoring agent." - checks: [Check!] - geo: StateGeo - observer: StateObserver - monitor: MonitorState - summary: Summary! - timestamp: UnsignedInteger! - "Transport encryption information." - tls: [StateTLS] - url: StateUrl - } - - "Represents the current state and associated data for an Uptime monitor." - type MonitorSummary { - "The ID assigned by the config or generated by the user." - monitor_id: String! - "The state of the monitor and its associated details." - state: State! - histogram: SummaryHistogram - } - - "The primary object returned for monitor states." - type MonitorSummaryResult { - "Used to go to the next page of results" - prevPagePagination: String - "Used to go to the previous page of results" - nextPagePagination: String - "The objects representing the state of a series of heartbeat monitors." - summaries: [MonitorSummary!] - "The number of summaries." - totalSummaryCount: Int! - } - - enum CursorDirection { - AFTER - BEFORE - } - - enum SortOrder { - ASC - DESC - } - - type Query { - "Fetches the current state of Uptime monitors for the given parameters." - getMonitorStates( - dateRangeStart: String! - dateRangeEnd: String! - pagination: String - filters: String - statusFilter: String - pageSize: Int - ): MonitorSummaryResult - } -`; diff --git a/x-pack/plugins/uptime/server/graphql/pings/index.ts b/x-pack/plugins/uptime/server/graphql/pings/index.ts deleted file mode 100644 index 100ce29c398ec..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/pings/index.ts +++ /dev/null @@ -1,7 +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. - */ - -export { pingsSchema } from './schema.gql'; diff --git a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts deleted file mode 100644 index 179bca53db161..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts +++ /dev/null @@ -1,264 +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 pingsSchema = gql` - type PingResults { - "Total number of matching pings" - total: UnsignedInteger! - "Unique list of all locations the query matched" - locations: [String!]! - "List of pings " - pings: [Ping!]! - } - - type ContainerImage { - name: String - tag: String - } - - type Container { - id: String - image: ContainerImage - name: String - runtime: String - } - - type DocCount { - count: UnsignedInteger! - } - - "The monitor's status for a ping" - type Duration { - us: UnsignedInteger - } - - "An agent for recording a beat" - type Beat { - hostname: String - name: String - timezone: String - type: String - } - - type Docker { - id: String - image: String - name: String - } - - type ECS { - version: String - } - - type Error { - code: Int - message: String - type: String - } - - type OS { - family: String - kernel: String - platform: String - version: String - name: String - build: String - } - - "Geolocation data added via processors to enrich events." - type Geo { - "Name of the city in which the agent is running." - city_name: String - "The name of the continent on which the agent is running." - continent_name: String - "ISO designation for the agent's country." - country_iso_code: String - "The name of the agent's country." - country_name: String - "The lat/long of the agent." - location: String - "A name for the host's location, e.g. 'us-east-1' or 'LAX'." - name: String - "ISO designation of the agent's region." - region_iso_code: String - "Name of the region hosting the agent." - region_name: String - } - - type Host { - architecture: String - id: String - hostname: String - ip: String - mac: String - name: String - os: OS - } - - type HttpRTT { - content: Duration - response_header: Duration - total: Duration - validate: Duration - validate_body: Duration - write_request: Duration - } - - type HTTPBody { - "Size of HTTP response body in bytes" - bytes: UnsignedInteger - "Hash of the HTTP response body" - hash: String - "Response body of the HTTP Response. May be truncated based on client settings." - content: String - "Byte length of the content string, taking into account multibyte chars." - content_bytes: UnsignedInteger - } - - type HTTPResponse { - status_code: UnsignedInteger - body: HTTPBody - } - - type HTTP { - response: HTTPResponse - rtt: HttpRTT - url: String - } - - type ICMP { - requests: Int - rtt: Int - } - - type KubernetesContainer { - image: String - name: String - } - - type KubernetesNode { - name: String - } - - type KubernetesPod { - name: String - uid: String - } - - type Kubernetes { - container: KubernetesContainer - namespace: String - node: KubernetesNode - pod: KubernetesPod - } - - type MetaCloud { - availability_zone: String - instance_id: String - instance_name: String - machine_type: String - project_id: String - provider: String - region: String - } - - type Meta { - cloud: MetaCloud - } - - type Monitor { - duration: Duration - host: String - "The id of the monitor" - id: String - "The IP pinged by the monitor" - ip: String - "The name of the protocol being monitored" - name: String - "The protocol scheme of the monitored host" - scheme: String - "The status of the monitored host" - status: String - "The type of host being monitored" - type: String - check_group: String - } - - "Metadata added by a proccessor, which is specified in its configuration." - type Observer { - "Geolocation data for the agent." - geo: Geo - } - - type Resolve { - host: String - ip: String - rtt: Duration - } - - type RTT { - connect: Duration - handshake: Duration - validate: Duration - } - - type Socks5 { - rtt: RTT - } - - type TCP { - port: Int - rtt: RTT - } - - "Contains monitor transmission encryption information." - type PingTLS { - "The date and time after which the certificate is invalid." - certificate_not_valid_after: String - certificate_not_valid_before: String - certificates: String - rtt: RTT - } - - type URL { - full: String - scheme: String - domain: String - port: Int - path: String - query: String - } - - "A request sent from a monitor to a host" - type Ping { - "unique ID for this ping" - id: String! - "The timestamp of the ping's creation" - timestamp: String! - "The agent that recorded the ping" - beat: Beat - container: Container - docker: Docker - ecs: ECS - error: Error - host: Host - http: HTTP - icmp: ICMP - kubernetes: Kubernetes - meta: Meta - monitor: Monitor - observer: Observer - resolve: Resolve - socks5: Socks5 - summary: Summary - tags: String - tcp: TCP - tls: PingTLS - url: URL - } -`; diff --git a/x-pack/plugins/uptime/server/graphql/types.ts b/x-pack/plugins/uptime/server/graphql/types.ts deleted file mode 100644 index 5f0a6749eb599..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/types.ts +++ /dev/null @@ -1,23 +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 { RequestHandlerContext, CallAPIOptions, SavedObjectsClient } from 'src/core/server'; -import { UMServerLibs } from '../lib/lib'; - -export type UMContext = RequestHandlerContext & { - APICaller: ( - endpoint: string, - clientParams?: Record, - options?: CallAPIOptions | undefined - ) => Promise; - savedObjectsClient: SavedObjectsClient; -}; - -export interface UMGraphQLResolver { - Query?: any; -} - -export type CreateUMGraphQLResolvers = (libs: UMServerLibs) => any; diff --git a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_literal.test.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_literal.test.ts deleted file mode 100644 index 7c357abcf8e1d..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_literal.test.ts +++ /dev/null @@ -1,42 +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 { parseLiteral } from '../resolvers'; - -describe('parseLiteral', () => { - it('parses string literal of type IntValue', () => { - const result = parseLiteral({ - kind: 'IntValue', - value: '1562605032000', - }); - expect(result).toBe(1562605032000); - }); - - it('parses string literal of type FloatValue', () => { - const result = parseLiteral({ - kind: 'FloatValue', - value: '1562605032000.0', - }); - expect(result).toBe(1562605032000); - }); - - it('parses string literal of type String', () => { - const result = parseLiteral({ - kind: 'StringValue', - value: '1562605032000', - }); - expect(result).toBe(1562605032000); - }); - - it('returns `null` for unsupported types', () => { - expect( - parseLiteral({ - kind: 'EnumValue', - value: 'false', - }) - ).toBeNull(); - }); -}); diff --git a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_value.test.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_value.test.ts deleted file mode 100644 index cb8958918c6dc..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_value.test.ts +++ /dev/null @@ -1,19 +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 { parseValue } from '../resolvers'; - -describe('parseValue', () => { - it(`parses a number value and returns it if its > 0`, () => { - const result = parseValue('1562605032000'); - expect(result).toBe(1562605032000); - }); - - it(`parses a number and returns null if its value is < 0`, () => { - const result = parseValue('-1562605032000'); - expect(result).toBeNull(); - }); -}); diff --git a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/serialize.test.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/serialize.test.ts deleted file mode 100644 index 2271d12ee7e13..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/serialize.test.ts +++ /dev/null @@ -1,24 +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 { serialize } from '../resolvers'; - -describe('serialize', () => { - it('serializes date strings correctly', () => { - const result = serialize('2019-07-08T16:59:09.796Z'); - expect(result).toBe(1562605149796); - }); - - it('serializes timestamp strings correctly', () => { - const result = serialize('1562605032000'); - expect(result).toBe(1562605032000); - }); - - it('serializes non-date and non-numeric values to NaN', () => { - const result = serialize('foo'); - expect(result).toBeNaN(); - }); -}); diff --git a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/index.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/index.ts deleted file mode 100644 index a8819f543a851..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/index.ts +++ /dev/null @@ -1,8 +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. - */ - -export { unsignedIntegerResolverFunctions } from './resolvers'; -export { unsignedIntegerSchema } from './schema.gql'; diff --git a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/resolvers.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/resolvers.ts deleted file mode 100644 index 9b8fe145e7ff5..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/resolvers.ts +++ /dev/null @@ -1,51 +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 { GraphQLScalarType, Kind, ValueNode } from 'graphql'; -import { UMServerLibs } from '../../lib/lib'; -import { CreateUMGraphQLResolvers } from '../types'; - -export const serialize = (value: any): number => { - // `parseInt` will yield `2019` for a value such as "2019-07-08T16:59:09.796Z" - if (isNaN(Number(value))) { - return Date.parse(value); - } - return parseInt(value, 10); -}; - -export const parseValue = (value: any) => { - const parsed = parseInt(value, 10); - if (parsed < 0) { - return null; - } - return parsed; -}; - -export const parseLiteral = (ast: ValueNode) => { - switch (ast.kind) { - case Kind.INT: - case Kind.FLOAT: - case Kind.STRING: - return parseInt(ast.value, 10); - } - return null; -}; - -const unsignedIntegerScalar = new GraphQLScalarType({ - name: 'UnsignedInteger', - description: 'Represents an unsigned 32-bit integer', - serialize, - parseValue, - parseLiteral, -}); - -/** - * This scalar resolver will parse an integer string of > 32 bits and return a value of type `number`. - * This assumes that the code is running in an environment that supports big ints. - */ -export const unsignedIntegerResolverFunctions: CreateUMGraphQLResolvers = (libs: UMServerLibs) => ({ - UnsignedInteger: unsignedIntegerScalar, -}); diff --git a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/schema.gql.ts deleted file mode 100644 index 6af2c8bc8827f..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/schema.gql.ts +++ /dev/null @@ -1,11 +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 unsignedIntegerSchema = gql` - scalar UnsignedInteger -`; diff --git a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts index 47fe5f2af4263..98c6be5aa3c8e 100644 --- a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { GraphQLSchema } from 'graphql'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { IRouter, @@ -44,5 +43,4 @@ export interface UptimeCorePlugins { export interface UMBackendFrameworkAdapter { registerRoute(route: UMKibanaRoute): void; - registerGraphQLEndpoint(routePath: string, schema: GraphQLSchema): void; } diff --git a/x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts index 1f92c8212b393..0176471aec1be 100644 --- a/x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts @@ -4,9 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { GraphQLSchema } from 'graphql'; -import { schema as kbnSchema } from '@kbn/config-schema'; -import { runHttpQuery } from 'apollo-server-core'; import { UptimeCoreSetup } from './adapter_types'; import { UMBackendFrameworkAdapter } from './adapter_types'; import { UMKibanaRoute } from '../../../rest_api'; @@ -33,71 +30,4 @@ export class UMKibanaBackendFrameworkAdapter implements UMBackendFrameworkAdapte throw new Error(`Handler for method ${method} is not defined`); } } - - public registerGraphQLEndpoint(routePath: string, schema: GraphQLSchema): void { - this.server.route.post( - { - path: routePath, - validate: { - body: kbnSchema.object({ - operationName: kbnSchema.nullable(kbnSchema.string()), - query: kbnSchema.string(), - variables: kbnSchema.recordOf(kbnSchema.string(), kbnSchema.any()), - }), - }, - options: { - tags: ['access:uptime-read'], - }, - }, - async (context, request, resp): Promise => { - const { - core: { - elasticsearch: { - dataClient: { callAsCurrentUser }, - }, - }, - } = context; - const options = { - graphQLOptions: (_req: any) => { - return { - context: { - ...context, - APICaller: callAsCurrentUser, - savedObjectsClient: context.core.savedObjects.client, - }, - schema, - }; - }, - path: routePath, - route: { - tags: ['access:uptime-read'], - }, - }; - try { - const query = request.body as Record; - - const graphQLResponse = await runHttpQuery([request], { - method: 'POST', - options: options.graphQLOptions, - query, - }); - - return resp.ok({ - body: graphQLResponse, - headers: { - 'content-type': 'application/json', - }, - }); - } catch (error) { - if (error.isGraphQLError === true) { - return resp.internalError({ - body: { message: error.message }, - headers: { 'content-type': 'application/json' }, - }); - } - return resp.internalError(); - } - } - ); - } } diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts index 8393370e1516b..4ce7176b57b19 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts @@ -68,11 +68,11 @@ export const getMonitorDetails: UMElasticsearchQueryFn< const data = result.hits.hits[0]?._source; const monitorError: MonitorError | undefined = data?.error; - const errorTimeStamp: string | undefined = data?.['@timestamp']; + const errorTimestamp: string | undefined = data?.['@timestamp']; return { monitorId, error: monitorError, - timestamp: errorTimeStamp, + timestamp: errorTimestamp, }; }; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts index d7842d1a0b4aa..4b40943a85705 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts @@ -8,10 +8,11 @@ import { CONTEXT_DEFAULTS } from '../../../../../legacy/plugins/uptime/common/co import { fetchPage } from './search'; import { UMElasticsearchQueryFn } from '../adapters'; import { - MonitorSummary, SortOrder, CursorDirection, -} from '../../../../../legacy/plugins/uptime/common/graphql/types'; + MonitorSummary, +} from '../../../../../legacy/plugins/uptime/common/runtime_types'; + import { QueryContext } from './search'; export interface CursorPagination { diff --git a/x-pack/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts index f542773f32796..2a8f681ab3453 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts @@ -12,7 +12,7 @@ import { MonitorGroupsPage, } from '../fetch_page'; import { QueryContext } from '../query_context'; -import { MonitorSummary } from '../../../../../../../legacy/plugins/uptime/common/graphql/types'; +import { MonitorSummary } from '../../../../../../../legacy/plugins/uptime/common/runtime_types'; import { nextPagination, prevPagination, simpleQueryContext } from './test_helpers'; const simpleFixture: MonitorGroups[] = [ @@ -53,12 +53,16 @@ const simpleFetcher = (monitorGroups: MonitorGroups[]): MonitorGroupsFetcher => }; const simpleEnricher = (monitorGroups: MonitorGroups[]): MonitorEnricher => { - return async (queryContext: QueryContext, checkGroups: string[]): Promise => { + return async (_queryContext: QueryContext, checkGroups: string[]): Promise => { return checkGroups.map(cg => { const monitorGroup = monitorGroups.find(mg => mg.groups.some(g => g.checkGroup === cg))!; return { monitor_id: monitorGroup.id, - state: { summary: {}, timestamp: new Date(Date.parse('1999-12-31')).toISOString() }, + state: { + summary: {}, + timestamp: new Date(Date.parse('1999-12-31')).valueOf().toString(), + url: {}, + }, }; }); }; @@ -71,16 +75,37 @@ describe('fetching a page', () => { simpleFetcher(simpleFixture), simpleEnricher(simpleFixture) ); - expect(res).toEqual({ - items: [ - { - monitor_id: 'foo', - state: { summary: {}, timestamp: '1999-12-31T00:00:00.000Z' }, + expect(res).toMatchInlineSnapshot(` + Object { + "items": Array [ + Object { + "monitor_id": "foo", + "state": Object { + "summary": Object {}, + "timestamp": "946598400000", + "url": Object {}, + }, + }, + Object { + "monitor_id": "bar", + "state": Object { + "summary": Object {}, + "timestamp": "946598400000", + "url": Object {}, + }, + }, + ], + "nextPagePagination": Object { + "cursorDirection": "AFTER", + "cursorKey": "bar", + "sortOrder": "ASC", }, - { monitor_id: 'bar', state: { summary: {}, timestamp: '1999-12-31T00:00:00.000Z' } }, - ], - nextPagePagination: { cursorDirection: 'AFTER', sortOrder: 'ASC', cursorKey: 'bar' }, - prevPagePagination: { cursorDirection: 'BEFORE', sortOrder: 'ASC', cursorKey: 'foo' }, - }); + "prevPagePagination": Object { + "cursorDirection": "BEFORE", + "cursorKey": "foo", + "sortOrder": "ASC", + }, + } + `); }); }); diff --git a/x-pack/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts index a6c98541fba1d..84774cdeed856 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts @@ -9,7 +9,7 @@ import { CursorPagination } from '../types'; import { CursorDirection, SortOrder, -} from '../../../../../../../legacy/plugins/uptime/common/graphql/types'; +} from '../../../../../../../legacy/plugins/uptime/common/runtime_types'; describe(QueryContext, () => { // 10 minute range diff --git a/x-pack/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts index d1212daf5304f..47034c2130116 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts @@ -8,7 +8,7 @@ import { CursorPagination } from '../types'; import { CursorDirection, SortOrder, -} from '../../../../../../../legacy/plugins/uptime/common/graphql/types'; +} from '../../../../../../../legacy/plugins/uptime/common/runtime_types'; import { QueryContext } from '../query_context'; export const prevPagination = (key: any): CursorPagination => { diff --git a/x-pack/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts b/x-pack/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts index 1798550875276..4739c804d24e7 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts @@ -8,12 +8,12 @@ import { get, sortBy } from 'lodash'; import { QueryContext } from './query_context'; import { QUERY, STATES } from '../../../../../../legacy/plugins/uptime/common/constants'; import { - MonitorSummary, - SummaryHistogram, Check, + Histogram, + MonitorSummary, CursorDirection, SortOrder, -} from '../../../../../../legacy/plugins/uptime/common/graphql/types'; +} from '../../../../../../legacy/plugins/uptime/common/runtime_types'; import { MonitorEnricher } from './fetch_page'; export const enrichMonitorGroups: MonitorEnricher = async ( @@ -250,11 +250,8 @@ export const enrichMonitorGroups: MonitorEnricher = async ( const summaries: MonitorSummary[] = monitorBuckets.map((monitor: any) => { const monitorId = get(monitor, 'key.monitor_id'); monitorIds.push(monitorId); - let state = get(monitor, 'state.value'); - state = { - ...state, - timestamp: state['@timestamp'], - }; + const state: any = monitor.state?.value; + state.timestamp = state['@timestamp']; const { checks } = state; if (checks) { state.checks = sortBy(checks, checksSortBy); @@ -289,7 +286,7 @@ export const enrichMonitorGroups: MonitorEnricher = async ( const getHistogramForMonitors = async ( queryContext: QueryContext, monitorIds: string[] -): Promise<{ [key: string]: SummaryHistogram }> => { +): Promise<{ [key: string]: Histogram }> => { const params = { index: queryContext.heartbeatIndices, body: { diff --git a/x-pack/plugins/uptime/server/lib/requests/search/fetch_page.ts b/x-pack/plugins/uptime/server/lib/requests/search/fetch_page.ts index 62144dacbd377..84167840d5d9b 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/fetch_page.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/fetch_page.ts @@ -12,7 +12,7 @@ import { CursorDirection, MonitorSummary, SortOrder, -} from '../../../../../../legacy/plugins/uptime/common/graphql/types'; +} from '../../../../../../legacy/plugins/uptime/common/runtime_types'; import { enrichMonitorGroups } from './enrich_monitor_groups'; import { MonitorGroupIterator } from './monitor_group_iterator'; diff --git a/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts b/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts index 424c097853ad3..3449febfa5b05 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts @@ -5,7 +5,7 @@ */ import { get, set } from 'lodash'; -import { CursorDirection } from '../../../../../../legacy/plugins/uptime/common/graphql/types'; +import { CursorDirection } from '../../../../../../legacy/plugins/uptime/common/runtime_types'; import { QueryContext } from './query_context'; // This is the first phase of the query. In it, we find the most recent check groups that matched the given query. diff --git a/x-pack/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts b/x-pack/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts index 267551907c5e8..31d9166eb1e73 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts @@ -6,7 +6,7 @@ import { QueryContext } from './query_context'; import { fetchChunk } from './fetch_chunk'; -import { CursorDirection } from '../../../../../../legacy/plugins/uptime/common/graphql/types'; +import { CursorDirection } from '../../../../../../legacy/plugins/uptime/common/runtime_types'; import { MonitorGroups } from './fetch_page'; import { CursorPagination } from './types'; diff --git a/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts index 218eb2f121a81..43fc54fb25808 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts @@ -5,7 +5,7 @@ */ import { QueryContext } from './query_context'; -import { CursorDirection } from '../../../../../../legacy/plugins/uptime/common/graphql/types'; +import { CursorDirection } from '../../../../../../legacy/plugins/uptime/common/runtime_types'; import { MonitorGroups, MonitorLocCheckGroup } from './fetch_page'; /** diff --git a/x-pack/plugins/uptime/server/lib/requests/search/types.ts b/x-pack/plugins/uptime/server/lib/requests/search/types.ts index 42c98ace6e8f5..2ec52d400b597 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/types.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/types.ts @@ -7,7 +7,7 @@ import { CursorDirection, SortOrder, -} from '../../../../../../legacy/plugins/uptime/common/graphql/types'; +} from '../../../../../../legacy/plugins/uptime/common/runtime_types'; export interface CursorPagination { cursorKey?: any; diff --git a/x-pack/plugins/uptime/server/rest_api/index.ts b/x-pack/plugins/uptime/server/rest_api/index.ts index c0412e588fa93..ae1e499dcc26c 100644 --- a/x-pack/plugins/uptime/server/rest_api/index.ts +++ b/x-pack/plugins/uptime/server/rest_api/index.ts @@ -12,6 +12,7 @@ import { createGetSnapshotCount } from './snapshot'; import { UMRestApiRouteFactory } from './types'; import { createGetMonitorDetailsRoute, + createMonitorListRoute, createGetMonitorLocationsRoute, createGetStatusBarRoute, } from './monitors'; @@ -30,6 +31,7 @@ export const restApiRoutes: UMRestApiRouteFactory[] = [ createPostDynamicSettingsRoute, createGetMonitorDetailsRoute, createGetMonitorLocationsRoute, + createMonitorListRoute, createGetStatusBarRoute, createGetSnapshotCount, createLogPageViewRoute, diff --git a/x-pack/plugins/uptime/server/rest_api/monitors/index.ts b/x-pack/plugins/uptime/server/rest_api/monitors/index.ts index 51b39037049b5..256f885d550ed 100644 --- a/x-pack/plugins/uptime/server/rest_api/monitors/index.ts +++ b/x-pack/plugins/uptime/server/rest_api/monitors/index.ts @@ -5,5 +5,6 @@ */ export { createGetMonitorDetailsRoute } from './monitors_details'; +export { createMonitorListRoute } from './monitor_list'; export { createGetMonitorLocationsRoute } from './monitor_locations'; export { createGetStatusBarRoute } from './monitor_status'; diff --git a/x-pack/plugins/uptime/server/rest_api/monitors/monitor_list.ts b/x-pack/plugins/uptime/server/rest_api/monitors/monitor_list.ts new file mode 100644 index 0000000000000..5cb4e8a6241b7 --- /dev/null +++ b/x-pack/plugins/uptime/server/rest_api/monitors/monitor_list.ts @@ -0,0 +1,69 @@ +/* + * 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 { UMRestApiRouteFactory } from '../types'; +import { CONTEXT_DEFAULTS } from '../../../../../legacy/plugins/uptime/common/constants'; +import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants/rest_api'; + +export const createMonitorListRoute: UMRestApiRouteFactory = libs => ({ + method: 'GET', + path: API_URLS.MONITOR_LIST, + validate: { + query: schema.object({ + dateRangeStart: schema.string(), + dateRangeEnd: schema.string(), + filters: schema.maybe(schema.string()), + pagination: schema.maybe(schema.string()), + statusFilter: schema.maybe(schema.string()), + pageSize: schema.number(), + }), + }, + options: { + tags: ['access:uptime-read'], + }, + handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => { + const { + dateRangeStart, + dateRangeEnd, + filters, + pagination, + statusFilter, + pageSize, + } = request.query; + + const decodedPagination = pagination + ? JSON.parse(decodeURIComponent(pagination)) + : CONTEXT_DEFAULTS.CURSOR_PAGINATION; + const [indexStatus, { summaries, nextPagePagination, prevPagePagination }] = await Promise.all([ + libs.requests.getIndexStatus({ callES, dynamicSettings }), + libs.requests.getMonitorStates({ + callES, + dynamicSettings, + dateRangeStart, + dateRangeEnd, + pagination: decodedPagination, + pageSize, + filters, + // this is added to make typescript happy, + // this sort of reassignment used to be further downstream but I've moved it here + // because this code is going to be decomissioned soon + statusFilter: statusFilter || undefined, + }), + ]); + + const totalSummaryCount = indexStatus?.docCount ?? 0; + + return response.ok({ + body: { + summaries, + nextPagePagination, + prevPagePagination, + totalSummaryCount, + }, + }); + }, +}); diff --git a/x-pack/plugins/uptime/server/uptime_server.ts b/x-pack/plugins/uptime/server/uptime_server.ts index d4b38b8ad27a0..cc6fe85b80cb2 100644 --- a/x-pack/plugins/uptime/server/uptime_server.ts +++ b/x-pack/plugins/uptime/server/uptime_server.ts @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { makeExecutableSchema } from 'graphql-tools'; -import { DEFAULT_GRAPHQL_PATH, resolvers, typeDefs } from './graphql'; import { UMServerLibs } from './lib/lib'; import { createRouteWithAuth, restApiRoutes, uptimeRouteWrapper } from './rest_api'; import { UptimeCoreSetup, UptimeCorePlugins } from './lib/adapters'; @@ -23,10 +21,4 @@ export const initUptimeServer = ( uptimeAlertTypeFactories.forEach(alertTypeFactory => plugins.alerting.registerType(alertTypeFactory(server, libs)) ); - - const graphQLSchema = makeExecutableSchema({ - resolvers: resolvers.map(createResolversFn => createResolversFn(libs)), - typeDefs, - }); - libs.framework.registerGraphQLEndpoint(DEFAULT_GRAPHQL_PATH, graphQLSchema); }; diff --git a/x-pack/test/api_integration/apis/uptime/feature_controls.ts b/x-pack/test/api_integration/apis/uptime/feature_controls.ts index 8b82735fc38b0..6d125807e169d 100644 --- a/x-pack/test/api_integration/apis/uptime/feature_controls.ts +++ b/x-pack/test/api_integration/apis/uptime/feature_controls.ts @@ -26,17 +26,6 @@ export default function featureControlsTests({ getService }: FtrProviderContext) expect(result.response).to.have.property('statusCode', 200); }; - const executeRESTAPIQuery = async (username: string, password: string, spaceId?: string) => { - const basePath = spaceId ? `/s/${spaceId}` : ''; - - return await supertest - .get(basePath + API_URLS.INDEX_STATUS) - .auth(username, password) - .set('kbn-xsrf', 'foo') - .then((response: any) => ({ error: undefined, response })) - .catch((error: any) => ({ error, response: undefined })); - }; - const executePingsRequest = async (username: string, password: string, spaceId?: string) => { const basePath = spaceId ? `/s/${spaceId}` : ''; @@ -72,9 +61,6 @@ export default function featureControlsTests({ getService }: FtrProviderContext) full_name: 'a kibana user', }); - const graphQLResult = await executeRESTAPIQuery(username, password); - expect404(graphQLResult); - const pingsResult = await executePingsRequest(username, password); expect404(pingsResult); } finally { @@ -111,9 +97,6 @@ export default function featureControlsTests({ getService }: FtrProviderContext) full_name: 'a kibana user', }); - const graphQLResult = await executeRESTAPIQuery(username, password); - expectResponse(graphQLResult); - const pingsResult = await executePingsRequest(username, password); expectResponse(pingsResult); } finally { @@ -153,9 +136,6 @@ export default function featureControlsTests({ getService }: FtrProviderContext) full_name: 'a kibana user', }); - const graphQLResult = await executeRESTAPIQuery(username, password); - expect404(graphQLResult); - const pingsResult = await executePingsRequest(username, password); expect404(pingsResult); } finally { @@ -222,17 +202,11 @@ export default function featureControlsTests({ getService }: FtrProviderContext) }); it('user_1 can access APIs in space_1', async () => { - const graphQLResult = await executeRESTAPIQuery(username, password, space1Id); - expectResponse(graphQLResult); - const pingsResult = await executePingsRequest(username, password, space1Id); expectResponse(pingsResult); }); it(`user_1 can't access APIs in space_2`, async () => { - const graphQLResult = await executeRESTAPIQuery(username, password); - expect404(graphQLResult); - const pingsResult = await executePingsRequest(username, password); expect404(pingsResult); }); diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states.json deleted file mode 100644 index a748225dda7cf..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": null, - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0009-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0000-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0001-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0002-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0003-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0004-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0005-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0006-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0007-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0008-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0009-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_id_filtered.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_id_filtered.json deleted file mode 100644 index 44644be5a0724..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_id_filtered.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": null, - "nextPagePagination": null, - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0002-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_1.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_1.json deleted file mode 100644 index a748225dda7cf..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_1.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": null, - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0009-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0000-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0001-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0002-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0003-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0004-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0005-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0006-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0007-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0008-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0009-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_10.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_10.json deleted file mode 100644 index fbd0776fade62..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_10.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0090-intermittent\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": null, - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0090-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0091-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0092-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0093-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0094-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0095-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0096-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234376" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234376 - } - }, - { - "monitor_id": "0097-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234405" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234405 - } - }, - { - "monitor_id": "0098-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234406" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234406 - } - }, - { - "monitor_id": "0099-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234406" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234406 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_10_previous.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_10_previous.json deleted file mode 100644 index e630e227f473b..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_10_previous.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0080-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0089-up\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"AFTER\"}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0080-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0081-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0082-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0083-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0084-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0085-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0086-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0087-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0088-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0089-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_2.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_2.json deleted file mode 100644 index 26b4b1a195567..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_2.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0010-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0019-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0010-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0011-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0012-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0013-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0014-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0015-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0016-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0017-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0018-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0019-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_2_previous.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_2_previous.json deleted file mode 100644 index 0b93e66f50246..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_2_previous.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": null, - "nextPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0009-up\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"AFTER\"}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0000-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0001-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0002-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0003-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0004-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0005-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0006-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0007-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0008-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0009-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_3.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_3.json deleted file mode 100644 index 7b47742f8859a..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_3.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0020-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0029-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0020-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0021-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0022-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0023-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0024-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0025-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0026-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0027-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0028-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0029-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_3_previous.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_3_previous.json deleted file mode 100644 index 0d5a76059d004..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_3_previous.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0010-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0019-up\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"AFTER\"}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0010-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0011-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0012-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0013-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0014-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0015-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0016-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0017-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0018-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0019-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_4.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_4.json deleted file mode 100644 index 4caff800ac96e..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_4.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0030-intermittent\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0039-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0030-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0031-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0032-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0033-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0034-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0035-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0036-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0037-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0038-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0039-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_4_previous.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_4_previous.json deleted file mode 100644 index 02bd149b50247..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_4_previous.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0020-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0029-up\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"AFTER\"}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0020-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0021-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0022-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0023-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0024-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0025-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0026-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0027-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0028-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0029-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_5.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_5.json deleted file mode 100644 index 11e880f1ec329..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_5.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0040-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0049-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0040-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0041-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0042-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0043-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0044-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0045-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0046-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0047-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234390" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234390 - } - }, - { - "monitor_id": "0048-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234386" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234386 - } - }, - { - "monitor_id": "0049-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234405" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234405 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_5_previous.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_5_previous.json deleted file mode 100644 index 26cfa7c7162e8..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_5_previous.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0030-intermittent\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0039-up\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"AFTER\"}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0030-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0031-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0032-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0033-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0034-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0035-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0036-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0037-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0038-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0039-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_6.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_6.json deleted file mode 100644 index 8f4b5d4c52e71..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_6.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0050-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0059-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0050-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234386" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234386 - } - }, - { - "monitor_id": "0051-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0052-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0053-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0054-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0055-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0056-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0057-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0058-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0059-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_6_previous.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_6_previous.json deleted file mode 100644 index 50f8f61b13d68..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_6_previous.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0040-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0049-up\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"AFTER\"}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0040-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0041-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0042-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0043-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0044-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0045-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0046-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0047-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234390" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234390 - } - }, - { - "monitor_id": "0048-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234386" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234386 - } - }, - { - "monitor_id": "0049-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234405" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234405 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_7.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_7.json deleted file mode 100644 index 18ab2c6fdf336..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_7.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0060-intermittent\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0069-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0060-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0061-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0062-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0063-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0064-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0065-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0066-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0067-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0068-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0069-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_7_previous.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_7_previous.json deleted file mode 100644 index 825d6365e3a9d..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_7_previous.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0050-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0059-up\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"AFTER\"}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0050-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234386" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234386 - } - }, - { - "monitor_id": "0051-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0052-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0053-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0054-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0055-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0056-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0057-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0058-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0059-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_8.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_8.json deleted file mode 100644 index abb9bcdd804ed..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_8.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0070-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0079-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0070-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0071-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0072-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234376" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234376 - } - }, - { - "monitor_id": "0073-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234406" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234406 - } - }, - { - "monitor_id": "0074-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234410" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234410 - } - }, - { - "monitor_id": "0075-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234406" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234406 - } - }, - { - "monitor_id": "0076-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234387" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234387 - } - }, - { - "monitor_id": "0077-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234389" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234389 - } - }, - { - "monitor_id": "0078-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0079-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_8_previous.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_8_previous.json deleted file mode 100644 index 46a5f195e6a82..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_8_previous.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0060-intermittent\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0069-up\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"AFTER\"}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0060-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0061-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0062-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0063-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0064-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0065-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0066-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0067-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0068-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234374" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234374 - } - }, - { - "monitor_id": "0069-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_9.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_9.json deleted file mode 100644 index 035baf0ab5b5e..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_9.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0080-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorDirection\":\"AFTER\",\"sortOrder\":\"ASC\",\"cursorKey\":{\"monitor_id\":\"0089-up\"}}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0080-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0081-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0082-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234372" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234372 - } - }, - { - "monitor_id": "0083-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0084-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0085-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0086-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0087-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0088-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - }, - { - "monitor_id": "0089-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234373" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234373 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_9_previous.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_9_previous.json deleted file mode 100644 index a6d274056eec6..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_states_page_9_previous.json +++ /dev/null @@ -1,1609 +0,0 @@ -{ - "monitorStates": { - "prevPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0070-down\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"BEFORE\"}", - "nextPagePagination": "{\"cursorKey\":{\"monitor_id\":\"0079-up\"},\"sortOrder\":\"ASC\",\"cursorDirection\":\"AFTER\"}", - "totalSummaryCount": 2000, - "summaries": [ - { - "monitor_id": "0070-down", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172694000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172724000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172754000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172784000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172874000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172904000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172934000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172964000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173054000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173084000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173174000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173204000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173234000, - "up": 0, - "down": 1 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "down" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "down", - "type": null - }, - "summary": { - "up": 0, - "down": 1, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=400x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0071-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234375" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234375 - } - }, - { - "monitor_id": "0072-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234376" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234376 - } - }, - { - "monitor_id": "0073-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234406" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234406 - } - }, - { - "monitor_id": "0074-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234410" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234410 - } - }, - { - "monitor_id": "0075-intermittent", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 0, - "down": 1 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234406" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x5,500x1", - "domain": "localhost" - }, - "timestamp": 1568173234406 - } - }, - { - "monitor_id": "0076-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234387" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234387 - } - }, - { - "monitor_id": "0077-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234389" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234389 - } - }, - { - "monitor_id": "0078-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - }, - { - "monitor_id": "0079-up", - "histogram": { - "count": 20, - "points": [ - { - "timestamp": 1568172664000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172694000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172724000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172754000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172784000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172814000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172844000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172874000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172904000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172934000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172964000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568172994000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173024000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173054000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173084000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173114000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173144000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173174000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173204000, - "up": 1, - "down": 0 - }, - { - "timestamp": 1568173234000, - "up": 1, - "down": 0 - } - ] - }, - "state": { - "agent": null, - "checks": [ - { - "agent": { - "id": "04e1d082-65bc-4929-8d65-d0768a2621c4" - }, - "container": null, - "kubernetes": null, - "monitor": { - "ip": "127.0.0.1", - "name": "", - "status": "up" - }, - "observer": { - "geo": { - "name": "mpls", - "location": { - "lat": 37.926867976784706, - "lon": -78.02490200847387 - } - } - }, - "timestamp": "1568173234371" - } - ], - "geo": null, - "observer": { - "geo": { - "name": [ - "mpls" - ], - "location": null - } - }, - "monitor": { - "id": null, - "name": null, - "status": "up", - "type": null - }, - "summary": { - "up": 1, - "down": 0, - "geo": null - }, - "url": { - "full": "http://localhost:5678/pattern?r=200x1", - "domain": "localhost" - }, - "timestamp": 1568173234371 - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/index.ts b/x-pack/test/api_integration/apis/uptime/graphql/index.ts deleted file mode 100644 index 862cce47f257a..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/index.ts +++ /dev/null @@ -1,17 +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 { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function({ loadTestFile }: FtrProviderContext) { - describe('graphql', () => { - // each of these test files imports a GQL query from - // the uptime app and runs it against the live HTTP server, - // verifying the pre-loaded documents are returned in a way that - // matches the snapshots contained in './fixtures' - loadTestFile(require.resolve('./monitor_states')); - }); -} diff --git a/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts b/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts deleted file mode 100644 index 216560583249c..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/monitor_states.ts +++ /dev/null @@ -1,245 +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 expect from '@kbn/expect'; -import { expectFixtureEql } from './helpers/expect_fixture_eql'; -import { FtrProviderContext } from '../../../ftr_provider_context'; -import { makeChecksWithStatus } from './helpers/make_checks'; -import { monitorStatesQueryString } from '../../../../../legacy/plugins/uptime/public/queries/monitor_states_query'; -import { MonitorSummary } from '../../../../../legacy/plugins/uptime/common/graphql/types'; - -export default function({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - let dateRangeStart: string; - let dateRangeEnd: string; - - const getMonitorStates = async (variables: { [key: string]: any } = {}) => { - const query = { - operationName: 'MonitorStates', - query: monitorStatesQueryString, - variables: { - dateRangeStart, - dateRangeEnd, - pageSize: 10, - ...variables, - }, - }; - - const { - body: { data }, - } = await supertest - .post('/api/uptime/graphql') - .set('kbn-xsrf', 'foo') - .send({ ...query }); - - return data; - }; - - describe('monitor states', async () => { - describe('with real world data', () => { - before('load heartbeat data', () => getService('esArchiver').load('uptime/full_heartbeat')); - after('unload heartbeat index', () => - getService('esArchiver').unload('uptime/full_heartbeat') - ); - - before('set start/end', () => { - dateRangeStart = '2019-09-11T03:31:04.380Z'; - dateRangeEnd = '2019-09-11T03:40:34.410Z'; - }); - - it('will fetch monitor state data for the given filters and range', async () => { - const data: any = await getMonitorStates({ - statusFilter: 'up', - filters: - '{"bool":{"must":[{"match":{"monitor.id":{"query":"0002-up","operator":"and"}}}]}}', - }); - // await new Promise(r => setTimeout(r, 90000)); - expectFixtureEql(data, 'monitor_states_id_filtered'); - }); - - it('will fetch monitor state data for the given date range', async () => { - expectFixtureEql(await getMonitorStates(), 'monitor_states'); - }); - - it('can navigate forward and backward using pagination', async () => { - const expectedResultsCount = 100; - const expectedPageCount = expectedResultsCount / 10; - - let pagination: string | null = null; - for (let page = 1; page <= expectedPageCount; page++) { - const data: any = await getMonitorStates({ pagination }); - pagination = data.monitorStates.nextPagePagination; - expectFixtureEql(data, `monitor_states_page_${page}`); - - // Test to see if the previous page pagination works on every page (other than the first) - if (page > 1) { - const prevData = await getMonitorStates({ - pagination: data.monitorStates.prevPagePagination, - }); - expectFixtureEql(prevData, `monitor_states_page_${page}_previous`); - } - } - }); - }); - - describe('monitor state scoping', async () => { - const numIps = 4; // Must be > 2 for IP uniqueness checks - - before('load heartbeat data', () => getService('esArchiver').load('uptime/blank')); - after('unload heartbeat index', () => getService('esArchiver').unload('uptime/blank')); - - describe('query document scoping with mismatched check statuses', async () => { - let checks: any[] = []; - let nonSummaryIp: string | null = null; - const testMonitorId = 'scope-test-id'; - const makeApiParams = (monitorId: string, filterClauses: any[] = []): any => { - return { - filters: JSON.stringify({ - bool: { - filter: [{ match: { 'monitor.id': monitorId } }, ...filterClauses], - }, - }), - }; - }; - - before(async () => { - const es = getService('legacyEs'); - dateRangeStart = new Date().toISOString(); - checks = await makeChecksWithStatus(es, testMonitorId, 1, numIps, 1, {}, 'up', d => { - // turn an all up status into having at least one down - if (d.summary) { - d.monitor.status = 'down'; - d.summary.up--; - d.summary.down++; - } - return d; - }); - - dateRangeEnd = new Date().toISOString(); - nonSummaryIp = checks[0][0].monitor.ip; - }); - - it('should return all IPs', async () => { - const res = await getMonitorStates(makeApiParams(testMonitorId)); - - const uniqueIps = new Set(); - res.monitorStates.summaries[0].state.checks.forEach((c: any) => - uniqueIps.add(c.monitor.ip) - ); - - expect(uniqueIps.size).to.eql(4); - }); - - it('should match non summary documents without a status filter', async () => { - const params = makeApiParams(testMonitorId, [{ match: { 'monitor.ip': nonSummaryIp } }]); - - const nonSummaryRes = await getMonitorStates(params); - expect(nonSummaryRes.monitorStates.summaries.length).to.eql(1); - }); - - it('should not match non summary documents if the check status does not match the document status', async () => { - const params = makeApiParams(testMonitorId, [{ match: { 'monitor.ip': nonSummaryIp } }]); - params.statusFilter = 'down'; - - const nonSummaryRes = await getMonitorStates(params); - expect(nonSummaryRes.monitorStates.summaries.length).to.eql(0); - }); - - it('should not non match non summary documents if the check status does not match', async () => { - const params = makeApiParams(testMonitorId, [{ match: { 'monitor.ip': nonSummaryIp } }]); - params.statusFilter = 'up'; - - const nonSummaryRes = await getMonitorStates(params); - expect(nonSummaryRes.monitorStates.summaries.length).to.eql(0); - }); - - describe('matching outside of the date range', async () => { - before('set date range to future', () => { - const futureDate = new Date(); - - // Set dateRangeStart to one day from now - futureDate.setDate(futureDate.getDate() + 1); - dateRangeStart = futureDate.toISOString(); - - // Set dateRangeStart to two days from now - futureDate.setDate(futureDate.getDate() + 1); - dateRangeEnd = futureDate.toISOString(); - }); - - it('should not match any documents', async () => { - const params = makeApiParams(testMonitorId); - params.statusFilter = 'up'; - - const nonSummaryRes = await getMonitorStates(params); - expect(nonSummaryRes.monitorStates.summaries.length).to.eql(0); - }); - }); - }); - }); - - describe(' test status filter', async () => { - const upMonitorId = 'up-test-id'; - const downMonitorId = 'down-test-id'; - const mixMonitorId = 'mix-test-id'; - before('generate three monitors with up, down, mix state', async () => { - await getService('esArchiver').load('uptime/blank'); - - const es = getService('legacyEs'); - - const observer = { - geo: { - name: 'US-East', - location: '40.7128, -74.0060', - }, - }; - - // Generating three monitors each with two geo locations, - // One in a down state , - // One in an up state, - // One in a mix state - - dateRangeStart = new Date().toISOString(); - - await makeChecksWithStatus(es, upMonitorId, 1, 4, 1, {}, 'up'); - await makeChecksWithStatus(es, upMonitorId, 1, 4, 1, { observer }, 'up'); - - await makeChecksWithStatus(es, downMonitorId, 1, 4, 1, {}, 'down'); - await makeChecksWithStatus(es, downMonitorId, 1, 4, 1, { observer }, 'down'); - - await makeChecksWithStatus(es, mixMonitorId, 1, 4, 1, {}, 'up'); - await makeChecksWithStatus(es, mixMonitorId, 1, 4, 1, { observer }, 'down'); - - dateRangeEnd = new Date().toISOString(); - }); - - after('unload heartbeat index', () => getService('esArchiver').unload('uptime/blank')); - - it('should return all monitor when no status filter', async () => { - const { monitorStates } = await getMonitorStates({}); - expect(monitorStates.summaries.length).to.eql(3); - // Summaries are by default sorted by monitor names - expect( - monitorStates.summaries.map((summary: MonitorSummary) => summary.monitor_id) - ).to.eql([downMonitorId, mixMonitorId, upMonitorId]); - }); - - it('should return a monitor with mix state if check status filter is down', async () => { - const { monitorStates } = await getMonitorStates({ statusFilter: 'down' }); - expect(monitorStates.summaries.length).to.eql(2); - monitorStates.summaries.forEach((summary: MonitorSummary) => { - expect(summary.monitor_id).to.not.eql(upMonitorId); - }); - }); - - it('should not return a monitor with mix state if check status filter is up', async () => { - const { monitorStates } = await getMonitorStates({ statusFilter: 'up' }); - - expect(monitorStates.summaries.length).to.eql(1); - expect(monitorStates.summaries[0].monitor_id).to.eql(upMonitorId); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/uptime/index.ts b/x-pack/test/api_integration/apis/uptime/index.ts index 8def64b71a110..13af60196f00d 100644 --- a/x-pack/test/api_integration/apis/uptime/index.ts +++ b/x-pack/test/api_integration/apis/uptime/index.ts @@ -20,7 +20,6 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./get_all_pings')); - loadTestFile(require.resolve('./graphql')); loadTestFile(require.resolve('./rest')); }); } diff --git a/x-pack/test/api_integration/apis/uptime/rest/doc_count.ts b/x-pack/test/api_integration/apis/uptime/rest/doc_count.ts index 3f42511dd165c..5258426cf193c 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/doc_count.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/doc_count.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { FtrProviderContext } from '../../../ftr_provider_context'; -import { expectFixtureEql } from '../graphql/helpers/expect_fixture_eql'; +import { expectFixtureEql } from './helper/expect_fixture_eql'; import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants'; export default function({ getService }: FtrProviderContext) { diff --git a/x-pack/test/api_integration/apis/uptime/rest/filters.ts b/x-pack/test/api_integration/apis/uptime/rest/filters.ts index 6cec6143a6d7c..35bf32a1d404d 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/filters.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/filters.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { expectFixtureEql } from '../graphql/helpers/expect_fixture_eql'; +import { expectFixtureEql } from './helper/expect_fixture_eql'; import { FtrProviderContext } from '../../../ftr_provider_context'; const getApiPath = (dateRangeStart: string, dateRangeEnd: string, filters?: string) => diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/filters.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/filters.json similarity index 100% rename from x-pack/test/api_integration/apis/uptime/graphql/fixtures/filters.json rename to x-pack/test/api_integration/apis/uptime/rest/fixtures/filters.json diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_status.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_status.json similarity index 100% rename from x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_status.json rename to x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_status.json diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_status_all.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_status_all.json similarity index 100% rename from x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_status_all.json rename to x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_status_all.json diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitors_with_location.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitors_with_location.json similarity index 100% rename from x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitors_with_location.json rename to x-pack/test/api_integration/apis/uptime/rest/fixtures/monitors_with_location.json diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot.json similarity index 100% rename from x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot.json rename to x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot.json diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_empty.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_empty.json similarity index 100% rename from x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_empty.json rename to x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_empty.json diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_filtered_by_down.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_down.json similarity index 100% rename from x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_filtered_by_down.json rename to x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_down.json diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_filtered_by_up.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_up.json similarity index 100% rename from x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_filtered_by_up.json rename to x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_up.json diff --git a/x-pack/test/api_integration/apis/uptime/graphql/helpers/expect_fixture_eql.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/expect_fixture_eql.ts similarity index 87% rename from x-pack/test/api_integration/apis/uptime/graphql/helpers/expect_fixture_eql.ts rename to x-pack/test/api_integration/apis/uptime/rest/helper/expect_fixture_eql.ts index d5a4f3976e079..abf5ec6f697b0 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/helpers/expect_fixture_eql.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/helper/expect_fixture_eql.ts @@ -10,7 +10,6 @@ import { join } from 'path'; import { cloneDeep, isEqual } from 'lodash'; const fixturesDir = join(__dirname, '..', 'fixtures'); -const restFixturesDir = join(__dirname, '../../rest/', 'fixtures'); const excludeFieldsFrom = (from: any, excluder?: (d: any) => any): any => { const clone = cloneDeep(from); @@ -24,10 +23,7 @@ export const expectFixtureEql = (data: T, fixtureName: string, excluder?: (d: expect(data).not.to.eql(null); expect(data).not.to.eql(undefined); - let fixturePath = join(fixturesDir, `${fixtureName}.json`); - if (!fs.existsSync(fixturePath)) { - fixturePath = join(restFixturesDir, `${fixtureName}.json`); - } + const fixturePath = join(fixturesDir, `${fixtureName}.json`); excluder = excluder || (d => d); const dataExcluded = excludeFieldsFrom(data, excluder); diff --git a/x-pack/test/api_integration/apis/uptime/graphql/helpers/make_checks.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts similarity index 100% rename from x-pack/test/api_integration/apis/uptime/graphql/helpers/make_checks.ts rename to x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts 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 3f8df81856f5c..29755bbddbc86 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/index.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts @@ -42,6 +42,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./snapshot')); loadTestFile(require.resolve('./dynamic_settings')); + loadTestFile(require.resolve('./monitor_states_generated')); loadTestFile(require.resolve('./telemetry_collectors')); }); describe('with real-world data', () => { @@ -52,6 +53,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./ping_list')); loadTestFile(require.resolve('./monitor_duration')); loadTestFile(require.resolve('./doc_count')); + loadTestFile(require.resolve('./monitor_states_real_data')); }); }); } diff --git a/x-pack/test/api_integration/apis/uptime/rest/monitor_duration.ts b/x-pack/test/api_integration/apis/uptime/rest/monitor_duration.ts index acc50e9b8f3d6..7e93f9cfff8a1 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/monitor_duration.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/monitor_duration.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { expectFixtureEql } from '../graphql/helpers/expect_fixture_eql'; +import { expectFixtureEql } from './helper/expect_fixture_eql'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getService }: FtrProviderContext) { diff --git a/x-pack/test/api_integration/apis/uptime/rest/monitor_latest_status.ts b/x-pack/test/api_integration/apis/uptime/rest/monitor_latest_status.ts index 749b304c87ee3..6547816bb7c16 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/monitor_latest_status.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/monitor_latest_status.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { expectFixtureEql } from '../graphql/helpers/expect_fixture_eql'; +import { expectFixtureEql } from './helper/expect_fixture_eql'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getService }: FtrProviderContext) { diff --git a/x-pack/test/api_integration/apis/uptime/rest/monitor_states_generated.ts b/x-pack/test/api_integration/apis/uptime/rest/monitor_states_generated.ts new file mode 100644 index 0000000000000..3c17370532f91 --- /dev/null +++ b/x-pack/test/api_integration/apis/uptime/rest/monitor_states_generated.ts @@ -0,0 +1,193 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { makeChecksWithStatus } from './helper/make_checks'; +import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants'; +import { MonitorSummary } from '../../../../../legacy/plugins/uptime/common/runtime_types'; + +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + describe('monitor state scoping', async () => { + const numIps = 4; // Must be > 2 for IP uniqueness checks + + let dateRangeStart: string; + let dateRangeEnd: string; + + const getBaseUrl = (from: string, to: string) => + `${API_URLS.MONITOR_LIST}?dateRangeStart=${from}&dateRangeEnd=${to}&pageSize=10`; + + before('load heartbeat data', () => getService('esArchiver').load('uptime/blank')); + after('unload heartbeat index', () => getService('esArchiver').unload('uptime/blank')); + + describe('query document scoping with mismatched check statuses', async () => { + let checks: any[] = []; + let nonSummaryIp: string | null = null; + const testMonitorId = 'scope-test-id'; + const makeApiParams = (monitorId: string, filterClauses: any[] = []): any => { + return JSON.stringify({ + bool: { + filter: [{ match: { 'monitor.id': monitorId } }, ...filterClauses], + }, + }); + }; + + before(async () => { + const es = getService('legacyEs'); + dateRangeStart = new Date().toISOString(); + checks = await makeChecksWithStatus(es, testMonitorId, 1, numIps, 1, {}, 'up', d => { + // turn an all up status into having at least one down + if (d.summary) { + d.monitor.status = 'down'; + d.summary.up--; + d.summary.down++; + } + return d; + }); + + dateRangeEnd = new Date().toISOString(); + nonSummaryIp = checks[0][0].monitor.ip; + }); + + it('should return all IPs', async () => { + const filters = makeApiParams(testMonitorId); + const url = getBaseUrl(dateRangeStart, dateRangeEnd) + `&filters=${filters}`; + const apiResponse = await supertest.get(url); + const res = apiResponse.body; + + const uniqueIps = new Set(); + res.summaries[0].state.checks.forEach((c: any) => uniqueIps.add(c.monitor.ip)); + + expect(uniqueIps.size).to.eql(4); + }); + + it('should match non summary documents without a status filter', async () => { + const filters = makeApiParams(testMonitorId, [{ match: { 'monitor.ip': nonSummaryIp } }]); + + const url = getBaseUrl(dateRangeStart, dateRangeEnd) + `&filters=${filters}`; + const apiResponse = await supertest.get(url); + const nonSummaryRes = apiResponse.body; + expect(nonSummaryRes.summaries.length).to.eql(1); + }); + + it('should not match non summary documents if the check status does not match the document status', async () => { + const filters = makeApiParams(testMonitorId, [{ match: { 'monitor.ip': nonSummaryIp } }]); + const url = + getBaseUrl(dateRangeStart, dateRangeEnd) + `&filters=${filters}&statusFilter=down`; + + const apiResponse = await supertest.get(url); + const nonSummaryRes = apiResponse.body; + expect(nonSummaryRes.summaries.length).to.eql(0); + }); + + it('should not non match non summary documents if the check status does not match', async () => { + const filters = makeApiParams(testMonitorId, [{ match: { 'monitor.ip': nonSummaryIp } }]); + const url = + getBaseUrl(dateRangeStart, dateRangeEnd) + `&filters=${filters}&statusFilter=up`; + + const apiResponse = await supertest.get(url); + const nonSummaryRes = apiResponse.body; + expect(nonSummaryRes.summaries.length).to.eql(0); + }); + + describe('matching outside of the date range', async () => { + before('set date range to future', () => { + const futureDate = new Date(); + + // Set dateRangeStart to one day from now + futureDate.setDate(futureDate.getDate() + 1); + dateRangeStart = futureDate.toISOString(); + + // Set dateRangeStart to two days from now + futureDate.setDate(futureDate.getDate() + 1); + dateRangeEnd = futureDate.toISOString(); + }); + + it('should not match any documents', async () => { + const filters = makeApiParams(testMonitorId); + const url = + getBaseUrl(dateRangeStart, dateRangeEnd) + `&filters=${filters}&statusFilter=up`; + + const apiResponse = await supertest.get(url); + const nonSummaryRes = apiResponse.body; + expect(nonSummaryRes.summaries.length).to.eql(0); + }); + }); + }); + + describe('test status filter', async () => { + const upMonitorId = 'up-test-id'; + const downMonitorId = 'down-test-id'; + const mixMonitorId = 'mix-test-id'; + before('generate three monitors with up, down, mix state', async () => { + await getService('esArchiver').load('uptime/blank'); + + const es = getService('legacyEs'); + + const observer = { + geo: { + name: 'US-East', + location: '40.7128, -74.0060', + }, + }; + + // Generating three monitors each with two geo locations, + // One in a down state , + // One in an up state, + // One in a mix state + + dateRangeStart = new Date().toISOString(); + + await makeChecksWithStatus(es, upMonitorId, 1, 4, 1, {}, 'up'); + await makeChecksWithStatus(es, upMonitorId, 1, 4, 1, { observer }, 'up'); + + await makeChecksWithStatus(es, downMonitorId, 1, 4, 1, {}, 'down'); + await makeChecksWithStatus(es, downMonitorId, 1, 4, 1, { observer }, 'down'); + + await makeChecksWithStatus(es, mixMonitorId, 1, 4, 1, {}, 'up'); + await makeChecksWithStatus(es, mixMonitorId, 1, 4, 1, { observer }, 'down'); + + dateRangeEnd = new Date().toISOString(); + }); + + after('unload heartbeat index', () => getService('esArchiver').unload('uptime/blank')); + + it('should return all monitor when no status filter', async () => { + const apiResponse = await supertest.get(getBaseUrl(dateRangeStart, dateRangeEnd)); + const { summaries } = apiResponse.body; + expect(summaries.length).to.eql(3); + // Summaries are by default sorted by monitor names + expect(summaries.map((summary: MonitorSummary) => summary.monitor_id)).to.eql([ + downMonitorId, + mixMonitorId, + upMonitorId, + ]); + }); + + it('should return a monitor with mix state if check status filter is down', async () => { + const apiResponse = await supertest.get( + getBaseUrl(dateRangeStart, dateRangeEnd) + '&statusFilter=down' + ); + const { summaries } = apiResponse.body; + expect(summaries.length).to.eql(2); + summaries.forEach((summary: MonitorSummary) => { + expect(summary.monitor_id).to.not.eql(upMonitorId); + }); + }); + + it('should not return a monitor with mix state if check status filter is up', async () => { + const apiResponse = await supertest.get( + getBaseUrl(dateRangeStart, dateRangeEnd) + '&statusFilter=up' + ); + const { summaries } = apiResponse.body; + + expect(summaries.length).to.eql(1); + expect(summaries[0].monitor_id).to.eql(upMonitorId); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/uptime/rest/monitor_states_real_data.ts b/x-pack/test/api_integration/apis/uptime/rest/monitor_states_real_data.ts new file mode 100644 index 0000000000000..f1e37bff405fd --- /dev/null +++ b/x-pack/test/api_integration/apis/uptime/rest/monitor_states_real_data.ts @@ -0,0 +1,525 @@ +/* + * 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 expect from '@kbn/expect'; +import { isRight } from 'fp-ts/lib/Either'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants'; +import { MonitorSummaryResultType } from '../../../../../legacy/plugins/uptime/common/runtime_types'; + +interface ExpectedMonitorStatesPage { + response: any; + statesIds: string[]; + statuses: string[]; + absFrom: number; + absTo: number; + size: number; + totalCount: number; + prevPagination: null | string; + nextPagination: null | string; +} + +type PendingExpectedMonitorStatesPage = Pick< + ExpectedMonitorStatesPage, + 'statesIds' | 'statuses' | 'prevPagination' | 'nextPagination' +>; + +const checkMonitorStatesResponse = ({ + response, + statesIds, + statuses, + absFrom, + absTo, + size, + totalCount, + prevPagination, + nextPagination, +}: ExpectedMonitorStatesPage) => { + const decoded = MonitorSummaryResultType.decode(response); + expect(isRight(decoded)).to.be.ok(); + if (isRight(decoded)) { + const { summaries, prevPagePagination, nextPagePagination, totalSummaryCount } = decoded.right; + expect(summaries).to.have.length(size); + expect(summaries?.map(s => s.monitor_id)).to.eql(statesIds); + expect( + summaries?.map(s => (s.state.summary?.up && !s.state.summary?.down ? 'up' : 'down')) + ).to.eql(statuses); + (summaries ?? []).forEach(s => { + expect(s.state.url.full).to.be.ok(); + expect(s.histogram?.count).to.be(20); + (s.histogram?.points ?? []).forEach(point => { + expect(point.timestamp).to.be.greaterThan(absFrom); + expect(point.timestamp).to.be.lessThan(absTo); + }); + }); + expect(totalSummaryCount).to.be(totalCount); + expect(prevPagePagination).to.be(prevPagination); + expect(nextPagePagination).to.eql(nextPagination); + } +}; + +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + describe('monitor states endpoint', () => { + const from = '2019-09-11T03:30:04.380Z'; + const to = '2019-09-11T03:40:34.410Z'; + const absFrom = new Date(from).valueOf(); + const absTo = new Date(to).valueOf(); + + it('will fetch monitor state data for the given filters and range', async () => { + const statusFilter = 'up'; + const size = 10; + const filters = + '{"bool":{"must":[{"match":{"monitor.id":{"query":"0002-up","operator":"and"}}}]}}'; + const apiResponse = await supertest.get( + `${API_URLS.MONITOR_LIST}?dateRangeStart=${from}&dateRangeEnd=${to}&statusFilter=${statusFilter}&filters=${filters}&pageSize=${size}` + ); + checkMonitorStatesResponse({ + response: apiResponse.body, + statesIds: ['0002-up'], + statuses: ['up'], + absFrom, + absTo, + size: 1, + totalCount: 2000, + prevPagination: null, + nextPagination: null, + }); + }); + + it('can navigate forward and backward using pagination', async () => { + const expectedResultsCount = 100; + const size = 10; + const expectedPageCount = expectedResultsCount / size; + const expectedNextResults: PendingExpectedMonitorStatesPage[] = [ + { + statesIds: [ + '0000-intermittent', + '0001-up', + '0002-up', + '0003-up', + '0004-up', + '0005-up', + '0006-up', + '0007-up', + '0008-up', + '0009-up', + ], + statuses: ['up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0009-up"}}', + prevPagination: null, + }, + { + statesIds: [ + '0010-down', + '0011-up', + '0012-up', + '0013-up', + '0014-up', + '0015-intermittent', + '0016-up', + '0017-up', + '0018-up', + '0019-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0019-up"}}', + prevPagination: + '{"cursorKey":{"monitor_id":"0010-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0020-down', + '0021-up', + '0022-up', + '0023-up', + '0024-up', + '0025-up', + '0026-up', + '0027-up', + '0028-up', + '0029-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0029-up"}}', + prevPagination: + '{"cursorKey":{"monitor_id":"0020-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0030-intermittent', + '0031-up', + '0032-up', + '0033-up', + '0034-up', + '0035-up', + '0036-up', + '0037-up', + '0038-up', + '0039-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0039-up"}}', + prevPagination: + '{"cursorKey":{"monitor_id":"0030-intermittent"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0040-down', + '0041-up', + '0042-up', + '0043-up', + '0044-up', + '0045-intermittent', + '0046-up', + '0047-up', + '0048-up', + '0049-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0049-up"}}', + prevPagination: + '{"cursorKey":{"monitor_id":"0040-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0050-down', + '0051-up', + '0052-up', + '0053-up', + '0054-up', + '0055-up', + '0056-up', + '0057-up', + '0058-up', + '0059-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0059-up"}}', + prevPagination: + '{"cursorKey":{"monitor_id":"0050-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0060-intermittent', + '0061-up', + '0062-up', + '0063-up', + '0064-up', + '0065-up', + '0066-up', + '0067-up', + '0068-up', + '0069-up', + ], + statuses: ['up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0069-up"}}', + prevPagination: + '{"cursorKey":{"monitor_id":"0060-intermittent"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0070-down', + '0071-up', + '0072-up', + '0073-up', + '0074-up', + '0075-intermittent', + '0076-up', + '0077-up', + '0078-up', + '0079-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0079-up"}}', + prevPagination: + '{"cursorKey":{"monitor_id":"0070-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0080-down', + '0081-up', + '0082-up', + '0083-up', + '0084-up', + '0085-up', + '0086-up', + '0087-up', + '0088-up', + '0089-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0089-up"}}', + prevPagination: + '{"cursorKey":{"monitor_id":"0080-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0090-intermittent', + '0091-up', + '0092-up', + '0093-up', + '0094-up', + '0095-up', + '0096-up', + '0097-up', + '0098-up', + '0099-up', + ], + statuses: ['up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: null, + prevPagination: + '{"cursorKey":{"monitor_id":"0090-intermittent"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + ]; + + const expectedPrevResults: PendingExpectedMonitorStatesPage[] = [ + { + statesIds: [ + '0000-intermittent', + '0001-up', + '0002-up', + '0003-up', + '0004-up', + '0005-up', + '0006-up', + '0007-up', + '0008-up', + '0009-up', + ], + statuses: ['up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorKey":{"monitor_id":"0009-up"},"sortOrder":"ASC","cursorDirection":"AFTER"}', + prevPagination: null, + }, + { + statesIds: [ + '0010-down', + '0011-up', + '0012-up', + '0013-up', + '0014-up', + '0015-intermittent', + '0016-up', + '0017-up', + '0018-up', + '0019-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorKey":{"monitor_id":"0019-up"},"sortOrder":"ASC","cursorDirection":"AFTER"}', + prevPagination: + '{"cursorKey":{"monitor_id":"0010-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0020-down', + '0021-up', + '0022-up', + '0023-up', + '0024-up', + '0025-up', + '0026-up', + '0027-up', + '0028-up', + '0029-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorKey":{"monitor_id":"0029-up"},"sortOrder":"ASC","cursorDirection":"AFTER"}', + prevPagination: + '{"cursorKey":{"monitor_id":"0020-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0030-intermittent', + '0031-up', + '0032-up', + '0033-up', + '0034-up', + '0035-up', + '0036-up', + '0037-up', + '0038-up', + '0039-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorKey":{"monitor_id":"0039-up"},"sortOrder":"ASC","cursorDirection":"AFTER"}', + prevPagination: + '{"cursorKey":{"monitor_id":"0030-intermittent"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0040-down', + '0041-up', + '0042-up', + '0043-up', + '0044-up', + '0045-intermittent', + '0046-up', + '0047-up', + '0048-up', + '0049-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorKey":{"monitor_id":"0049-up"},"sortOrder":"ASC","cursorDirection":"AFTER"}', + prevPagination: + '{"cursorKey":{"monitor_id":"0040-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0050-down', + '0051-up', + '0052-up', + '0053-up', + '0054-up', + '0055-up', + '0056-up', + '0057-up', + '0058-up', + '0059-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorKey":{"monitor_id":"0059-up"},"sortOrder":"ASC","cursorDirection":"AFTER"}', + prevPagination: + '{"cursorKey":{"monitor_id":"0050-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0060-intermittent', + '0061-up', + '0062-up', + '0063-up', + '0064-up', + '0065-up', + '0066-up', + '0067-up', + '0068-up', + '0069-up', + ], + statuses: ['up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorKey":{"monitor_id":"0069-up"},"sortOrder":"ASC","cursorDirection":"AFTER"}', + prevPagination: + '{"cursorKey":{"monitor_id":"0060-intermittent"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0070-down', + '0071-up', + '0072-up', + '0073-up', + '0074-up', + '0075-intermittent', + '0076-up', + '0077-up', + '0078-up', + '0079-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorKey":{"monitor_id":"0079-up"},"sortOrder":"ASC","cursorDirection":"AFTER"}', + prevPagination: + '{"cursorKey":{"monitor_id":"0070-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + { + statesIds: [ + '0080-down', + '0081-up', + '0082-up', + '0083-up', + '0084-up', + '0085-up', + '0086-up', + '0087-up', + '0088-up', + '0089-up', + ], + statuses: ['down', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + nextPagination: + '{"cursorKey":{"monitor_id":"0089-up"},"sortOrder":"ASC","cursorDirection":"AFTER"}', + prevPagination: + '{"cursorKey":{"monitor_id":"0080-down"},"sortOrder":"ASC","cursorDirection":"BEFORE"}', + }, + ]; + + const totalCount = 2000; + let pagination: string | null = null; + for (let page = 1; page <= expectedPageCount; page++) { + const baseUrl = `${API_URLS.MONITOR_LIST}?dateRangeStart=${from}&dateRangeEnd=${to}&pageSize=${size}`; + const nextUrl: string = baseUrl + `&pagination=${pagination ?? ''}`; + const nextApiResponse = await supertest.get(nextUrl); + const nextData = nextApiResponse.body; + pagination = nextData.nextPagePagination; + checkMonitorStatesResponse({ + response: nextData, + ...expectedNextResults[page - 1], + absFrom, + absTo, + size, + totalCount, + }); + + // Test to see if the previous page pagination works on every page (other than the first) + if (page > 1) { + const prevUrl: string = baseUrl + `&pagination=${nextData.prevPagePagination}`; + const prevApiResponse = await supertest.get(prevUrl); + const prevData = prevApiResponse.body; + checkMonitorStatesResponse({ + response: prevData, + ...expectedPrevResults[page - 2], + absFrom, + absTo, + size, + totalCount, + }); + } + } + }); + + it('will fetch monitor state data for the given date range', async () => { + const LENGTH = 10; + const { body } = await supertest.get( + `${API_URLS.MONITOR_LIST}?dateRangeStart=${from}&dateRangeEnd=${to}&pageSize=${LENGTH}` + ); + checkMonitorStatesResponse({ + response: body, + statesIds: [ + '0000-intermittent', + '0001-up', + '0002-up', + '0003-up', + '0004-up', + '0005-up', + '0006-up', + '0007-up', + '0008-up', + '0009-up', + ], + statuses: ['up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up', 'up'], + absFrom, + absTo, + size: LENGTH, + totalCount: 2000, + prevPagination: null, + nextPagination: + '{"cursorDirection":"AFTER","sortOrder":"ASC","cursorKey":{"monitor_id":"0009-up"}}', + }); + }); + }); +} 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 index 0982d5fef7cb4..b1afe4c8e0d7d 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/ping_histogram.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/ping_histogram.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { expectFixtureEql } from '../graphql/helpers/expect_fixture_eql'; +import { expectFixtureEql } from './helper/expect_fixture_eql'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { assertCloseTo } from '../../../../../plugins/uptime/server/lib/helper'; diff --git a/x-pack/test/api_integration/apis/uptime/rest/snapshot.ts b/x-pack/test/api_integration/apis/uptime/rest/snapshot.ts index 20fe59d149ae8..9a8951741948e 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/snapshot.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/snapshot.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { expectFixtureEql } from '../graphql/helpers/expect_fixture_eql'; +import { expectFixtureEql } from './helper/expect_fixture_eql'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { makeChecksWithStatus, getChecksDateRange } from '../graphql/helpers/make_checks'; +import { makeChecksWithStatus, getChecksDateRange } from './helper/make_checks'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); diff --git a/x-pack/test/api_integration/apis/uptime/rest/telemetry_collectors.ts b/x-pack/test/api_integration/apis/uptime/rest/telemetry_collectors.ts index b2ec96be0f288..017ef02afe5ea 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/telemetry_collectors.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/telemetry_collectors.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants'; -import { makeChecksWithStatus } from '../graphql/helpers/make_checks'; +import { makeChecksWithStatus } from './helper/make_checks'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); diff --git a/x-pack/test/functional/apps/uptime/locations.ts b/x-pack/test/functional/apps/uptime/locations.ts index bbf50344f3493..e266594e6a762 100644 --- a/x-pack/test/functional/apps/uptime/locations.ts +++ b/x-pack/test/functional/apps/uptime/locations.ts @@ -5,7 +5,7 @@ */ import moment from 'moment'; -import { makeChecksWithStatus } from '../../../api_integration/apis/uptime/graphql/helpers/make_checks'; +import { makeChecksWithStatus } from '../../../api_integration/apis/uptime/rest/helper/make_checks'; import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ getPageObjects, getService }: FtrProviderContext) => { diff --git a/x-pack/test/functional/apps/uptime/settings.ts b/x-pack/test/functional/apps/uptime/settings.ts index 64cfee50ac982..e81bbc5ae42f9 100644 --- a/x-pack/test/functional/apps/uptime/settings.ts +++ b/x-pack/test/functional/apps/uptime/settings.ts @@ -10,7 +10,7 @@ import { defaultDynamicSettings, DynamicSettings, } from '../../../../legacy/plugins/uptime/common/runtime_types'; -import { makeChecks } from '../../../api_integration/apis/uptime/graphql/helpers/make_checks'; +import { makeChecks } from '../../../api_integration/apis/uptime/rest/helper/make_checks'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const { uptime: uptimePage } = getPageObjects(['uptime']); From 550d6af2cb2ef2cc03d1dd5745908f87286fe323 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 17 Apr 2020 18:07:27 +0200 Subject: [PATCH 18/22] Migrate rollup client side code (#63227) --- x-pack/.i18nrc.json | 2 +- x-pack/legacy/plugins/rollup/README.md | 12 ++--- x-pack/legacy/plugins/rollup/common/index.ts | 22 +------- x-pack/legacy/plugins/rollup/index.ts | 26 +-------- x-pack/legacy/plugins/rollup/public/legacy.ts | 13 ----- x-pack/plugins/rollup/common/index.ts | 27 ++++++++++ .../plugins/rollup/common/ui_metric.ts | 0 .../plugins/rollup/fixtures/index.js | 0 .../plugins/rollup/fixtures/job.js | 2 +- x-pack/plugins/rollup/kibana.json | 5 +- .../plugins/rollup/public/application.tsx | 6 ++- .../rollup/public/crud_app/_crud_app.scss | 0 .../plugins/rollup/public/crud_app/app.js | 3 +- .../rollup/public/crud_app/constants/index.js | 0 .../crud_app/constants/metrics_config.js | 0 .../rollup/public/crud_app/constants/paths.js | 0 .../components/field_list/field_list.js | 0 .../sections/components/field_list/index.js | 0 .../crud_app/sections/components/index.js | 0 .../confirm_delete_modal.js | 0 .../confirm_delete_modal/index.js | 0 .../components/job_action_menu/index.js | 0 .../job_action_menu.container.js | 0 .../job_action_menu/job_action_menu.js | 0 .../sections/components/job_details/index.js | 0 .../components/job_details/job_details.js | 0 .../components/job_details/tabs/index.js | 0 .../job_details/tabs/tab_histogram.js | 0 .../components/job_details/tabs/tab_json.js | 0 .../job_details/tabs/tab_metrics.js | 0 .../job_details/tabs/tab_request.js | 0 .../job_details/tabs/tab_summary.js | 0 .../components/job_details/tabs/tab_terms.js | 0 .../sections/components/job_status/index.js | 0 .../components/job_status/job_status.js | 0 .../rollup/public/crud_app/sections/index.js | 0 .../crud_app/sections/job_create/index.js | 0 .../job_create/job_create.container.js | 0 .../sections/job_create/job_create.js | 2 +- .../sections/job_create/navigation/index.js | 0 .../job_create/navigation/navigation.js | 0 .../steps/components/field_chooser.js | 0 .../job_create/steps/components/index.js | 0 .../job_create/steps/components/step_error.js | 0 .../sections/job_create/steps/index.js | 0 .../job_create/steps/step_date_histogram.js | 2 +- .../job_create/steps/step_histogram.js | 0 .../job_create/steps/step_logistics.js | 4 +- .../sections/job_create/steps/step_metrics.js | 0 .../sections/job_create/steps/step_review.js | 0 .../sections/job_create/steps/step_terms.js | 0 .../sections/job_create/steps_config/index.js | 4 +- .../validate_date_histogram_field.js | 0 .../validate_date_histogram_interval.js | 2 +- .../validate_histogram_interval.js | 0 .../job_create/steps_config/validate_id.js | 0 .../steps_config/validate_index_pattern.js | 2 +- .../steps_config/validate_metrics.js | 0 .../steps_config/validate_rollup_cron.js | 0 .../steps_config/validate_rollup_delay.js | 2 +- .../steps_config/validate_rollup_index.js | 0 .../steps_config/validate_rollup_page_size.js | 0 .../detail_panel/detail_panel.container.js | 0 .../job_list/detail_panel/detail_panel.js | 3 +- .../detail_panel/detail_panel.test.js | 7 ++- .../sections/job_list/detail_panel/index.js | 0 .../crud_app/sections/job_list/index.js | 0 .../sections/job_list/job_list.container.js | 0 .../crud_app/sections/job_list/job_list.js | 2 +- .../sections/job_list/job_list.test.js | 8 ++- .../sections/job_list/job_table/index.js | 0 .../job_list/job_table/job_table.container.js | 0 .../sections/job_list/job_table/job_table.js | 3 +- .../job_list/job_table/job_table.test.js | 7 ++- .../rollup/public/crud_app/services/api.js | 0 .../public/crud_app/services/api_errors.ts | 0 .../public/crud_app/services/breadcrumbs.js | 0 .../crud_app/services/documentation_links.js | 0 .../public/crud_app/services/filter_items.js | 0 .../crud_app/services/flatten_panel_tree.js | 0 .../public/crud_app/services/format_fields.js | 0 .../public/crud_app/services/http_provider.ts | 2 +- .../rollup/public/crud_app/services/index.js | 2 +- .../rollup/public/crud_app/services/jobs.js | 0 .../crud_app/services/noticeable_delay.js | 0 .../public/crud_app/services/query_params.js | 0 .../crud_app/services/retype_metrics.js | 0 .../public/crud_app/services/routing.js | 0 .../public/crud_app/services/sort_table.js | 0 .../crud_app/services/track_ui_metric.ts} | 10 ++-- .../public/crud_app/store/action_types.js | 0 .../store/actions/change_job_status.js | 0 .../crud_app/store/actions/clone_job.js | 0 .../crud_app/store/actions/create_job.js | 0 .../crud_app/store/actions/delete_jobs.js | 0 .../crud_app/store/actions/detail_panel.js | 0 .../public/crud_app/store/actions/index.js | 0 .../crud_app/store/actions/load_jobs.js | 0 .../crud_app/store/actions/refresh_jobs.js | 0 .../crud_app/store/actions/table_state.js | 0 .../rollup/public/crud_app/store/index.js | 0 .../crud_app/store/middleware/clone_job.js | 0 .../crud_app/store/middleware/detail_panel.js | 0 .../public/crud_app/store/middleware/index.js | 0 .../crud_app/store/reducers/clone_job.js | 0 .../crud_app/store/reducers/create_job.js | 0 .../crud_app/store/reducers/detail_panel.js | 0 .../public/crud_app/store/reducers/index.js | 0 .../public/crud_app/store/reducers/jobs.js | 0 .../crud_app/store/reducers/table_state.js | 0 .../crud_app/store/reducers/update_job.js | 0 .../public/crud_app/store/selectors/index.js | 0 .../rollup/public/crud_app/store/store.js | 0 .../public/extend_index_management/index.ts | 0 .../plugins/rollup/public/index.scss | 3 -- .../rollup/public/index.ts} | 4 +- .../components/rollup_prompt/index.js | 0 .../components/rollup_prompt/rollup_prompt.js | 0 .../rollup_index_pattern_creation_config.js | 2 +- .../rollup_index_pattern_list_config.js | 2 +- .../plugins/rollup/public/kibana_services.ts | 19 ++++++- .../plugins/rollup/public/plugin.ts | 40 +++++++++----- .../public/search/rollup_search_strategy.ts | 4 +- .../plugins/rollup/public/shared_imports.ts | 2 +- .../client_integration/helpers/constants.js | 0 .../test}/client_integration/helpers/index.js | 0 .../helpers/job_clone.helpers.js | 6 +-- .../helpers/job_create.helpers.js | 4 +- .../helpers/job_list.helpers.js | 6 +-- .../helpers/setup_context.tsx | 0 .../helpers/setup_environment.ts | 0 .../job_create_clone.test.js | 19 ++++--- .../job_create_date_histogram.test.js | 23 ++++---- .../job_create_histogram.test.js | 27 +++++----- .../job_create_logistics.test.js | 25 +++++---- .../job_create_metrics.test.js | 25 +++++---- .../job_create_review.test.js | 53 +++++++++++-------- .../job_create_terms.test.js | 21 ++++---- .../test}/client_integration/job_list.test.js | 27 ++++++---- .../client_integration/job_list_clone.test.js | 27 ++++++---- .../public/visualize/agg_type_field_filter.js | 0 .../public/visualize/agg_type_filter.js | 0 x-pack/plugins/rollup/server/plugin.ts | 23 +++++++- 143 files changed, 288 insertions(+), 254 deletions(-) delete mode 100644 x-pack/legacy/plugins/rollup/public/legacy.ts create mode 100644 x-pack/plugins/rollup/common/index.ts rename x-pack/{legacy => }/plugins/rollup/common/ui_metric.ts (100%) rename x-pack/{legacy => }/plugins/rollup/fixtures/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/fixtures/job.js (95%) rename x-pack/{legacy => }/plugins/rollup/public/application.tsx (87%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/_crud_app.scss (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/app.js (93%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/constants/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/constants/metrics_config.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/constants/paths.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/field_list/field_list.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/field_list/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/confirm_delete_modal.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_action_menu/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.container.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_details/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_details/job_details.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_details/tabs/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_histogram.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_json.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_metrics.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_request.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_summary.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_terms.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_status/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/components/job_status/job_status.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/job_create.container.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/job_create.js (99%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/navigation/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/components/field_chooser.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/components/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/components/step_error.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/step_date_histogram.js (99%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js (99%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/index.js (96%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_field.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_interval.js (95%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_histogram_interval.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_id.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_index_pattern.js (95%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_metrics.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_cron.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_delay.js (95%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_page_size.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.container.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.js (98%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js (98%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/detail_panel/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/job_list.container.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/job_list.js (98%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js (90%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/job_table/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.container.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js (99%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.test.js (96%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/api.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/api_errors.ts (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/breadcrumbs.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/documentation_links.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/filter_items.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/flatten_panel_tree.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/format_fields.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/http_provider.ts (91%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/index.js (95%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/jobs.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/noticeable_delay.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/query_params.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/retype_metrics.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/routing.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/services/sort_table.js (100%) rename x-pack/{legacy/plugins/rollup/public/crud_app/services/track_ui_metric.js => plugins/rollup/public/crud_app/services/track_ui_metric.ts} (70%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/action_types.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/actions/change_job_status.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/actions/clone_job.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/actions/create_job.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/actions/delete_jobs.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/actions/detail_panel.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/actions/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/actions/load_jobs.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/actions/refresh_jobs.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/actions/table_state.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/middleware/clone_job.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/middleware/detail_panel.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/middleware/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/reducers/clone_job.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/reducers/create_job.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/reducers/detail_panel.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/reducers/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/reducers/jobs.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/reducers/table_state.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/reducers/update_job.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/selectors/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/crud_app/store/store.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/extend_index_management/index.ts (100%) rename x-pack/{legacy => }/plugins/rollup/public/index.scss (67%) rename x-pack/{legacy/plugins/rollup/public/legacy_imports.ts => plugins/rollup/public/index.ts} (72%) rename x-pack/{legacy => }/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/index.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/rollup_prompt.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js (97%) rename x-pack/{legacy => }/plugins/rollup/public/index_pattern_list/rollup_index_pattern_list_config.js (93%) rename x-pack/{legacy => }/plugins/rollup/public/kibana_services.ts (57%) rename x-pack/{legacy => }/plugins/rollup/public/plugin.ts (73%) rename x-pack/{legacy => }/plugins/rollup/public/search/rollup_search_strategy.ts (96%) rename x-pack/{legacy => }/plugins/rollup/public/shared_imports.ts (76%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/helpers/constants.js (100%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/helpers/index.js (100%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/helpers/job_clone.helpers.js (83%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/helpers/job_create.helpers.js (96%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/helpers/job_list.helpers.js (74%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/helpers/setup_context.tsx (100%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/helpers/setup_environment.ts (100%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/job_create_clone.test.js (93%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/job_create_date_histogram.test.js (88%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/job_create_histogram.test.js (91%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/job_create_logistics.test.js (96%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/job_create_metrics.test.js (95%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/job_create_review.test.js (71%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/job_create_terms.test.js (93%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/job_list.test.js (77%) rename x-pack/{legacy/plugins/rollup/__jest__ => plugins/rollup/public/test}/client_integration/job_list_clone.test.js (74%) rename x-pack/{legacy => }/plugins/rollup/public/visualize/agg_type_field_filter.js (100%) rename x-pack/{legacy => }/plugins/rollup/public/visualize/agg_type_filter.js (100%) diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 50f36ddd21c97..14e958397a181 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -32,7 +32,7 @@ "xpack.remoteClusters": "plugins/remote_clusters", "xpack.painlessLab": "plugins/painless_lab", "xpack.reporting": ["plugins/reporting", "legacy/plugins/reporting"], - "xpack.rollupJobs": "legacy/plugins/rollup", + "xpack.rollupJobs": ["legacy/plugins/rollup", "plugins/rollup"], "xpack.searchProfiler": "plugins/searchprofiler", "xpack.security": ["legacy/plugins/security", "plugins/security"], "xpack.server": "legacy/server", diff --git a/x-pack/legacy/plugins/rollup/README.md b/x-pack/legacy/plugins/rollup/README.md index 6d04973de591e..3647be38b6a09 100644 --- a/x-pack/legacy/plugins/rollup/README.md +++ b/x-pack/legacy/plugins/rollup/README.md @@ -14,7 +14,7 @@ The rest of this doc dives into the implementation details of each of the above ## Create and manage rollup jobs -The most straight forward part of this plugin! A new app called Rollup Jobs is registered in the Management section and follows a typical CRUD UI pattern. This app allows users to create, start, stop, clone, and delete rollup jobs. There is no way to edit an existing rollup job; instead, the UI offers a cloning ability. The client-side portion of this app lives [here](public/crud_app) and uses endpoints registered [here](server/routes/api/jobs.js). +The most straight forward part of this plugin! A new app called Rollup Jobs is registered in the Management section and follows a typical CRUD UI pattern. This app allows users to create, start, stop, clone, and delete rollup jobs. There is no way to edit an existing rollup job; instead, the UI offers a cloning ability. The client-side portion of this app lives [here](../../../plugins/rollup/public/crud_app) and uses endpoints registered [here](server/routes/api/jobs.js). Refer to the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/rollup-getting-started.html) to understand rollup indices and how to create rollup jobs. @@ -22,22 +22,22 @@ Refer to the [Elasticsearch documentation](https://www.elastic.co/guide/en/elast Kibana uses index patterns to consume and visualize rollup indices. Typically, Kibana can inspect the indices captured by an index pattern, identify its aggregations and fields, and determine how to consume the data. Rollup indices don't contain this type of information, so we predefine how to consume a rollup index pattern with the type and typeMeta fields on the index pattern saved object. All rollup index patterns have `type` defined as "rollup" and `typeMeta` defined as an object of the index pattern's capabilities. -In the Index Pattern app, the "Create index pattern" button includes a context menu when a rollup index is detected. This menu offers items for creating a standard index pattern and a rollup index pattern. A [rollup config is registered to index pattern creation extension point](public/index_pattern_creation/rollup_index_pattern_creation_config.js). The context menu behavior in particular uses the `getIndexPatternCreationOption()` method. When the user chooses to create a rollup index pattern, this config changes the behavior of the index pattern creation wizard: +In the Index Pattern app, the "Create index pattern" button includes a context menu when a rollup index is detected. This menu offers items for creating a standard index pattern and a rollup index pattern. A [rollup config is registered to index pattern creation extension point](../../../plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js). The context menu behavior in particular uses the `getIndexPatternCreationOption()` method. When the user chooses to create a rollup index pattern, this config changes the behavior of the index pattern creation wizard: 1. Adds a `Rollup` badge to rollup indices using `getIndexTags()`. 2. Enforces index pattern rules using `checkIndicesForErrors()`. Rollup index patterns must match **one** rollup index, and optionally, any number of regular indices. A rollup index pattern configured with one or more regular indices is known as a "hybrid" index pattern. This allows the user to visualize historical (rollup) data and live (regular) data in the same visualization. 3. Routes to this plugin's [rollup `_fields_for_wildcard` endpoint](server/routes/api/index_patterns.js), instead of the standard one, using `getFetchForWildcardOptions()`, so that the internal rollup data field names are mapped to the original field names. 4. Writes additional information about aggregations, fields, histogram interval, and date histogram interval and timezone to the rollup index pattern saved object using `getIndexPatternMappings()`. This collection of information is referred to as its "capabilities". -Once a rollup index pattern is created, it is tagged with `Rollup` in the list of index patterns, and its details page displays capabilities information. This is done by registering [yet another config for the index pattern list](public/index_pattern_list/rollup_index_pattern_list_config.js) extension points. +Once a rollup index pattern is created, it is tagged with `Rollup` in the list of index patterns, and its details page displays capabilities information. This is done by registering [yet another config for the index pattern list](../../../plugins/rollup/public/index_pattern_list/rollup_index_pattern_list_config.js) extension points. ## Create visualizations from rollup index patterns This plugin enables the user to create visualizations from rollup data using the Visualize app, excluding TSVB, Vega, and Timelion. When Visualize sends search requests, this plugin routes the requests to the [Elasticsearch rollup search endpoint](https://www.elastic.co/guide/en/elasticsearch/reference/current/rollup-search.html), which searches the special document structure within rollup indices. The visualization options available to users are based on the capabilities of the rollup index pattern they're visualizing. -Routing to the Elasticsearch rollup search endpoint is done by creating an extension point in Courier, effectively allowing multiple "search strategies" to be registered. A [rollup search strategy](public/search/register.js) is registered by this plugin that queries [this plugin's rollup search endpoint](server/routes/api/search.js). +Routing to the Elasticsearch rollup search endpoint is done by creating an extension point in Courier, effectively allowing multiple "search strategies" to be registered. A [rollup search strategy](../../../plugins/rollup/public/search/register.js) is registered by this plugin that queries [this plugin's rollup search endpoint](server/routes/api/search.js). -Limiting visualization editor options is done by [registering configs](public/visualize/index.js) to various vis extension points. These configs use information stored on the rollup index pattern to limit: +Limiting visualization editor options is done by [registering configs](../../../plugins/rollup/public/visualize/index.js) to various vis extension points. These configs use information stored on the rollup index pattern to limit: * Available aggregation types * Available fields for a particular aggregation * Default and base interval for histogram aggregation @@ -47,6 +47,6 @@ Limiting visualization editor options is done by [registering configs](public/vi In Index Management, similar to system indices, rollup indices are hidden by default. A toggle is provided to show rollup indices and add a badge to the table rows. This is done by using Index Management's extension points. -The toggle and badge are registered on client-side [here](public/extend_index_management/index.js). +The toggle and badge are registered on client-side [here](../../../plugins/rollup/public/extend_index_management/index.js). Additional data needed to filter rollup indices in Index Management is provided with a [data enricher](rollup_data_enricher.js). diff --git a/x-pack/legacy/plugins/rollup/common/index.ts b/x-pack/legacy/plugins/rollup/common/index.ts index 4229803462203..526af055a3ef6 100644 --- a/x-pack/legacy/plugins/rollup/common/index.ts +++ b/x-pack/legacy/plugins/rollup/common/index.ts @@ -16,24 +16,4 @@ export const PLUGIN = { }, }; -export const CONFIG_ROLLUPS = 'rollups:enableIndexPatterns'; - -export const API_BASE_PATH = '/api/rollup'; - -export { - UIM_APP_NAME, - UIM_APP_LOAD, - UIM_JOB_CREATE, - UIM_JOB_DELETE, - UIM_JOB_DELETE_MANY, - UIM_JOB_START, - UIM_JOB_START_MANY, - UIM_JOB_STOP, - UIM_JOB_STOP_MANY, - UIM_SHOW_DETAILS_CLICK, - UIM_DETAIL_PANEL_SUMMARY_TAB_CLICK, - UIM_DETAIL_PANEL_TERMS_TAB_CLICK, - UIM_DETAIL_PANEL_HISTOGRAM_TAB_CLICK, - UIM_DETAIL_PANEL_METRICS_TAB_CLICK, - UIM_DETAIL_PANEL_JSON_TAB_CLICK, -} from './ui_metric'; +export * from '../../../../plugins/rollup/common'; diff --git a/x-pack/legacy/plugins/rollup/index.ts b/x-pack/legacy/plugins/rollup/index.ts index 621667f3618b2..f33ae7cfee0a2 100644 --- a/x-pack/legacy/plugins/rollup/index.ts +++ b/x-pack/legacy/plugins/rollup/index.ts @@ -4,40 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resolve } from 'path'; -import { i18n } from '@kbn/i18n'; import { PluginInitializerContext } from 'src/core/server'; import { RollupSetup } from '../../../plugins/rollup/server'; -import { PLUGIN, CONFIG_ROLLUPS } from './common'; +import { PLUGIN } from './common'; import { plugin } from './server'; export function rollup(kibana: any) { return new kibana.Plugin({ id: PLUGIN.ID, configPrefix: 'xpack.rollup', - publicDir: resolve(__dirname, 'public'), require: ['kibana', 'elasticsearch', 'xpack_main'], - uiExports: { - styleSheetPaths: resolve(__dirname, 'public/index.scss'), - managementSections: ['plugins/rollup/legacy'], - uiSettingDefaults: { - [CONFIG_ROLLUPS]: { - name: i18n.translate('xpack.rollupJobs.rollupIndexPatternsTitle', { - defaultMessage: 'Enable rollup index patterns', - }), - value: true, - description: i18n.translate('xpack.rollupJobs.rollupIndexPatternsDescription', { - defaultMessage: `Enable the creation of index patterns which capture rollup indices, - which in turn enable visualizations based on rollup data. Refresh - the page to apply the changes.`, - }), - category: ['rollups'], - }, - }, - indexManagement: ['plugins/rollup/legacy'], - visualize: ['plugins/rollup/legacy'], - search: ['plugins/rollup/legacy'], - }, init(server: any) { const { core: coreSetup, plugins } = server.newPlatform.setup; const { usageCollection, visTypeTimeseries, indexManagement } = plugins; diff --git a/x-pack/legacy/plugins/rollup/public/legacy.ts b/x-pack/legacy/plugins/rollup/public/legacy.ts deleted file mode 100644 index 83945110c2c76..0000000000000 --- a/x-pack/legacy/plugins/rollup/public/legacy.ts +++ /dev/null @@ -1,13 +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 { npSetup, npStart } from 'ui/new_platform'; -import { RollupPlugin } from './plugin'; - -const plugin = new RollupPlugin(); - -export const setup = plugin.setup(npSetup.core, npSetup.plugins); -export const start = plugin.start(npStart.core, npStart.plugins); diff --git a/x-pack/plugins/rollup/common/index.ts b/x-pack/plugins/rollup/common/index.ts new file mode 100644 index 0000000000000..aeffa3dc3959f --- /dev/null +++ b/x-pack/plugins/rollup/common/index.ts @@ -0,0 +1,27 @@ +/* + * 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 const CONFIG_ROLLUPS = 'rollups:enableIndexPatterns'; + +export const API_BASE_PATH = '/api/rollup'; + +export { + UIM_APP_NAME, + UIM_APP_LOAD, + UIM_JOB_CREATE, + UIM_JOB_DELETE, + UIM_JOB_DELETE_MANY, + UIM_JOB_START, + UIM_JOB_START_MANY, + UIM_JOB_STOP, + UIM_JOB_STOP_MANY, + UIM_SHOW_DETAILS_CLICK, + UIM_DETAIL_PANEL_SUMMARY_TAB_CLICK, + UIM_DETAIL_PANEL_TERMS_TAB_CLICK, + UIM_DETAIL_PANEL_HISTOGRAM_TAB_CLICK, + UIM_DETAIL_PANEL_METRICS_TAB_CLICK, + UIM_DETAIL_PANEL_JSON_TAB_CLICK, +} from './ui_metric'; diff --git a/x-pack/legacy/plugins/rollup/common/ui_metric.ts b/x-pack/plugins/rollup/common/ui_metric.ts similarity index 100% rename from x-pack/legacy/plugins/rollup/common/ui_metric.ts rename to x-pack/plugins/rollup/common/ui_metric.ts diff --git a/x-pack/legacy/plugins/rollup/fixtures/index.js b/x-pack/plugins/rollup/fixtures/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/fixtures/index.js rename to x-pack/plugins/rollup/fixtures/index.js diff --git a/x-pack/legacy/plugins/rollup/fixtures/job.js b/x-pack/plugins/rollup/fixtures/job.js similarity index 95% rename from x-pack/legacy/plugins/rollup/fixtures/job.js rename to x-pack/plugins/rollup/fixtures/job.js index 3889cc6087d83..310244a5031e7 100644 --- a/x-pack/legacy/plugins/rollup/fixtures/job.js +++ b/x-pack/plugins/rollup/fixtures/job.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getRandomString } from '../../../../test_utils'; +import { getRandomString } from '../../../test_utils'; const initialValues = { dateHistogramField: 'timestamp', diff --git a/x-pack/plugins/rollup/kibana.json b/x-pack/plugins/rollup/kibana.json index 6ab2fc8907c0d..8f832f6c6a345 100644 --- a/x-pack/plugins/rollup/kibana.json +++ b/x-pack/plugins/rollup/kibana.json @@ -2,5 +2,8 @@ "id": "rollup", "version": "8.0.0", "kibanaVersion": "kibana", - "server": true + "server": true, + "ui": true, + "optionalPlugins": ["home", "indexManagement", "indexPatternManagement", "usageCollection"], + "requiredPlugins": ["management", "data"] } diff --git a/x-pack/legacy/plugins/rollup/public/application.tsx b/x-pack/plugins/rollup/public/application.tsx similarity index 87% rename from x-pack/legacy/plugins/rollup/public/application.tsx rename to x-pack/plugins/rollup/public/application.tsx index df17d37bc3465..1bdf940d746b2 100644 --- a/x-pack/legacy/plugins/rollup/public/application.tsx +++ b/x-pack/plugins/rollup/public/application.tsx @@ -5,15 +5,17 @@ */ import React from 'react'; +import { ChromeBreadcrumb, CoreSetup } from 'kibana/public'; import { render, unmountComponentAtNode } from 'react-dom'; import { Provider } from 'react-redux'; -import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; -import { ChromeBreadcrumb, CoreSetup } from '../../../../../src/core/public'; +import { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public'; // @ts-ignore import { rollupJobsStore } from './crud_app/store'; // @ts-ignore import { App } from './crud_app/app'; +import './index.scss'; + /** * This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle. */ diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/_crud_app.scss b/x-pack/plugins/rollup/public/crud_app/_crud_app.scss similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/_crud_app.scss rename to x-pack/plugins/rollup/public/crud_app/_crud_app.scss diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/app.js b/x-pack/plugins/rollup/public/crud_app/app.js similarity index 93% rename from x-pack/legacy/plugins/rollup/public/crud_app/app.js rename to x-pack/plugins/rollup/public/crud_app/app.js index da35c8a56f2d2..0ef3253eeb94e 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/app.js +++ b/x-pack/plugins/rollup/public/crud_app/app.js @@ -10,7 +10,8 @@ import { HashRouter, Switch, Route, Redirect, withRouter } from 'react-router-do import { UIM_APP_LOAD } from '../../common'; import { CRUD_APP_BASE_PATH } from './constants'; -import { registerRouter, setUserHasLeftApp, trackUiMetric, METRIC_TYPE } from './services'; +import { registerRouter, setUserHasLeftApp, METRIC_TYPE } from './services'; +import { trackUiMetric } from '../kibana_services'; import { JobList, JobCreate } from './sections'; class ShareRouterComponent extends Component { diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/constants/index.js b/x-pack/plugins/rollup/public/crud_app/constants/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/constants/index.js rename to x-pack/plugins/rollup/public/crud_app/constants/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/constants/metrics_config.js b/x-pack/plugins/rollup/public/crud_app/constants/metrics_config.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/constants/metrics_config.js rename to x-pack/plugins/rollup/public/crud_app/constants/metrics_config.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/constants/paths.js b/x-pack/plugins/rollup/public/crud_app/constants/paths.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/constants/paths.js rename to x-pack/plugins/rollup/public/crud_app/constants/paths.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/field_list/field_list.js b/x-pack/plugins/rollup/public/crud_app/sections/components/field_list/field_list.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/field_list/field_list.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/field_list/field_list.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/field_list/index.js b/x-pack/plugins/rollup/public/crud_app/sections/components/field_list/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/field_list/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/field_list/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/index.js b/x-pack/plugins/rollup/public/crud_app/sections/components/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/confirm_delete_modal.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/confirm_delete_modal.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/confirm_delete_modal.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/confirm_delete_modal.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/index.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/confirm_delete_modal/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/index.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.container.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.container.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.container.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.container.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/index.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_details/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_details/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/job_details.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_details/job_details.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/job_details.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_details/job_details.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/index.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_histogram.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_histogram.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_histogram.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_histogram.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_json.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_json.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_json.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_json.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_metrics.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_metrics.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_metrics.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_metrics.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_request.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_request.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_request.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_request.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_summary.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_summary.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_summary.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_summary.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_terms.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_terms.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_terms.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_details/tabs/tab_terms.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_status/index.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_status/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_status/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_status/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_status/job_status.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_status/job_status.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/components/job_status/job_status.js rename to x-pack/plugins/rollup/public/crud_app/sections/components/job_status/job_status.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/index.js b/x-pack/plugins/rollup/public/crud_app/sections/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/index.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/job_create.container.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.container.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/job_create.container.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.container.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/job_create.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js similarity index 99% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/job_create.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js index 5379778c77e2f..4458054f30dd1 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/job_create.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js @@ -14,7 +14,7 @@ import first from 'lodash/array/first'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/'; +import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { EuiCallOut, diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/navigation/index.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/navigation/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/components/field_chooser.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/components/field_chooser.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/components/field_chooser.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/components/field_chooser.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/components/index.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/components/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/components/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/components/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/components/step_error.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/components/step_error.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/components/step_error.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/components/step_error.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/index.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_date_histogram.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_date_histogram.js similarity index 99% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_date_histogram.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_date_histogram.js index ba65d082c0b4b..c327e51a6b7ee 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_date_histogram.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_date_histogram.js @@ -24,7 +24,7 @@ import { EuiTitle, } from '@elastic/eui'; -import { search } from '../../../../../../../../../src/plugins/data/public'; +import { search } from '../../../../../../../../src/plugins/data/public'; const { parseEsInterval } = search.aggs; import { getDateHistogramDetailsUrl, getDateHistogramAggregationUrl } from '../../../services'; diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js similarity index 99% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js index 5462a46bf59b9..0fd76e572b2e5 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js @@ -24,8 +24,8 @@ import { EuiTitle, } from '@elastic/eui'; -import { CronEditor } from '../../../../../../../../../src/plugins/es_ui_shared/public'; -import { indexPatterns } from '../../../../../../../../../src/plugins/data/public'; +import { CronEditor } from '../../../../../../../../src/plugins/es_ui_shared/public'; +import { indexPatterns } from '../../../../../../../../src/plugins/data/public'; import { indices } from '../../../../shared_imports'; import { getLogisticalDetailsUrl, getCronUrl } from '../../../services'; diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/index.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/index.js similarity index 96% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/index.js index e1efcfdd24627..4a55c4679c3d8 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/index.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/index.js @@ -8,7 +8,7 @@ import cloneDeep from 'lodash/lang/cloneDeep'; import get from 'lodash/object/get'; import pick from 'lodash/object/pick'; -import { WEEK } from '../../../../../../../../../src/plugins/es_ui_shared/public'; +import { WEEK } from '../../../../../../../../src/plugins/es_ui_shared/public'; import { validateId } from './validate_id'; import { validateIndexPattern } from './validate_index_pattern'; @@ -42,7 +42,7 @@ export const stepIds = [ * 1. getDefaultFields: (overrides) => object * 2. fieldValidations * - * See x-pack/legacy/plugins/rollup/public/crud_app/services/jobs.js for more information on override's shape + * See x-pack/plugins/rollup/public/crud_app/services/jobs.js for more information on override's shape */ export const stepIdToStepConfigMap = { [STEP_LOGISTICS]: { diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_field.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_field.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_field.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_field.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_interval.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_interval.js similarity index 95% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_interval.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_interval.js index b6c824bc8c553..819c814e373d5 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_interval.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_date_histogram_interval.js @@ -6,7 +6,7 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { search } from '../../../../../../../../../src/plugins/data/public'; +import { search } from '../../../../../../../../src/plugins/data/public'; const { InvalidEsIntervalFormatError, InvalidEsCalendarIntervalError, diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_histogram_interval.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_histogram_interval.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_histogram_interval.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_histogram_interval.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_id.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_id.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_id.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_id.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_index_pattern.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_index_pattern.js similarity index 95% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_index_pattern.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_index_pattern.js index 206cc325813c0..534fcaa744744 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_index_pattern.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_index_pattern.js @@ -7,7 +7,7 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { indexPatterns } from '../../../../../../../../../src/plugins/data/public'; +import { indexPatterns } from '../../../../../../../../src/plugins/data/public'; export function validateIndexPattern(indexPattern, rollupIndex) { if (!indexPattern || !indexPattern.trim()) { return [ diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_metrics.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_metrics.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_metrics.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_metrics.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_cron.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_cron.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_cron.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_cron.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_delay.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_delay.js similarity index 95% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_delay.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_delay.js index 37c2ca9a1d775..66bfd43bc3d1b 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_delay.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_delay.js @@ -6,7 +6,7 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { search } from '../../../../../../../../../src/plugins/data/public'; +import { search } from '../../../../../../../../src/plugins/data/public'; const { InvalidEsIntervalFormatError, InvalidEsCalendarIntervalError, diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_index.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_index.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_page_size.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_page_size.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_page_size.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_create/steps_config/validate_rollup_page_size.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.container.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.container.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.container.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.container.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.js similarity index 98% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.js index f774b1d7f63b7..3f168a66feed8 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.js @@ -34,7 +34,8 @@ import { UIM_DETAIL_PANEL_METRICS_TAB_CLICK, UIM_DETAIL_PANEL_JSON_TAB_CLICK, } from '../../../../../common'; -import { trackUiMetric, METRIC_TYPE } from '../../../services'; +import { METRIC_TYPE } from '../../../services'; +import { trackUiMetric } from '../../../../kibana_services'; import { JobActionMenu, diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js similarity index 98% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js index 9ac8e6075e4cf..cea5b3c3e96e5 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/detail_panel.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { registerTestBed } from '../../../../../../../../test_utils'; +import { registerTestBed } from '../../../../../../../test_utils'; import { getJob } from '../../../../../fixtures'; import { rollupJobsStore } from '../../../store'; import { DetailPanel } from './detail_panel'; @@ -17,9 +17,8 @@ import { tabToHumanizedMap, } from '../../components'; -jest.mock('ui/new_platform'); -jest.mock('../../../services', () => { - const services = require.requireActual('../../../services'); +jest.mock('../../../../kibana_services', () => { + const services = require.requireActual('../../../../kibana_services'); return { ...services, trackUiMetric: jest.fn(), diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/index.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/detail_panel/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/detail_panel/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/index.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.container.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.container.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.container.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.container.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js similarity index 98% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js index 98329a687217a..011becded148c 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js @@ -25,7 +25,7 @@ import { EuiCallOut, } from '@elastic/eui'; -import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/'; +import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { CRUD_APP_BASE_PATH } from '../../constants'; import { getRouterLinkProps, extractQueryParams, listBreadcrumb } from '../../services'; diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js similarity index 90% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js index 725789fc584de..8c3bffd223ca9 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js @@ -5,16 +5,14 @@ */ import React from 'react'; -import { registerTestBed } from '../../../../../../../test_utils'; +import { registerTestBed } from '../../../../../../test_utils'; import { rollupJobsStore } from '../../store'; import { JobList } from './job_list'; -import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public'; -import { coreMock } from '../../../../../../../../src/core/public/mocks'; +import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public'; +import { coreMock } from '../../../../../../../src/core/public/mocks'; const startMock = coreMock.createStart(); -jest.mock('ui/new_platform'); - jest.mock('../../services', () => { const services = require.requireActual('../../services'); return { diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/index.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/index.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.container.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.container.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.container.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.container.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js similarity index 99% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js index 4dbe396ab8410..f47992e1b501a 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js @@ -30,7 +30,8 @@ import { } from '@elastic/eui'; import { UIM_SHOW_DETAILS_CLICK } from '../../../../../common'; -import { trackUiMetric, METRIC_TYPE } from '../../../services'; +import { METRIC_TYPE } from '../../../services'; +import { trackUiMetric } from '../../../../kibana_services'; import { JobActionMenu, JobStatus } from '../../components'; const COLUMNS = [ diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.test.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.test.js similarity index 96% rename from x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.test.js rename to x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.test.js index c688343d5f768..c6a3d3a8f69ad 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.test.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.test.js @@ -6,14 +6,13 @@ import { Pager } from '@elastic/eui'; -import { registerTestBed } from '../../../../../../../../test_utils'; +import { registerTestBed } from '../../../../../../../test_utils'; import { getJobs, jobCount } from '../../../../../fixtures'; import { rollupJobsStore } from '../../../store'; import { JobTable } from './job_table'; -jest.mock('ui/new_platform'); -jest.mock('../../../services', () => { - const services = require.requireActual('../../../services'); +jest.mock('../../../../kibana_services', () => { + const services = require.requireActual('../../../../kibana_services'); return { ...services, trackUiMetric: jest.fn(), diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/api.js b/x-pack/plugins/rollup/public/crud_app/services/api.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/api.js rename to x-pack/plugins/rollup/public/crud_app/services/api.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/api_errors.ts b/x-pack/plugins/rollup/public/crud_app/services/api_errors.ts similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/api_errors.ts rename to x-pack/plugins/rollup/public/crud_app/services/api_errors.ts diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/breadcrumbs.js b/x-pack/plugins/rollup/public/crud_app/services/breadcrumbs.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/breadcrumbs.js rename to x-pack/plugins/rollup/public/crud_app/services/breadcrumbs.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/documentation_links.js b/x-pack/plugins/rollup/public/crud_app/services/documentation_links.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/documentation_links.js rename to x-pack/plugins/rollup/public/crud_app/services/documentation_links.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/filter_items.js b/x-pack/plugins/rollup/public/crud_app/services/filter_items.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/filter_items.js rename to x-pack/plugins/rollup/public/crud_app/services/filter_items.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/flatten_panel_tree.js b/x-pack/plugins/rollup/public/crud_app/services/flatten_panel_tree.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/flatten_panel_tree.js rename to x-pack/plugins/rollup/public/crud_app/services/flatten_panel_tree.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/format_fields.js b/x-pack/plugins/rollup/public/crud_app/services/format_fields.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/format_fields.js rename to x-pack/plugins/rollup/public/crud_app/services/format_fields.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/http_provider.ts b/x-pack/plugins/rollup/public/crud_app/services/http_provider.ts similarity index 91% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/http_provider.ts rename to x-pack/plugins/rollup/public/crud_app/services/http_provider.ts index dd84328084d05..93898610b844e 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/services/http_provider.ts +++ b/x-pack/plugins/rollup/public/crud_app/services/http_provider.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HttpStart } from 'src/core/public'; +import { HttpStart } from 'kibana/public'; let _http: HttpStart | null = null; diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/index.js b/x-pack/plugins/rollup/public/crud_app/services/index.js similarity index 95% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/index.js rename to x-pack/plugins/rollup/public/crud_app/services/index.js index 790770b9b6a9f..0b45b1bdb6b5f 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/services/index.js +++ b/x-pack/plugins/rollup/public/crud_app/services/index.js @@ -47,4 +47,4 @@ export { sortTable } from './sort_table'; export { retypeMetrics } from './retype_metrics'; -export { trackUiMetric, METRIC_TYPE } from './track_ui_metric'; +export { METRIC_TYPE } from './track_ui_metric'; diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/jobs.js b/x-pack/plugins/rollup/public/crud_app/services/jobs.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/jobs.js rename to x-pack/plugins/rollup/public/crud_app/services/jobs.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/noticeable_delay.js b/x-pack/plugins/rollup/public/crud_app/services/noticeable_delay.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/noticeable_delay.js rename to x-pack/plugins/rollup/public/crud_app/services/noticeable_delay.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/query_params.js b/x-pack/plugins/rollup/public/crud_app/services/query_params.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/query_params.js rename to x-pack/plugins/rollup/public/crud_app/services/query_params.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/retype_metrics.js b/x-pack/plugins/rollup/public/crud_app/services/retype_metrics.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/retype_metrics.js rename to x-pack/plugins/rollup/public/crud_app/services/retype_metrics.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/routing.js b/x-pack/plugins/rollup/public/crud_app/services/routing.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/routing.js rename to x-pack/plugins/rollup/public/crud_app/services/routing.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/sort_table.js b/x-pack/plugins/rollup/public/crud_app/services/sort_table.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/sort_table.js rename to x-pack/plugins/rollup/public/crud_app/services/sort_table.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/services/track_ui_metric.js b/x-pack/plugins/rollup/public/crud_app/services/track_ui_metric.ts similarity index 70% rename from x-pack/legacy/plugins/rollup/public/crud_app/services/track_ui_metric.js rename to x-pack/plugins/rollup/public/crud_app/services/track_ui_metric.ts index 69a5995386bd7..aa1cc2dfea323 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/services/track_ui_metric.js +++ b/x-pack/plugins/rollup/public/crud_app/services/track_ui_metric.ts @@ -4,20 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - createUiStatsReporter, - METRIC_TYPE, -} from '../../../../../../../src/legacy/core_plugins/ui_metric/public'; -import { UIM_APP_NAME } from '../../../common'; +import { METRIC_TYPE } from '@kbn/analytics'; +import { trackUiMetric } from '../../kibana_services'; -export const trackUiMetric = createUiStatsReporter(UIM_APP_NAME); export { METRIC_TYPE }; /** * Transparently return provided request Promise, while allowing us to track * a successful completion of the request. */ -export function trackUserRequest(request, actionType) { +export function trackUserRequest(request: Promise, actionType: string) { // Only track successful actions. return request.then(response => { trackUiMetric(METRIC_TYPE.LOADED, actionType); diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/action_types.js b/x-pack/plugins/rollup/public/crud_app/store/action_types.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/action_types.js rename to x-pack/plugins/rollup/public/crud_app/store/action_types.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/change_job_status.js b/x-pack/plugins/rollup/public/crud_app/store/actions/change_job_status.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/actions/change_job_status.js rename to x-pack/plugins/rollup/public/crud_app/store/actions/change_job_status.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/clone_job.js b/x-pack/plugins/rollup/public/crud_app/store/actions/clone_job.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/actions/clone_job.js rename to x-pack/plugins/rollup/public/crud_app/store/actions/clone_job.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/create_job.js b/x-pack/plugins/rollup/public/crud_app/store/actions/create_job.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/actions/create_job.js rename to x-pack/plugins/rollup/public/crud_app/store/actions/create_job.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/delete_jobs.js b/x-pack/plugins/rollup/public/crud_app/store/actions/delete_jobs.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/actions/delete_jobs.js rename to x-pack/plugins/rollup/public/crud_app/store/actions/delete_jobs.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/detail_panel.js b/x-pack/plugins/rollup/public/crud_app/store/actions/detail_panel.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/actions/detail_panel.js rename to x-pack/plugins/rollup/public/crud_app/store/actions/detail_panel.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/index.js b/x-pack/plugins/rollup/public/crud_app/store/actions/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/actions/index.js rename to x-pack/plugins/rollup/public/crud_app/store/actions/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/load_jobs.js b/x-pack/plugins/rollup/public/crud_app/store/actions/load_jobs.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/actions/load_jobs.js rename to x-pack/plugins/rollup/public/crud_app/store/actions/load_jobs.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/refresh_jobs.js b/x-pack/plugins/rollup/public/crud_app/store/actions/refresh_jobs.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/actions/refresh_jobs.js rename to x-pack/plugins/rollup/public/crud_app/store/actions/refresh_jobs.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/actions/table_state.js b/x-pack/plugins/rollup/public/crud_app/store/actions/table_state.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/actions/table_state.js rename to x-pack/plugins/rollup/public/crud_app/store/actions/table_state.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/index.js b/x-pack/plugins/rollup/public/crud_app/store/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/index.js rename to x-pack/plugins/rollup/public/crud_app/store/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/middleware/clone_job.js b/x-pack/plugins/rollup/public/crud_app/store/middleware/clone_job.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/middleware/clone_job.js rename to x-pack/plugins/rollup/public/crud_app/store/middleware/clone_job.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/middleware/detail_panel.js b/x-pack/plugins/rollup/public/crud_app/store/middleware/detail_panel.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/middleware/detail_panel.js rename to x-pack/plugins/rollup/public/crud_app/store/middleware/detail_panel.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/middleware/index.js b/x-pack/plugins/rollup/public/crud_app/store/middleware/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/middleware/index.js rename to x-pack/plugins/rollup/public/crud_app/store/middleware/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/clone_job.js b/x-pack/plugins/rollup/public/crud_app/store/reducers/clone_job.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/clone_job.js rename to x-pack/plugins/rollup/public/crud_app/store/reducers/clone_job.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/create_job.js b/x-pack/plugins/rollup/public/crud_app/store/reducers/create_job.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/create_job.js rename to x-pack/plugins/rollup/public/crud_app/store/reducers/create_job.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/detail_panel.js b/x-pack/plugins/rollup/public/crud_app/store/reducers/detail_panel.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/detail_panel.js rename to x-pack/plugins/rollup/public/crud_app/store/reducers/detail_panel.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/index.js b/x-pack/plugins/rollup/public/crud_app/store/reducers/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/index.js rename to x-pack/plugins/rollup/public/crud_app/store/reducers/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/jobs.js b/x-pack/plugins/rollup/public/crud_app/store/reducers/jobs.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/jobs.js rename to x-pack/plugins/rollup/public/crud_app/store/reducers/jobs.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/table_state.js b/x-pack/plugins/rollup/public/crud_app/store/reducers/table_state.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/table_state.js rename to x-pack/plugins/rollup/public/crud_app/store/reducers/table_state.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/update_job.js b/x-pack/plugins/rollup/public/crud_app/store/reducers/update_job.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/reducers/update_job.js rename to x-pack/plugins/rollup/public/crud_app/store/reducers/update_job.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/selectors/index.js b/x-pack/plugins/rollup/public/crud_app/store/selectors/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/selectors/index.js rename to x-pack/plugins/rollup/public/crud_app/store/selectors/index.js diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/store/store.js b/x-pack/plugins/rollup/public/crud_app/store/store.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/crud_app/store/store.js rename to x-pack/plugins/rollup/public/crud_app/store/store.js diff --git a/x-pack/legacy/plugins/rollup/public/extend_index_management/index.ts b/x-pack/plugins/rollup/public/extend_index_management/index.ts similarity index 100% rename from x-pack/legacy/plugins/rollup/public/extend_index_management/index.ts rename to x-pack/plugins/rollup/public/extend_index_management/index.ts diff --git a/x-pack/legacy/plugins/rollup/public/index.scss b/x-pack/plugins/rollup/public/index.scss similarity index 67% rename from x-pack/legacy/plugins/rollup/public/index.scss rename to x-pack/plugins/rollup/public/index.scss index 0ad0eac50f7b9..cbbedcebb043e 100644 --- a/x-pack/legacy/plugins/rollup/public/index.scss +++ b/x-pack/plugins/rollup/public/index.scss @@ -1,6 +1,3 @@ -// Import the EUI global scope so we can use EUI constants -@import 'src/legacy/ui/public/styles/_styling_constants'; - // Index management plugin styles // Prefix all styles with "rollup" to avoid conflicts. diff --git a/x-pack/legacy/plugins/rollup/public/legacy_imports.ts b/x-pack/plugins/rollup/public/index.ts similarity index 72% rename from x-pack/legacy/plugins/rollup/public/legacy_imports.ts rename to x-pack/plugins/rollup/public/index.ts index e82a41f60b1ca..4c965fc38f4e7 100644 --- a/x-pack/legacy/plugins/rollup/public/legacy_imports.ts +++ b/x-pack/plugins/rollup/public/index.ts @@ -4,4 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -export { PluginsStart } from 'ui/new_platform/new_platform'; +import { RollupPlugin } from './plugin'; + +export const plugin = () => new RollupPlugin(); diff --git a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/index.js b/x-pack/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/index.js rename to x-pack/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/index.js diff --git a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/rollup_prompt.js b/x-pack/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/rollup_prompt.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/rollup_prompt.js rename to x-pack/plugins/rollup/public/index_pattern_creation/components/rollup_prompt/rollup_prompt.js diff --git a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js b/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js similarity index 97% rename from x-pack/legacy/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js rename to x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js index f4de2a3098127..c29fba44285be 100644 --- a/x-pack/legacy/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js +++ b/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js @@ -8,7 +8,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { RollupPrompt } from './components/rollup_prompt'; -import { IndexPatternCreationConfig } from '../../../../../../src/plugins/index_pattern_management/public'; +import { IndexPatternCreationConfig } from '../../../../../src/plugins/index_pattern_management/public'; const rollupIndexPatternTypeName = i18n.translate( 'xpack.rollupJobs.editRollupIndexPattern.createIndex.defaultTypeName', diff --git a/x-pack/legacy/plugins/rollup/public/index_pattern_list/rollup_index_pattern_list_config.js b/x-pack/plugins/rollup/public/index_pattern_list/rollup_index_pattern_list_config.js similarity index 93% rename from x-pack/legacy/plugins/rollup/public/index_pattern_list/rollup_index_pattern_list_config.js rename to x-pack/plugins/rollup/public/index_pattern_list/rollup_index_pattern_list_config.js index 809a76d1868b2..e61287d303643 100644 --- a/x-pack/legacy/plugins/rollup/public/index_pattern_list/rollup_index_pattern_list_config.js +++ b/x-pack/plugins/rollup/public/index_pattern_list/rollup_index_pattern_list_config.js @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { IndexPatternListConfig } from '../../../../../../src/plugins/index_pattern_management/public'; +import { IndexPatternListConfig } from '../../../../../src/plugins/index_pattern_management/public'; function isRollup(indexPattern) { return ( diff --git a/x-pack/legacy/plugins/rollup/public/kibana_services.ts b/x-pack/plugins/rollup/public/kibana_services.ts similarity index 57% rename from x-pack/legacy/plugins/rollup/public/kibana_services.ts rename to x-pack/plugins/rollup/public/kibana_services.ts index 335eeb90282ca..edbf69568f5e5 100644 --- a/x-pack/legacy/plugins/rollup/public/kibana_services.ts +++ b/x-pack/plugins/rollup/public/kibana_services.ts @@ -4,7 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { NotificationsStart, FatalErrorsSetup } from 'src/core/public'; +import { NotificationsStart, FatalErrorsSetup } from 'kibana/public'; +import { UiStatsMetricType } from '@kbn/analytics'; +import { createGetterSetter } from '../../../../src/plugins/kibana_utils/common'; let notifications: NotificationsStart | null = null; let fatalErrors: FatalErrorsSetup | null = null; @@ -28,3 +30,18 @@ export function getFatalErrors() { export function setFatalErrors(newFatalErrors: FatalErrorsSetup) { fatalErrors = newFatalErrors; } + +export const [getUiStatsReporter, setUiStatsReporter] = createGetterSetter< + (type: UiStatsMetricType, eventNames: string | string[], count?: number) => void +>('uiMetric'); + +// default value if usageCollection is not available +setUiStatsReporter(() => {}); + +export function trackUiMetric( + type: UiStatsMetricType, + eventNames: string | string[], + count?: number +) { + getUiStatsReporter()(type, eventNames, count); +} diff --git a/x-pack/legacy/plugins/rollup/public/plugin.ts b/x-pack/plugins/rollup/public/plugin.ts similarity index 73% rename from x-pack/legacy/plugins/rollup/public/plugin.ts rename to x-pack/plugins/rollup/public/plugin.ts index 17ec8a5a4aedf..fd1b90fbc9855 100644 --- a/x-pack/legacy/plugins/rollup/public/plugin.ts +++ b/x-pack/plugins/rollup/public/plugin.ts @@ -6,7 +6,6 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; -import { PluginsStart } from './legacy_imports'; import { rollupBadgeExtension, rollupToggleExtension } from './extend_index_management'; // @ts-ignore import { RollupIndexPatternCreationConfig } from './index_pattern_creation/rollup_index_pattern_creation_config'; @@ -16,35 +15,49 @@ import { RollupIndexPatternListConfig } from './index_pattern_list/rollup_index_ import { initAggTypeFilter } from './visualize/agg_type_filter'; // @ts-ignore import { initAggTypeFieldFilter } from './visualize/agg_type_field_filter'; -import { CONFIG_ROLLUPS } from '../common'; +import { CONFIG_ROLLUPS, UIM_APP_NAME } from '../common'; import { FeatureCatalogueCategory, HomePublicPluginSetup, -} from '../../../../../src/plugins/home/public'; +} from '../../../../src/plugins/home/public'; // @ts-ignore import { CRUD_APP_BASE_PATH } from './crud_app/constants'; -import { ManagementSetup } from '../../../../../src/plugins/management/public'; -import { IndexManagementPluginSetup } from '../../../../plugins/index_management/public'; -import { IndexPatternManagementSetup } from '../../../../../src/plugins/index_pattern_management/public'; -import { search } from '../../../../../src/plugins/data/public'; +import { ManagementSetup } from '../../../../src/plugins/management/public'; +import { IndexManagementPluginSetup } from '../../index_management/public'; +import { IndexPatternManagementSetup } from '../../../../src/plugins/index_pattern_management/public'; +import { DataPublicPluginStart, search } from '../../../../src/plugins/data/public'; // @ts-ignore -import { setEsBaseAndXPackBase, setHttp } from './crud_app/services'; -import { setNotifications, setFatalErrors } from './kibana_services'; -import { renderApp } from './application'; +import { setEsBaseAndXPackBase, setHttp } from './crud_app/services/index'; +import { setNotifications, setFatalErrors, setUiStatsReporter } from './kibana_services'; +import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public'; export interface RollupPluginSetupDependencies { home?: HomePublicPluginSetup; management: ManagementSetup; indexManagement?: IndexManagementPluginSetup; indexPatternManagement: IndexPatternManagementSetup; + usageCollection?: UsageCollectionSetup; +} + +export interface RollupPluginStartDependencies { + data: DataPublicPluginStart; } export class RollupPlugin implements Plugin { setup( core: CoreSetup, - { home, management, indexManagement, indexPatternManagement }: RollupPluginSetupDependencies + { + home, + management, + indexManagement, + indexPatternManagement, + usageCollection, + }: RollupPluginSetupDependencies ) { setFatalErrors(core.fatalErrors); + if (usageCollection) { + setUiStatsReporter(usageCollection.reportUiStats.bind(usageCollection, UIM_APP_NAME)); + } if (indexManagement) { indexManagement.extensionsService.addBadge(rollupBadgeExtension); @@ -79,7 +92,7 @@ export class RollupPlugin implements Plugin { id: 'rollup_jobs', title: i18n.translate('xpack.rollupJobs.appTitle', { defaultMessage: 'Rollup Jobs' }), order: 3, - mount(params) { + async mount(params) { params.setBreadcrumbs([ { text: i18n.translate('xpack.rollupJobs.breadcrumbsTitle', { @@ -87,6 +100,7 @@ export class RollupPlugin implements Plugin { }), }, ]); + const { renderApp } = await import('./application'); return renderApp(core, params); }, @@ -94,7 +108,7 @@ export class RollupPlugin implements Plugin { } } - start(core: CoreStart, plugins: PluginsStart) { + start(core: CoreStart, plugins: RollupPluginStartDependencies) { setHttp(core.http); setNotifications(core.notifications); setEsBaseAndXPackBase(core.docLinks.ELASTIC_WEBSITE_URL, core.docLinks.DOC_LINK_VERSION); diff --git a/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.ts b/x-pack/plugins/rollup/public/search/rollup_search_strategy.ts similarity index 96% rename from x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.ts rename to x-pack/plugins/rollup/public/search/rollup_search_strategy.ts index 4709c0aa498f8..d1c3b9cba5f9d 100644 --- a/x-pack/legacy/plugins/rollup/public/search/rollup_search_strategy.ts +++ b/x-pack/plugins/rollup/public/search/rollup_search_strategy.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HttpSetup } from 'src/core/public'; +import { HttpSetup } from 'kibana/public'; import { SearchError, getSearchErrorType, @@ -12,7 +12,7 @@ import { SearchStrategyProvider, SearchResponse, SearchRequest, -} from '../../../../../../src/plugins/data/public'; +} from '../../../../../src/plugins/data/public'; function serializeFetchParams(searchRequests: SearchRequest[]) { return JSON.stringify( diff --git a/x-pack/legacy/plugins/rollup/public/shared_imports.ts b/x-pack/plugins/rollup/public/shared_imports.ts similarity index 76% rename from x-pack/legacy/plugins/rollup/public/shared_imports.ts rename to x-pack/plugins/rollup/public/shared_imports.ts index 6bf74da6db6fe..1ac25a1a0e5f8 100644 --- a/x-pack/legacy/plugins/rollup/public/shared_imports.ts +++ b/x-pack/plugins/rollup/public/shared_imports.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { indices } from '../../../../../src/plugins/es_ui_shared/public'; +export { indices } from '../../../../src/plugins/es_ui_shared/public'; diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/constants.js b/x-pack/plugins/rollup/public/test/client_integration/helpers/constants.js similarity index 100% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/constants.js rename to x-pack/plugins/rollup/public/test/client_integration/helpers/constants.js diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/index.js b/x-pack/plugins/rollup/public/test/client_integration/helpers/index.js similarity index 100% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/index.js rename to x-pack/plugins/rollup/public/test/client_integration/helpers/index.js diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/job_clone.helpers.js b/x-pack/plugins/rollup/public/test/client_integration/helpers/job_clone.helpers.js similarity index 83% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/job_clone.helpers.js rename to x-pack/plugins/rollup/public/test/client_integration/helpers/job_clone.helpers.js index a8376bb31b23f..fa9929a207615 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/job_clone.helpers.js +++ b/x-pack/plugins/rollup/public/test/client_integration/helpers/job_clone.helpers.js @@ -5,10 +5,10 @@ */ import { registerTestBed } from '../../../../../../test_utils'; -import { createRollupJobsStore } from '../../../public/crud_app/store'; -import { JobCreate } from '../../../public/crud_app/sections'; +import { createRollupJobsStore } from '../../../crud_app/store'; +import { JobCreate } from '../../../crud_app/sections'; import { JOB_TO_CLONE } from './constants'; -import { deserializeJob } from '../../../public/crud_app/services'; +import { deserializeJob } from '../../../crud_app/services'; import { wrapComponent } from './setup_context'; diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/job_create.helpers.js b/x-pack/plugins/rollup/public/test/client_integration/helpers/job_create.helpers.js similarity index 96% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/job_create.helpers.js rename to x-pack/plugins/rollup/public/test/client_integration/helpers/job_create.helpers.js index 2395fd014dd1e..7ddcfa9eb83ff 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/job_create.helpers.js +++ b/x-pack/plugins/rollup/public/test/client_integration/helpers/job_create.helpers.js @@ -5,8 +5,8 @@ */ import { registerTestBed } from '../../../../../../test_utils'; -import { rollupJobsStore } from '../../../public/crud_app/store'; -import { JobCreate } from '../../../public/crud_app/sections'; +import { rollupJobsStore } from '../../../crud_app/store'; +import { JobCreate } from '../../../crud_app/sections'; import { JOB_TO_CREATE } from './constants'; diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/job_list.helpers.js b/x-pack/plugins/rollup/public/test/client_integration/helpers/job_list.helpers.js similarity index 74% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/job_list.helpers.js rename to x-pack/plugins/rollup/public/test/client_integration/helpers/job_list.helpers.js index bcad8c29c87c0..fda1ec8cfed22 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/job_list.helpers.js +++ b/x-pack/plugins/rollup/public/test/client_integration/helpers/job_list.helpers.js @@ -5,9 +5,9 @@ */ import { registerTestBed } from '../../../../../../test_utils'; -import { registerRouter } from '../../../public/crud_app/services'; -import { createRollupJobsStore } from '../../../public/crud_app/store'; -import { JobList } from '../../../public/crud_app/sections/job_list'; +import { registerRouter } from '../../../crud_app/services'; +import { createRollupJobsStore } from '../../../crud_app/store'; +import { JobList } from '../../../crud_app/sections/job_list'; import { wrapComponent } from './setup_context'; diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/setup_context.tsx b/x-pack/plugins/rollup/public/test/client_integration/helpers/setup_context.tsx similarity index 100% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/setup_context.tsx rename to x-pack/plugins/rollup/public/test/client_integration/helpers/setup_context.tsx diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/setup_environment.ts b/x-pack/plugins/rollup/public/test/client_integration/helpers/setup_environment.ts similarity index 100% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/helpers/setup_environment.ts rename to x-pack/plugins/rollup/public/test/client_integration/helpers/setup_environment.ts diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_clone.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_clone.test.js similarity index 93% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_clone.test.js rename to x-pack/plugins/rollup/public/test/client_integration/job_create_clone.test.js index b7c98ed179c7a..7b61a03dcde45 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_clone.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_clone.test.js @@ -4,11 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setHttp } from '../../public/crud_app/services'; +import { setHttp } from '../../crud_app/services'; import { mockHttpRequest, pageHelpers, nextTick } from './helpers'; import { JOB_TO_CLONE, JOB_CLONE_INDEX_PATTERN_CHECK } from './helpers/constants'; - -jest.mock('ui/new_platform'); +import { coreMock } from '../../../../../../src/core/public/mocks'; jest.mock('lodash/function/debounce', () => fn => fn); @@ -23,23 +22,23 @@ describe('Cloning a rollup job through create job wizard', () => { let form; let table; let actions; - let npStart; + let startMock; beforeAll(() => { - npStart = require('ui/new_platform').npStart; // eslint-disable-line - setHttp(npStart.core.http); + startMock = coreMock.createStart(); + setHttp(startMock.http); }); beforeEach(() => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: JOB_CLONE_INDEX_PATTERN_CHECK }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: JOB_CLONE_INDEX_PATTERN_CHECK }); ({ exists, find, form, actions, table } = setup()); }); afterEach(() => { - npStart.core.http.get.mockClear(); - npStart.core.http.post.mockClear(); - npStart.core.http.put.mockClear(); + startMock.http.get.mockClear(); + startMock.http.post.mockClear(); + startMock.http.put.mockClear(); }); it('should have fields correctly pre-populated', async () => { diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_date_histogram.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_date_histogram.test.js similarity index 88% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_date_histogram.test.js rename to x-pack/plugins/rollup/public/test/client_integration/job_create_date_histogram.test.js index b8ec7d9f85d00..095609ac2b2d7 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_date_histogram.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_date_histogram.test.js @@ -6,10 +6,9 @@ import moment from 'moment-timezone'; -import { setHttp } from '../../public/crud_app/services'; +import { setHttp } from '../../crud_app/services'; import { mockHttpRequest, pageHelpers } from './helpers'; - -jest.mock('ui/new_platform'); +import { coreMock } from '../../../../../../src/core/public/mocks'; jest.mock('lodash/function/debounce', () => fn => fn); @@ -22,23 +21,23 @@ describe('Create Rollup Job, step 2: Date histogram', () => { let goToStep; let form; let getEuiStepsHorizontalActive; - let npStart; + let startMock; beforeAll(() => { - npStart = require('ui/new_platform').npStart; // eslint-disable-line - setHttp(npStart.core.http); + startMock = coreMock.createStart(); + setHttp(startMock.http); }); beforeEach(() => { // Set "default" mock responses by not providing any arguments - mockHttpRequest(npStart.core.http); + mockHttpRequest(startMock.http); ({ find, exists, actions, form, getEuiStepsHorizontalActive, goToStep } = setup()); }); afterEach(() => { - npStart.core.http.get.mockClear(); - npStart.core.http.post.mockClear(); - npStart.core.http.put.mockClear(); + startMock.http.get.mockClear(); + startMock.http.post.mockClear(); + startMock.http.put.mockClear(); }); describe('layout', () => { @@ -73,7 +72,7 @@ describe('Create Rollup Job, step 2: Date histogram', () => { describe('Date field select', () => { it('should set the options value from the index pattern', async () => { const dateFields = ['field1', 'field2', 'field3']; - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { dateFields } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { dateFields } }); await goToStep(2); @@ -85,7 +84,7 @@ describe('Create Rollup Job, step 2: Date histogram', () => { it('should sort the options in ascending order', async () => { const dateFields = ['field3', 'field2', 'field1']; - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { dateFields } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { dateFields } }); await goToStep(2); diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_histogram.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_histogram.test.js similarity index 91% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_histogram.test.js rename to x-pack/plugins/rollup/public/test/client_integration/job_create_histogram.test.js index c4b5d753f1a26..141aa06843556 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_histogram.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_histogram.test.js @@ -4,10 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setHttp } from '../../public/crud_app/services'; +import { setHttp } from '../../crud_app/services'; import { mockHttpRequest, pageHelpers } from './helpers'; - -jest.mock('ui/new_platform'); +import { coreMock } from '../../../../../../src/core/public/mocks'; jest.mock('lodash/function/debounce', () => fn => fn); @@ -21,24 +20,24 @@ describe('Create Rollup Job, step 4: Histogram', () => { let goToStep; let table; let form; - let npStart; + let startMock; beforeAll(() => { - npStart = require('ui/new_platform').npStart; // eslint-disable-line - setHttp(npStart.core.http); + startMock = coreMock.createStart(); + setHttp(startMock.http); }); beforeEach(() => { // Set "default" mock responses by not providing any arguments - mockHttpRequest(npStart.core.http); + mockHttpRequest(startMock.http); ({ find, exists, actions, getEuiStepsHorizontalActive, goToStep, table, form } = setup()); }); afterEach(() => { - npStart.core.http.get.mockClear(); - npStart.core.http.post.mockClear(); - npStart.core.http.put.mockClear(); + startMock.http.get.mockClear(); + startMock.http.post.mockClear(); + startMock.http.put.mockClear(); }); const numericFields = ['a-numericField', 'b-numericField']; @@ -111,7 +110,7 @@ describe('Create Rollup Job, step 4: Histogram', () => { describe('when no histogram fields are availalbe', () => { it('should indicate it to the user', async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { numericFields: [] } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields: [] } }); await goToStepAndOpenFieldChooser(); const { tableCellsValues } = table.getMetaData('rollupJobHistogramFieldChooser-table'); @@ -122,7 +121,7 @@ describe('Create Rollup Job, step 4: Histogram', () => { describe('when histogram fields are available', () => { beforeEach(async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { numericFields } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields } }); await goToStepAndOpenFieldChooser(); }); @@ -156,7 +155,7 @@ describe('Create Rollup Job, step 4: Histogram', () => { it('should have a delete button on each row to remove an histogram field', async () => { // First let's add a term to the list - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { numericFields } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields } }); await goToStepAndOpenFieldChooser(); const { rows: fieldChooserRows } = table.getMetaData('rollupJobHistogramFieldChooser-table'); fieldChooserRows[0].reactWrapper.simulate('click'); @@ -183,7 +182,7 @@ describe('Create Rollup Job, step 4: Histogram', () => { }; beforeEach(async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { numericFields } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields } }); await goToStep(4); addHistogramFieldToList(); }); diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_logistics.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_logistics.test.js similarity index 96% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_logistics.test.js rename to x-pack/plugins/rollup/public/test/client_integration/job_create_logistics.test.js index ebc03e40cc2b9..7b89244bb52a9 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_logistics.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_logistics.test.js @@ -13,10 +13,9 @@ import { YEAR, } from '../../../../../../src/plugins/es_ui_shared/public'; import { indexPatterns } from '../../../../../../src/plugins/data/public'; -import { setHttp } from '../../public/crud_app/services'; +import { setHttp } from '../../crud_app/services'; import { mockHttpRequest, pageHelpers } from './helpers'; - -jest.mock('ui/new_platform'); +import { coreMock } from '../../../../../../src/core/public/mocks'; jest.mock('lodash/function/debounce', () => fn => fn); @@ -28,24 +27,24 @@ describe('Create Rollup Job, step 1: Logistics', () => { let actions; let form; let getEuiStepsHorizontalActive; - let npStart; + let startMock; beforeAll(() => { - npStart = require('ui/new_platform').npStart; // eslint-disable-line - setHttp(npStart.core.http); + startMock = coreMock.createStart(); + setHttp(startMock.http); }); beforeEach(() => { // Set "default" mock responses by not providing any arguments - mockHttpRequest(npStart.core.http); + mockHttpRequest(startMock.http); ({ find, exists, actions, form, getEuiStepsHorizontalActive } = setup()); }); afterEach(() => { - npStart.core.http.get.mockClear(); - npStart.core.http.post.mockClear(); - npStart.core.http.put.mockClear(); + startMock.http.get.mockClear(); + startMock.http.post.mockClear(); + startMock.http.put.mockClear(); }); it('should have the horizontal step active on "Logistics"', () => { @@ -97,14 +96,14 @@ describe('Create Rollup Job, step 1: Logistics', () => { }); it('should not allow an unknown index pattern', async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { doesMatchIndices: false } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { doesMatchIndices: false } }); await form.setInputValue('rollupIndexPattern', 'unknown', true); actions.clickNextStep(); expect(form.getErrorsMessages()).toContain("Index pattern doesn't match any indices."); }); it('should not allow an index pattern without time fields', async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { dateFields: [] } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { dateFields: [] } }); await form.setInputValue('rollupIndexPattern', 'abc', true); actions.clickNextStep(); expect(form.getErrorsMessages()).toContain( @@ -113,7 +112,7 @@ describe('Create Rollup Job, step 1: Logistics', () => { }); it('should not allow an index pattern that matches a rollup index', async () => { - mockHttpRequest(npStart.core.http, { + mockHttpRequest(startMock.http, { indxPatternVldtResp: { doesMatchRollupIndices: true }, }); await form.setInputValue('rollupIndexPattern', 'abc', true); diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_metrics.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_metrics.test.js similarity index 95% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_metrics.test.js rename to x-pack/plugins/rollup/public/test/client_integration/job_create_metrics.test.js index a72dc8b25c083..1e9dd88648da6 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_metrics.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_metrics.test.js @@ -4,10 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setHttp } from '../../public/crud_app/services'; +import { setHttp } from '../../crud_app/services'; import { mockHttpRequest, pageHelpers } from './helpers'; - -jest.mock('ui/new_platform'); +import { coreMock } from '../../../../../../src/core/public/mocks'; jest.mock('lodash/function/debounce', () => fn => fn); @@ -21,24 +20,24 @@ describe('Create Rollup Job, step 5: Metrics', () => { let goToStep; let table; let metrics; - let npStart; + let startMock; beforeAll(() => { - npStart = require('ui/new_platform').npStart; // eslint-disable-line - setHttp(npStart.core.http); + startMock = coreMock.createStart(); + setHttp(startMock.http); }); beforeEach(() => { // Set "default" mock responses by not providing any arguments - mockHttpRequest(npStart.core.http); + mockHttpRequest(startMock.http); ({ find, exists, actions, getEuiStepsHorizontalActive, goToStep, table, metrics } = setup()); }); afterEach(() => { - npStart.core.http.get.mockClear(); - npStart.core.http.post.mockClear(); - npStart.core.http.put.mockClear(); + startMock.http.get.mockClear(); + startMock.http.post.mockClear(); + startMock.http.put.mockClear(); }); const numericFields = ['a-numericField', 'c-numericField']; @@ -112,7 +111,7 @@ describe('Create Rollup Job, step 5: Metrics', () => { describe('table', () => { beforeEach(async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { numericFields, dateFields } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields, dateFields } }); await goToStepAndOpenFieldChooser(); }); @@ -169,7 +168,7 @@ describe('Create Rollup Job, step 5: Metrics', () => { describe('when fields are added', () => { beforeEach(async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { numericFields, dateFields } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields, dateFields } }); await goToStepAndOpenFieldChooser(); }); @@ -260,7 +259,7 @@ describe('Create Rollup Job, step 5: Metrics', () => { let getFieldListTableRows; beforeEach(async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { numericFields, dateFields } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields, dateFields } }); await goToStep(5); await addFieldToList('numeric'); diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_review.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_review.test.js similarity index 71% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_review.test.js rename to x-pack/plugins/rollup/public/test/client_integration/job_create_review.test.js index 0fa9509368d3f..d625b8f11208f 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_review.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_review.test.js @@ -6,13 +6,20 @@ import { pageHelpers, mockHttpRequest } from './helpers'; import { first } from 'lodash'; -import { setHttp } from '../../public/crud_app/services'; +import { setHttp } from '../../crud_app/services'; import { JOBS } from './helpers/constants'; - -jest.mock('ui/new_platform'); +import { coreMock } from '../../../../../../src/core/public/mocks'; jest.mock('lodash/function/debounce', () => fn => fn); +jest.mock('../../kibana_services', () => { + const services = require.requireActual('../../kibana_services'); + return { + ...services, + getUiStatsReporter: jest.fn(() => () => {}), + }; +}); + const { setup } = pageHelpers.jobCreate; describe('Create Rollup Job, step 6: Review', () => { @@ -23,23 +30,23 @@ describe('Create Rollup Job, step 6: Review', () => { let goToStep; let table; let form; - let npStart; + let startMock; beforeAll(() => { - npStart = require('ui/new_platform').npStart; // eslint-disable-line - setHttp(npStart.core.http); + startMock = coreMock.createStart(); + setHttp(startMock.http); }); beforeEach(() => { // Set "default" mock responses by not providing any arguments - mockHttpRequest(npStart.core.http); + mockHttpRequest(startMock.http); ({ find, exists, actions, getEuiStepsHorizontalActive, goToStep, table, form } = setup()); }); afterEach(() => { - npStart.core.http.get.mockClear(); - npStart.core.http.post.mockClear(); - npStart.core.http.put.mockClear(); + startMock.http.get.mockClear(); + startMock.http.post.mockClear(); + startMock.http.put.mockClear(); }); describe('layout', () => { @@ -84,7 +91,7 @@ describe('Create Rollup Job, step 6: Review', () => { }); it('should have a "Summary", "Terms" & "Request" tab if a term aggregation was added', async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { numericFields: ['my-field'] } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields: ['my-field'] } }); await goToStep(3); selectFirstField('Terms'); @@ -96,7 +103,7 @@ describe('Create Rollup Job, step 6: Review', () => { }); it('should have a "Summary", "Histogram" & "Request" tab if a histogram field was added', async () => { - mockHttpRequest(npStart.core.http, { indxPatternVldtResp: { numericFields: ['a-field'] } }); + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields: ['a-field'] } }); await goToStep(4); selectFirstField('Histogram'); form.setInputValue('rollupJobCreateHistogramInterval', 3); // set an interval @@ -108,7 +115,7 @@ describe('Create Rollup Job, step 6: Review', () => { }); it('should have a "Summary", "Metrics" & "Request" tab if a histogram field was added', async () => { - mockHttpRequest(npStart.core.http, { + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields: ['a-field'], dateFields: ['b-field'], @@ -130,28 +137,28 @@ describe('Create Rollup Job, step 6: Review', () => { describe('without starting job after creation', () => { it('should call the "create" Api server endpoint', async () => { - mockHttpRequest(npStart.core.http, { + mockHttpRequest(startMock.http, { createdJob: first(JOBS.jobs), }); await goToStep(6); - expect(npStart.core.http.put).not.toHaveBeenCalledWith(jobCreateApiPath); // make sure it hasn't been called - expect(npStart.core.http.get).not.toHaveBeenCalledWith(jobStartApiPath); // make sure it hasn't been called + expect(startMock.http.put).not.toHaveBeenCalledWith(jobCreateApiPath); // make sure it hasn't been called + expect(startMock.http.get).not.toHaveBeenCalledWith(jobStartApiPath); // make sure it hasn't been called actions.clickSave(); - // Given the following anti-jitter sleep x-pack/legacy/plugins/rollup/public/crud_app/store/actions/create_job.js + // Given the following anti-jitter sleep x-pack/plugins/rollup/public/crud_app/store/actions/create_job.js // we add a longer sleep here :( await new Promise(res => setTimeout(res, 750)); - expect(npStart.core.http.put).toHaveBeenCalledWith(jobCreateApiPath, expect.anything()); // It has been called! - expect(npStart.core.http.get).not.toHaveBeenCalledWith(jobStartApiPath); // It has still not been called! + expect(startMock.http.put).toHaveBeenCalledWith(jobCreateApiPath, expect.anything()); // It has been called! + expect(startMock.http.get).not.toHaveBeenCalledWith(jobStartApiPath); // It has still not been called! }); }); describe('with starting job after creation', () => { it('should call the "create" and "start" Api server endpoints', async () => { - mockHttpRequest(npStart.core.http, { + mockHttpRequest(startMock.http, { createdJob: first(JOBS.jobs), }); @@ -161,14 +168,14 @@ describe('Create Rollup Job, step 6: Review', () => { target: { checked: true }, }); - expect(npStart.core.http.post).not.toHaveBeenCalledWith(jobStartApiPath); // make sure it hasn't been called + expect(startMock.http.post).not.toHaveBeenCalledWith(jobStartApiPath); // make sure it hasn't been called actions.clickSave(); - // Given the following anti-jitter sleep x-pack/legacy/plugins/rollup/public/crud_app/store/actions/create_job.js + // Given the following anti-jitter sleep x-pack/plugins/rollup/public/crud_app/store/actions/create_job.js // we add a longer sleep here :( await new Promise(res => setTimeout(res, 750)); - expect(npStart.core.http.post).toHaveBeenCalledWith(jobStartApiPath, expect.anything()); // It has been called! + expect(startMock.http.post).toHaveBeenCalledWith(jobStartApiPath, expect.anything()); // It has been called! }); }); }); diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_terms.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_create_terms.test.js similarity index 93% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_terms.test.js rename to x-pack/plugins/rollup/public/test/client_integration/job_create_terms.test.js index f111a7df2c250..61993f3092840 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_create_terms.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_create_terms.test.js @@ -4,10 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setHttp } from '../../public/crud_app/services'; +import { setHttp } from '../../crud_app/services'; import { pageHelpers, mockHttpRequest } from './helpers'; - -jest.mock('ui/new_platform'); +import { coreMock } from '../../../../../../src/core/public/mocks'; jest.mock('lodash/function/debounce', () => fn => fn); @@ -20,22 +19,22 @@ describe('Create Rollup Job, step 3: Terms', () => { let getEuiStepsHorizontalActive; let goToStep; let table; - let npStart; + let startMock; beforeAll(() => { - npStart = require('ui/new_platform').npStart; // eslint-disable-line - setHttp(npStart.core.http); + startMock = coreMock.createStart(); + setHttp(startMock.http); }); beforeEach(() => { // Set "default" mock responses by not providing any arguments - mockHttpRequest(npStart.core.http); + mockHttpRequest(startMock.http); ({ find, exists, actions, getEuiStepsHorizontalActive, goToStep, table } = setup()); }); afterEach(() => { - npStart.core.http.get.mockClear(); + startMock.http.get.mockClear(); }); const numericFields = ['a-numericField', 'c-numericField']; @@ -109,7 +108,7 @@ describe('Create Rollup Job, step 3: Terms', () => { describe('when no terms are available', () => { it('should indicate it to the user', async () => { - mockHttpRequest(npStart.core.http, { + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields: [], keywordFields: [], @@ -125,7 +124,7 @@ describe('Create Rollup Job, step 3: Terms', () => { describe('when terms are available', () => { beforeEach(async () => { - mockHttpRequest(npStart.core.http, { + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields, keywordFields, @@ -171,7 +170,7 @@ describe('Create Rollup Job, step 3: Terms', () => { it('should have a delete button on each row to remove a term', async () => { // First let's add a term to the list - mockHttpRequest(npStart.core.http, { + mockHttpRequest(startMock.http, { indxPatternVldtResp: { numericFields, keywordFields, diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_list.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_list.test.js similarity index 77% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/job_list.test.js rename to x-pack/plugins/rollup/public/test/client_integration/job_list.test.js index a9e474cf0b559..c6988236d6b7c 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_list.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_list.test.js @@ -4,20 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getRouter, setHttp } from '../../public/crud_app/services'; +import { getRouter, setHttp } from '../../crud_app/services'; import { mockHttpRequest, pageHelpers, nextTick } from './helpers'; import { JOBS } from './helpers/constants'; +import { coreMock } from '../../../../../../src/core/public/mocks'; -jest.mock('ui/new_platform'); - -jest.mock('../../public/crud_app/services', () => { - const services = require.requireActual('../../public/crud_app/services'); +jest.mock('../../crud_app/services', () => { + const services = require.requireActual('../../crud_app/services'); return { ...services, getRouterLinkProps: link => ({ href: link }), }; }); +jest.mock('../../kibana_services', () => { + const services = require.requireActual('../../kibana_services'); + return { + ...services, + getUiStatsReporter: jest.fn(() => () => {}), + }; +}); + const { setup } = pageHelpers.jobList; describe('', () => { @@ -25,15 +32,15 @@ describe('', () => { let component; let table; let exists; - let npStart; + let startMock; beforeAll(() => { - npStart = require('ui/new_platform').npStart; // eslint-disable-line - setHttp(npStart.core.http); + startMock = coreMock.createStart(); + setHttp(startMock.http); }); beforeEach(async () => { - mockHttpRequest(npStart.core.http, { jobs: JOBS }); + mockHttpRequest(startMock.http, { jobs: JOBS }); ({ component, exists, table } = setup()); @@ -42,7 +49,7 @@ describe('', () => { }); afterEach(() => { - npStart.core.http.get.mockClear(); + startMock.http.get.mockClear(); }); test('should open the detail panel when clicking on a job in the table', () => { diff --git a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_list_clone.test.js b/x-pack/plugins/rollup/public/test/client_integration/job_list_clone.test.js similarity index 74% rename from x-pack/legacy/plugins/rollup/__jest__/client_integration/job_list_clone.test.js rename to x-pack/plugins/rollup/public/test/client_integration/job_list_clone.test.js index 8a36af83def4c..bdf57a555cdad 100644 --- a/x-pack/legacy/plugins/rollup/__jest__/client_integration/job_list_clone.test.js +++ b/x-pack/plugins/rollup/public/test/client_integration/job_list_clone.test.js @@ -6,14 +6,21 @@ import { mockHttpRequest, pageHelpers, nextTick } from './helpers'; import { JOB_TO_CLONE, JOB_CLONE_INDEX_PATTERN_CHECK } from './helpers/constants'; -import { getRouter } from '../../public/crud_app/services/routing'; -import { setHttp } from '../../public/crud_app/services'; -import { CRUD_APP_BASE_PATH } from '../../public/crud_app/constants'; - -jest.mock('ui/new_platform'); +import { getRouter } from '../../crud_app/services/routing'; +import { setHttp } from '../../crud_app/services'; +import { CRUD_APP_BASE_PATH } from '../../crud_app/constants'; +import { coreMock } from '../../../../../../src/core/public/mocks'; jest.mock('lodash/function/debounce', () => fn => fn); +jest.mock('../../kibana_services', () => { + const services = require.requireActual('../../kibana_services'); + return { + ...services, + getUiStatsReporter: jest.fn(() => () => {}), + }; +}); + const { setup } = pageHelpers.jobList; describe('Smoke test cloning an existing rollup job from job list', () => { @@ -21,15 +28,15 @@ describe('Smoke test cloning an existing rollup job from job list', () => { let find; let component; let exists; - let npStart; + let startMock; beforeAll(() => { - npStart = require('ui/new_platform').npStart; // eslint-disable-line - setHttp(npStart.core.http); + startMock = coreMock.createStart(); + setHttp(startMock.http); }); beforeEach(async () => { - mockHttpRequest(npStart.core.http, { + mockHttpRequest(startMock.http, { jobs: JOB_TO_CLONE, indxPatternVldtResp: JOB_CLONE_INDEX_PATTERN_CHECK, }); @@ -41,7 +48,7 @@ describe('Smoke test cloning an existing rollup job from job list', () => { }); afterEach(() => { - npStart.core.http.get.mockClear(); + startMock.http.get.mockClear(); }); it('should navigate to create view with default values set', async () => { diff --git a/x-pack/legacy/plugins/rollup/public/visualize/agg_type_field_filter.js b/x-pack/plugins/rollup/public/visualize/agg_type_field_filter.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/visualize/agg_type_field_filter.js rename to x-pack/plugins/rollup/public/visualize/agg_type_field_filter.js diff --git a/x-pack/legacy/plugins/rollup/public/visualize/agg_type_filter.js b/x-pack/plugins/rollup/public/visualize/agg_type_filter.js similarity index 100% rename from x-pack/legacy/plugins/rollup/public/visualize/agg_type_filter.js rename to x-pack/plugins/rollup/public/visualize/agg_type_filter.js diff --git a/x-pack/plugins/rollup/server/plugin.ts b/x-pack/plugins/rollup/server/plugin.ts index fa05b8d1307d6..ea6d197e22029 100644 --- a/x-pack/plugins/rollup/server/plugin.ts +++ b/x-pack/plugins/rollup/server/plugin.ts @@ -4,7 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Plugin, PluginInitializerContext } from 'src/core/server'; +import { CoreSetup, Plugin, PluginInitializerContext } from 'src/core/server'; +import { i18n } from '@kbn/i18n'; +import { schema } from '@kbn/config-schema'; +import { CONFIG_ROLLUPS } from '../common'; export class RollupPlugin implements Plugin { private readonly initContext: PluginInitializerContext; @@ -13,7 +16,23 @@ export class RollupPlugin implements Plugin { this.initContext = initContext; } - public setup() { + public setup(core: CoreSetup) { + core.uiSettings.register({ + [CONFIG_ROLLUPS]: { + name: i18n.translate('xpack.rollupJobs.rollupIndexPatternsTitle', { + defaultMessage: 'Enable rollup index patterns', + }), + value: true, + description: i18n.translate('xpack.rollupJobs.rollupIndexPatternsDescription', { + defaultMessage: `Enable the creation of index patterns which capture rollup indices, + which in turn enable visualizations based on rollup data. Refresh + the page to apply the changes.`, + }), + category: ['rollups'], + schema: schema.boolean(), + }, + }); + return { __legacy: { config: this.initContext.config, From fb1ff02ed33ca423970eb62ad4746df8f8544366 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Fri, 17 Apr 2020 12:07:51 -0400 Subject: [PATCH 19/22] Fix task manager cancel warning (#63756) Co-authored-by: Elastic Machine --- x-pack/plugins/apm/server/lib/apm_telemetry/index.ts | 3 ++- x-pack/plugins/lens/server/usage/task.ts | 1 + x-pack/plugins/oss_telemetry/server/lib/tasks/index.ts | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts index a78b2b93a250d..3eb61bb130725 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts @@ -87,7 +87,8 @@ export async function createApmTelemetry({ return { run: async () => { await collectAndStore(); - } + }, + cancel: async () => {} }; } } diff --git a/x-pack/plugins/lens/server/usage/task.ts b/x-pack/plugins/lens/server/usage/task.ts index 469457f973b62..e1a0bf20f7b48 100644 --- a/x-pack/plugins/lens/server/usage/task.ts +++ b/x-pack/plugins/lens/server/usage/task.ts @@ -210,6 +210,7 @@ export function telemetryTaskRunner( }) .catch(errMsg => logger.warn(`Error executing lens telemetry task: ${errMsg}`)); }, + async cancel() {}, }; }; } diff --git a/x-pack/plugins/oss_telemetry/server/lib/tasks/index.ts b/x-pack/plugins/oss_telemetry/server/lib/tasks/index.ts index 9342c2574bedd..415aeb2791d9e 100644 --- a/x-pack/plugins/oss_telemetry/server/lib/tasks/index.ts +++ b/x-pack/plugins/oss_telemetry/server/lib/tasks/index.ts @@ -41,6 +41,7 @@ export function registerTasks({ createTaskRunner({ taskInstance }: { taskInstance: TaskInstance }) { return { run: visualizationsTaskRunner(taskInstance, config, esClientPromise), + cancel: async () => {}, }; }, }, From 199271608687936b75651d3f341739278ccb335d Mon Sep 17 00:00:00 2001 From: Robert Oskamp Date: Fri, 17 Apr 2020 18:10:46 +0200 Subject: [PATCH 20/22] [ML] Functional tests - refactor test resources (#63724) This PR changes the way how test resources like indices and saved objects are used in ML and Transform functional tests. No actual test logic is changed. --- .../apis/ml/bucket_span_estimator.ts | 15 +- .../apis/ml/calculate_model_memory_limit.ts | 15 +- .../apis/ml/categorization_field_examples.ts | 9 +- .../api_integration/apis/ml/get_module.ts | 4 + x-pack/test/api_integration/apis/ml/index.ts | 9 + .../apis/ml/recognize_module.ts | 13 +- .../api_integration/apis/ml/setup_module.ts | 25 +- x-pack/test/api_integration/services/ml.ts | 3 + .../anomaly_detection/advanced_job.ts | 22 +- .../anomaly_detection/anomaly_explorer.ts | 11 +- .../anomaly_detection/categorization_job.ts | 20 +- .../anomaly_detection/date_nanos_job.ts | 12 +- .../anomaly_detection/multi_metric_job.ts | 16 +- .../anomaly_detection/population_job.ts | 16 +- .../anomaly_detection/saved_search_job.ts | 21 +- .../anomaly_detection/single_metric_job.ts | 16 +- .../anomaly_detection/single_metric_viewer.ts | 8 +- .../classification_creation.ts | 11 +- .../data_frame_analytics/cloning.ts | 21 +- .../outlier_detection_creation.ts | 9 +- .../regression_creation.ts | 9 +- .../data_visualizer/file_data_visualizer.ts | 2 + .../data_visualizer/index_data_visualizer.ts | 17 +- .../feature_controls/ml_security.ts | 4 - .../feature_controls/ml_spaces.ts | 9 - .../functional/apps/machine_learning/index.ts | 21 + .../functional/apps/machine_learning/pages.ts | 7 +- .../test/functional/apps/transform/cloning.ts | 9 +- .../apps/transform/creation_index_pattern.ts | 11 +- .../apps/transform/creation_saved_search.ts | 12 +- .../test/functional/apps/transform/index.ts | 11 + .../ml/bm_classification/data.json.gz | Bin 169485 -> 168183 bytes .../ml/bm_classification/mappings.json | 1454 +------- .../ml/categorization/data.json.gz | Bin 331971 -> 330822 bytes .../ml/categorization/mappings.json | 834 +---- .../es_archives/ml/ecommerce/data.json.gz | Bin 1007039 -> 1006034 bytes .../es_archives/ml/ecommerce/mappings.json | 1017 +----- .../ml/egs_regression/data.json.gz | Bin 279698 -> 279119 bytes .../ml/egs_regression/mappings.json | 1394 +------- .../ml/event_rate_nanos/data.json.gz | Bin 1656445 -> 1653388 bytes .../ml/event_rate_nanos/mappings.json | 1454 +------- .../es_archives/ml/farequote/data.json.gz | Bin 1359631 -> 1367398 bytes .../es_archives/ml/farequote/mappings.json | 1041 +----- .../es_archives/ml/ihp_outlier/data.json.gz | Bin 70805 -> 69988 bytes .../es_archives/ml/ihp_outlier/mappings.json | 1394 +------- .../es_archives/ml/sample_logs/data.json.gz | Bin 1643792 -> 1642819 bytes .../es_archives/ml/sample_logs/mappings.json | 2995 ----------------- .../services/machine_learning/index.ts | 1 + .../machine_learning/test_resources.ts | 219 ++ .../machine_learning/test_resources_data.ts | 249 ++ x-pack/test/functional/services/ml.ts | 3 + x-pack/test/functional/services/transform.ts | 4 + 52 files changed, 727 insertions(+), 11720 deletions(-) create mode 100644 x-pack/test/functional/services/machine_learning/test_resources.ts create mode 100644 x-pack/test/functional/services/machine_learning/test_resources_data.ts diff --git a/x-pack/test/api_integration/apis/ml/bucket_span_estimator.ts b/x-pack/test/api_integration/apis/ml/bucket_span_estimator.ts index 3f56fb927d131..bc0dc3019d7c9 100644 --- a/x-pack/test/api_integration/apis/ml/bucket_span_estimator.ts +++ b/x-pack/test/api_integration/apis/ml/bucket_span_estimator.ts @@ -28,7 +28,7 @@ export default ({ getService }: FtrProviderContext) => { aggTypes: ['avg'], duration: { start: 1560297859000, end: 1562975136000 }, fields: ['taxless_total_price'], - index: 'ecommerce', + index: 'ft_ecommerce', query: { bool: { must: [{ match_all: {} }] } }, timeField: 'order_date', }, @@ -44,7 +44,7 @@ export default ({ getService }: FtrProviderContext) => { aggTypes: ['avg', 'sum'], duration: { start: 1560297859000, end: 1562975136000 }, fields: ['products.base_price', 'products.base_unit_price'], - index: 'ecommerce', + index: 'ft_ecommerce', query: { bool: { must: [{ match_all: {} }] } }, timeField: 'order_date', }, @@ -60,7 +60,7 @@ export default ({ getService }: FtrProviderContext) => { aggTypes: ['avg'], duration: { start: 1560297859000, end: 1562975136000 }, fields: ['taxless_total_price'], - index: 'ecommerce', + index: 'ft_ecommerce', query: { bool: { must: [{ match_all: {} }] } }, splitField: 'customer_first_name.keyword', timeField: 'order_date', @@ -78,7 +78,7 @@ export default ({ getService }: FtrProviderContext) => { duration: { start: 1560297859000, end: 1562975136000 }, fields: ['taxless_total_price'], filters: [], - index: 'ecommerce', + index: 'ft_ecommerce', query: { bool: { must: [{ match_all: {} }] } }, timeField: 'order_date', }, @@ -91,11 +91,8 @@ export default ({ getService }: FtrProviderContext) => { describe('bucket span estimator', function() { before(async () => { - await esArchiver.load('ml/ecommerce'); - }); - - after(async () => { - await esArchiver.unload('ml/ecommerce'); + await esArchiver.loadIfNeeded('ml/ecommerce'); + await ml.testResources.setKibanaTimeZoneToUTC(); }); describe('with default settings', function() { diff --git a/x-pack/test/api_integration/apis/ml/calculate_model_memory_limit.ts b/x-pack/test/api_integration/apis/ml/calculate_model_memory_limit.ts index 975a10c2aed2a..59e3dfcca00f9 100644 --- a/x-pack/test/api_integration/apis/ml/calculate_model_memory_limit.ts +++ b/x-pack/test/api_integration/apis/ml/calculate_model_memory_limit.ts @@ -22,7 +22,7 @@ export default ({ getService }: FtrProviderContext) => { testTitleSuffix: 'when no partition field is provided with regular function', user: USER.ML_POWERUSER, requestBody: { - indexPattern: 'ecommerce', + indexPattern: 'ft_ecommerce', analysisConfig: { bucket_span: '15m', detectors: [ @@ -51,7 +51,7 @@ export default ({ getService }: FtrProviderContext) => { testTitleSuffix: 'with 1 metric and 1 influencer same as split field', user: USER.ML_POWERUSER, requestBody: { - indexPattern: 'ecommerce', + indexPattern: 'ft_ecommerce', analysisConfig: { bucket_span: '15m', detectors: [ @@ -77,7 +77,7 @@ export default ({ getService }: FtrProviderContext) => { testTitleSuffix: 'with 3 influencers, split by city', user: USER.ML_POWERUSER, requestBody: { - indexPattern: 'ecommerce', + indexPattern: 'ft_ecommerce', analysisConfig: { bucket_span: '15m', detectors: [ @@ -104,7 +104,7 @@ export default ({ getService }: FtrProviderContext) => { '2 detectors split by city and manufacturer, 4 influencers, filtering by country code', user: USER.ML_POWERUSER, requestBody: { - indexPattern: 'ecommerce', + indexPattern: 'ft_ecommerce', analysisConfig: { bucket_span: '2d', detectors: [ @@ -148,11 +148,8 @@ export default ({ getService }: FtrProviderContext) => { describe('calculate model memory limit', function() { before(async () => { - await esArchiver.load('ml/ecommerce'); - }); - - after(async () => { - await esArchiver.unload('ml/ecommerce'); + await esArchiver.loadIfNeeded('ml/ecommerce'); + await ml.testResources.setKibanaTimeZoneToUTC(); }); for (const testData of testDataList) { diff --git a/x-pack/test/api_integration/apis/ml/categorization_field_examples.ts b/x-pack/test/api_integration/apis/ml/categorization_field_examples.ts index b8ee2e7f6562c..df0153f965942 100644 --- a/x-pack/test/api_integration/apis/ml/categorization_field_examples.ts +++ b/x-pack/test/api_integration/apis/ml/categorization_field_examples.ts @@ -66,7 +66,7 @@ const analyzer = { ], }; const defaultRequestBody = { - indexPatternTitle: 'categorization_functional_test', + indexPatternTitle: 'ft_categorization', query: { bool: { must: [{ match_all: {} }] } }, size: 5, timeField: '@timestamp', @@ -289,11 +289,8 @@ export default ({ getService }: FtrProviderContext) => { describe('Categorization example endpoint - ', function() { before(async () => { - await esArchiver.load('ml/categorization'); - }); - - after(async () => { - await esArchiver.unload('ml/categorization'); + await esArchiver.loadIfNeeded('ml/categorization'); + await ml.testResources.setKibanaTimeZoneToUTC(); }); for (const testData of testDataList) { diff --git a/x-pack/test/api_integration/apis/ml/get_module.ts b/x-pack/test/api_integration/apis/ml/get_module.ts index 6dcd9594fc9aa..a50d3c0abe430 100644 --- a/x-pack/test/api_integration/apis/ml/get_module.ts +++ b/x-pack/test/api_integration/apis/ml/get_module.ts @@ -50,6 +50,10 @@ export default ({ getService }: FtrProviderContext) => { } describe('get_module', function() { + before(async () => { + await ml.testResources.setKibanaTimeZoneToUTC(); + }); + it('lists all modules', async () => { const rspBody = await executeGetModuleRequest('', USER.ML_POWERUSER, 200); expect(rspBody).to.be.an(Array); diff --git a/x-pack/test/api_integration/apis/ml/index.ts b/x-pack/test/api_integration/apis/ml/index.ts index 4e21faa610bfe..f012883c46ca3 100644 --- a/x-pack/test/api_integration/apis/ml/index.ts +++ b/x-pack/test/api_integration/apis/ml/index.ts @@ -7,6 +7,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); const ml = getService('ml'); describe('Machine Learning', function() { @@ -20,6 +21,14 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { after(async () => { await ml.securityCommon.cleanMlUsers(); await ml.securityCommon.cleanMlRoles(); + + await ml.testResources.deleteIndexPattern('kibana_sample_data_logs'); + + await esArchiver.unload('ml/ecommerce'); + await esArchiver.unload('ml/categorization'); + await esArchiver.unload('ml/sample_logs'); + + await ml.testResources.resetKibanaTimeZone(); }); loadTestFile(require.resolve('./bucket_span_estimator')); diff --git a/x-pack/test/api_integration/apis/ml/recognize_module.ts b/x-pack/test/api_integration/apis/ml/recognize_module.ts index 2110bded7394c..8e360579c1459 100644 --- a/x-pack/test/api_integration/apis/ml/recognize_module.ts +++ b/x-pack/test/api_integration/apis/ml/recognize_module.ts @@ -32,7 +32,6 @@ export default ({ getService }: FtrProviderContext) => { }, { testTitleSuffix: 'for non existent index pattern', - sourceDataArchive: 'empty_kibana', indexPattern: 'non-existent-index-pattern', user: USER.ML_POWERUSER, expected: { @@ -53,14 +52,16 @@ export default ({ getService }: FtrProviderContext) => { } describe('module recognizer', function() { + before(async () => { + await ml.testResources.setKibanaTimeZoneToUTC(); + }); + for (const testData of testDataList) { describe('lists matching modules', function() { before(async () => { - await esArchiver.load(testData.sourceDataArchive); - }); - - after(async () => { - await esArchiver.unload(testData.sourceDataArchive); + if (testData.hasOwnProperty('sourceDataArchive')) { + await esArchiver.loadIfNeeded(testData.sourceDataArchive!); + } }); it(testData.testTitleSuffix, async () => { diff --git a/x-pack/test/api_integration/apis/ml/setup_module.ts b/x-pack/test/api_integration/apis/ml/setup_module.ts index 71f3910cd4e93..e603782b25717 100644 --- a/x-pack/test/api_integration/apis/ml/setup_module.ts +++ b/x-pack/test/api_integration/apis/ml/setup_module.ts @@ -25,6 +25,7 @@ export default ({ getService }: FtrProviderContext) => { { testTitleSuffix: 'for sample logs dataset with prefix and startDatafeed false', sourceDataArchive: 'ml/sample_logs', + indexPattern: { name: 'kibana_sample_data_logs', timeField: '@timestamp' }, module: 'sample_data_weblogs', user: USER.ML_POWERUSER, requestBody: { @@ -58,7 +59,6 @@ export default ({ getService }: FtrProviderContext) => { const testDataListNegative = [ { testTitleSuffix: 'for non existent index pattern', - sourceDataArchive: 'empty_kibana', module: 'sample_data_weblogs', user: USER.ML_POWERUSER, requestBody: { @@ -75,6 +75,7 @@ export default ({ getService }: FtrProviderContext) => { { testTitleSuffix: 'for unauthorized user', sourceDataArchive: 'ml/sample_logs', + indexPattern: { name: 'kibana_sample_data_logs', timeField: '@timestamp' }, module: 'sample_data_weblogs', user: USER.ML_UNAUTHORIZED, requestBody: { @@ -118,14 +119,21 @@ export default ({ getService }: FtrProviderContext) => { } describe('module setup', function() { + before(async () => { + await ml.testResources.setKibanaTimeZoneToUTC(); + }); + for (const testData of testDataListPositive) { describe('sets up module data', function() { before(async () => { - await esArchiver.load(testData.sourceDataArchive); + await esArchiver.loadIfNeeded(testData.sourceDataArchive); + await ml.testResources.createIndexPatternIfNeeded( + testData.indexPattern.name, + testData.indexPattern.timeField + ); }); after(async () => { - await esArchiver.unload(testData.sourceDataArchive); await ml.api.cleanMlIndices(); }); @@ -199,11 +207,18 @@ export default ({ getService }: FtrProviderContext) => { for (const testData of testDataListNegative) { describe('rejects request', function() { before(async () => { - await esArchiver.load(testData.sourceDataArchive); + if (testData.hasOwnProperty('sourceDataArchive')) { + await esArchiver.loadIfNeeded(testData.sourceDataArchive!); + } + if (testData.hasOwnProperty('indexPattern')) { + await ml.testResources.createIndexPatternIfNeeded( + testData.indexPattern!.name as string, + testData.indexPattern!.timeField as string + ); + } }); after(async () => { - await esArchiver.unload(testData.sourceDataArchive); await ml.api.cleanMlIndices(); }); diff --git a/x-pack/test/api_integration/services/ml.ts b/x-pack/test/api_integration/services/ml.ts index 841b200b87080..c295af7dc73ab 100644 --- a/x-pack/test/api_integration/services/ml.ts +++ b/x-pack/test/api_integration/services/ml.ts @@ -9,14 +9,17 @@ import { FtrProviderContext } from '../../functional/ftr_provider_context'; import { MachineLearningAPIProvider, MachineLearningSecurityCommonProvider, + MachineLearningTestResourcesProvider, } from '../../functional/services/machine_learning'; export function MachineLearningProvider(context: FtrProviderContext) { const api = MachineLearningAPIProvider(context); const securityCommon = MachineLearningSecurityCommonProvider(context); + const testResources = MachineLearningTestResourcesProvider(context); return { api, securityCommon, + testResources, }; } diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/advanced_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/advanced_job.ts index 53b1cb83c524b..a5faf325aa6cb 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/advanced_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/advanced_job.ts @@ -110,13 +110,13 @@ export default function({ getService }: FtrProviderContext) { const testDataList = [ { suiteTitle: 'with multiple metric detectors and custom datafeed settings', - jobSource: 'ecommerce', + jobSource: 'ft_ecommerce', jobId: `ec_advanced_1_${Date.now()}`, get jobIdClone(): string { return `${this.jobId}_clone`; }, jobDescription: - 'Create advanced job from ecommerce dataset with multiple metric detectors and custom datafeed settings', + 'Create advanced job from ft_ecommerce dataset with multiple metric detectors and custom datafeed settings', jobGroups: ['automated', 'ecommerce', 'advanced'], get jobGroupsClone(): string[] { return [...this.jobGroups, 'clone']; @@ -207,13 +207,13 @@ export default function({ getService }: FtrProviderContext) { }, { suiteTitle: 'with categorization detector and default datafeed settings', - jobSource: 'ecommerce', + jobSource: 'ft_ecommerce', jobId: `ec_advanced_2_${Date.now()}`, get jobIdClone(): string { return `${this.jobId}_clone`; }, jobDescription: - 'Create advanced job from ecommerce dataset with a categorization detector and default datafeed settings', + 'Create advanced job from ft_ecommerce dataset with a categorization detector and default datafeed settings', jobGroups: ['automated', 'ecommerce', 'advanced'], get jobGroupsClone(): string[] { return [...this.jobGroups, 'clone']; @@ -274,16 +274,20 @@ export default function({ getService }: FtrProviderContext) { }, ]; + const calendarId = `wizard-test-calendar_${Date.now()}`; + describe('advanced job', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/ecommerce'); - await ml.api.createCalendar('wizard-test-calendar'); + await esArchiver.loadIfNeeded('ml/ecommerce'); + await ml.testResources.createIndexPatternIfNeeded('ft_ecommerce', 'order_date'); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await ml.api.createCalendar(calendarId); await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { - await esArchiver.unload('ml/ecommerce'); await ml.api.cleanMlIndices(); }); @@ -475,7 +479,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job creation assigns calendars', async () => { - await ml.jobWizardCommon.addCalendar('wizard-test-calendar'); + await ml.jobWizardCommon.addCalendar(calendarId); }); it('job creation displays the model plot switch', async () => { @@ -734,7 +738,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job cloning persists assigned calendars', async () => { - await ml.jobWizardCommon.assertCalendarsSelection(['wizard-test-calendar']); + await ml.jobWizardCommon.assertCalendarsSelection([calendarId]); }); it('job cloning pre-fills the model plot switch', async () => { diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/anomaly_explorer.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/anomaly_explorer.ts index 83e9c01a46319..8827559a5f470 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/anomaly_explorer.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/anomaly_explorer.ts @@ -29,7 +29,7 @@ const JOB_CONFIG: Job = { const DATAFEED_CONFIG: Datafeed = { datafeed_id: 'datafeed-fq_multi_1_se', - indices: ['farequote'], + indices: ['ft_farequote'], job_id: 'fq_multi_1_ae', query: { bool: { must: [{ match_all: {} }] } }, }; @@ -59,12 +59,11 @@ export default function({ getService }: FtrProviderContext) { describe('anomaly explorer', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/farequote'); - await ml.securityUI.loginAsMlPowerUser(); - }); + await esArchiver.loadIfNeeded('ml/farequote'); + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await ml.testResources.setKibanaTimeZoneToUTC(); - after(async () => { - await esArchiver.unload('ml/farequote'); + await ml.securityUI.loginAsMlPowerUser(); }); for (const testData of testDataList) { diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/categorization_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/categorization_job.ts index 6408c6de1f928..9b5ae171d4115 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/categorization_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/categorization_job.ts @@ -16,7 +16,7 @@ export default function({ getService }: FtrProviderContext) { const jobId = `categorization_${Date.now()}`; const jobIdClone = `${jobId}_clone`; const jobDescription = - 'Create categorization job based on the categorization_functional_test dataset with a count rare'; + 'Create categorization job based on the ft_categorization dataset with a count rare'; const jobGroups = ['automated', 'categorization']; const jobGroupsClone = [...jobGroups, 'clone']; const detectorTypeIdentifier = 'Rare'; @@ -74,16 +74,20 @@ export default function({ getService }: FtrProviderContext) { }; } + const calendarId = `wizard-test-calendar_${Date.now()}`; + describe('categorization', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/categorization'); - await ml.api.createCalendar('wizard-test-calendar'); + await esArchiver.loadIfNeeded('ml/categorization'); + await ml.testResources.createIndexPatternIfNeeded('ft_categorization', '@timestamp'); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await ml.api.createCalendar(calendarId); await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { - await esArchiver.unload('ml/categorization'); await ml.api.cleanMlIndices(); }); @@ -97,9 +101,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job creation loads the job type selection page', async () => { - await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob( - 'categorization_functional_test' - ); + await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob('ft_categorization'); }); it('job creation loads the categorization job wizard page', async () => { @@ -178,7 +180,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job creation assigns calendars', async () => { - await ml.jobWizardCommon.addCalendar('wizard-test-calendar'); + await ml.jobWizardCommon.addCalendar(calendarId); }); it('job creation opens the advanced section', async () => { @@ -310,7 +312,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job cloning persists assigned calendars', async () => { - await ml.jobWizardCommon.assertCalendarsSelection(['wizard-test-calendar']); + await ml.jobWizardCommon.assertCalendarsSelection([calendarId]); }); it('job cloning opens the advanced section', async () => { diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/date_nanos_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/date_nanos_job.ts index 2a9824f46778d..570deee01c684 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/date_nanos_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/date_nanos_job.ts @@ -104,7 +104,7 @@ export default function({ getService }: FtrProviderContext) { const testDataList = [ { suiteTitle: 'with count detector and model plot disabled', - jobSource: 'event_rate_gen_trend_nanos', + jobSource: 'ft_event_rate_gen_trend_nanos', jobId: `event_rate_nanos_count_1_${Date.now()}`, jobDescription: 'Create advanced job based on the event rate dataset with a date_nanos time field, 30m bucketspan and count', @@ -168,12 +168,18 @@ export default function({ getService }: FtrProviderContext) { describe('job on data set with date_nanos time field', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/event_rate_nanos'); + await esArchiver.loadIfNeeded('ml/event_rate_nanos'); + await ml.testResources.createIndexPatternIfNeeded( + 'ft_event_rate_gen_trend_nanos', + '@timestamp' + ); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await esArchiver.loadIfNeeded('ml/event_rate_nanos'); await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { - await esArchiver.unload('ml/event_rate_nanos'); await ml.api.cleanMlIndices(); }); diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts index 08175b7946259..4739f987541d6 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts @@ -71,16 +71,20 @@ export default function({ getService }: FtrProviderContext) { }; } + const calendarId = `wizard-test-calendar_${Date.now()}`; + describe('multi metric', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/farequote'); - await ml.api.createCalendar('wizard-test-calendar'); + await esArchiver.loadIfNeeded('ml/farequote'); + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await ml.api.createCalendar(calendarId); await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { - await esArchiver.unload('ml/farequote'); await ml.api.cleanMlIndices(); }); @@ -94,7 +98,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job creation loads the job type selection page', async () => { - await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob('farequote'); + await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob('ft_farequote'); }); it('job creation loads the multi metric job wizard page', async () => { @@ -181,7 +185,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job creation assigns calendars', async () => { - await ml.jobWizardCommon.addCalendar('wizard-test-calendar'); + await ml.jobWizardCommon.addCalendar(calendarId); }); it('job creation opens the advanced section', async () => { @@ -329,7 +333,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job cloning persists assigned calendars', async () => { - await ml.jobWizardCommon.assertCalendarsSelection(['wizard-test-calendar']); + await ml.jobWizardCommon.assertCalendarsSelection([calendarId]); }); it('job cloning opens the advanced section', async () => { diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts index 512d13307ea05..0279c70bb73a9 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts @@ -85,16 +85,20 @@ export default function({ getService }: FtrProviderContext) { }; } + const calendarId = `wizard-test-calendar_${Date.now()}`; + describe('population', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/ecommerce'); - await ml.api.createCalendar('wizard-test-calendar'); + await esArchiver.loadIfNeeded('ml/ecommerce'); + await ml.testResources.createIndexPatternIfNeeded('ft_ecommerce', 'order_date'); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await ml.api.createCalendar(calendarId); await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { - await esArchiver.unload('ml/farequote'); await ml.api.cleanMlIndices(); }); @@ -108,7 +112,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job creation loads the job type selection page', async () => { - await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob('ecommerce'); + await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob('ft_ecommerce'); }); it('job creation loads the population job wizard page', async () => { @@ -208,7 +212,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job creation assigns calendars', async () => { - await ml.jobWizardCommon.addCalendar('wizard-test-calendar'); + await ml.jobWizardCommon.addCalendar(calendarId); }); it('job creation opens the advanced section', async () => { @@ -367,7 +371,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job cloning persists assigned calendars', async () => { - await ml.jobWizardCommon.assertCalendarsSelection(['wizard-test-calendar']); + await ml.jobWizardCommon.assertCalendarsSelection([calendarId]); }); it('job cloning opens the advanced section', async () => { diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts index a13cf3d61128e..a5652d76358eb 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts @@ -15,7 +15,7 @@ export default function({ getService }: FtrProviderContext) { const testDataList = [ { suiteTitle: 'with filter', - jobSource: 'farequote_filter', + jobSource: 'ft_farequote_filter', jobId: `fq_saved_search_1_${Date.now()}`, jobDescription: 'Create multi metric job based on a saved search with filter', jobGroups: ['automated', 'farequote', 'multi-metric', 'saved-search'], @@ -66,7 +66,7 @@ export default function({ getService }: FtrProviderContext) { }, { suiteTitle: 'with lucene query', - jobSource: 'farequote_lucene', + jobSource: 'ft_farequote_lucene', jobId: `fq_saved_search_2_${Date.now()}`, jobDescription: 'Create multi metric job based on a saved search with lucene query', jobGroups: ['automated', 'farequote', 'multi-metric', 'saved-search'], @@ -117,7 +117,7 @@ export default function({ getService }: FtrProviderContext) { }, { suiteTitle: 'with kuery query', - jobSource: 'farequote_kuery', + jobSource: 'ft_farequote_kuery', jobId: `fq_saved_search_3_${Date.now()}`, jobDescription: 'Create multi metric job based on a saved search with kuery query', jobGroups: ['automated', 'farequote', 'multi-metric', 'saved-search'], @@ -168,7 +168,7 @@ export default function({ getService }: FtrProviderContext) { }, { suiteTitle: 'with filter and lucene query', - jobSource: 'farequote_filter_and_lucene', + jobSource: 'ft_farequote_filter_and_lucene', jobId: `fq_saved_search_4_${Date.now()}`, jobDescription: 'Create multi metric job based on a saved search with filter and lucene query', @@ -220,7 +220,7 @@ export default function({ getService }: FtrProviderContext) { }, { suiteTitle: 'with filter and kuery query', - jobSource: 'farequote_filter_and_kuery', + jobSource: 'ft_farequote_filter_and_kuery', jobId: `fq_saved_search_5_${Date.now()}`, jobDescription: 'Create multi metric job based on a saved search with filter and kuery query', jobGroups: ['automated', 'farequote', 'multi-metric', 'saved-search'], @@ -274,12 +274,19 @@ export default function({ getService }: FtrProviderContext) { describe('saved search', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/farequote'); + await esArchiver.loadIfNeeded('ml/farequote'); + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await ml.testResources.createSavedSearchFarequoteFilterIfNeeded(); + await ml.testResources.createSavedSearchFarequoteLuceneIfNeeded(); + await ml.testResources.createSavedSearchFarequoteKueryIfNeeded(); + await ml.testResources.createSavedSearchFarequoteFilterAndLuceneIfNeeded(); + await ml.testResources.createSavedSearchFarequoteFilterAndKueryIfNeeded(); + await ml.testResources.setKibanaTimeZoneToUTC(); + await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { - await esArchiver.unload('ml/farequote'); await ml.api.cleanMlIndices(); }); diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts index 4e6d480c12d82..43053decb3924 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts @@ -70,16 +70,20 @@ export default function({ getService }: FtrProviderContext) { }; } + const calendarId = `wizard-test-calendar_${Date.now()}`; + describe('single metric', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/farequote'); - await ml.api.createCalendar('wizard-test-calendar'); + await esArchiver.loadIfNeeded('ml/farequote'); + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await ml.api.createCalendar(calendarId); await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { - await esArchiver.unload('ml/farequote'); await ml.api.cleanMlIndices(); }); @@ -93,7 +97,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job creation loads the job type selection page', async () => { - await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob('farequote'); + await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob('ft_farequote'); }); it('job creation loads the single metric job wizard page', async () => { @@ -162,7 +166,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job creation assigns calendars', async () => { - await ml.jobWizardCommon.addCalendar('wizard-test-calendar'); + await ml.jobWizardCommon.addCalendar(calendarId); }); it('job creation opens the advanced section', async () => { @@ -294,7 +298,7 @@ export default function({ getService }: FtrProviderContext) { }); it('job cloning persists assigned calendars', async () => { - await ml.jobWizardCommon.assertCalendarsSelection(['wizard-test-calendar']); + await ml.jobWizardCommon.assertCalendarsSelection([calendarId]); }); it('job cloning opens the advanced section', async () => { diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_viewer.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_viewer.ts index 62b801daa3479..cc7c9828ce87d 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_viewer.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_viewer.ts @@ -29,7 +29,7 @@ const JOB_CONFIG: Job = { const DATAFEED_CONFIG: Datafeed = { datafeed_id: 'datafeed-fq_single_1_smv', - indices: ['farequote'], + indices: ['ft_farequote'], job_id: 'fq_single_1_smv', query: { bool: { must: [{ match_all: {} }] } }, }; @@ -42,13 +42,15 @@ export default function({ getService }: FtrProviderContext) { describe('single metric viewer', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/farequote'); + await esArchiver.loadIfNeeded('ml/farequote'); + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await ml.testResources.setKibanaTimeZoneToUTC(); + await ml.api.createAndRunAnomalyDetectionLookbackJob(JOB_CONFIG, DATAFEED_CONFIG); await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { - await esArchiver.unload('ml/farequote'); await ml.api.cleanMlIndices(); }); diff --git a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/classification_creation.ts b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/classification_creation.ts index a7c92cac2072f..8a6741bd88daa 100644 --- a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/classification_creation.ts +++ b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/classification_creation.ts @@ -14,13 +14,15 @@ export default function({ getService }: FtrProviderContext) { describe('classification creation', function() { this.tags(['smoke']); before(async () => { - await esArchiver.load('ml/bm_classification'); + await esArchiver.loadIfNeeded('ml/bm_classification'); + await ml.testResources.createIndexPatternIfNeeded('ft_bank_marketing', '@timestamp'); + await ml.testResources.setKibanaTimeZoneToUTC(); + await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { await ml.api.cleanMlIndices(); - await esArchiver.unload('ml/bm_classification'); }); const testDataList = [ @@ -29,8 +31,8 @@ export default function({ getService }: FtrProviderContext) { jobType: 'classification', jobId: `bm_1_${Date.now()}`, jobDescription: - "Classification job based on 'bank-marketing' dataset with dependentVariable 'y' and trainingPercent '20'", - source: 'bank-marketing*', + "Classification job based on 'ft_bank_marketing' dataset with dependentVariable 'y' and trainingPercent '20'", + source: 'ft_bank_marketing', get destinationIndex(): string { return `user-${this.jobId}`; }, @@ -51,6 +53,7 @@ export default function({ getService }: FtrProviderContext) { describe(`${testData.suiteTitle}`, function() { after(async () => { await ml.api.deleteIndices(testData.destinationIndex); + await ml.testResources.deleteIndexPattern(testData.destinationIndex); }); it('loads the data frame analytics page', async () => { diff --git a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/cloning.ts b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/cloning.ts index caf382b532273..d98d8feaaf4fe 100644 --- a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/cloning.ts +++ b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/cloning.ts @@ -19,6 +19,7 @@ export default function({ getService }: FtrProviderContext) { const testDataList: Array<{ suiteTitle: string; archive: string; + indexPattern: { name: string; timeField: string }; job: DeepPartial; }> = (() => { const timestamp = Date.now(); @@ -27,12 +28,13 @@ export default function({ getService }: FtrProviderContext) { { suiteTitle: 'classification job supported by the form', archive: 'ml/bm_classification', + indexPattern: { name: 'ft_bank_marketing', timeField: '@timestamp' }, job: { id: `bm_1_${timestamp}`, description: - "Classification job based on 'bank-marketing' dataset with dependentVariable 'y' and trainingPercent '20'", + "Classification job based on 'ft_bank_marketing' dataset with dependentVariable 'y' and trainingPercent '20'", source: { - index: ['bank-marketing*'], + index: ['ft_bank_marketing'], query: { match_all: {}, }, @@ -60,11 +62,12 @@ export default function({ getService }: FtrProviderContext) { { suiteTitle: 'outlier detection job supported by the form', archive: 'ml/ihp_outlier', + indexPattern: { name: 'ft_ihp_outlier', timeField: '@timestamp' }, job: { id: `ihp_1_${timestamp}`, description: 'This is the job description', source: { - index: ['ihp_outlier'], + index: ['ft_ihp_outlier'], query: { match_all: {}, }, @@ -88,11 +91,12 @@ export default function({ getService }: FtrProviderContext) { { suiteTitle: 'regression job supported by the form', archive: 'ml/egs_regression', + indexPattern: { name: 'ft_egs_regression', timeField: '@timestamp' }, job: { id: `egs_1_${timestamp}`, description: 'This is the job description', source: { - index: ['egs_regression'], + index: ['ft_egs_regression'], query: { match_all: {}, }, @@ -120,6 +124,7 @@ export default function({ getService }: FtrProviderContext) { })(); before(async () => { + await ml.testResources.setKibanaTimeZoneToUTC(); await ml.securityUI.loginAsMlPowerUser(); }); @@ -133,7 +138,11 @@ export default function({ getService }: FtrProviderContext) { const cloneDestIndex = `${testData.job!.dest!.index}_clone`; before(async () => { - await esArchiver.load(testData.archive); + await esArchiver.loadIfNeeded(testData.archive); + await ml.testResources.createIndexPatternIfNeeded( + testData.indexPattern.name, + testData.indexPattern.timeField + ); await ml.api.createDataFrameAnalyticsJob(testData.job as DataFrameAnalyticsConfig); await ml.navigation.navigateToMl(); @@ -146,7 +155,7 @@ export default function({ getService }: FtrProviderContext) { after(async () => { await ml.api.deleteIndices(cloneDestIndex); await ml.api.deleteIndices(testData.job.dest!.index as string); - await esArchiver.unload(testData.archive); + await ml.testResources.deleteIndexPattern(testData.job.dest!.index as string); }); it('should open the flyout with a proper header', async () => { diff --git a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/outlier_detection_creation.ts b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/outlier_detection_creation.ts index 5481977351d8b..8dfe058cf6885 100644 --- a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/outlier_detection_creation.ts +++ b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/outlier_detection_creation.ts @@ -14,13 +14,15 @@ export default function({ getService }: FtrProviderContext) { describe('outlier detection creation', function() { this.tags(['smoke']); before(async () => { - await esArchiver.load('ml/ihp_outlier'); + await esArchiver.loadIfNeeded('ml/ihp_outlier'); + await ml.testResources.createIndexPatternIfNeeded('ft_ihp_outlier', '@timestamp'); + await ml.testResources.setKibanaTimeZoneToUTC(); + await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { await ml.api.cleanMlIndices(); - await esArchiver.unload('ml/ihp_outlier'); }); const testDataList = [ @@ -29,7 +31,7 @@ export default function({ getService }: FtrProviderContext) { jobType: 'outlier_detection', jobId: `ihp_1_${Date.now()}`, jobDescription: 'This is the job description', - source: 'ihp_outlier', + source: 'ft_ihp_outlier', get destinationIndex(): string { return `user-${this.jobId}`; }, @@ -49,6 +51,7 @@ export default function({ getService }: FtrProviderContext) { describe(`${testData.suiteTitle}`, function() { after(async () => { await ml.api.deleteIndices(testData.destinationIndex); + await ml.testResources.deleteIndexPattern(testData.destinationIndex); }); it('loads the data frame analytics page', async () => { diff --git a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/regression_creation.ts b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/regression_creation.ts index aa1a133c81187..271f3e2018dad 100644 --- a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/regression_creation.ts +++ b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/regression_creation.ts @@ -14,13 +14,15 @@ export default function({ getService }: FtrProviderContext) { describe('regression creation', function() { this.tags(['smoke']); before(async () => { - await esArchiver.load('ml/egs_regression'); + await esArchiver.loadIfNeeded('ml/egs_regression'); + await ml.testResources.createIndexPatternIfNeeded('ft_egs_regression', '@timestamp'); + await ml.testResources.setKibanaTimeZoneToUTC(); + await ml.securityUI.loginAsMlPowerUser(); }); after(async () => { await ml.api.cleanMlIndices(); - await esArchiver.unload('ml/egs_regression'); }); const testDataList = [ @@ -29,7 +31,7 @@ export default function({ getService }: FtrProviderContext) { jobType: 'regression', jobId: `egs_1_${Date.now()}`, jobDescription: 'This is the job description', - source: 'egs_regression', + source: 'ft_egs_regression', get destinationIndex(): string { return `user-${this.jobId}`; }, @@ -51,6 +53,7 @@ export default function({ getService }: FtrProviderContext) { describe(`${testData.suiteTitle}`, function() { after(async () => { await ml.api.deleteIndices(testData.destinationIndex); + await ml.testResources.deleteIndexPattern(testData.destinationIndex); }); it('loads the data frame analytics page', async () => { diff --git a/x-pack/test/functional/apps/machine_learning/data_visualizer/file_data_visualizer.ts b/x-pack/test/functional/apps/machine_learning/data_visualizer/file_data_visualizer.ts index 94b28e5035edf..ae958ad7f570f 100644 --- a/x-pack/test/functional/apps/machine_learning/data_visualizer/file_data_visualizer.ts +++ b/x-pack/test/functional/apps/machine_learning/data_visualizer/file_data_visualizer.ts @@ -36,6 +36,8 @@ export default function({ getService }: FtrProviderContext) { describe('file based', function() { this.tags(['smoke', 'mlqa']); before(async () => { + await ml.testResources.setKibanaTimeZoneToUTC(); + await ml.securityUI.loginAsMlPowerUser(); await ml.navigation.navigateToMl(); }); diff --git a/x-pack/test/functional/apps/machine_learning/data_visualizer/index_data_visualizer.ts b/x-pack/test/functional/apps/machine_learning/data_visualizer/index_data_visualizer.ts index 1ee74368c72fa..e71b57a4562e7 100644 --- a/x-pack/test/functional/apps/machine_learning/data_visualizer/index_data_visualizer.ts +++ b/x-pack/test/functional/apps/machine_learning/data_visualizer/index_data_visualizer.ts @@ -45,7 +45,7 @@ export default function({ getService }: FtrProviderContext) { const farequoteIndexPatternTestData: TestData = { suiteTitle: 'index pattern', - sourceIndexOrSavedSearch: 'farequote', + sourceIndexOrSavedSearch: 'ft_farequote', advancedJobWizardDatafeedQuery: `{ "bool": { "must": [ @@ -128,7 +128,7 @@ export default function({ getService }: FtrProviderContext) { const farequoteKQLSearchTestData: TestData = { suiteTitle: 'KQL saved search', - sourceIndexOrSavedSearch: 'farequote_kuery', + sourceIndexOrSavedSearch: 'ft_farequote_kuery', advancedJobWizardDatafeedQuery: `{ "bool": { "must": [ @@ -211,7 +211,7 @@ export default function({ getService }: FtrProviderContext) { const farequoteLuceneSearchTestData: TestData = { suiteTitle: 'lucene saved search', - sourceIndexOrSavedSearch: 'farequote_lucene', + sourceIndexOrSavedSearch: 'ft_farequote_lucene', advancedJobWizardDatafeedQuery: `{ "bool": { "must": [ @@ -378,12 +378,13 @@ export default function({ getService }: FtrProviderContext) { describe('index based', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('ml/farequote'); - await ml.securityUI.loginAsMlPowerUser(); - }); + await esArchiver.loadIfNeeded('ml/farequote'); + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await ml.testResources.createSavedSearchFarequoteLuceneIfNeeded(); + await ml.testResources.createSavedSearchFarequoteKueryIfNeeded(); + await ml.testResources.setKibanaTimeZoneToUTC(); - after(async () => { - await esArchiver.unload('ml/farequote'); + await ml.securityUI.loginAsMlPowerUser(); }); // TODO - add tests for diff --git a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts index f3731f46a5bce..ec4b708152a4c 100644 --- a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts +++ b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_security.ts @@ -7,15 +7,12 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); const security = getService('security'); const appsMenu = getService('appsMenu'); const PageObjects = getPageObjects(['common', 'security']); describe('security', function() { before(async () => { - await esArchiver.load('empty_kibana'); - await security.role.create('global_all_role', { elasticsearch: { indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }], @@ -33,7 +30,6 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { - await esArchiver.unload('empty_kibana'); await security.role.delete('global_all_role'); // logout, so the other tests don't accidentally run as the custom users we're testing below diff --git a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts index fc94688e98811..828d7bcc0ae2f 100644 --- a/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts +++ b/x-pack/test/functional/apps/machine_learning/feature_controls/ml_spaces.ts @@ -7,21 +7,12 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ getPageObjects, getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); const spacesService = getService('spaces'); const PageObjects = getPageObjects(['common', 'dashboard', 'security', 'error']); const appsMenu = getService('appsMenu'); const testSubjects = getService('testSubjects'); describe('spaces', () => { - before(async () => { - await esArchiver.load('empty_kibana'); - }); - - after(async () => { - await esArchiver.unload('empty_kibana'); - }); - describe('space with no features disabled', () => { before(async () => { await spacesService.create({ diff --git a/x-pack/test/functional/apps/machine_learning/index.ts b/x-pack/test/functional/apps/machine_learning/index.ts index 47c699e309491..3e1991120d2d2 100644 --- a/x-pack/test/functional/apps/machine_learning/index.ts +++ b/x-pack/test/functional/apps/machine_learning/index.ts @@ -6,6 +6,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); const ml = getService('ml'); describe('machine learning', function() { @@ -19,6 +20,26 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { after(async () => { await ml.securityCommon.cleanMlUsers(); await ml.securityCommon.cleanMlRoles(); + + await ml.testResources.deleteSavedSearches(); + + await ml.testResources.deleteIndexPattern('ft_farequote'); + await ml.testResources.deleteIndexPattern('ft_ecommerce'); + await ml.testResources.deleteIndexPattern('ft_categorization'); + await ml.testResources.deleteIndexPattern('ft_event_rate_gen_trend_nanos'); + await ml.testResources.deleteIndexPattern('ft_bank_marketing'); + await ml.testResources.deleteIndexPattern('ft_ihp_outlier'); + await ml.testResources.deleteIndexPattern('ft_egs_regression'); + + await esArchiver.unload('ml/farequote'); + await esArchiver.unload('ml/ecommerce'); + await esArchiver.unload('ml/categorization'); + await esArchiver.unload('ml/event_rate_nanos'); + await esArchiver.unload('ml/bm_classification'); + await esArchiver.unload('ml/ihp_outlier'); + await esArchiver.unload('ml/egs_regression'); + + await ml.testResources.resetKibanaTimeZone(); }); loadTestFile(require.resolve('./feature_controls')); diff --git a/x-pack/test/functional/apps/machine_learning/pages.ts b/x-pack/test/functional/apps/machine_learning/pages.ts index 78c6ec4f1b2ff..95930f18061fa 100644 --- a/x-pack/test/functional/apps/machine_learning/pages.ts +++ b/x-pack/test/functional/apps/machine_learning/pages.ts @@ -7,20 +7,15 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function({ getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); const ml = getService('ml'); describe('page navigation', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.load('empty_kibana'); + await ml.api.cleanMlIndices(); await ml.securityUI.loginAsMlPowerUser(); }); - after(async () => { - await esArchiver.unload('empty_kibana'); - }); - it('loads the home page', async () => { await ml.navigation.navigateToMl(); }); diff --git a/x-pack/test/functional/apps/transform/cloning.ts b/x-pack/test/functional/apps/transform/cloning.ts index 5f05fdb093d10..e6e12f60f0bcc 100644 --- a/x-pack/test/functional/apps/transform/cloning.ts +++ b/x-pack/test/functional/apps/transform/cloning.ts @@ -11,7 +11,7 @@ function getTransformConfig(): TransformPivotConfig { const date = Date.now(); return { id: `ec_2_${date}`, - source: { index: ['ecommerce'] }, + source: { index: ['ft_ecommerce'] }, pivot: { group_by: { category: { terms: { field: 'category.keyword' } } }, aggregations: { 'products.base_price.avg': { avg: { field: 'products.base_price' } } }, @@ -31,13 +31,16 @@ export default function({ getService }: FtrProviderContext) { const transformConfig = getTransformConfig(); before(async () => { - await esArchiver.load('ml/ecommerce'); + await esArchiver.loadIfNeeded('ml/ecommerce'); + await transform.testResources.createIndexPatternIfNeeded('ft_ecommerce', 'order_date'); await transform.api.createAndRunTransform(transformConfig); + await transform.testResources.setKibanaTimeZoneToUTC(); + await transform.securityUI.loginAsTransformPowerUser(); }); after(async () => { - await esArchiver.unload('ml/ecommerce'); + await transform.testResources.deleteIndexPattern(transformConfig.dest.index); await transform.api.deleteIndices(transformConfig.dest.index); await transform.api.cleanTransformIndices(); }); diff --git a/x-pack/test/functional/apps/transform/creation_index_pattern.ts b/x-pack/test/functional/apps/transform/creation_index_pattern.ts index f3cc4ab8d7601..bea6b814ee8a3 100644 --- a/x-pack/test/functional/apps/transform/creation_index_pattern.ts +++ b/x-pack/test/functional/apps/transform/creation_index_pattern.ts @@ -20,19 +20,21 @@ export default function({ getService }: FtrProviderContext) { describe('creation_index_pattern', function() { this.tags(['smoke']); before(async () => { - await esArchiver.load('ml/ecommerce'); + await esArchiver.loadIfNeeded('ml/ecommerce'); + await transform.testResources.createIndexPatternIfNeeded('ft_ecommerce', 'order_date'); + await transform.testResources.setKibanaTimeZoneToUTC(); + await transform.securityUI.loginAsTransformPowerUser(); }); after(async () => { - await esArchiver.unload('ml/ecommerce'); await transform.api.cleanTransformIndices(); }); const testDataList = [ { suiteTitle: 'batch transform with terms+date_histogram groups and avg agg', - source: 'ecommerce', + source: 'ft_ecommerce', groupByEntries: [ { identifier: 'terms(category.keyword)', @@ -96,7 +98,7 @@ export default function({ getService }: FtrProviderContext) { }, { suiteTitle: 'batch transform with terms group and percentiles agg', - source: 'ecommerce', + source: 'ft_ecommerce', groupByEntries: [ { identifier: 'terms(geoip.country_iso_code)', @@ -154,6 +156,7 @@ export default function({ getService }: FtrProviderContext) { describe(`${testData.suiteTitle}`, function() { after(async () => { await transform.api.deleteIndices(testData.destinationIndex); + await transform.testResources.deleteIndexPattern(testData.destinationIndex); }); it('loads the home page', async () => { diff --git a/x-pack/test/functional/apps/transform/creation_saved_search.ts b/x-pack/test/functional/apps/transform/creation_saved_search.ts index bf501c65bc79b..993bd3a79abbc 100644 --- a/x-pack/test/functional/apps/transform/creation_saved_search.ts +++ b/x-pack/test/functional/apps/transform/creation_saved_search.ts @@ -20,19 +20,22 @@ export default function({ getService }: FtrProviderContext) { describe('creation_saved_search', function() { this.tags(['smoke']); before(async () => { - await esArchiver.load('ml/farequote'); + await esArchiver.loadIfNeeded('ml/farequote'); + await transform.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await transform.testResources.createSavedSearchFarequoteFilterIfNeeded(); + await transform.testResources.setKibanaTimeZoneToUTC(); + await transform.securityUI.loginAsTransformPowerUser(); }); after(async () => { - await esArchiver.unload('ml/farequote'); await transform.api.cleanTransformIndices(); }); const testDataList = [ { suiteTitle: 'batch transform with terms groups and avg agg with saved search filter', - source: 'farequote_filter', + source: 'ft_farequote_filter', groupByEntries: [ { identifier: 'terms(airline)', @@ -61,7 +64,7 @@ export default function({ getService }: FtrProviderContext) { mode: 'batch', progress: '100', }, - sourceIndex: 'farequote', + sourceIndex: 'ft_farequote', sourcePreview: { column: 2, values: ['ASA'], @@ -74,6 +77,7 @@ export default function({ getService }: FtrProviderContext) { describe(`${testData.suiteTitle}`, function() { after(async () => { await transform.api.deleteIndices(testData.destinationIndex); + await transform.testResources.deleteIndexPattern(testData.destinationIndex); }); it('loads the home page', async () => { diff --git a/x-pack/test/functional/apps/transform/index.ts b/x-pack/test/functional/apps/transform/index.ts index 60b72f122f113..bf720ce85d824 100644 --- a/x-pack/test/functional/apps/transform/index.ts +++ b/x-pack/test/functional/apps/transform/index.ts @@ -6,6 +6,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); const transform = getService('transform'); describe('transform', function() { @@ -19,6 +20,16 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { after(async () => { await transform.securityCommon.cleanTransformUsers(); await transform.securityCommon.cleanTransformRoles(); + + await transform.testResources.deleteSavedSearches(); + + await transform.testResources.deleteIndexPattern('ft_farequote'); + await transform.testResources.deleteIndexPattern('ft_ecommerce'); + + await esArchiver.unload('ml/farequote'); + await esArchiver.unload('ml/ecommerce'); + + await transform.testResources.resetKibanaTimeZone(); }); loadTestFile(require.resolve('./creation_index_pattern')); diff --git a/x-pack/test/functional/es_archives/ml/bm_classification/data.json.gz b/x-pack/test/functional/es_archives/ml/bm_classification/data.json.gz index 12ccf6ae605124649f58c89acdfa5ea0a8f2bf62..8c0dc38d3dedbf17d308949c55f54eddb9d21fd8 100644 GIT binary patch literal 168183 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 D`se~5 literal 169485 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