From 2994d324198045b1f17a6c6342995d8f1535b9d6 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Mon, 14 Sep 2020 16:51:59 -0400 Subject: [PATCH 01/26] skip flaky suite (#59975) --- test/accessibility/apps/discover.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts index 7e905fbe89fbd..44639af9da9f8 100644 --- a/test/accessibility/apps/discover.ts +++ b/test/accessibility/apps/discover.ts @@ -34,7 +34,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ['geo.src', 'IN'], ]; - describe('Discover', () => { + // Failing: See https://github.com/elastic/kibana/issues/59975 + describe.skip('Discover', () => { before(async () => { await esArchiver.load('discover'); await esArchiver.loadIfNeeded('logstash_functional'); From 525660413e6f802957e1c97c7484c5e1b0603c8b Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 14 Sep 2020 17:19:41 -0400 Subject: [PATCH 02/26] [Ingest Manager] Manually build Fleet kuery with Node arguments (#76589) --- .../common/es_query/kuery/node_types/types.ts | 1 + .../server/services/agents/actions.ts | 31 ++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/plugins/data/common/es_query/kuery/node_types/types.ts b/src/plugins/data/common/es_query/kuery/node_types/types.ts index 6d3019e75d483..894bd1812f084 100644 --- a/src/plugins/data/common/es_query/kuery/node_types/types.ts +++ b/src/plugins/data/common/es_query/kuery/node_types/types.ts @@ -76,6 +76,7 @@ export interface NamedArgTypeBuildNode { } interface WildcardType { + wildcardSymbol: string; buildNode: (value: string) => WildcardTypeBuildNode | KueryNode; test: (node: any, string: string) => boolean; toElasticsearchQuery: (node: any) => string; diff --git a/x-pack/plugins/ingest_manager/server/services/agents/actions.ts b/x-pack/plugins/ingest_manager/server/services/agents/actions.ts index 8519714334986..254c2c8b21e32 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/actions.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/actions.ts @@ -74,18 +74,19 @@ export async function getAgentActionsForCheckin( const filter = nodeTypes.function.buildNode('and', [ nodeTypes.function.buildNode( 'not', - nodeTypes.function.buildNode( - 'is', - `${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.sent_at`, - '*' - ) - ), - nodeTypes.function.buildNode( - 'is', - `${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.agent_id`, - agentId + nodeTypes.function.buildNodeWithArgumentNodes('is', [ + nodeTypes.literal.buildNode(`${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.sent_at`), + nodeTypes.wildcard.buildNode(nodeTypes.wildcard.wildcardSymbol), + nodeTypes.literal.buildNode(false), + ]) ), + nodeTypes.function.buildNodeWithArgumentNodes('is', [ + nodeTypes.literal.buildNode(`${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.agent_id`), + nodeTypes.literal.buildNode(agentId), + nodeTypes.literal.buildNode(false), + ]), ]); + const res = await soClient.find({ type: AGENT_ACTION_SAVED_OBJECT_TYPE, filter, @@ -176,11 +177,11 @@ export async function getNewActionsSince(soClient: SavedObjectsClientContract, t const filter = nodeTypes.function.buildNode('and', [ nodeTypes.function.buildNode( 'not', - nodeTypes.function.buildNode( - 'is', - `${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.sent_at`, - '*' - ) + nodeTypes.function.buildNodeWithArgumentNodes('is', [ + nodeTypes.literal.buildNode(`${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.sent_at`), + nodeTypes.wildcard.buildNode(nodeTypes.wildcard.wildcardSymbol), + nodeTypes.literal.buildNode(false), + ]) ), nodeTypes.function.buildNode( 'range', From 5a2f7ae89701573cb6ce4f4baac9ad3cb2cda03e Mon Sep 17 00:00:00 2001 From: Caroline Horn <549577+cchaos@users.noreply.github.com> Date: Mon, 14 Sep 2020 18:23:13 -0400 Subject: [PATCH 03/26] [Lens] Move configuration popover to flyout (#76046) * Moving to a Flyout implementation * Fix up inner layout of flyout * Fix up form rows --- .../editor_frame/_frame_layout.scss | 15 +- .../editor_frame/config_panel/_index.scss | 2 - .../{_config_panel.scss => config_panel.scss} | 0 .../config_panel/config_panel.tsx | 1 + .../config_panel/dimension_container.scss | 29 ++ .../config_panel/dimension_container.tsx | 134 +++++++++ .../config_panel/dimension_popover.scss | 18 -- .../config_panel/dimension_popover.tsx | 50 ---- .../{_layer_panel.scss => layer_panel.scss} | 3 +- .../config_panel/layer_panel.test.tsx | 26 +- .../editor_frame/config_panel/layer_panel.tsx | 138 ++++----- .../editor_frame/config_panel/types.ts | 3 +- .../editor_frame/index.scss | 1 - .../indexpattern_datasource/_field_item.scss | 6 +- .../dimension_panel/bucket_nesting_editor.tsx | 1 + .../dimension_panel/dimension_editor.scss | 21 ++ ...opover_editor.tsx => dimension_editor.tsx} | 281 +++++++++--------- .../dimension_panel/dimension_panel.test.tsx | 14 +- .../dimension_panel/dimension_panel.tsx | 8 +- .../dimension_panel/field_select.tsx | 14 +- .../dimension_panel/format_selector.tsx | 138 ++++----- .../dimension_panel/popover_editor.scss | 20 -- .../indexpattern_datasource/field_item.tsx | 4 +- .../operations/definitions/date_histogram.tsx | 9 +- .../operations/definitions/terms.test.tsx | 2 +- .../operations/definitions/terms.tsx | 3 + x-pack/plugins/lens/public/types.ts | 2 +- x-pack/plugins/lens/readme.md | 2 +- .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - .../test/functional/page_objects/lens_page.ts | 3 +- 31 files changed, 525 insertions(+), 429 deletions(-) delete mode 100644 x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_index.scss rename x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/{_config_panel.scss => config_panel.scss} (100%) create mode 100644 x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss create mode 100644 x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx delete mode 100644 x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.scss delete mode 100644 x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx rename x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/{_layer_panel.scss => layer_panel.scss} (95%) create mode 100644 x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss rename x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/{popover_editor.tsx => dimension_editor.tsx} (64%) delete mode 100644 x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss index c2e8d4f6c0049..9367e59b11717 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss @@ -11,7 +11,7 @@ .lnsFrameLayout__pageContent { display: flex; - overflow: auto; + overflow: hidden; flex-grow: 1; } @@ -39,11 +39,16 @@ } .lnsFrameLayout__sidebar--right { - @include euiScrollBar; + flex-basis: 25%; background-color: lightOrDarkTheme($euiColorLightestShade, $euiColorInk); min-width: $lnsPanelMinWidth + $euiSizeXL; - overflow-x: hidden; - overflow-y: scroll; - padding: $euiSize 0 $euiSize $euiSize; + max-width: $euiFormMaxWidth + $euiSizeXXL; max-height: 100%; + + .lnsConfigPanel { + @include euiScrollBar; + padding: $euiSize 0 $euiSize $euiSize; + overflow-x: hidden; + overflow-y: scroll; + } } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_index.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_index.scss deleted file mode 100644 index 954fbfadf159b..0000000000000 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'config_panel'; -@import 'layer_panel'; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_config_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.scss similarity index 100% rename from x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_config_panel.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.scss diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx index 446f5b44c2e50..ad16038f44911 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.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 './config_panel.scss'; import React, { useMemo, memo } from 'react'; import { EuiFlexItem, EuiToolTip, EuiButton, EuiForm } from '@elastic/eui'; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss new file mode 100644 index 0000000000000..f200e25453a2a --- /dev/null +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss @@ -0,0 +1,29 @@ +@import '@elastic/eui/src/components/flyout/variables'; +@import '@elastic/eui/src/components/flyout/mixins'; + +.lnsDimensionContainer { + // Use the EuiFlyout style + @include euiFlyout; + // But with custom positioning to keep it within the sidebar contents + position: absolute; + right: 0; + left: 0; + top: 0; + bottom: 0; + animation: euiFlyout $euiAnimSpeedNormal $euiAnimSlightResistance; +} + +.lnsDimensionContainer--noAnimation { + animation: none; +} + +.lnsDimensionContainer__footer, +.lnsDimensionContainer__header { + padding: $euiSizeS; +} + +.lnsDimensionContainer__trigger { + width: 100%; + display: block; + word-break: break-word; +} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx new file mode 100644 index 0000000000000..d6b395ac74cce --- /dev/null +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx @@ -0,0 +1,134 @@ +/* + * 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 './dimension_container.scss'; + +import React, { useState, useEffect } from 'react'; +import { + EuiFlyoutHeader, + EuiFlyoutFooter, + EuiTitle, + EuiButtonEmpty, + EuiFlexItem, + EuiFocusTrap, +} from '@elastic/eui'; + +import classNames from 'classnames'; +import { i18n } from '@kbn/i18n'; +import { VisualizationDimensionGroupConfig } from '../../../types'; +import { DimensionContainerState } from './types'; + +export function DimensionContainer({ + dimensionContainerState, + setDimensionContainerState, + groups, + accessor, + groupId, + trigger, + panel, + panelTitle, +}: { + dimensionContainerState: DimensionContainerState; + setDimensionContainerState: (newState: DimensionContainerState) => void; + groups: VisualizationDimensionGroupConfig[]; + accessor: string; + groupId: string; + trigger: React.ReactElement; + panel: React.ReactElement; + panelTitle: React.ReactNode; +}) { + const [openByCreation, setIsOpenByCreation] = useState( + dimensionContainerState.openId === accessor + ); + const [focusTrapIsEnabled, setFocusTrapIsEnabled] = useState(false); + const [flyoutIsVisible, setFlyoutIsVisible] = useState(false); + + const noMatch = dimensionContainerState.isOpen + ? !groups.some((d) => d.accessors.includes(accessor)) + : false; + + const closeFlyout = () => { + setDimensionContainerState({ + isOpen: false, + openId: null, + addingToGroupId: null, + }); + setIsOpenByCreation(false); + setFocusTrapIsEnabled(false); + setFlyoutIsVisible(false); + }; + + const openFlyout = () => { + setFlyoutIsVisible(true); + setTimeout(() => { + setFocusTrapIsEnabled(true); + }, 255); + }; + + const flyoutShouldBeOpen = + dimensionContainerState.isOpen && + (dimensionContainerState.openId === accessor || + (noMatch && dimensionContainerState.addingToGroupId === groupId)); + + useEffect(() => { + if (flyoutShouldBeOpen) { + openFlyout(); + } + }); + + useEffect(() => { + if (!flyoutShouldBeOpen) { + if (flyoutIsVisible) { + setFlyoutIsVisible(false); + } + if (focusTrapIsEnabled) { + setFocusTrapIsEnabled(false); + } + } + }, [flyoutShouldBeOpen, flyoutIsVisible, focusTrapIsEnabled]); + + const flyout = flyoutIsVisible && ( + +
+ + + + {panelTitle} + + + + + {panel} + + + + {i18n.translate('xpack.lens.dimensionContainer.close', { + defaultMessage: 'Close', + })} + + +
+
+ ); + + return ( + <> +
{trigger}
+ {flyout} + + ); +} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.scss deleted file mode 100644 index 98036c7f31bd9..0000000000000 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.scss +++ /dev/null @@ -1,18 +0,0 @@ -.lnsDimensionPopover { - line-height: 0; - flex-grow: 1; - max-width: calc(100% - #{$euiSizeL}); -} - -.lnsDimensionPopover__trigger { - max-width: 100%; - display: block; - word-break: break-word; -} - -// todo: remove after closing https://github.com/elastic/eui/issues/3548 -.lnsDimensionPopover__fixTranslateDnd { - // sass-lint:disable-block no-important - transform: none !important; -} - diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx deleted file mode 100644 index a90bd8122d18e..0000000000000 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx +++ /dev/null @@ -1,50 +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 './dimension_popover.scss'; - -import React from 'react'; -import { EuiPopover } from '@elastic/eui'; -import { VisualizationDimensionGroupConfig } from '../../../types'; -import { DimensionPopoverState } from './types'; - -export function DimensionPopover({ - popoverState, - setPopoverState, - groups, - accessor, - groupId, - trigger, - panel, -}: { - popoverState: DimensionPopoverState; - setPopoverState: (newState: DimensionPopoverState) => void; - groups: VisualizationDimensionGroupConfig[]; - accessor: string; - groupId: string; - trigger: React.ReactElement; - panel: React.ReactElement; -}) { - const noMatch = popoverState.isOpen ? !groups.some((d) => d.accessors.includes(accessor)) : false; - return ( - { - setPopoverState({ isOpen: false, openId: null, addingToGroupId: null, tabId: null }); - }} - button={trigger} - anchorPosition="leftUp" - panelPaddingSize="none" - > - {panel} - - ); -} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss similarity index 95% rename from x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss index ab53ff983ca26..34cefd7d1b101 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss @@ -52,6 +52,5 @@ } .lnsLayerPanel__styleEditor { - width: $euiSize * 30; - padding: $euiSizeS; + padding: 0 $euiSizeS $euiSizeS; } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx index 85dbee6de524f..a9e2d6dc696ab 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx @@ -13,7 +13,7 @@ import { DatasourceMock, } from '../../mocks'; import { ChildDragDropProvider } from '../../../drag_drop'; -import { EuiFormRow, EuiPopover } from '@elastic/eui'; +import { EuiFormRow } from '@elastic/eui'; import { mount } from 'enzyme'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { Visualization } from '../../../types'; @@ -203,7 +203,7 @@ describe('LayerPanel', () => { expect(group).toHaveLength(1); }); - it('should render the datasource and visualization panels inside the dimension popover', () => { + it('should render the datasource and visualization panels inside the dimension container', () => { mockVisualization.getConfiguration.mockReturnValueOnce({ groups: [ { @@ -221,16 +221,16 @@ describe('LayerPanel', () => { const component = mountWithIntl(); - const group = component.find('DimensionPopover'); + const group = component.find('DimensionContainer'); const panel = mount(group.prop('panel')); - expect(panel.find('EuiTabbedContent').prop('tabs')).toHaveLength(2); + expect(panel.children()).toHaveLength(2); }); - it('should keep the popover open when configuring a new dimension', () => { + it('should keep the DimensionContainer open when configuring a new dimension', () => { /** * The ID generation system for new dimensions has been messy before, so - * this tests that the ID used in the first render is used to keep the popover + * this tests that the ID used in the first render is used to keep the container * open in future renders */ (generateId as jest.Mock).mockReturnValueOnce(`newid`); @@ -264,20 +264,20 @@ describe('LayerPanel', () => { const component = mountWithIntl(); - const group = component.find('DimensionPopover'); + const group = component.find('DimensionContainer'); const triggerButton = mountWithIntl(group.prop('trigger')); act(() => { triggerButton.find('[data-test-subj="lns-empty-dimension"]').first().simulate('click'); }); component.update(); - expect(component.find(EuiPopover).prop('isOpen')).toBe(true); + expect(component.find('EuiFlyoutHeader').exists()).toBe(true); }); - it('should close the popover when the active visualization changes', () => { + it('should close the DimensionContainer when the active visualization changes', () => { /** * The ID generation system for new dimensions has been messy before, so - * this tests that the ID used in the first render is used to keep the popover + * this tests that the ID used in the first render is used to keep the container * open in future renders */ @@ -312,18 +312,18 @@ describe('LayerPanel', () => { const component = mountWithIntl(); - const group = component.find('DimensionPopover'); + const group = component.find('DimensionContainer'); const triggerButton = mountWithIntl(group.prop('trigger')); act(() => { triggerButton.find('[data-test-subj="lns-empty-dimension"]').first().simulate('click'); }); component.update(); - expect(component.find(EuiPopover).prop('isOpen')).toBe(true); + expect(component.find('EuiFlyoutHeader').exists()).toBe(true); act(() => { component.setProps({ activeVisualizationId: 'vis2' }); }); component.update(); - expect(component.find(EuiPopover).prop('isOpen')).toBe(false); + expect(component.find('EuiFlyoutHeader').exists()).toBe(false); }); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index b45dd13bfa4fd..258aadc82fbf2 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.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 './layer_panel.scss'; import React, { useContext, useState, useEffect } from 'react'; import { @@ -13,7 +14,6 @@ import { EuiFlexItem, EuiButtonEmpty, EuiFormRow, - EuiTabbedContent, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -24,14 +24,13 @@ import { DragContext, DragDrop, ChildDragDropProvider } from '../../../drag_drop import { LayerSettings } from './layer_settings'; import { trackUiEvent } from '../../../lens_ui_telemetry'; import { generateId } from '../../../id_generator'; -import { ConfigPanelWrapperProps, DimensionPopoverState } from './types'; -import { DimensionPopover } from './dimension_popover'; +import { ConfigPanelWrapperProps, DimensionContainerState } from './types'; +import { DimensionContainer } from './dimension_container'; -const initialPopoverState = { +const initialDimensionContainerState = { isOpen: false, openId: null, addingToGroupId: null, - tabId: null, }; export function LayerPanel( @@ -50,13 +49,15 @@ export function LayerPanel( } ) { const dragDropContext = useContext(DragContext); - const [popoverState, setPopoverState] = useState(initialPopoverState); + const [dimensionContainerState, setDimensionContainerState] = useState( + initialDimensionContainerState + ); const { framePublicAPI, layerId, isOnlyLayer, onRemoveLayer, dataTestSubj } = props; const datasourcePublicAPI = framePublicAPI.datasourceLayers[layerId]; useEffect(() => { - setPopoverState(initialPopoverState); + setDimensionContainerState(initialDimensionContainerState); }, [props.activeVisualizationId]); if ( @@ -159,7 +160,9 @@ export function LayerPanel( return ( <> {group.accessors.map((accessor) => { - const tabs = [ - { - id: 'datasource', - name: i18n.translate('xpack.lens.editorFrame.quickFunctionsLabel', { - defaultMessage: 'Quick functions', - }), - content: ( + const datasourceDimensionEditor = ( + + ); + const visDimensionEditor = + activeVisualization.renderDimensionEditor && group.enableDimensionEditor ? ( +
- ), - }, - ]; - - if (activeVisualization.renderDimensionEditor && group.enableDimensionEditor) { - tabs.push({ - id: 'visualization', - name: i18n.translate('xpack.lens.editorFrame.formatStyleLabel', { - defaultMessage: 'Format & style', - }), - content: ( -
- -
- ), - }); - } - +
+ ) : null; return ( - { - if (popoverState.isOpen) { - setPopoverState(initialPopoverState); + onClick: () => { + if (dimensionContainerState.isOpen) { + setDimensionContainerState(initialDimensionContainerState); } else { - setPopoverState({ + setDimensionContainerState({ isOpen: true, openId: accessor, addingToGroupId: null, // not set for existing dimension - tabId: 'datasource', }); } }, @@ -298,22 +283,21 @@ export function LayerPanel( /> } panel={ - t.id === popoverState.tabId) || tabs[0]} - size="s" - onTabClick={(tab) => { - setPopoverState({ - ...popoverState, - tabId: tab.id as typeof popoverState['tabId'], - }); - }} - /> + <> + {datasourceDimensionEditor} + {visDimensionEditor} + } + panelTitle={i18n.translate('xpack.lens.configure.configurePanelTitle', { + defaultMessage: '{groupLabel} configuration', + values: { + groupLabel: group.groupLabel, + }, + })} /> - { - if (popoverState.isOpen) { - setPopoverState(initialPopoverState); + if (dimensionContainerState.isOpen) { + setDimensionContainerState(initialDimensionContainerState); } else { - setPopoverState({ + setDimensionContainerState({ isOpen: true, openId: newId, addingToGroupId: group.groupId, - tabId: 'datasource', }); } }} @@ -428,6 +411,12 @@ export function LayerPanel( } + panelTitle={i18n.translate('xpack.lens.configure.configurePanelTitle', { + defaultMessage: '{groupLabel} configuration', + values: { + groupLabel: group.groupLabel, + }, + })} panel={ <> button { + padding-top: 0; + padding-bottom: 0; +} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx similarity index 64% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx index d5f0110f071f1..98e9389a85819 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx @@ -4,21 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import './popover_editor.scss'; +import './dimension_editor.scss'; import _ from 'lodash'; import React, { useState, useMemo, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { - EuiFlexItem, - EuiFlexGroup, EuiListGroup, - EuiCallOut, EuiFormRow, EuiFieldText, EuiSpacer, EuiListGroupItemProps, } from '@elastic/eui'; -import classNames from 'classnames'; +import { EuiFormLabel } from '@elastic/eui'; import { IndexPatternColumn, OperationType } from '../indexpattern'; import { IndexPatternDimensionEditorProps, OperationFieldSupportMatrix } from './dimension_panel'; import { @@ -37,7 +34,7 @@ import { FormatSelector } from './format_selector'; const operationPanels = getOperationDisplay(); -export interface PopoverEditorProps extends IndexPatternDimensionEditorProps { +export interface DimensionEditorProps extends IndexPatternDimensionEditorProps { selectedColumn?: IndexPatternColumn; operationFieldSupportMatrix: OperationFieldSupportMatrix; currentIndexPattern: IndexPattern; @@ -72,16 +69,25 @@ const LabelInput = ({ value, onChange }: { value: string; onChange: (value: stri }; return ( - + + + ); }; -export function PopoverEditor(props: PopoverEditorProps) { +export function DimensionEditor(props: DimensionEditorProps) { const { selectedColumn, operationFieldSupportMatrix, @@ -128,8 +134,8 @@ export function PopoverEditor(props: PopoverEditorProps) { ); } - function getSideNavItems(): EuiListGroupItemProps[] { - return getOperationTypes().map(({ operationType, compatibleWithCurrentField }) => { + const sideNavItems: EuiListGroupItemProps[] = getOperationTypes().map( + ({ operationType, compatibleWithCurrentField }) => { const isActive = Boolean( incompatibleSelectedOperationType === operationType || (!incompatibleSelectedOperationType && @@ -220,13 +226,42 @@ export function PopoverEditor(props: PopoverEditorProps) { ); }, }; - }); - } + } + ); return ( -
- - +
+
+ + {i18n.translate('xpack.lens.indexPattern.functionsLabel', { + defaultMessage: 'Choose a function', + })} + + + 3 ? 'lnsIndexPatternDimensionEditor__columns' : ''} + gutterSize="none" + listItems={sideNavItems} + maxWidth={false} + /> +
+ +
+ - - - - - - - - {incompatibleSelectedOperationType && selectedColumn && ( - <> - - - - )} - {incompatibleSelectedOperationType && !selectedColumn && ( - <> - - - - )} - {!incompatibleSelectedOperationType && ParamEditor && ( - <> - - - - )} - {!incompatibleSelectedOperationType && selectedColumn && ( - - { - setState({ - ...state, - layers: { - ...state.layers, - [layerId]: { - ...state.layers[layerId], - columns: { - ...state.layers[layerId].columns, - [columnId]: { - ...selectedColumn, - label: value, - customLabel: true, - }, - }, - }, - }, - }); - }} - /> - - )} + - {!hideGrouping && ( - { - setState({ - ...state, - layers: { - ...state.layers, - [props.layerId]: { - ...state.layers[props.layerId], - columnOrder, - }, + {!incompatibleSelectedOperationType && ParamEditor && ( + <> + + + + )} +
+ + + +
+ {!incompatibleSelectedOperationType && selectedColumn && ( + { + setState({ + ...state, + layers: { + ...state.layers, + [layerId]: { + ...state.layers[layerId], + columns: { + ...state.layers[layerId].columns, + [columnId]: { + ...selectedColumn, + label: value, + customLabel: true, }, - }); - }} - /> - )} + }, + }, + }, + }); + }} + /> + )} - {selectedColumn && selectedColumn.dataType === 'number' ? ( - { - setState( - updateColumnParam({ - state, - layerId, - currentColumn: selectedColumn, - paramName: 'format', - value: newFormat, - }) - ); - }} - /> - ) : null} - - - - + {!hideGrouping && ( + { + setState({ + ...state, + layers: { + ...state.layers, + [props.layerId]: { + ...state.layers[props.layerId], + columnOrder, + }, + }, + }); + }} + /> + )} + + {selectedColumn && selectedColumn.dataType === 'number' ? ( + { + setState( + updateColumnParam({ + state, + layerId, + currentColumn: selectedColumn, + paramName: 'format', + value: newFormat, + }) + ); + }} + /> + ) : null} +
); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx index f184d5628ab1c..dd7611ca7f41f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx @@ -7,7 +7,7 @@ import { ReactWrapper, ShallowWrapper } from 'enzyme'; import React from 'react'; import { act } from 'react-dom/test-utils'; -import { EuiComboBox, EuiListGroupItemProps, EuiListGroup, EuiFieldNumber } from '@elastic/eui'; +import { EuiComboBox, EuiListGroupItemProps, EuiListGroup, EuiRange } from '@elastic/eui'; import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; import { changeColumn } from '../state_helpers'; import { @@ -619,9 +619,9 @@ describe('IndexPatternDimensionEditorPanel', () => { .find('button[data-test-subj="lns-indexPatternDimension-terms incompatible"]') .simulate('click'); - expect(wrapper.find('[data-test-subj="indexPattern-invalid-operation"]')).not.toHaveLength( - 0 - ); + expect( + wrapper.find('[data-test-subj="indexPattern-field-selection-row"]').first().prop('error') + ).toBeDefined(); expect(setState).not.toHaveBeenCalled(); }); @@ -1188,7 +1188,7 @@ describe('IndexPatternDimensionEditorPanel', () => { expect( wrapper - .find(EuiFieldNumber) + .find(EuiRange) .filter('[data-test-subj="indexPattern-dimension-formatDecimals"]') .prop('value') ).toEqual(0); @@ -1224,9 +1224,9 @@ describe('IndexPatternDimensionEditorPanel', () => { act(() => { wrapper - .find(EuiFieldNumber) + .find(EuiRange) .filter('[data-test-subj="indexPattern-dimension-formatDecimals"]') - .prop('onChange')!({ target: { value: '0' } }); + .prop('onChange')!({ currentTarget: { value: '0' } }); }); expect(setState).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx index 1fbbefd8f1117..923f7145d1c64 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx @@ -20,7 +20,7 @@ import { import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; import { IndexPatternColumn, OperationType } from '../indexpattern'; import { getAvailableOperationsByMetadata, buildColumn, changeField } from '../operations'; -import { PopoverEditor } from './popover_editor'; +import { DimensionEditor } from './dimension_editor'; import { changeColumn } from '../state_helpers'; import { isDraggedField, hasField } from '../utils'; import { IndexPatternPrivateState, IndexPatternField } from '../types'; @@ -239,9 +239,7 @@ export const IndexPatternDimensionTriggerComponent = function IndexPatternDimens { - props.togglePopover(); - }} + onClick={props.onClick} data-test-subj="lns-dimensionTrigger" aria-label={i18n.translate('xpack.lens.configure.editConfig', { defaultMessage: 'Edit configuration', @@ -267,7 +265,7 @@ export const IndexPatternDimensionEditorComponent = function IndexPatternDimensi props.state.layers[layerId].columns[props.columnId] || null; return ( - { currentIndexPattern: IndexPattern; fieldMap: Record; incompatibleSelectedOperationType: OperationType | null; @@ -47,6 +53,7 @@ export function FieldSelect({ onChoose, onDeleteColumn, existingFields, + ...rest }: FieldSelectProps) { const { operationByField } = operationFieldSupportMatrix; const memoizedFieldOptions = useMemo(() => { @@ -155,7 +162,7 @@ export function FieldSelect({ defaultMessage: 'Field', })} options={(memoizedFieldOptions as unknown) as EuiComboBoxOptionOption[]} - isInvalid={Boolean(incompatibleSelectedOperationType && selectedColumnOperationType)} + isInvalid={Boolean(incompatibleSelectedOperationType)} selectedOptions={ ((selectedColumnOperationType ? selectedColumnSourceField @@ -194,6 +201,7 @@ export function FieldSelect({
); }} + {...rest} /> ); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx index b3b0190b9c400..8d9a91397cf2f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx @@ -6,7 +6,7 @@ import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiFormRow, EuiFieldNumber, EuiComboBox } from '@elastic/eui'; +import { EuiFormRow, EuiComboBox, EuiSpacer, EuiRange } from '@elastic/eui'; import { IndexPatternColumn } from '../indexpattern'; const supportedFormats: Record = { @@ -57,80 +57,84 @@ export function FormatSelector(props: FormatSelectorProps) { }), }; + const label = i18n.translate('xpack.lens.indexPattern.columnFormatLabel', { + defaultMessage: 'Value format', + }); + + const decimalsLabel = i18n.translate('xpack.lens.indexPattern.decimalPlacesLabel', { + defaultMessage: 'Decimals', + }); + return ( <> - - ({ - value: id, - label: format.title ?? id, - })), - ]} - selectedOptions={ - currentFormat - ? [ - { - value: currentFormat.id, - label: selectedFormat?.title ?? currentFormat.id, - }, - ] - : [defaultOption] - } - onChange={(choices) => { - if (choices.length === 0) { - return; - } - - if (!choices[0].value) { - onChange(); - return; + +
+ ({ + value: id, + label: format.title ?? id, + })), + ]} + selectedOptions={ + currentFormat + ? [ + { + value: currentFormat.id, + label: selectedFormat?.title ?? currentFormat.id, + }, + ] + : [defaultOption] } - onChange({ - id: choices[0].value, - params: { decimals: state.decimalPlaces }, - }); - }} - /> - + onChange={(choices) => { + if (choices.length === 0) { + return; + } - {currentFormat ? ( - - { - setState({ decimalPlaces: Number(e.target.value) }); + if (!choices[0].value) { + onChange(); + return; + } onChange({ - id: (selectedColumn.params as { format: { id: string } }).format.id, - params: { - decimals: Number(e.target.value), - }, + id: choices[0].value, + params: { decimals: state.decimalPlaces }, }); }} - compressed - fullWidth /> - - ) : null} + {currentFormat ? ( + <> + + { + setState({ decimalPlaces: Number(e.currentTarget.value) }); + onChange({ + id: (selectedColumn.params as { format: { id: string } }).format.id, + params: { + decimals: Number(e.currentTarget.value), + }, + }); + }} + data-test-subj="indexPattern-dimension-formatDecimals" + compressed + fullWidth + prepend={decimalsLabel} + aria-label={decimalsLabel} + /> + + ) : null} +
+
); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss deleted file mode 100644 index 3f75b5ad86669..0000000000000 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss +++ /dev/null @@ -1,20 +0,0 @@ -.lnsIndexPatternDimensionEditor { - width: $euiSize * 30; - padding: $euiSizeS; - max-width: 100%; -} - -.lnsIndexPatternDimensionEditor__left, -.lnsIndexPatternDimensionEditor__right { - padding: $euiSizeS; -} - -.lnsIndexPatternDimensionEditor__left { - background-color: $euiPageBackgroundColor; - width: $euiSize * 8; -} - -.lnsIndexPatternDimensionEditor__operation > button { - padding-top: 0; - padding-bottom: 0; -} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx index cf15c29844053..1f6d7911b3a33 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx @@ -231,7 +231,7 @@ export const InnerFieldItem = function InnerFieldItem(props: FieldItemProps) { isOpen={infoIsOpen} closePopover={() => setOpen(false)} anchorPosition="rightUp" - panelClassName="lnsFieldItem__fieldPopoverPanel" + panelClassName="lnsFieldItem__fieldPanel" > @@ -316,7 +316,7 @@ function FieldItemPopoverContents(props: State & FieldItemProps) { if (histogram && histogram.buckets.length && topValues && topValues.buckets.length) { title = ( {!intervalIsRestricted && ( - + )} @@ -197,6 +198,8 @@ export const dateHistogramOperation: OperationDefinition {intervalIsRestricted ? ( ) : ( <> - + { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx index 2972ed2d0231b..6f67cb7531e1c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx @@ -345,7 +345,7 @@ describe('terms', () => { }); }); - describe('popover param editor', () => { + describe('param editor', () => { it('should render current order by value and options', () => { const setStateSpy = jest.fn(); const instance = shallow( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx index c1b19fd5549e7..20c421008a746 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx @@ -177,6 +177,7 @@ export const termsOperation: OperationDefinition = { defaultMessage: 'Number of values', })} display="columnCompressed" + fullWidth > = { defaultMessage: 'Order by', })} display="columnCompressed" + fullWidth > = { defaultMessage: 'Order direction', })} display="columnCompressed" + fullWidth > = DatasourceDimensionPro export type DatasourceDimensionTriggerProps = DatasourceDimensionProps & { dragDropContext: DragContextState; - togglePopover: () => void; + onClick: () => void; }; export interface DatasourceLayerPanelProps { diff --git a/x-pack/plugins/lens/readme.md b/x-pack/plugins/lens/readme.md index e69ba9ec9506d..98bb60827af42 100644 --- a/x-pack/plugins/lens/readme.md +++ b/x-pack/plugins/lens/readme.md @@ -30,7 +30,7 @@ Lens has a lot of UI elements – to make it easier to refer to them in issues o * **Config panel** Panel to the right showing configuration of the current chart, separated by layers * **Layer panel** One of multiple panels in the config panel, holding configuration for separate layers * **Dimension trigger** Chart dimension like "X axis", "Break down by" or "Slice by" in the config panel - * **Dimension popover** Popover shown when clicking a dimension trigger + * **Dimension container** Container shown when clicking a dimension trigger and contains the dimension settints * **Layer settings popover** Popover shown when clicking the button in the top left of a layer panel * **Workspace panel** Center panel containing the chart preview, title and toolbar * **Chart preview** Full-sized rendered chart in the center of the screen diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 86a132f669f67..a0aa285b43848 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9559,10 +9559,8 @@ "xpack.lens.editorFrame.emptyWorkspaceHeading": "レンズはビジュアライゼーションを作成するための新しいツールです", "xpack.lens.editorFrame.expandRenderingErrorButton": "エラーの詳細を表示", "xpack.lens.editorFrame.expressionFailure": "表現を正常に実行できませんでした", - "xpack.lens.editorFrame.formatStyleLabel": "書式とスタイル", "xpack.lens.editorFrame.goToForums": "リクエストとフィードバック", "xpack.lens.editorFrame.previewErrorLabel": "レンダリングのプレビューに失敗しました", - "xpack.lens.editorFrame.quickFunctionsLabel": "クイック機能", "xpack.lens.editorFrame.requiredDimensionWarningLabel": "必要な次元", "xpack.lens.editorFrame.suggestionPanelTitle": "提案", "xpack.lens.embeddable.failure": "ビジュアライゼーションを表示できませんでした", @@ -9616,7 +9614,6 @@ "xpack.lens.indexPattern.existenceErrorLabel": "フィールド情報を読み込めません", "xpack.lens.indexPattern.fieldDistributionLabel": "分布", "xpack.lens.indexPattern.fieldItemTooltip": "可視化するには、ドラッグアンドドロップします。", - "xpack.lens.indexPattern.fieldlessOperationLabel": "この関数を使用するには、フィールドを選択してください。", "xpack.lens.indexPattern.fieldPanelEmptyStringValue": "空の文字列", "xpack.lens.indexPattern.fieldPlaceholder": "フィールド", "xpack.lens.indexPattern.fieldStatsButtonLabel": "フィールドプレビューを表示するには、クリックします。可視化するには、ドラッグアンドドロップします。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e860efb487e52..01cd7f569d13b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9565,10 +9565,8 @@ "xpack.lens.editorFrame.emptyWorkspaceHeading": "Lens 是用于创建可视化的新工具", "xpack.lens.editorFrame.expandRenderingErrorButton": "显示错误的详情", "xpack.lens.editorFrame.expressionFailure": "无法成功执行表达式", - "xpack.lens.editorFrame.formatStyleLabel": "格式和样式", "xpack.lens.editorFrame.goToForums": "提出请求并提供反馈", "xpack.lens.editorFrame.previewErrorLabel": "预览呈现失败", - "xpack.lens.editorFrame.quickFunctionsLabel": "快选函数", "xpack.lens.editorFrame.requiredDimensionWarningLabel": "所需尺寸", "xpack.lens.editorFrame.suggestionPanelTitle": "建议", "xpack.lens.embeddable.failure": "无法显示可视化", @@ -9622,7 +9620,6 @@ "xpack.lens.indexPattern.existenceErrorLabel": "无法加载字段信息", "xpack.lens.indexPattern.fieldDistributionLabel": "分布", "xpack.lens.indexPattern.fieldItemTooltip": "拖放以可视化。", - "xpack.lens.indexPattern.fieldlessOperationLabel": "要使用此函数,请选择字段。", "xpack.lens.indexPattern.fieldPanelEmptyStringValue": "空字符串", "xpack.lens.indexPattern.fieldPlaceholder": "字段", "xpack.lens.indexPattern.fieldStatsButtonLabel": "单击以进行字段预览,或拖放以进行可视化。", diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index acba3fa472b1a..edd7c2a43b343 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -105,13 +105,14 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont const target = await testSubjects.find('indexPattern-dimension-field'); await comboBox.openOptionsList(target); await comboBox.setElement(target, opts.field); + await testSubjects.click('lns-indexPattern-dimensionContainerTitle'); }, /** * Removes the dimension matching a specific test subject */ async removeDimension(dimensionTestSubj: string) { - await testSubjects.click(`${dimensionTestSubj} > indexPattern-dimensionPopover-remove`); + await testSubjects.click(`${dimensionTestSubj} > indexPattern-dimension-remove`); }, /** From 273806bf9b1ef424188ed3776c771d3381c701f7 Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Mon, 14 Sep 2020 19:52:05 -0500 Subject: [PATCH 04/26] Move remaining uses of serviceName away from urlParams (#77248) * Move remaining uses of serviceName away from urlParams There were a few of these that were either missed or lost in merge conflict resolution. I went through everything that's used as a path parameter and made sure it wasn't being used anywhere with `urlParams`. Previously none of the charts were working, now they all are. Looks like #67791 introduced a find/replace change that broke APM's e2e tests. This reverts that change. --- .../apm/e2e/cypress/integration/apm.feature | 2 +- .../e2e/cypress/support/step_definitions/apm.ts | 2 +- .../support/step_definitions/rum/rum_dashboard.ts | 2 +- .../app/RumDashboard/CoreVitals/index.tsx | 5 +++-- .../components/app/ServiceMap/Popover/Buttons.tsx | 6 +----- .../public/components/shared/DatePicker/index.tsx | 3 +-- .../ErroneousTransactionsRateChart/index.tsx | 14 ++++---------- ...er.test.ts => useAvgDurationByBrowser.test.tsx} | 10 +++++++++- .../apm/public/hooks/useAvgDurationByBrowser.ts | 10 ++++++---- .../apm/public/hooks/useAvgDurationByCountry.ts | 5 +++-- .../apm/public/hooks/useTransactionBreakdown.ts | 4 +++- .../apm/public/hooks/useTransactionCharts.ts | 4 +++- .../apm/public/hooks/useTransactionDistribution.ts | 9 +++++---- .../services/rest/apm_overview_fetchers.test.ts | 6 +++--- .../public/services/rest/apm_overview_fetchers.ts | 2 +- 15 files changed, 45 insertions(+), 39 deletions(-) rename x-pack/plugins/apm/public/hooks/{useAvgDurationByBrowser.test.ts => useAvgDurationByBrowser.test.tsx} (82%) diff --git a/x-pack/plugins/apm/e2e/cypress/integration/apm.feature b/x-pack/plugins/apm/e2e/cypress/integration/apm.feature index 82d896c5ba17e..285615108266b 100644 --- a/x-pack/plugins/apm/e2e/cypress/integration/apm.feature +++ b/x-pack/plugins/apm/e2e/cypress/integration/apm.feature @@ -1,4 +1,4 @@ -KibanaFeature: APM +Feature: APM Scenario: Transaction duration charts Given a user browses the APM UI application diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts index 66d604a663fbf..ab2bf20b36ed4 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts @@ -12,7 +12,7 @@ export const DEFAULT_TIMEOUT = 60 * 1000; Given(`a user browses the APM UI application`, () => { // open service overview page - loginAndWaitForPage(`/app/apm#/services`, { + loginAndWaitForPage(`/app/apm/services`, { from: '2020-06-01T14:59:32.686Z', to: '2020-06-16T16:59:36.219Z', }); diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_dashboard.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_dashboard.ts index 804974d8d437d..31aef30c4e23f 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_dashboard.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_dashboard.ts @@ -15,7 +15,7 @@ Given(`a user browses the APM UI application for RUM Data`, () => { // open service overview page const RANGE_FROM = 'now-24h'; const RANGE_TO = 'now'; - loginAndWaitForPage(`/app/apm#/rum-preview`, { + loginAndWaitForPage(`/app/apm/rum-preview`, { from: RANGE_FROM, to: RANGE_TO, }); diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/CoreVitals/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/CoreVitals/index.tsx index e8305a6aef0d4..d0bd674ef5c79 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/CoreVitals/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/CoreVitals/index.tsx @@ -20,10 +20,11 @@ const CoreVitalsThresholds = { export function CoreVitals() { const { urlParams, uiFilters } = useUrlParams(); - const { start, end, serviceName } = urlParams; + const { start, end } = urlParams; const { data, status } = useFetcher( (callApmApi) => { + const { serviceName } = uiFilters; if (start && end && serviceName) { return callApmApi({ pathname: '/api/apm/rum-client/web-core-vitals', @@ -34,7 +35,7 @@ export function CoreVitals() { } return Promise.resolve(null); }, - [start, end, serviceName, uiFilters] + [start, end, uiFilters] ); const { lcp, lcpRanks, fid, fidRanks, cls, clsRanks } = data || {}; diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx index 55d068cba5935..8670cf623c253 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx @@ -25,11 +25,7 @@ export function Buttons({ }: ButtonsProps) { const { core } = useApmPluginContext(); const { basePath } = core.http; - // The params may contain the service name. We want to use the selected node's - // service name in the button URLs, so make a copy and set the - // `serviceName` property. - const urlParams = { ...useUrlParams().urlParams } as APMQueryParams; - urlParams.serviceName = selectedNodeServiceName; + const urlParams = useUrlParams().urlParams as APMQueryParams; const detailsUrl = getAPMHref({ basePath, diff --git a/x-pack/plugins/apm/public/components/shared/DatePicker/index.tsx b/x-pack/plugins/apm/public/components/shared/DatePicker/index.tsx index 549ee228b7afe..b4d716f89169e 100644 --- a/x-pack/plugins/apm/public/components/shared/DatePicker/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/DatePicker/index.tsx @@ -7,10 +7,9 @@ import { EuiSuperDatePicker } from '@elastic/eui'; import { isEmpty, isEqual, pickBy } from 'lodash'; import React from 'react'; -import { useHistory } from 'react-router-dom'; +import { useHistory, useLocation } from 'react-router-dom'; import { UI_SETTINGS } from '../../../../../../../src/plugins/data/common'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; -import { useLocation } from '../../../hooks/useLocation'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { clearCache } from '../../../services/rest/callApi'; import { fromQuery, toQuery } from '../Links/url_helpers'; diff --git a/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx index 1a91e398cec76..85d975870d9bc 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx @@ -3,12 +3,11 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { EuiTitle } from '@elastic/eui'; +import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import React, { useCallback } from 'react'; -import { EuiPanel } from '@elastic/eui'; -import { EuiSpacer } from '@elastic/eui'; +import { useParams } from 'react-router-dom'; import { asPercent } from '../../../../../common/utils/formatters'; import { useChartsSync } from '../../../../hooks/useChartsSync'; import { useFetcher } from '../../../../hooks/useFetcher'; @@ -22,16 +21,11 @@ const tickFormatY = (y?: number) => { }; export function ErroneousTransactionsRateChart() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { urlParams, uiFilters } = useUrlParams(); const syncedChartsProps = useChartsSync(); - const { - serviceName, - start, - end, - transactionType, - transactionName, - } = urlParams; + const { start, end, transactionType, transactionName } = urlParams; const { data } = useFetcher(() => { if (serviceName && start && end) { diff --git a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.tsx similarity index 82% rename from x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts rename to x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.tsx index b34cc95a26399..bb947e307437e 100644 --- a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts +++ b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.tsx @@ -8,6 +8,12 @@ import { renderHook } from '@testing-library/react-hooks'; import theme from '@elastic/eui/dist/eui_theme_light.json'; import * as useFetcherModule from './useFetcher'; import { useAvgDurationByBrowser } from './useAvgDurationByBrowser'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; + +function Wrapper({ children }: { children?: ReactNode }) { + return {children}; +} describe('useAvgDurationByBrowser', () => { it('returns data', () => { @@ -19,7 +25,9 @@ describe('useAvgDurationByBrowser', () => { refetch: () => {}, status: 'success' as useFetcherModule.FETCH_STATUS, }); - const { result } = renderHook(() => useAvgDurationByBrowser()); + const { result } = renderHook(() => useAvgDurationByBrowser(), { + wrapper: Wrapper, + }); expect(result.current.data).toEqual([ { diff --git a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts index a8312dd0448e6..78dc4210711ef 100644 --- a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts +++ b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts @@ -5,12 +5,13 @@ */ import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { useFetcher } from './useFetcher'; -import { useUrlParams } from './useUrlParams'; +import { useParams } from 'react-router-dom'; +import { getVizColorForIndex } from '../../common/viz_colors'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AvgDurationByBrowserAPIResponse } from '../../server/lib/transactions/avg_duration_by_browser'; import { TimeSeries } from '../../typings/timeseries'; -import { getVizColorForIndex } from '../../common/viz_colors'; +import { useFetcher } from './useFetcher'; +import { useUrlParams } from './useUrlParams'; function toTimeSeries(data?: AvgDurationByBrowserAPIResponse): TimeSeries[] { if (!data) { @@ -27,8 +28,9 @@ function toTimeSeries(data?: AvgDurationByBrowserAPIResponse): TimeSeries[] { } export function useAvgDurationByBrowser() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - urlParams: { serviceName, start, end, transactionName }, + urlParams: { start, end, transactionName }, uiFilters, } = useUrlParams(); diff --git a/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts b/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts index 818657226cb14..983f949b72961 100644 --- a/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts +++ b/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts @@ -3,13 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import { useParams } from 'react-router-dom'; import { useFetcher } from './useFetcher'; import { useUrlParams } from './useUrlParams'; export function useAvgDurationByCountry() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - urlParams: { serviceName, start, end, transactionName }, + urlParams: { start, end, transactionName }, uiFilters, } = useUrlParams(); diff --git a/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts b/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts index 9db78fde2d8c8..08d2300c3254a 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts @@ -4,12 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import { useParams } from 'react-router-dom'; import { useFetcher } from './useFetcher'; import { useUrlParams } from './useUrlParams'; export function useTransactionBreakdown() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - urlParams: { serviceName, start, end, transactionName, transactionType }, + urlParams: { start, end, transactionName, transactionType }, uiFilters, } = useUrlParams(); diff --git a/x-pack/plugins/apm/public/hooks/useTransactionCharts.ts b/x-pack/plugins/apm/public/hooks/useTransactionCharts.ts index 2ecd900386496..e66d70a53afa6 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionCharts.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionCharts.ts @@ -5,13 +5,15 @@ */ import { useMemo } from 'react'; +import { useParams } from 'react-router-dom'; import { getTransactionCharts } from '../selectors/chartSelectors'; import { useFetcher } from './useFetcher'; import { useUrlParams } from './useUrlParams'; export function useTransactionCharts() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - urlParams: { serviceName, transactionType, start, end, transactionName }, + urlParams: { transactionType, start, end, transactionName }, uiFilters, } = useUrlParams(); diff --git a/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts b/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts index 539918c432783..d93a27df1c861 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts @@ -4,11 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IUrlParams } from '../context/UrlParamsContext/types'; -import { useFetcher } from './useFetcher'; -import { useUiFilters } from '../context/UrlParamsContext'; +import { useParams } from 'react-router-dom'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { TransactionDistributionAPIResponse } from '../../server/lib/transactions/distribution'; +import { useUiFilters } from '../context/UrlParamsContext'; +import { IUrlParams } from '../context/UrlParamsContext/types'; +import { useFetcher } from './useFetcher'; const INITIAL_DATA = { buckets: [] as TransactionDistributionAPIResponse['buckets'], @@ -17,8 +18,8 @@ const INITIAL_DATA = { }; export function useTransactionDistribution(urlParams: IUrlParams) { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - serviceName, start, end, transactionType, diff --git a/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.test.ts b/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.test.ts index 8b3ed38e25319..4e306c93805d0 100644 --- a/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.test.ts +++ b/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.test.ts @@ -51,7 +51,7 @@ describe('Observability dashboard data', () => { ); const response = await fetchOverviewPageData(params); expect(response).toEqual({ - appLink: '/app/apm#/services?rangeFrom=now-15m&rangeTo=now', + appLink: '/app/apm/services?rangeFrom=now-15m&rangeTo=now', stats: { services: { type: 'number', @@ -82,7 +82,7 @@ describe('Observability dashboard data', () => { ); const response = await fetchOverviewPageData(params); expect(response).toEqual({ - appLink: '/app/apm#/services?rangeFrom=now-15m&rangeTo=now', + appLink: '/app/apm/services?rangeFrom=now-15m&rangeTo=now', stats: { services: { type: 'number', @@ -109,7 +109,7 @@ describe('Observability dashboard data', () => { ); const response = await fetchOverviewPageData(params); expect(response).toEqual({ - appLink: '/app/apm#/services?rangeFrom=now-15m&rangeTo=now', + appLink: '/app/apm/services?rangeFrom=now-15m&rangeTo=now', stats: { services: { type: 'number', diff --git a/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.ts b/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.ts index a20f89fac2d60..422c7b882e5dc 100644 --- a/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.ts +++ b/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.ts @@ -32,7 +32,7 @@ export const fetchOverviewPageData = async ({ const { serviceCount, transactionCoordinates } = data; return { - appLink: `/app/apm#/services?rangeFrom=${relativeTime.start}&rangeTo=${relativeTime.end}`, + appLink: `/app/apm/services?rangeFrom=${relativeTime.start}&rangeTo=${relativeTime.end}`, stats: { services: { type: 'number', From 88caa798a9336e16541681fd4e2cfadbad35432a Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Mon, 14 Sep 2020 20:59:21 -0400 Subject: [PATCH 05/26] [SECURITY_SOLUTION] Task/hostname policy response ux updates (#76444) --- .../components/formatted_date/index.tsx | 18 +++++++++ .../pages/endpoint_hosts/store/selectors.ts | 6 +++ .../view/details/endpoint_details.tsx | 6 +-- .../endpoint_hosts/view/details/index.tsx | 12 +++++- .../pages/endpoint_hosts/view/index.test.tsx | 4 +- .../pages/endpoint_hosts/view/index.tsx | 40 ++++++++++++------- .../apps/endpoint/endpoint_list.ts | 16 ++++---- 7 files changed, 72 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx b/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx index 687d2a36da610..38c2a8583f7e9 100644 --- a/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx @@ -22,6 +22,24 @@ export const PreferenceFormattedDate = React.memo<{ dateFormat?: string; value: PreferenceFormattedDate.displayName = 'PreferenceFormattedDate'; +export const PreferenceFormattedDateFromPrimitive = ({ + value, +}: { + value?: string | number | null; +}) => { + if (value == null) { + return getOrEmptyTagFromValue(value); + } + const maybeDate = getMaybeDate(value); + if (!maybeDate.isValid()) { + return getOrEmptyTagFromValue(value); + } + const date = maybeDate.toDate(); + return ; +}; + +PreferenceFormattedDateFromPrimitive.displayName = 'PreferenceFormattedDateFromPrimitive'; + /** * This function may be passed to `Array.find()` to locate the `P1DT` * configuration (sub) setting, a string array that contains two entries diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts index 852bc9791fc90..a3eee8063d6f7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts @@ -72,6 +72,12 @@ export const patternsError = (state: Immutable) => state.patterns const detailsPolicyAppliedResponse = (state: Immutable) => state.policyResponse && state.policyResponse.Endpoint.policy.applied; +/** + * Returns the policy response timestamp from the endpoint after a user modifies a policy. + */ +export const policyResponseTimestamp = (state: Immutable) => + state.policyResponse && state.policyResponse['@timestamp']; + /** * Returns the response configurations from the endpoint after a user modifies a policy. */ diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx index b76b7e51b2c1b..47f4fbb8830ae 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx @@ -125,7 +125,7 @@ export const EndpointDetails = memo(({ details }: { details: HostMetadata }) => return [ { title: i18n.translate('xpack.securitySolution.endpoint.details.policy', { - defaultMessage: 'Integration', + defaultMessage: 'Integration Policy', }), description: ( <> @@ -140,7 +140,7 @@ export const EndpointDetails = memo(({ details }: { details: HostMetadata }) => }, { title: i18n.translate('xpack.securitySolution.endpoint.details.policyStatus', { - defaultMessage: 'Configuration response', + defaultMessage: 'Policy Response', }), description: ( diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx index a37ddd0bd61d9..43d3b39474fc7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx @@ -32,6 +32,7 @@ import { policyResponseFailedOrWarningActionCount, policyResponseError, policyResponseLoading, + policyResponseTimestamp, } from '../../store/selectors'; import { EndpointDetails } from './endpoint_details'; import { PolicyResponse } from './policy_response'; @@ -41,6 +42,7 @@ import { useNavigateByRouterEventHandler } from '../../../../../common/hooks/end import { getEndpointListPath } from '../../../../common/routing'; import { SecurityPageName } from '../../../../../app/types'; import { useFormatUrl } from '../../../../../common/components/link_to'; +import { PreferenceFormattedDateFromPrimitive } from '../../../../../common/components/formatted_date'; export const EndpointDetailsFlyout = memo(() => { const history = useHistory(); @@ -122,6 +124,7 @@ const PolicyResponseFlyoutPanel = memo<{ const loading = useEndpointSelector(policyResponseLoading); const error = useEndpointSelector(policyResponseError); const { formatUrl } = useFormatUrl(SecurityPageName.administration); + const responseTimestamp = useEndpointSelector(policyResponseTimestamp); const [detailsUri, detailsRoutePath] = useMemo( () => [ formatUrl( @@ -161,16 +164,21 @@ const PolicyResponseFlyoutPanel = memo<{

+ + + + + {error && ( } /> diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx index 14167f25d5b90..2bdf17b806079 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx @@ -510,7 +510,7 @@ describe('when on the list page', () => { const renderResult = await renderAndWaitForData(); const linkToReassign = await renderResult.findByTestId('endpointDetailsLinkToIngest'); expect(linkToReassign).not.toBeNull(); - expect(linkToReassign.textContent).toEqual('Reassign Configuration'); + expect(linkToReassign.textContent).toEqual('Reassign Policy'); expect(linkToReassign.getAttribute('href')).toEqual( `/app/ingestManager#/fleet/agents/${agentId}/activity?openReassignFlyout=true` ); @@ -572,7 +572,7 @@ describe('when on the list page', () => { it('should include the sub-panel title', async () => { expect( (await renderResult.findByTestId('endpointDetailsPolicyResponseFlyoutTitle')).textContent - ).toBe('Configuration Response'); + ).toBe('Policy Response'); }); it('should show a configuration section for each protection', async () => { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index 166f1660bf3d6..ecee2bee0c58b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -270,17 +270,20 @@ export const EndpointList = () => { ); const toRouteUrl = formatUrl(toRoutePath); return ( - + + + ); }, }, { field: 'host_status', + width: '9%', name: i18n.translate('xpack.securitySolution.endpoint.list.hostStatus', { defaultMessage: 'Agent Status', }), @@ -303,27 +306,31 @@ export const EndpointList = () => { }, { field: 'metadata.Endpoint.policy.applied', + width: '15%', name: i18n.translate('xpack.securitySolution.endpoint.list.policy', { - defaultMessage: 'Integration', + defaultMessage: 'Integration Policy', }), truncateText: true, // eslint-disable-next-line react/display-name render: (policy: HostInfo['metadata']['Endpoint']['policy']['applied']) => { return ( - - {policy.name} - + + + {policy.name} + + ); }, }, { field: 'metadata.Endpoint.policy.applied', + width: '9%', name: i18n.translate('xpack.securitySolution.endpoint.list.policyStatus', { - defaultMessage: 'Configuration Status', + defaultMessage: 'Policy Status', }), render: (policy: HostInfo['metadata']['Endpoint']['policy']['applied'], item: HostInfo) => { const toRoutePath = getEndpointDetailsPath({ @@ -350,6 +357,7 @@ export const EndpointList = () => { }, { field: 'metadata.host.os.name', + width: '10%', name: i18n.translate('xpack.securitySolution.endpoint.list.os', { defaultMessage: 'Operating System', }), @@ -375,6 +383,7 @@ export const EndpointList = () => { }, { field: 'metadata.agent.version', + width: '5%', name: i18n.translate('xpack.securitySolution.endpoint.list.endpointVersion', { defaultMessage: 'Version', }), @@ -394,6 +403,7 @@ export const EndpointList = () => { }, { field: '', + width: '5%', name: i18n.translate('xpack.securitySolution.endpoint.list.actions', { defaultMessage: 'Actions', }), diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index b0b8d14108004..7485e5db20478 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -22,8 +22,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { [ 'Hostname', 'Agent Status', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'Operating System', 'IP Address', 'Version', @@ -188,8 +188,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 'OS', 'Last Seen', 'Alerts', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'IP Address', 'Hostname', 'Sensor Version', @@ -236,8 +236,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { [ 'Hostname', 'Agent Status', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'Operating System', 'IP Address', 'Version', @@ -267,8 +267,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { [ 'Hostname', 'Agent Status', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'Operating System', 'IP Address', 'Version', From 98e6475980caaa27749094e8f5b42aaace43f793 Mon Sep 17 00:00:00 2001 From: Constance Date: Mon, 14 Sep 2020 18:59:45 -0700 Subject: [PATCH 06/26] [Enterprise Search] Update enterpriseSearchRequestHandler to manage range of errors + add handleAPIErrors helper (#77258) * Update/refactor EnterpriseSearchRequestHandler to manage internal endpoint error behavior + pull out / refactor all errors into their own methods instead of relying on a single 'error connecting' message * Fix http interceptor bug preventing 4xx/5xx responses from being caught * Add handleAPIError helper - New and improved from ent-search - this one automatically sets flash messages for you so you don't have to pass in a callback! * Fix type check * [Feedback] Add option to queue flash messages to handleAPIError - Should be hopefully useful for calls that need to queue an error and then redirect to another page * PR feedback: Add test case for bodies flagged as JSON which are not * Rename handleAPIError to flashAPIErrors --- .../flash_messages/handle_api_errors.test.ts | 65 +++++ .../flash_messages/handle_api_errors.ts | 56 ++++ .../shared/http/http_logic.test.ts | 9 +- .../applications/shared/http/http_logic.ts | 6 +- .../enterprise_search_request_handler.test.ts | 250 +++++++++++++----- .../lib/enterprise_search_request_handler.ts | 133 ++++++++-- 6 files changed, 426 insertions(+), 93 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts new file mode 100644 index 0000000000000..6f2aec757eb37 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +jest.mock('./', () => ({ + FlashMessagesLogic: { + actions: { + setFlashMessages: jest.fn(), + setQueuedMessages: jest.fn(), + }, + }, +})); +import { FlashMessagesLogic } from './'; + +import { flashAPIErrors } from './handle_api_errors'; + +describe('flashAPIErrors', () => { + const mockHttpError = { + body: { + statusCode: 404, + error: 'Not Found', + message: 'Could not find X,Could not find Y,Something else bad happened', + attributes: { + errors: ['Could not find X', 'Could not find Y', 'Something else bad happened'], + }, + }, + } as any; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('converts API errors into flash messages', () => { + flashAPIErrors(mockHttpError); + + expect(FlashMessagesLogic.actions.setFlashMessages).toHaveBeenCalledWith([ + { type: 'error', message: 'Could not find X' }, + { type: 'error', message: 'Could not find Y' }, + { type: 'error', message: 'Something else bad happened' }, + ]); + }); + + it('queues messages when isQueued is passed', () => { + flashAPIErrors(mockHttpError, { isQueued: true }); + + expect(FlashMessagesLogic.actions.setQueuedMessages).toHaveBeenCalledWith([ + { type: 'error', message: 'Could not find X' }, + { type: 'error', message: 'Could not find Y' }, + { type: 'error', message: 'Something else bad happened' }, + ]); + }); + + it('displays a generic error message and re-throws non-API errors', () => { + try { + flashAPIErrors(Error('whatever') as any); + } catch (e) { + expect(e.message).toEqual('whatever'); + expect(FlashMessagesLogic.actions.setFlashMessages).toHaveBeenCalledWith([ + { type: 'error', message: 'An unexpected error occurred' }, + ]); + } + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts new file mode 100644 index 0000000000000..5e56c4fb0bd22 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts @@ -0,0 +1,56 @@ +/* + * 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 { HttpResponse } from 'src/core/public'; + +import { FlashMessagesLogic, IFlashMessage } from './'; + +/** + * The API errors we are handling can come from one of two ways: + * - When our http calls recieve a response containing an error code, such as a 404 or 500 + * - Our own JS while handling a successful response + * + * In the first case, if it is a purposeful error (like a 404) we will receive an + * `errors` property in the response's data, which will contain messages we can + * display to the user. + */ +interface IErrorResponse { + statusCode: number; + error: string; + message: string; + attributes: { + errors: string[]; + }; +} +interface IOptions { + isQueued?: boolean; +} + +/** + * Converts API/HTTP errors into user-facing Flash Messages + */ +export const flashAPIErrors = ( + error: HttpResponse, + { isQueued }: IOptions = {} +) => { + const defaultErrorMessage = 'An unexpected error occurred'; + + const errorFlashMessages: IFlashMessage[] = Array.isArray(error?.body?.attributes?.errors) + ? error.body!.attributes.errors.map((message) => ({ type: 'error', message })) + : [{ type: 'error', message: defaultErrorMessage }]; + + if (isQueued) { + FlashMessagesLogic.actions.setQueuedMessages(errorFlashMessages); + } else { + FlashMessagesLogic.actions.setFlashMessages(errorFlashMessages); + } + + // If this was a programming error or a failed request (such as a CORS) error, + // we rethrow the error so it shows up in the developer console + if (!error?.body?.message) { + throw error; + } +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.test.ts index a6957340d33d3..c032e3b04ebe6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.test.ts @@ -74,21 +74,24 @@ describe('HttpLogic', () => { describe('errorConnectingInterceptor', () => { it('handles errors connecting to Enterprise Search', async () => { const { responseError } = mockHttp.intercept.mock.calls[0][0] as any; - await responseError({ response: { url: '/api/app_search/engines', status: 502 } }); + const httpResponse = { response: { url: '/api/app_search/engines', status: 502 } }; + await expect(responseError(httpResponse)).rejects.toEqual(httpResponse); expect(HttpLogic.actions.setErrorConnecting).toHaveBeenCalled(); }); it('does not handle non-502 Enterprise Search errors', async () => { const { responseError } = mockHttp.intercept.mock.calls[0][0] as any; - await responseError({ response: { url: '/api/workplace_search/overview', status: 404 } }); + const httpResponse = { response: { url: '/api/workplace_search/overview', status: 404 } }; + await expect(responseError(httpResponse)).rejects.toEqual(httpResponse); expect(HttpLogic.actions.setErrorConnecting).not.toHaveBeenCalled(); }); it('does not handle errors for unrelated calls', async () => { const { responseError } = mockHttp.intercept.mock.calls[0][0] as any; - await responseError({ response: { url: '/api/some_other_plugin/', status: 502 } }); + const httpResponse = { response: { url: '/api/some_other_plugin/', status: 502 } }; + await expect(responseError(httpResponse)).rejects.toEqual(httpResponse); expect(HttpLogic.actions.setErrorConnecting).not.toHaveBeenCalled(); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts index fb2d9b1061723..ec9db30ddef3b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts @@ -6,7 +6,7 @@ import { kea, MakeLogicType } from 'kea'; -import { HttpSetup } from 'src/core/public'; +import { HttpSetup, HttpInterceptorResponseError } from 'src/core/public'; export interface IHttpValues { http: HttpSetup; @@ -68,7 +68,9 @@ export const HttpLogic = kea>({ if (isApiResponse && hasErrorConnecting) { actions.setErrorConnecting(true); } - return httpResponse; + + // Re-throw error so that downstream catches work as expected + return Promise.reject(httpResponse) as Promise; }, }); httpInterceptors.push(errorConnectingInterceptor); diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts index 34f83ef3a3fd2..0c1e81e3aba46 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts @@ -30,109 +30,198 @@ describe('EnterpriseSearchRequestHandler', () => { fetchMock.mockReset(); }); - it('makes an API call and returns the response', async () => { - const responseBody = { - results: [{ name: 'engine1' }], - meta: { page: { total_results: 1 } }, - }; + describe('createRequest()', () => { + it('makes an API call and returns the response', async () => { + const responseBody = { + results: [{ name: 'engine1' }], + meta: { page: { total_results: 1 } }, + }; - EnterpriseSearchAPI.mockReturn(responseBody); + EnterpriseSearchAPI.mockReturn(responseBody); - const requestHandler = enterpriseSearchRequestHandler.createRequest({ - path: '/as/credentials/collection', - }); + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/as/credentials/collection', + }); - await makeAPICall(requestHandler, { - query: { - type: 'indexed', - pageIndex: 1, - }, - }); + await makeAPICall(requestHandler, { + query: { + type: 'indexed', + pageIndex: 1, + }, + }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith( - 'http://localhost:3002/as/credentials/collection?type=indexed&pageIndex=1', - { method: 'GET' } - ); + EnterpriseSearchAPI.shouldHaveBeenCalledWith( + 'http://localhost:3002/as/credentials/collection?type=indexed&pageIndex=1', + { method: 'GET' } + ); - expect(responseMock.custom).toHaveBeenCalledWith({ - body: responseBody, - statusCode: 200, + expect(responseMock.custom).toHaveBeenCalledWith({ + body: responseBody, + statusCode: 200, + }); }); - }); - describe('request passing', () => { - it('passes route method', async () => { - const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/example' }); + describe('request passing', () => { + it('passes route method', async () => { + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/api/example', + }); + + await makeAPICall(requestHandler, { route: { method: 'POST' } }); + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { + method: 'POST', + }); - await makeAPICall(requestHandler, { route: { method: 'POST' } }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { - method: 'POST', + await makeAPICall(requestHandler, { route: { method: 'DELETE' } }); + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { + method: 'DELETE', + }); }); - await makeAPICall(requestHandler, { route: { method: 'DELETE' } }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { - method: 'DELETE', + it('passes request body', async () => { + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/api/example', + }); + await makeAPICall(requestHandler, { body: { bodacious: true } }); + + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { + body: '{"bodacious":true}', + }); }); - }); - it('passes request body', async () => { - const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/example' }); - await makeAPICall(requestHandler, { body: { bodacious: true } }); + it('passes custom params set by the handler, which override request params', async () => { + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/api/example', + params: { someQuery: true }, + }); + await makeAPICall(requestHandler, { query: { someQuery: false } }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { - body: '{"bodacious":true}', + EnterpriseSearchAPI.shouldHaveBeenCalledWith( + 'http://localhost:3002/api/example?someQuery=true' + ); }); }); - it('passes custom params set by the handler, which override request params', async () => { - const requestHandler = enterpriseSearchRequestHandler.createRequest({ - path: '/api/example', - params: { someQuery: true }, + describe('response passing', () => { + it('returns the response status code from Enterprise Search', async () => { + EnterpriseSearchAPI.mockReturn({}, { status: 201 }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/api/example', + }); + await makeAPICall(requestHandler); + + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example'); + expect(responseMock.custom).toHaveBeenCalledWith({ body: {}, statusCode: 201 }); }); - await makeAPICall(requestHandler, { query: { someQuery: false } }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith( - 'http://localhost:3002/api/example?someQuery=true' - ); + // TODO: It's possible we may also pass back headers at some point + // from Enterprise Search, e.g. the x-read-only mode header }); }); - describe('response passing', () => { - it('returns the response status code from Enterprise Search', async () => { - EnterpriseSearchAPI.mockReturn({}, { status: 404 }); + describe('error responses', () => { + describe('handleClientError()', () => { + afterEach(() => { + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/4xx'); + expect(mockLogger.error).not.toHaveBeenCalled(); + }); - const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/example' }); - await makeAPICall(requestHandler); + it('passes back json.error', async () => { + const error = 'some error message'; + EnterpriseSearchAPI.mockReturn({ error }, { status: 404, headers: JSON_HEADER }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example'); - expect(responseMock.custom).toHaveBeenCalledWith({ body: {}, statusCode: 404 }); - }); + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); - // TODO: It's possible we may also pass back headers at some point - // from Enterprise Search, e.g. the x-read-only mode header - }); + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 404, + body: { + message: 'some error message', + attributes: { errors: ['some error message'] }, + }, + }); + }); - describe('error handling', () => { - afterEach(() => { - expect(mockLogger.error).toHaveBeenCalledWith( - expect.stringContaining('Error connecting to Enterprise Search') - ); + it('passes back json.errors', async () => { + const errors = ['one', 'two', 'three']; + EnterpriseSearchAPI.mockReturn({ errors }, { status: 400, headers: JSON_HEADER }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 400, + body: { + message: 'one,two,three', + attributes: { errors: ['one', 'two', 'three'] }, + }, + }); + }); + + it('handles empty json', async () => { + EnterpriseSearchAPI.mockReturn({}, { status: 400, headers: JSON_HEADER }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 400, + body: { + message: 'Bad Request', + attributes: { errors: ['Bad Request'] }, + }, + }); + }); + + it('handles invalid json', async () => { + EnterpriseSearchAPI.mockReturn('invalid' as any, { status: 400, headers: JSON_HEADER }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 400, + body: { + message: 'Bad Request', + attributes: { errors: ['Bad Request'] }, + }, + }); + }); + + it('handles blank bodies', async () => { + EnterpriseSearchAPI.mockReturn(undefined as any, { status: 404 }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 404, + body: { + message: 'Not Found', + attributes: { errors: ['Not Found'] }, + }, + }); + }); }); - it('returns an error when an API request fails', async () => { - EnterpriseSearchAPI.mockReturnError(); - const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/failed' }); + it('handleServerError()', async () => { + EnterpriseSearchAPI.mockReturn('something crashed!' as any, { status: 500 }); + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/5xx' }); await makeAPICall(requestHandler); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/failed'); + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/5xx'); expect(responseMock.customError).toHaveBeenCalledWith({ - body: 'Error connecting to Enterprise Search: Failed', statusCode: 502, + body: expect.stringContaining('Enterprise Search encountered an internal server error'), }); + expect(mockLogger.error).toHaveBeenCalledWith( + 'Enterprise Search Server Error 500 at : "something crashed!"' + ); }); - it('returns an error when `hasValidData` fails', async () => { + it('handleInvalidDataError()', async () => { EnterpriseSearchAPI.mockReturn({ results: false }); const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/invalid', @@ -143,15 +232,29 @@ describe('EnterpriseSearchRequestHandler', () => { EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/invalid'); expect(responseMock.customError).toHaveBeenCalledWith({ - body: 'Error connecting to Enterprise Search: Invalid data received', statusCode: 502, + body: 'Invalid data received from Enterprise Search', }); - expect(mockLogger.debug).toHaveBeenCalledWith( + expect(mockLogger.error).toHaveBeenCalledWith( 'Invalid data received from : {"results":false}' ); }); - describe('user authentication errors', () => { + it('handleConnectionError()', async () => { + EnterpriseSearchAPI.mockReturnError(); + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/failed' }); + + await makeAPICall(requestHandler); + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/failed'); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 502, + body: 'Error connecting to Enterprise Search: Failed', + }); + expect(mockLogger.error).toHaveBeenCalled(); + }); + + describe('handleAuthenticationError()', () => { afterEach(async () => { const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/unauthenticated', @@ -160,9 +263,10 @@ describe('EnterpriseSearchRequestHandler', () => { EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/unauthenticated'); expect(responseMock.customError).toHaveBeenCalledWith({ - body: 'Error connecting to Enterprise Search: Cannot authenticate Enterprise Search user', statusCode: 502, + body: 'Cannot authenticate Enterprise Search user', }); + expect(mockLogger.error).toHaveBeenCalled(); }); it('errors when redirected to /login', async () => { @@ -175,7 +279,7 @@ describe('EnterpriseSearchRequestHandler', () => { }); }); - it('has a helper for checking empty objects', async () => { + it('isEmptyObj', async () => { expect(enterpriseSearchRequestHandler.isEmptyObj({})).toEqual(true); expect(enterpriseSearchRequestHandler.isEmptyObj({ empty: false })).toEqual(false); }); diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts index 18f10c590847c..00d5eaf5d6a83 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import fetch from 'node-fetch'; +import fetch, { Response } from 'node-fetch'; import querystring from 'querystring'; import { RequestHandler, @@ -25,6 +25,12 @@ interface IRequestParams { params?: object; hasValidData?: (body?: ResponseBody) => boolean; } +interface IErrorResponse { + message: string; + attributes: { + errors: string[]; + }; +} export interface IEnterpriseSearchRequestHandler { createRequest(requestParams?: object): RequestHandler; } @@ -71,34 +77,131 @@ export class EnterpriseSearchRequestHandler { ? JSON.stringify(request.body) : undefined; - // Call the Enterprise Search API and pass back response to the front-end + // Call the Enterprise Search API const apiResponse = await fetch(url, { method, headers, body }); + // Handle authentication redirects if (apiResponse.url.endsWith('/login') || apiResponse.url.endsWith('/ent/select')) { - throw new Error('Cannot authenticate Enterprise Search user'); + return this.handleAuthenticationError(response); } + // Handle 400-500+ responses from the Enterprise Search server const { status } = apiResponse; - const json = await apiResponse.json(); + if (status >= 500) { + return this.handleServerError(response, apiResponse, url); + } else if (status >= 400) { + return this.handleClientError(response, apiResponse); + } - if (hasValidData(json)) { - return response.custom({ statusCode: status, body: json }); - } else { - this.log.debug(`Invalid data received from <${url}>: ${JSON.stringify(json)}`); - throw new Error('Invalid data received'); + // Check returned data + const json = await apiResponse.json(); + if (!hasValidData(json)) { + return this.handleInvalidDataError(response, url, json); } + + // Pass successful responses back to the front-end + return response.custom({ statusCode: status, body: json }); } catch (e) { - const errorMessage = `Error connecting to Enterprise Search: ${e?.message || e.toString()}`; + // Catch connection/auth errors + return this.handleConnectionError(response, e); + } + }; + } - this.log.error(errorMessage); - if (e instanceof Error) this.log.debug(e.stack as string); + /** + * Attempt to grab a usable error body from Enterprise Search - this isn't + * always possible because some of our internal endpoints send back blank + * bodies, and sometimes the server sends back Ruby on Rails error pages + */ + async getErrorResponseBody(apiResponse: Response) { + const { statusText } = apiResponse; + const contentType = apiResponse.headers.get('content-type') || ''; - return response.customError({ statusCode: 502, body: errorMessage }); - } + // Default response + let body: IErrorResponse = { + message: statusText, + attributes: { errors: [statusText] }, }; + + try { + if (contentType.includes('application/json')) { + // Try parsing body as JSON + const json = await apiResponse.json(); + + // Some of our internal endpoints return either an `error` or `errors` key, + // which can both return either a string or array of strings ¯\_(ツ)_/¯ + const errors = json.error || json.errors || [statusText]; + body = { + message: errors.toString(), + attributes: { errors: Array.isArray(errors) ? errors : [errors] }, + }; + } else { + // Try parsing body as text/html + const text = await apiResponse.text(); + if (text) { + body = { + message: text, + attributes: { errors: [text] }, + }; + } + } + } catch { + // Fail silently + } + + return body; + } + + /** + * Error response helpers + */ + + async handleClientError(response: KibanaResponseFactory, apiResponse: Response) { + const { status } = apiResponse; + const body = await this.getErrorResponseBody(apiResponse); + + return response.customError({ statusCode: status, body }); + } + + async handleServerError(response: KibanaResponseFactory, apiResponse: Response, url: string) { + const { status } = apiResponse; + const { message } = await this.getErrorResponseBody(apiResponse); + + // Don't expose server errors to the front-end, as they may contain sensitive stack traces + const errorMessage = + 'Enterprise Search encountered an internal server error. Please contact your system administrator if the problem persists.'; + + this.log.error(`Enterprise Search Server Error ${status} at <${url}>: ${message}`); + return response.customError({ statusCode: 502, body: errorMessage }); + } + + handleInvalidDataError(response: KibanaResponseFactory, url: string, json: object) { + const errorMessage = 'Invalid data received from Enterprise Search'; + + this.log.error(`Invalid data received from <${url}>: ${JSON.stringify(json)}`); + return response.customError({ statusCode: 502, body: errorMessage }); } - // Small helper + handleConnectionError(response: KibanaResponseFactory, e: Error) { + const errorMessage = `Error connecting to Enterprise Search: ${e?.message || e.toString()}`; + + this.log.error(errorMessage); + if (e instanceof Error) this.log.debug(e.stack as string); + + return response.customError({ statusCode: 502, body: errorMessage }); + } + + handleAuthenticationError(response: KibanaResponseFactory) { + const errorMessage = 'Cannot authenticate Enterprise Search user'; + + this.log.error(errorMessage); + return response.customError({ statusCode: 502, body: errorMessage }); + } + + /** + * Misc helpers + */ + isEmptyObj(obj: object) { return Object.keys(obj).length === 0; } From 3d911655183e60f748af2a18bd35a114a6ae59de Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Mon, 14 Sep 2020 22:55:27 -0500 Subject: [PATCH 07/26] [APM] Remove useLocation and some minor route improvements (#76343) * [APM] Remove useLocation and some minor route improvements * Replace `useLocation` and our `LocationContext` with `useLocation` from React Router. We can do this since we're now using the platform history, added in #76287. * Pass in `RouteComponentProps` where appropriate to routes to use `history` and `location`. This is in the service of #51963, but doesn't do anything with `useUrlParams` or any of the other changes specified in that issue. --- .../public/application/application.test.tsx | 4 ++ .../plugins/apm/public/application/index.tsx | 17 ++++---- .../List/__test__/List.test.tsx | 21 ++++++---- .../app/Main/route_config/index.tsx | 16 ++++---- .../route_handlers/agent_configuration.tsx | 20 +++++----- .../__test__/ServiceOverview.test.tsx | 19 +++++---- .../AgentConfigurations/List/index.tsx | 2 +- .../Settings/AgentConfigurations/index.tsx | 2 +- .../components/app/Settings/Settings.test.tsx | 14 ++++--- .../public/components/app/Settings/index.tsx | 24 +++++++----- .../app/TransactionDetails/index.tsx | 7 ++-- .../app/TransactionOverview/index.tsx | 2 +- .../DatePicker/__test__/DatePicker.test.tsx | 9 ++--- .../shared/EnvironmentFilter/index.tsx | 3 +- .../components/shared/KueryBar/index.tsx | 3 +- .../Links/DiscoverLinks/DiscoverLink.tsx | 2 +- .../Links/MachineLearningLinks/MLLink.tsx | 6 +-- .../useTimeSeriesExplorerHref.test.ts | 2 +- .../useTimeSeriesExplorerHref.ts | 4 +- .../components/shared/Links/apm/APMLink.tsx | 2 +- .../__test__/ErrorMetadata.test.tsx | 17 ++++++-- .../__test__/SpanMetadata.test.tsx | 15 +++++-- .../__test__/TransactionMetadata.test.tsx | 17 ++++++-- .../__test__/MetadataTable.test.tsx | 15 +++++-- .../components/shared/MetadataTable/index.tsx | 3 +- .../CustomLink/CustomLinkPopover.test.tsx | 7 +++- .../CustomLink/ManageCustomLink.test.tsx | 13 +++++-- .../CustomLink/index.test.tsx | 7 +++- .../TransactionActionMenu.tsx | 2 +- .../__test__/TransactionActionMenu.test.tsx | 39 ++++++++++--------- .../Timeline/Marker/ErrorMarker.test.tsx | 7 +++- .../apm/public/context/LocationContext.tsx | 18 --------- .../plugins/apm/public/hooks/useLocation.tsx | 12 ------ .../plugins/apm/public/utils/testHelpers.tsx | 5 +-- 34 files changed, 196 insertions(+), 160 deletions(-) delete mode 100644 x-pack/plugins/apm/public/context/LocationContext.tsx delete mode 100644 x-pack/plugins/apm/public/hooks/useLocation.tsx diff --git a/x-pack/plugins/apm/public/application/application.test.tsx b/x-pack/plugins/apm/public/application/application.test.tsx index fc369b9cf672a..0566ff19017f4 100644 --- a/x-pack/plugins/apm/public/application/application.test.tsx +++ b/x-pack/plugins/apm/public/application/application.test.tsx @@ -14,6 +14,10 @@ import { createCallApmApi } from '../services/rest/createCallApmApi'; import { renderApp } from './'; import { disableConsoleWarning } from '../utils/testHelpers'; +jest.mock('../services/rest/index_pattern', () => ({ + createStaticIndexPattern: () => Promise.resolve(undefined), +})); + describe('renderApp', () => { let mockConsole: jest.SpyInstance; diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx index 536d70b053f76..9843f73dafdbb 100644 --- a/x-pack/plugins/apm/public/application/index.tsx +++ b/x-pack/plugins/apm/public/application/index.tsx @@ -25,7 +25,6 @@ import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPat import { ApmPluginContext } from '../context/ApmPluginContext'; import { LicenseProvider } from '../context/LicenseContext'; import { LoadingIndicatorProvider } from '../context/LoadingIndicatorContext'; -import { LocationProvider } from '../context/LocationContext'; import { UrlParamsProvider } from '../context/UrlParamsContext'; import { useBreadcrumbs } from '../hooks/use_breadcrumbs'; import { ApmPluginSetupDeps } from '../plugin'; @@ -99,15 +98,13 @@ export function ApmAppRoot({ - - - - - - - - - + + + + + + + diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx index 1acfc5c49245d..84b72b62248b0 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx @@ -11,6 +11,7 @@ import { MockUrlParamsContextProvider } from '../../../../../context/UrlParamsCo import { mockMoment, toJson } from '../../../../../utils/testHelpers'; import { ErrorGroupList } from '../index'; import props from './props.json'; +import { MemoryRouter } from 'react-router-dom'; jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => { return { @@ -26,9 +27,11 @@ describe('ErrorGroupOverview -> List', () => { it('should render empty state', () => { const storeState = {}; const wrapper = mount( - - - , + + + + + , storeState ); @@ -37,11 +40,13 @@ describe('ErrorGroupOverview -> List', () => { it('should render with data', () => { const wrapper = mount( - - - - - + + + + + + + ); expect(toJson(wrapper)).toMatchSnapshot(); diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx index 0cefcbdc54228..4aa2d841e8deb 100644 --- a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx @@ -113,33 +113,33 @@ function ServiceDetailsTransactions( return ; } -function SettingsAgentConfiguration() { +function SettingsAgentConfiguration(props: RouteComponentProps<{}>) { return ( - + ); } -function SettingsAnomalyDetection() { +function SettingsAnomalyDetection(props: RouteComponentProps<{}>) { return ( - + ); } -function SettingsApmIndices() { +function SettingsApmIndices(props: RouteComponentProps<{}>) { return ( - + ); } -function SettingsCustomizeUI() { +function SettingsCustomizeUI(props: RouteComponentProps<{}>) { return ( - + ); diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx b/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx index cc07286457908..f2ae0c2ff99e8 100644 --- a/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx +++ b/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx @@ -13,10 +13,10 @@ import { AgentConfigurationCreateEdit } from '../../../Settings/AgentConfigurati type EditAgentConfigurationRouteHandler = RouteComponentProps<{}>; -export function EditAgentConfigurationRouteHandler({ - history, -}: EditAgentConfigurationRouteHandler) { - const { search } = history.location; +export function EditAgentConfigurationRouteHandler( + props: EditAgentConfigurationRouteHandler +) { + const { search } = props.history.location; // typescript complains because `pageStop` does not exist in `APMQueryParams` // Going forward we should move away from globally declared query params and this is a first step @@ -34,7 +34,7 @@ export function EditAgentConfigurationRouteHandler({ ); return ( - + ; -export function CreateAgentConfigurationRouteHandler({ - history, -}: CreateAgentConfigurationRouteHandlerProps) { - const { search } = history.location; +export function CreateAgentConfigurationRouteHandler( + props: CreateAgentConfigurationRouteHandlerProps +) { + const { search } = props.history.location; // Ignoring here because we specifically DO NOT want to add the query params to the global route handler // @ts-expect-error const { pageStep } = toQuery(search); return ( - + diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx index 8eeff018ad03f..e4ba1e36378d9 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx @@ -6,21 +6,22 @@ import { render, wait, waitForElement } from '@testing-library/react'; import { CoreStart } from 'kibana/public'; +import { merge } from 'lodash'; import React, { FunctionComponent, ReactChild } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { createKibanaReactContext } from 'src/plugins/kibana_react/public'; -import { merge } from 'lodash'; import { ServiceOverview } from '..'; +import { EuiThemeProvider } from '../../../../../../observability/public'; import { ApmPluginContextValue } from '../../../../context/ApmPluginContext'; import { mockApmPluginContextValue, MockApmPluginContextWrapper, } from '../../../../context/ApmPluginContext/MockApmPluginContext'; +import * as useAnomalyDetectionJobs from '../../../../hooks/useAnomalyDetectionJobs'; import { FETCH_STATUS } from '../../../../hooks/useFetcher'; import * as useLocalUIFilters from '../../../../hooks/useLocalUIFilters'; import * as urlParamsHooks from '../../../../hooks/useUrlParams'; -import * as useAnomalyDetectionJobs from '../../../../hooks/useAnomalyDetectionJobs'; import { SessionStorageMock } from '../../../../services/__test__/SessionStorageMock'; -import { EuiThemeProvider } from '../../../../../../../legacy/common/eui_styled_components'; const KibanaReactContext = createKibanaReactContext({ usageCollection: { reportUiStats: () => {} }, @@ -44,13 +45,15 @@ function wrapper({ children }: { children: ReactChild }) { }) as unknown) as ApmPluginContextValue; return ( - + - - {children} - + + + {children} + + - + ); } diff --git a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/List/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/List/index.tsx index 210b3c3da8d0b..a67df86b21b1e 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/List/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/List/index.tsx @@ -15,12 +15,12 @@ import { import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import React, { useState } from 'react'; +import { useLocation } from 'react-router-dom'; import { getOptionLabel } from '../../../../../../common/agent_configuration/all_option'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AgentConfigurationListAPIResponse } from '../../../../../../server/lib/settings/agent_configuration/list_configurations'; import { useApmPluginContext } from '../../../../../hooks/useApmPluginContext'; import { FETCH_STATUS } from '../../../../../hooks/useFetcher'; -import { useLocation } from '../../../../../hooks/useLocation'; import { useTheme } from '../../../../../hooks/useTheme'; import { px, units } from '../../../../../style/variables'; import { diff --git a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx index 06d3f883e211a..8e32c55da9161 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx @@ -15,10 +15,10 @@ import { import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import React from 'react'; +import { useLocation } from 'react-router-dom'; import { useTrackPageview } from '../../../../../../observability/public'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; import { useFetcher } from '../../../../hooks/useFetcher'; -import { useLocation } from '../../../../hooks/useLocation'; import { createAgentConfigurationHref } from '../../../shared/Links/apm/agentConfigurationLinks'; import { AgentConfigurationList } from './List'; diff --git a/x-pack/plugins/apm/public/components/app/Settings/Settings.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/Settings.test.tsx index 0e0194cac848c..21da12477b024 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/Settings.test.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/Settings.test.tsx @@ -8,23 +8,27 @@ import { render } from '@testing-library/react'; import { MockApmPluginContextWrapper } from '../../../context/ApmPluginContext/MockApmPluginContext'; import React, { ReactNode } from 'react'; import { Settings } from './'; -import { LocationContext } from '../../../context/LocationContext'; import { createMemoryHistory } from 'history'; +import { MemoryRouter, RouteComponentProps } from 'react-router-dom'; + +const { location } = createMemoryHistory(); function Wrapper({ children }: { children?: ReactNode }) { - const { location } = createMemoryHistory(); return ( - + {children} - + ); } describe('Settings', () => { it('renders', async () => { + const routerProps = ({ + location, + } as unknown) as RouteComponentProps<{}>; expect(() => render( - +
, { wrapper: Wrapper } diff --git a/x-pack/plugins/apm/public/components/app/Settings/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/index.tsx index 9ed3a85fe68b5..aa71050802215 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/index.tsx @@ -4,25 +4,29 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { ReactNode } from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiPage, - EuiSideNav, - EuiPageSideBar, EuiPageBody, + EuiPageSideBar, + EuiSideNav, } from '@elastic/eui'; -import { HomeLink } from '../../shared/Links/apm/HomeLink'; -import { useLocation } from '../../../hooks/useLocation'; -import { getAPMHref } from '../../shared/Links/apm/APMLink'; +import { i18n } from '@kbn/i18n'; +import React, { ReactNode } from 'react'; +import { RouteComponentProps } from 'react-router-dom'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; +import { getAPMHref } from '../../shared/Links/apm/APMLink'; +import { HomeLink } from '../../shared/Links/apm/HomeLink'; + +interface SettingsProps extends RouteComponentProps<{}> { + children: ReactNode; +} -export function Settings(props: { children: ReactNode }) { +export function Settings({ children, location }: SettingsProps) { const { core } = useApmPluginContext(); const { basePath } = core.http; const canAccessML = !!core.application.capabilities.ml?.canAccessML; - const { search, pathname } = useLocation(); + const { search, pathname } = location; function getSettingsHref(path: string) { return getAPMHref({ basePath, path: `/settings${path}`, search }); @@ -94,7 +98,7 @@ export function Settings(props: { children: ReactNode }) { ]} /> - {props.children} + {children} ); diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx index bab31c9a460d0..614089c0457ac 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx @@ -18,7 +18,6 @@ import { useTrackPageview } from '../../../../../observability/public'; import { Projection } from '../../../../common/projections'; import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext'; import { FETCH_STATUS } from '../../../hooks/useFetcher'; -import { useLocation } from '../../../hooks/useLocation'; import { useTransactionCharts } from '../../../hooks/useTransactionCharts'; import { useTransactionDistribution } from '../../../hooks/useTransactionDistribution'; import { useUrlParams } from '../../../hooks/useUrlParams'; @@ -32,9 +31,11 @@ import { WaterfallWithSummmary } from './WaterfallWithSummmary'; type TransactionDetailsProps = RouteComponentProps<{ serviceName: string }>; -export function TransactionDetails({ match }: TransactionDetailsProps) { +export function TransactionDetails({ + location, + match, +}: TransactionDetailsProps) { const { serviceName } = match.params; - const location = useLocation(); const { urlParams } = useUrlParams(); const { data: distributionData, diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx index 544e2450fe5d9..3e32b0ec23b13 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx @@ -19,11 +19,11 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { Location } from 'history'; import { first } from 'lodash'; import React, { useMemo } from 'react'; +import { useLocation } from 'react-router-dom'; import { useTrackPageview } from '../../../../../observability/public'; import { Projection } from '../../../../common/projections'; import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext'; import { IUrlParams } from '../../../context/UrlParamsContext/types'; -import { useLocation } from '../../../hooks/useLocation'; import { useServiceTransactionTypes } from '../../../hooks/useServiceTransactionTypes'; import { useTransactionCharts } from '../../../hooks/useTransactionCharts'; import { useTransactionList } from '../../../hooks/useTransactionList'; diff --git a/x-pack/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx b/x-pack/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx index 01b1628504b3b..9de70d50b25e1 100644 --- a/x-pack/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx @@ -11,7 +11,6 @@ import { createMemoryHistory } from 'history'; import React, { ReactNode } from 'react'; import { Router } from 'react-router-dom'; import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; -import { LocationProvider } from '../../../../context/LocationContext'; import { UrlParamsContext, useUiFilters, @@ -46,11 +45,9 @@ function mountDatePicker(params?: IUrlParams) { return mount( - - - - - + + + ); diff --git a/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx b/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx index 7e5c789507e07..c3ecaa1b053b6 100644 --- a/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx @@ -8,13 +8,12 @@ import { EuiSelect } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { History } from 'history'; import React from 'react'; -import { useHistory, useParams } from 'react-router-dom'; +import { useHistory, useLocation, useParams } from 'react-router-dom'; import { ENVIRONMENT_ALL, ENVIRONMENT_NOT_DEFINED, } from '../../../../common/environment_filter_values'; import { useEnvironments } from '../../../hooks/useEnvironments'; -import { useLocation } from '../../../hooks/useLocation'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { fromQuery, toQuery } from '../Links/url_helpers'; diff --git a/x-pack/plugins/apm/public/components/shared/KueryBar/index.tsx b/x-pack/plugins/apm/public/components/shared/KueryBar/index.tsx index efd1446f21b21..157e014bee424 100644 --- a/x-pack/plugins/apm/public/components/shared/KueryBar/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/KueryBar/index.tsx @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { startsWith, uniqueId } from 'lodash'; import React, { useState } from 'react'; -import { useHistory, useParams } from 'react-router-dom'; +import { useHistory, useLocation, useParams } from 'react-router-dom'; import styled from 'styled-components'; import { esKuery, @@ -16,7 +16,6 @@ import { } from '../../../../../../../src/plugins/data/public'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; import { useDynamicIndexPattern } from '../../../hooks/useDynamicIndexPattern'; -import { useLocation } from '../../../hooks/useLocation'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { fromQuery, toQuery } from '../Links/url_helpers'; import { getBoolFilter } from './get_bool_filter'; diff --git a/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx index d4b20782a5527..93b5672aa54f9 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx @@ -8,11 +8,11 @@ import { EuiLink } from '@elastic/eui'; import { Location } from 'history'; import { IBasePath } from 'kibana/public'; import React from 'react'; +import { useLocation } from 'react-router-dom'; import rison, { RisonValue } from 'rison-node'; import url from 'url'; import { APM_STATIC_INDEX_PATTERN_ID } from '../../../../../../../../src/plugins/apm_oss/public'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; -import { useLocation } from '../../../../hooks/useLocation'; import { getTimepickerRisonData } from '../rison_helpers'; interface Props { diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx index 5e2d728716704..d8ec212515c6f 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx @@ -6,11 +6,11 @@ import { EuiLink } from '@elastic/eui'; import React from 'react'; -import url from 'url'; +import { useLocation } from 'react-router-dom'; import rison, { RisonValue } from 'rison-node'; -import { useLocation } from '../../../../hooks/useLocation'; -import { getTimepickerRisonData, TimepickerRisonData } from '../rison_helpers'; +import url from 'url'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; +import { getTimepickerRisonData, TimepickerRisonData } from '../rison_helpers'; interface MlRisonData { ml?: { diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts index 28daae7fd830e..66f3903ba849b 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts @@ -12,7 +12,7 @@ jest.mock('../../../../hooks/useApmPluginContext', () => ({ }), })); -jest.mock('../../../../hooks/useLocation', () => ({ +jest.mock('react-router-dom', () => ({ useLocation: () => ({ search: '?rangeFrom=2020-07-29T17:27:29.000Z&rangeTo=2020-07-29T18:45:00.000Z&refreshInterval=10000&refreshPaused=true', diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts index 459ee8f0282ff..3b60962d797ed 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import url from 'url'; import querystring from 'querystring'; +import { useLocation } from 'react-router-dom'; import rison from 'rison-node'; -import { useLocation } from '../../../../hooks/useLocation'; +import url from 'url'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; import { getTimepickerRisonData } from '../rison_helpers'; diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx index cde2471cc4ce3..bd43f2455c545 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx @@ -8,9 +8,9 @@ import { EuiLink, EuiLinkAnchorProps } from '@elastic/eui'; import { IBasePath } from 'kibana/public'; import { pick } from 'lodash'; import React from 'react'; +import { useLocation } from 'react-router-dom'; import url from 'url'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; -import { useLocation } from '../../../../hooks/useLocation'; import { APMQueryParams, fromQuery, toQuery } from '../url_helpers'; interface Props extends EuiLinkAnchorProps { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx index de77115ce90ee..e95122f54aff1 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx @@ -4,18 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { ErrorMetadata } from '..'; import { render } from '@testing-library/react'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { ErrorMetadata } from '..'; import { APMError } from '../../../../../../typings/es_schemas/ui/apm_error'; +import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, expectTextsNotInDocument, } from '../../../../../utils/testHelpers'; -import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} const renderOptions = { - wrapper: MockApmPluginContextWrapper, + wrapper: Wrapper, }; function getError() { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/__test__/SpanMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/__test__/SpanMetadata.test.tsx index f27a7ebb780e0..1f10d923e351e 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/__test__/SpanMetadata.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/__test__/SpanMetadata.test.tsx @@ -4,18 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; import { render } from '@testing-library/react'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { SpanMetadata } from '..'; import { Span } from '../../../../../../typings/es_schemas/ui/span'; +import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, expectTextsNotInDocument, } from '../../../../../utils/testHelpers'; -import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} const renderOptions = { - wrapper: MockApmPluginContextWrapper, + wrapper: Wrapper, }; describe('SpanMetadata', () => { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx index 0577dca852bcf..8359716fc6966 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx @@ -4,18 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { TransactionMetadata } from '..'; import { render } from '@testing-library/react'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { TransactionMetadata } from '..'; import { Transaction } from '../../../../../../typings/es_schemas/ui/transaction'; +import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, expectTextsNotInDocument, } from '../../../../../utils/testHelpers'; -import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} const renderOptions = { - wrapper: MockApmPluginContextWrapper, + wrapper: Wrapper, }; function getTransaction() { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx index 0b40c2a727fa3..8e53aa4aa1089 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx @@ -4,15 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; import { render } from '@testing-library/react'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { MetadataTable } from '..'; +import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument } from '../../../../utils/testHelpers'; import { SectionsWithRows } from '../helper'; -import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} const renderOptions = { - wrapper: MockApmPluginContextWrapper, + wrapper: Wrapper, }; describe('MetadataTable', () => { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx index a8990e70150d1..1d2ac4d18a2a7 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx @@ -16,8 +16,7 @@ import { import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import React, { useCallback } from 'react'; -import { useHistory } from 'react-router-dom'; -import { useLocation } from '../../../hooks/useLocation'; +import { useHistory, useLocation } from 'react-router-dom'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink'; import { HeightRetainer } from '../HeightRetainer'; diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx index 0f42d8f9beb46..62952d1fb501b 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx @@ -5,6 +5,7 @@ */ import { act, fireEvent, render } from '@testing-library/react'; import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { CustomLink } from '../../../../../common/custom_link/custom_link_types'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; @@ -12,7 +13,11 @@ import { expectTextsInDocument } from '../../../../utils/testHelpers'; import { CustomLinkPopover } from './CustomLinkPopover'; function Wrapper({ children }: { children?: ReactNode }) { - return {children}; + return ( + + {children} + + ); } describe('CustomLinkPopover', () => { diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/ManageCustomLink.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/ManageCustomLink.test.tsx index a2a2a211a48b1..29e93a47629b3 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/ManageCustomLink.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/ManageCustomLink.test.tsx @@ -4,17 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import { act, fireEvent, render } from '@testing-library/react'; import React, { ReactNode } from 'react'; -import { render, act, fireEvent } from '@testing-library/react'; -import { ManageCustomLink } from './ManageCustomLink'; +import { MemoryRouter } from 'react-router-dom'; +import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, expectTextsNotInDocument, } from '../../../../utils/testHelpers'; -import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; +import { ManageCustomLink } from './ManageCustomLink'; function Wrapper({ children }: { children?: ReactNode }) { - return {children}; + return ( + + {children} + + ); } describe('ManageCustomLink', () => { diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx index 055fcc0955c68..5abeae265dfa6 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx @@ -6,6 +6,7 @@ import { act, fireEvent, render } from '@testing-library/react'; import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { CustomLink } from '.'; import { CustomLink as CustomLinkType } from '../../../../../common/custom_link/custom_link_types'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; @@ -17,7 +18,11 @@ import { } from '../../../../utils/testHelpers'; function Wrapper({ children }: { children?: ReactNode }) { - return {children}; + return ( + + {children} + + ); } describe('Custom links', () => { diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx index c7ce83053db5c..4a548b44cf361 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx @@ -7,6 +7,7 @@ import { EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useMemo, useState } from 'react'; +import { useLocation } from 'react-router-dom'; import { ActionMenu, ActionMenuDivider, @@ -21,7 +22,6 @@ import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; import { useFetcher } from '../../../hooks/useFetcher'; import { useLicense } from '../../../hooks/useLicense'; -import { useLocation } from '../../../hooks/useLocation'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { CustomLinkFlyout } from '../../app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout'; import { convertFiltersToQuery } from '../../app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper'; diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx index e45df2feff771..ec0b473c3ade8 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx @@ -6,6 +6,7 @@ import { act, fireEvent, render } from '@testing-library/react'; import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { License } from '../../../../../../licensing/common/license'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; @@ -19,13 +20,19 @@ import { import { TransactionActionMenu } from '../TransactionActionMenu'; import * as Transactions from './mockData'; +function Wrapper({ children }: { children?: React.ReactNode }) { + return ( + + {children} + + ); +} + const renderTransaction = async (transaction: Record) => { const rendered = render( , { - wrapper: ({ children }: { children?: React.ReactNode }) => ( - {children} - ), + wrapper: Wrapper, } ); @@ -246,14 +253,11 @@ describe('TransactionActionMenu component', () => { function renderTransactionActionMenuWithLicense(license: License) { return render( - - - - + + , + { wrapper: Wrapper } ); } it('doesnt show custom links when license is not valid', () => { @@ -286,14 +290,11 @@ describe('TransactionActionMenu component', () => { }); const component = render( - - - - + + , + { wrapper: Wrapper } ); act(() => { fireEvent.click(component.getByText('Actions')); diff --git a/x-pack/plugins/apm/public/components/shared/charts/Timeline/Marker/ErrorMarker.test.tsx b/x-pack/plugins/apm/public/components/shared/charts/Timeline/Marker/ErrorMarker.test.tsx index 6a5ab344d2ba0..abe81185635b5 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/Timeline/Marker/ErrorMarker.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/Timeline/Marker/ErrorMarker.test.tsx @@ -7,6 +7,7 @@ import { fireEvent } from '@testing-library/react'; import { act } from '@testing-library/react-hooks'; import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, @@ -16,7 +17,11 @@ import { ErrorMark } from '../../../../app/TransactionDetails/WaterfallWithSummm import { ErrorMarker } from './ErrorMarker'; function Wrapper({ children }: { children?: ReactNode }) { - return {children}; + return ( + + {children} + + ); } describe('ErrorMarker', () => { diff --git a/x-pack/plugins/apm/public/context/LocationContext.tsx b/x-pack/plugins/apm/public/context/LocationContext.tsx deleted file mode 100644 index 1e9c20494b42e..0000000000000 --- a/x-pack/plugins/apm/public/context/LocationContext.tsx +++ /dev/null @@ -1,18 +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 { Location } from 'history'; -import React, { createContext } from 'react'; -import { withRouter } from 'react-router-dom'; - -const initialLocation = {} as Location; - -const LocationContext = createContext(initialLocation); -const LocationProvider = withRouter(({ location, children }) => { - return ; -}); - -export { LocationContext, LocationProvider }; diff --git a/x-pack/plugins/apm/public/hooks/useLocation.tsx b/x-pack/plugins/apm/public/hooks/useLocation.tsx deleted file mode 100644 index e2b4e3e479629..0000000000000 --- a/x-pack/plugins/apm/public/hooks/useLocation.tsx +++ /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 { useContext } from 'react'; -import { LocationContext } from '../context/LocationContext'; - -export function useLocation() { - return useContext(LocationContext); -} diff --git a/x-pack/plugins/apm/public/utils/testHelpers.tsx b/x-pack/plugins/apm/public/utils/testHelpers.tsx index 037da01c74464..a69288f7bd4f9 100644 --- a/x-pack/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/plugins/apm/public/utils/testHelpers.tsx @@ -16,7 +16,6 @@ import { render, waitForElement } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { APMConfig } from '../../server'; -import { LocationProvider } from '../context/LocationContext'; import { PromiseReturnType } from '../../typings/common'; import { EuiThemeProvider } from '../../../observability/public'; import { @@ -68,9 +67,7 @@ export async function getRenderedHref(Component: React.FC, location: Location) { const el = render( - - - + ); From 948fad0b567bf951316bcf3b5569760f9769ea53 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Tue, 15 Sep 2020 08:13:20 +0100 Subject: [PATCH 08/26] [APM-UI][E2E] filter PRs from the uptime GH team (#77359) --- .ci/end2end.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/end2end.groovy b/.ci/end2end.groovy index 0d9f5c9d92453..025836a90204c 100644 --- a/.ci/end2end.groovy +++ b/.ci/end2end.groovy @@ -41,7 +41,7 @@ pipeline { // Filter when to run based on the below reasons: // - On a PRs when: // - There are changes related to the APM UI project - // - only when the owners of those changes are members of the apm-ui team (new filter) + // - only when the owners of those changes are members of the given GitHub teams // - On merges to branches when: // - There are changes related to the APM UI project // - FORCE parameter is set to true. @@ -51,7 +51,7 @@ pipeline { apm_updated = isGitRegionMatch(patterns: [ "^x-pack/plugins/apm/.*" ]) } if (isPR()) { - def isMember = isMemberOf(user: env.CHANGE_AUTHOR, team: 'apm-ui') + def isMember = isMemberOf(user: env.CHANGE_AUTHOR, team: ['apm-ui', 'uptime']) setEnvVar('RUN_APM_E2E', params.FORCE || (apm_updated && isMember)) } else { setEnvVar('RUN_APM_E2E', params.FORCE || apm_updated) From 37b9c81f173e1ce76590c5107aff6eaa49cce792 Mon Sep 17 00:00:00 2001 From: Sonja Krause-Harder Date: Tue, 15 Sep 2020 09:46:12 +0200 Subject: [PATCH 09/26] [Ingest Manager] Add route for package installation by upload (#77044) * Add route to accept a direct package upload. * Only accept application/zip or application/gzip * Use better name for response containing only a message. * Add integration test for direct package upload. --- .../ingest_manager/common/constants/routes.ts | 3 +- .../ingest_manager/common/services/routes.ts | 5 +- .../common/types/rest_spec/epm.ts | 4 ++ .../server/routes/epm/handlers.ts | 21 +++++-- .../ingest_manager/server/routes/epm/index.ts | 30 ++++++++-- .../server/types/rest_spec/epm.ts | 6 +- .../apis/epm/index.js | 1 + .../apis/epm/install_by_upload.ts | 55 ++++++++++++++++++ .../apache_0.1.4.tar.gz | Bin 0 -> 581243 bytes 9 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 x-pack/test/ingest_manager_api_integration/apis/epm/install_by_upload.ts create mode 100644 x-pack/test/ingest_manager_api_integration/apis/fixtures/direct_upload_packages/apache_0.1.4.tar.gz diff --git a/x-pack/plugins/ingest_manager/common/constants/routes.ts b/x-pack/plugins/ingest_manager/common/constants/routes.ts index 551a0f7d60164..3e065142ea101 100644 --- a/x-pack/plugins/ingest_manager/common/constants/routes.ts +++ b/x-pack/plugins/ingest_manager/common/constants/routes.ts @@ -21,7 +21,8 @@ export const EPM_API_ROUTES = { LIST_PATTERN: EPM_PACKAGES_MANY, LIMITED_LIST_PATTERN: `${EPM_PACKAGES_MANY}/limited`, INFO_PATTERN: EPM_PACKAGES_ONE, - INSTALL_PATTERN: EPM_PACKAGES_ONE, + INSTALL_FROM_REGISTRY_PATTERN: EPM_PACKAGES_ONE, + INSTALL_BY_UPLOAD_PATTERN: EPM_PACKAGES_MANY, DELETE_PATTERN: EPM_PACKAGES_ONE, FILEPATH_PATTERN: `${EPM_PACKAGES_FILE}/{filePath*}`, CATEGORIES_PATTERN: `${EPM_API_ROOT}/categories`, diff --git a/x-pack/plugins/ingest_manager/common/services/routes.ts b/x-pack/plugins/ingest_manager/common/services/routes.ts index 1d802739a1b86..b7521f95b4f83 100644 --- a/x-pack/plugins/ingest_manager/common/services/routes.ts +++ b/x-pack/plugins/ingest_manager/common/services/routes.ts @@ -40,7 +40,10 @@ export const epmRouteService = { }, getInstallPath: (pkgkey: string) => { - return EPM_API_ROUTES.INSTALL_PATTERN.replace('{pkgkey}', pkgkey).replace(/\/$/, ''); // trim trailing slash + return EPM_API_ROUTES.INSTALL_FROM_REGISTRY_PATTERN.replace('{pkgkey}', pkgkey).replace( + /\/$/, + '' + ); // trim trailing slash }, getRemovePath: (pkgkey: string) => { diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts index 5fb718f91b876..54e767fee4b22 100644 --- a/x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts @@ -71,6 +71,10 @@ export interface InstallPackageResponse { response: AssetReference[]; } +export interface MessageResponse { + response: string; +} + export interface DeletePackageRequest { params: { pkgkey: string; diff --git a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts index 385e256933c12..c40e0e4ac5c0b 100644 --- a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts @@ -9,6 +9,7 @@ import { appContextService } from '../../services'; import { GetInfoResponse, InstallPackageResponse, + MessageResponse, DeletePackageResponse, GetCategoriesResponse, GetPackagesResponse, @@ -19,7 +20,8 @@ import { GetPackagesRequestSchema, GetFileRequestSchema, GetInfoRequestSchema, - InstallPackageRequestSchema, + InstallPackageFromRegistryRequestSchema, + InstallPackageByUploadRequestSchema, DeletePackageRequestSchema, } from '../../types'; import { @@ -129,10 +131,10 @@ export const getInfoHandler: RequestHandler, +export const installPackageFromRegistryHandler: RequestHandler< + TypeOf, undefined, - TypeOf + TypeOf > = async (context, request, response) => { const logger = appContextService.getLogger(); const savedObjectsClient = context.core.savedObjects.client; @@ -183,6 +185,17 @@ export const installPackageHandler: RequestHandler< } }; +export const installPackageByUploadHandler: RequestHandler< + undefined, + undefined, + TypeOf +> = async (context, request, response) => { + const body: MessageResponse = { + response: 'package upload was received ok, but not installed (not implemented yet)', + }; + return response.ok({ body }); +}; + export const deletePackageHandler: RequestHandler> = async (context, request, response) => { diff --git a/x-pack/plugins/ingest_manager/server/routes/epm/index.ts b/x-pack/plugins/ingest_manager/server/routes/epm/index.ts index b524a7b33923e..9048652f0e8a9 100644 --- a/x-pack/plugins/ingest_manager/server/routes/epm/index.ts +++ b/x-pack/plugins/ingest_manager/server/routes/epm/index.ts @@ -11,7 +11,8 @@ import { getLimitedListHandler, getFileHandler, getInfoHandler, - installPackageHandler, + installPackageFromRegistryHandler, + installPackageByUploadHandler, deletePackageHandler, } from './handlers'; import { @@ -19,10 +20,13 @@ import { GetPackagesRequestSchema, GetFileRequestSchema, GetInfoRequestSchema, - InstallPackageRequestSchema, + InstallPackageFromRegistryRequestSchema, + InstallPackageByUploadRequestSchema, DeletePackageRequestSchema, } from '../../types'; +const MAX_FILE_SIZE_BYTES = 104857600; // 100MB + export const registerRoutes = (router: IRouter) => { router.get( { @@ -71,11 +75,27 @@ export const registerRoutes = (router: IRouter) => { router.post( { - path: EPM_API_ROUTES.INSTALL_PATTERN, - validate: InstallPackageRequestSchema, + path: EPM_API_ROUTES.INSTALL_FROM_REGISTRY_PATTERN, + validate: InstallPackageFromRegistryRequestSchema, options: { tags: [`access:${PLUGIN_ID}-all`] }, }, - installPackageHandler + installPackageFromRegistryHandler + ); + + router.post( + { + path: EPM_API_ROUTES.INSTALL_BY_UPLOAD_PATTERN, + validate: InstallPackageByUploadRequestSchema, + options: { + tags: [`access:${PLUGIN_ID}-all`], + body: { + accepts: ['application/gzip', 'application/zip'], + parse: false, + maxBytes: MAX_FILE_SIZE_BYTES, + }, + }, + }, + installPackageByUploadHandler ); router.delete( diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts b/x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts index 191014606f220..d7a801feec34f 100644 --- a/x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts +++ b/x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts @@ -32,7 +32,7 @@ export const GetInfoRequestSchema = { }), }; -export const InstallPackageRequestSchema = { +export const InstallPackageFromRegistryRequestSchema = { params: schema.object({ pkgkey: schema.string(), }), @@ -43,6 +43,10 @@ export const InstallPackageRequestSchema = { ), }; +export const InstallPackageByUploadRequestSchema = { + body: schema.buffer(), +}; + export const DeletePackageRequestSchema = { params: schema.object({ pkgkey: schema.string(), diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/index.js b/x-pack/test/ingest_manager_api_integration/apis/epm/index.js index 8555814245909..28743ee5f43c2 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/index.js +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/index.js @@ -11,6 +11,7 @@ export default function loadTests({ loadTestFile }) { loadTestFile(require.resolve('./file')); //loadTestFile(require.resolve('./template')); loadTestFile(require.resolve('./ilm')); + loadTestFile(require.resolve('./install_by_upload')); loadTestFile(require.resolve('./install_overrides')); loadTestFile(require.resolve('./install_prerelease')); loadTestFile(require.resolve('./install_remove_assets')); diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/install_by_upload.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/install_by_upload.ts new file mode 100644 index 0000000000000..e6d2affaec0cd --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/install_by_upload.ts @@ -0,0 +1,55 @@ +/* + * 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 fs from 'fs'; +import path from 'path'; +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { warnAndSkipTest } from '../../helpers'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const dockerServers = getService('dockerServers'); + const log = getService('log'); + + const testPkgArchiveTgz = path.join( + path.dirname(__filename), + '../fixtures/direct_upload_packages/apache_0.1.4.tar.gz' + ); + const testPkgKey = 'apache-0.14'; + const server = dockerServers.get('registry'); + + const deletePackage = async (pkgkey: string) => { + await supertest.delete(`/api/ingest_manager/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx'); + }; + + describe('installs packages from direct upload', async () => { + after(async () => { + if (server.enabled) { + // remove the package just in case it being installed will affect other tests + await deletePackage(testPkgKey); + } + }); + + it('should install a tar archive correctly', async function () { + if (server.enabled) { + const buf = fs.readFileSync(testPkgArchiveTgz); + const res = await supertest + .post(`/api/ingest_manager/epm/packages`) + .set('kbn-xsrf', 'xxxx') + .type('application/gzip') + .send(buf) + .expect(200); + expect(res.body.response).to.equal( + 'package upload was received ok, but not installed (not implemented yet)' + ); + } else { + warnAndSkipTest(this, log); + } + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/direct_upload_packages/apache_0.1.4.tar.gz b/x-pack/test/ingest_manager_api_integration/apis/fixtures/direct_upload_packages/apache_0.1.4.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..cc983f6ac6d1aa53ac1b4a5b38b020a072a2326a GIT binary patch literal 581243 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%0ACAy_3eJxwA35lM)JU2ERw^}4Wy*eM<@tx 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%0AE0$ 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 ^aNduwIe@y2-d=s3M>P$b1}bBx5zNbNecrrOas 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

-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�X1tA0YJY;4?XSwizFjpS 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�_wgl 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

pj=-ikxap8#+=D23dL7w2_xPmWv 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≶B3jEBYi! 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 fCqISJ$`)ZU5g>jdN>37)(H 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�r;j5BFYFZ$B75mPbrGxxsaGBNip8Ei1mFL}C)4;iXY zx2tt*-=E%5Iqcr>z4gXZ3(Ia>4WVnf^lDp8SSzIcD{u`s1Hsd$Zv}+=L&}94;{xAT zv9vW{#)He#g$aQW;ejFW$&WGPf~bcFfm{67Lx&VRl;80&2J>7>D(Ki9Y|v=Z<3scd zVMcg=yKkW&YY{tr+|jDGC{=VqyJdn$OJ3_;($-Yl{REq77GbQtDs0g`#ua`x^TVa? z;z+2h7B1>nd{TEa%cZ*FouRI?YPMT-bK&M$dv&VD{LW5hMOKCL!3cP*f#2QyomMt3 z_tpDBhrM~~HCFtTn8H@ksx-h4a%|8%9sbJ�hDTo=v*`(fx05&Yw^;cZkL zQp5T%A0A~fYtY$>Ob0sLcbvvs{h-1oXDU@(rXyK~3Hb^&%Y&z&pkXl|fLPBGM8f?3 zIHbRGe%+2rFe)>%9x{zgr(lp^)Z*?XHGzsoHsAZsCv?PE*gW)^EK`E6?hdAk*YgIf zaRot#(+Dm-y)JBEwM_0=daT0xX@Hw$f_Po>0rkLbr?#WO`3B*bm;7jp#r}g>$T98o zw6vY?Sztf0#a(`iVPnfHtzlxEzI&VKfrAZ=!zVs?Oz0E{>DKRF`lpU#DwswSmCrg^ zsH`9$edcg@PYa3ax^H%-k&j)PH9(HqpPD57)6VP{l$>on-~gFUOrX80+eCs)J9a8Z zMLHT!1eo+q_5-#ycRs-}1N7Nf_ZOgi@2iWojn23fUPL@!8e%zJE(+jfZZ?HA_NSNq zYbuSTM|*_cx<)(2Op}2QR;cU2zBn3cV`I`ENZ3AL-l@JBu@d*QJ3@l&T{N%FRFKzB z#YEV6P%!TX&%E?pMtWDCa2LpRUAW|f)iNde?IXM~+bE0gKb}iS@;DI~b&3fBQ)Hd+0UHwRP49Qno)M6@VOl&(K zN5lg{ycXF`T;I}DKS8uE<~U#Wso6=%w4sbtjMD1z*GT?9hLKL148m&L&K z$MjB!h`6VFeo@_mb5geGS&f^n-8uGy)jy!lOUe0caUZZhMxy#L;Xq^q2_W;z1a5c) z)XD}`_hFTh^)wUsU9i`6a?5APckl2cuyJ~l43WtC_D=K7oEbFgddn;I?=5ym2Q_{L z6;{0)45|oK`(%t)usc!6 z!jbo(j}{ev288HbjT~Lz7#^JPoY&d5#UjM>+tW+bV9 z@h`~$%Xq%^7@-Mov!GO%8DnW4Y2tE%1C?1DPt}l&b!|9ary@ec@I{mAG^GfAW87Zz zzuJla&}@dZkrYUg4-&!QHX6wCT+l;TiV6&GHyRvyZo$)FAw@tM64K}U(g8fH57M}U zT5~j^nGcMaE4wazY^NhILo^$GAbooIK3ZI-17t$K4Oai`Tcr0bGf-K7+?8II??5** z*-v%SWq7%{_F5S^PxqhaVOW>O60V-BKq*d!o9kMjyHN8R+6ZqCWKQuuRs9Xejrw^z z6L_thFjrxkye*wLXtG|5W>jiEm&-_NSN_rgEodyJDI4t7LuRg(xmqN7*gD4o?BsPQ z!uI-@W&P)GzH&;Ny1231@Xi?aEGdyaGb4Od58oIs61+MkU!6x&n|GCdWPJ7;Nqq63 zzJ8{Xj`K|a%>`=^$PuUNc^?3_@LphfcYfNkX{gFU*~0cNll}c|e;_kj-gYjADoN(D zYSUzBW)EhW(of~`5{V4ytY-H1`^B4_ZD#w^kEgdGFnnVnB8Kn5gsOn5E>C}WY+XK^ znoatI8639mQ}^@A<%o{4$z|7; z(BagzQp=Lwu076JXAe}!s4IR~OVeUwk*lNVgk=Y!VQ2xjY-s2ZnX`MQRG&m2)e3Ma zu*H6jmeO$&=_N_cGq9*Y9z!Z0udXhTN_3}2)0*dnB1oz-?=X|U$Lgl-J!1yN3F zMfU--KpDYXwr7};An#ScGw~{JPTHN})A&^san7MHBg*ot6RLDtRWv5BXWhN|$(q|j zGl(B&lU&4PD4#v90zq>crqsj5&_{XuK$|iuJZyi@O;Z>3mYJ3a$KQl98T@PEUP%>| zXNlqg&pNS%flKjR!A9NK4*{@oz?J_DE75^L@9%j7UsX@3A1M>3SqCS50x(%%2V#Xc zE#O{(Y0u5gdPtAIDsE1zDPbwhtIdPoac1~E+X>i2$rcFDT$`vv61@_=EF{(Xh^$rLmYRlK=yGVjU;f=^?g?_5yPYge0CxM1`P3xqt zk*>UoV^wt`&$X4i|7w2h>+r@-i#q5fP$Duay(+qW|2dVRtNM#4GisWaYsL*GxovT=Uod~aSAv`Eq&|8BMO4)_4y4g^nD0_06r8?5Zv!x_ZA}Q!v=ua z2VVl0C|fhJbbd7wLLr-3VNt4Nz@?-epzjzgr{s+`d@QD{SpY>W_LKq9XESI-+ zVA|dD+*PlG8@38G!vKl+`;W4^Fu5I%Y!qhWzjav5aPwP%U`SS27R*uEyam4j8*(}L z^u9v;fQo6U0a$hiqckoVD@#{w5YbNj&~NOZS{i8^alEC*O%;V!IBM&mkiV@%PF+4*c@X+0fmZtqCzhjX;Z&vEd?n~r%-dyw|m zwxyF}I;l-UeXDBb6f?4^i~0l8PI@VbLZXubibj*Kr13KUwV#%tO4lYq3DH7c$wMhMOyCy;qHf+#s(o7FP$7u#pL)Nt;HyB-68AK3#} zks2G|YCIc)Ri19vHrqH8A7?xz*4pjuC>)nIA7|PjoU3P>n=fSwJsqkM8Cn0zPd@=t zdd!6tC1Yoj1CZys=&&t|#beGzP)OJ*WP(_@LL&EUYVMgQW7jwLop8?&Hv&)lyYkPc zqm4^b9cK;~(0H5V9*xRw*=y1`s9mn0>>r1DK1~lhOe?kTogD{*r&3*euP2m zKM|hU_&JBU3U~6Q(`j+E*NIXgvIrF)3!I%_4{Y8&58!Yiz8EV78EU5SQ2>tkZ-doS z1>-H^|A8X)@blSV7@eQ@35Bq4m~JD~-Yo~I9@)PU=8+$oq8e!UT-xa96I044j>m^vLTt^nq?-X9_$wPmw0kHS zOe+tZ#9->gxsj!Vo`OzGh!)nGE8a5E6a=|@8S-D4tJ}yBfK&g*7&Es08`QL zWfuno7Th-s=Ay8l5v@m{lCaZ#EzeNQ-*Z1>Yeur|ye>4q6&;~uvR@to99mAj%+1da z(I1ky$KPaKI4AV~12lbYe%jIm&6g9%8jf>`Dmxfw*q8xTLvqxzCF0p0CTKw;V&g(N9({}MO^+t%q= z-SQ;E!O%chn7o2-^Gr%(F(bqbqRRs3)vNOt<5(qdy*VK>XvnFN_a!r8kt4Sw_4UU` zwsBx$+t5fk&yGQqKBNEH+h-Oa@3sBsM+FLcQ;F{JM%m0#j9|0JyyF2JETyf5_5=6k zjWhHYSeAhB-^|~~$|$)hFh_O!r^I+t$RHe$fx@)0h2w7ijk${nj`seJ-Q@?Js}wuR z;_=&SHz!0_nAzQ?#0?I1OcX-z;Sl5P1olM+TwE}F+u%M?HhUW=Bw1F&25}xTa%yUw z=q}|&p2xX+X94_Q&fFFRIQ(`^7@D6CDY(X89eyd8 z(Fk81qL?p6%A0Z!h$_FJK$C8q>cv_ke3KFu5DNp>{6N5*pSE3h?e7xE zzoUoLo?>d*K!T8aKMidh;`$fWsDO;e>D=)bAj3Yrd_!O*e)Bx;72j?cnEI*i&Yj)k z^mc~Y;$*q_0Nl`k!nC<7`cgFibDnI9<`62&-Os%|@c2;KR+IGn*eWm24kZ0|Jn$9? z-_3aQS#lxazr%sGq?KR#%Cvih2 zpT0h!)8%^T?yepg(8Q&lzCOLhGM$i+&@$Z3-HKxnEM3qWBL-T?+Tmcql3=Hm1P*|lKQ_#xxEK~go4sV?E(e?;g&F`L(5q@%LULeQ^o!5 z&z!SA3zplVRO~-w7X>e2?@Ab-m>9S}nL|KDJt9+;lY=jkO7#mxA~ge6QB_5c5Xs-; zV*R^8ThO<`>Z+ZIU;hlB7(Qv~NTsrx8oK9~7u|^z`m}FF0kp(!r6{-yqMSRcQO8XFZVifE*tm==1Xv_G|rrLKp)$s7gGj^q<+x=L$h?SJ~8* z92T3S0A-5Chdj2tt7}t!`}*1j8kc9ib{ghy*H#ho-ISlHFcSYGba9F3%;w1|e@y|W zAoiZiKxiY8NZClaS@TX=|4&1FzMFD$Hb#_xHYCXb)TE@KA)}z=wzXkMOG~c?Jeif~ zo0(ArbH3Va)SD3T0dHh~8?3(67M;NVM-qm^qtog6Rsx6p_tz(a9*C=UWluWR|3
      )YB5qARSzrpsw5ObaveCg0p{@Vpl1bjE+lAbAM5;fJw0m+P+ zjwL^!Hr=4I4;C7^eP0nRHX0zxSq^gh<{x!7CXYU?H~Yu6vDx-k%4leW_zTg8@+w^n zFD0MX=5Y0uJu&MQ?fFh~OCqz@E-Tw~I2R8c4LL2`Hxs5W6`U={9jPA=uuapKtWL*O z8nC9jy08{3r?jb^j;#9o9ysOX=KN_9EorLTMa?stqt)*kTReBx=PtKDUO!w6H^G)S z7tP~{w6&XX&lauwiZ+6G&Kj*djd4xCJRAJWO9}JMpB@%OvmiL)@b?J**J*$6wwIfh zysznbCe7a{i;~G!JxflPArh9FZEq%b4_uxDWota1_|G@rnX|kP8L`Zr!!`){92ab{ zO3S$WQ^|YVue^LO;v%ufmGZ2v16{U@>tk@{n=DexVRh84@KSwO2^G zjr)E&zSt)GLZ23zy^yJQ_#kyTO82~gUCIPbDU*;_^a8eQmq^%tAl(`OGryHfYKE}x zzUNR%ax9*8@X|VW+~l$HaiV5P(}7!}4j|Ozj+)1@t`Bi^`2cg-og5sY=7>;);u*~U z+Sq*Qnbv_^<#yMOY`k1`!{zpWv6P&>XzP0Y&B(95{2T6n9i0IQ#LYnZaq}Mlm?!9Q#3vC!P6 z;E=6LvjO?+t_+@)4IP1ix=ecu)w2_ka?v}Q;3wO6Vi5uIsG+=zXPr-lib-mpLRp3~ zCo93y!XLrSmBXhSh2Y69`hE%1Y8C1&@OR1_?W+F6kHWZN-?(8li`PR+k6I5(Cu~NYta^8@aY>z-| zR@5FW?r-9;pL_>i6WQH>Ez8YNVAoKb7{uUJzsTqPI~0W=F06VXJk5j2Ls-imS5X9?cA>;Ic3-Pf7!t_^$ zGRZ`6p-(VR=YztwNiE6nHQ?-TL^>W_ae^YyLcWp44c|5C?aU^sv=ZY+?kLd8o77GU zP=PN}Yeou}v*;Pu{_I-6g;%e|Y^R_u;YkTMOn+S2P3&;uG#31J-rfwwQfjHOlHADuH|;tc7z_1KFw~Nsawtyei7m~=#RRMG zAqVbmb2aulMy=O0uO;eTFvJkT+NI% z9>XhJqr0_6`uT@v`~4HlGO;amJlnkCK)tovo?VyHFdXFI6DHJe9WGz$@XxsiEo%dtBidPm~)p&+&hj5dhZL8dQy?3kjhi6OVU{UUmLJ5|e zrw2S{oxHe7Z+EPA-kU1m1&@`(aWCODF6s!-P3Fao-b(u8b%iQ*l`2(do;Erw1RiY! zPedP`j9C!h@vna${;00T@w{Tng3!now(wlrWA6=RW&Pi6T23&c-1Me{3_ya_Qp9uK z#9&li;GtF_L8*1^ZeB;5pO9fFQZUYyl;{1~9l~;GYH~~elNA(=$%+awV(n(AqcDwF zZn9V4muSIGM(B;6;ywE!#aZ|*jLUofm5w+@&`xMCUFw9~A(kTO@C>an)_1XI=PlLp zkFo9-|1X`H8E_3cY9vuq?=V*T1v)kmzjJH)M0dRE8E{9pCxyYAB&(Amxa-AT!DCiC zvN(YcB2AqSPHUZB9^MG7%qW{o)!B-HcG?M1@q03j7^DDe9uFu?bF-VBbSQbmF%2D>Z;m%*4p(8^K2X40<@!(cCMCukh|W~i&zSWh)I!@sK)e7%1~}QYDW$-JFK)L zpnK_lwq23`=v~=uze(68Ay98Y+G*simJm&l*bgQ}`tjGz-B^DLCwz$k5n6ZPvMJ%p=3niTnu^I+bzD%F~mRxKb7m{@{e-#U8}2xv8m>$#LLWfBnxojmt0T$QjK& zzsrE@+ujq=UhG5cR%Unao+2#IQv>eRK@Vj)5s)Z*vFNq%B+TI)rhd}k)H548oRbl{ zCBP2=%iKG3FFQTHowkMjk0RVs z=wg-!AMR7-q&YJ<-4WejsWhxY?^}OMU2Ta-U#AM4n8!{1AUeHaIQ6mqa3xJULL!J{ zv%fzw-Klny>b=zd+peE{Ew1DRvb|!v=rY>MVscZIg3i&0c>7&!%fZ24%*5DKvF6eg zZ`SR%x*n2r#GAIJn2$dN$I~jf;E;xesF6-3ypxA5#ZweI*A)<5>d{zbWu-b){ zx;E@g?$T{sPHQ(WzfcN4rkI6?zF$jH^|-$L;O<#(l0dFG{RqeG)4<8;CfyH}tXRF3 z6}#Ak_%XWA$QWdtWW+IYzk%zSt}`j$+H3T=as`Pi7E@?lA7xN)Olb0o{d?UrNmVU2 zB*_}-cGJ`MzH#I;mF)UBB)8v`u&nDPE(28MN?a83!FaDL<;Fd@`xfqg1@s(evf!23 zo#q|ZA@tKcj?U?oX{@2*ScpeP48&~W?5kyBUNp*igPiFrpXuIs8S3~1ku5iw-?|w7 zXl#y~@v4Iop>^VFqUcaLPU==m$$yCw`Avr(`-!ppNgIXfY*y&J(R6=jbBZ+Ec>Kvctk2TUoQtW9QYrNexl{0U`Cp zY~!`gdI6I!Gy9BB@m6<2dJ?b(Q}4)e*Qm}WG%b?U!ME9E$f;6XpRw1PU5WY`$EI4c z@Jl6!XZUdHW3K5*a<=&Wo5)_d?WUu0?1{u^(0eN}sc? zylj`gaDF-^oNSr2m!1cBF6lT?Abmau-=16-u;*qr@$Ae%n(X&G4jTZ92= zu!_p(fIkJOiBaL!9Z_X@0d;Q&&X(+UFhfok$a3}73B zPsvGhpr8>@;DqH z>i#_x^FM!DS0sPU=q6mvDqp}7B`n9~?~m34bMJ5!EDGVh+viv(7T27W`d;|ECDto< z9f$&bky%-+f7#~x@JG4FqqcDl(@lYab{3r^_V(M9G#tE8kK#7KPQ?P!p|}@eiB(zC zj|A7W5(X^@R2EwBF6tv6ZV%e}?vSr@v3>3ElkNZ-e%_zHVO=xI<3|Swo01$^g%j&g zUW_tol9%Wwb2|95%0_iZu>p%GT@LuA0f}n_O@Y#rUNo7gH<^8i(q#{y-GcB#t01?X@{Mmp*n17a0+T2Iyi` zd#BH4qpxSr_I}-iu}4}MKywthlU2PDXXlH;vsfYLlU)HyGK^_RCu?fU>iZg8CTV-= z$}=4Og;v(|qT2<7+!viDoqgy#)@C{PaE@>>y z5@Y9XMN^d7z?JzcR3;33wo|F|j+pOKjY6zn&)3K76H?3sN#ZYpP3k5AgqA^6Lq0Ag zd;$a8xCROlW#ubA27+=s9UzaI6%h;eFiWbNwWmJwYMD;`?&PZyE~vi#K)`Z}4m#BG zff(WT4@m390Xi;-0ABOGiNB2^6TlBOPf7ji-UM@~GyibkBf`p@&_A3syQsB_y*+C{ zQBPN7Tva_&%<&h~D-^`Vx@psUm|f{OXRxVx`TX$~AlZT@t~}Lziy_ zbEQjv`vVGxZxUwxulmI`v5oSsl{xiIw-y0o9kg7n=cGcpB4`AS9BVh1!xY`B7!b*X zOr_Tmrs7rZX^-ewWut1HDxg*^6+bLaKj4OhMivF0o23#h$QD=xexY&gdh3&=Vn{WNdCL7A)Cjmb~hb|(NLd?7$d&Ilvyu-JkP5iW) z{Tv*s9$p}uQ{euJhRD@Cg%*HcJidr7a*Hx(RB}@Q@TG_yro9Fm7bOQlfh$w4aNph2SW3Hv} z!}#LLwbFZb%(vb7w9&&hB^rT~^|b{rs13>_y?&2+CdMLr-Eg}PyeQwd@i|ybx>Iv} zs%Gtf8MG`aBO23Li}|Sm_uOUA`Q~6P{z(KeQI#a5liCSkFA3zj`5JKe5zQP;99>m3 zkT#2c=zY8ICJ5|0zwUD|#0F_9D5C(K`(U?Njgbp-%eUpF`lDOZ0UJ;Dr`Bj`4YM{~ z8P{HT0%>TY)mqSA?{7s;m&~KPd9lR4+rG=%lp{-8D0nI?wtYm=)0>T#eM}hw%F&d#3g@}Xl*WL`teW1rceZY@yw`V0)=#)& zANR*)p46Ft17Pkt6(RE@g`#x_sRcfBV{l8f`1{Q^E(c!UoWF+AbzQ^?0lpVx83_{W zXnKxQS^b!qin5eY5AFsEugA^t>A=rCOxl&cS-WZrqMz-9HA$KK2H(X;K^ed6PkeD0 z^)y?SKE07OksqMs>Kj_8Zdpuax z7`3x;Db-8kahkFBpXrlFU^>_dI|GF^^<3QE&Fz|9#`Z2lVzo;Q8QF8Vln&rrW~(-! z-8#55PUivD z5uAK4rkYoj@7+{41G>uVQ6Ez(F0Zql2X7%`?%)GEb*6nM_FR#lZA85Rn}iwxsgAng zgZ*=jdWmCsI)se|(F7H;&S#Z^oU9F;``|*P;2C?&4 z_WX?NgSx)r2Ak%Y)mXqQlYjj>6PrQYq)Els(Tm827WUqBp{{djwljS&f!xVF=xCz4 z+LH13`($q)-<_)H4l^p$_lc>pJlVTW=bq&;>jh*zhaV#xRx&?c8m7HZU`xdmmuEqnGJ@vMsY{ zIm^*bOq8h;wUBg5#6Hlc%HA;GDjIQC0|7AD-~Du&q_3;lUkJyw28W^bj5)j#J zFF!2av%L*<-86#it}yxDC+fNf6b!JwoHf5ka_+KK)=WU6i|hYWgU~ME4b~0PH8P)+ zi7H=?gb;zc{~Y#Yi2Ct--)PuZ<$l1N7C}ae*(lE|aa4iw8$>N9dd+z6tDOF9`Bm+$ z`xrgavd+v#x41O@1geTeEgi8%SQin_<-6ZiB@$MreE&8+OGZz+@>F? zM*ZGn+wAK>XXnLXE9{&Zso+gRq$*mcSdC*HRy0Cpl!SxoOnaV>rR_MrP}Yejcr2OI z)YiiG?fL%TMYkSgOb3x{w{)g0U(a!_ZvYvr8cub!&c`n!i4S6Ns-tnhy8W*t|z&uQ8j~9@y7FzA=#m09I1LsUIkSd-YjAV9xS< z2_1}n;g$F?txdL#Z;3S!1*>AL!>gm~{pRZ9?(=Sk37*JoDlqJ+0Wx`GD3=YYUAq3D zp3vGgygsT#zsWTDoLA+%Eq3g?cDY5n5^Q5xZ+i8>p3Xd-zsTANYlUN+)=NnX+kUx?HigQ}m*Cvwvp&2f zEV-j&#>=NA(u>ISz`|z%Xci|9^yTS2>oJiPNA-(5XADtbM9N8^oiJ&nyX?`$@v&$y zD_zRd1Ywwsb#HwDy_cC##3FRax@GBwhnoy27KowBIxgi>^VZXoIq+S{`l~?oQQb_P zLqOVY=7%f3hA+*p-fzwVkH5sBUXD+X30w6r6JH%pkXIA1l)=s64n8qsN8QxRBtYJx z#ew}-B2`xOLFJ{y2tLn-v5|vZBXgsUrrJ!`YvPkd0E+S8O;H67RhlU#gfjXvbGDjp z1Y53F7<_8_$>|v?Jz+50Qil!C(+yeJpfUeLTV!EzA{VLVt`w%pF}XG!)&L@)@^xsO zTNcX*96EPV)e#JQ9cxe-YEeMQ`~MV8=b|HX&P~GRzOT`f6Ujy`+ROeN``I&h{6X9K=ZH;i@B9*}8Mf!x(GS8Tg@o+AZDIL!7ky7I2bBmL zpV&V741+*}uK;0oj-81Szi1ODTt9XEb^HLu07s4(F; zN3qetuJ2s8*tne5=$yEDv|2`9?lVtXrcXQt?9A!)+&&n2%ma2Tojzcw22cb8&-25n zn39iUb(S<*)_li6p_Eg7rD;b#hbU5E;Zf8HLdg*2=(!>WChsnMpNi`=0R^(#S;Cy% z+k=IcfCfe*=W#7Vm(eC#Cy-;efm3S_n9og<1N+#|22~rOc7cgu@eZnwiB-*IvsCB~ zFkK{XqA{pOVn}}qu`vJ-l{84D+c!MNJvG@yGIq%|A2g94wbo0era?(|wWbnUy{EEN zp~9)_Er#s=^U;eSkbXyN{abs>jmHdkuE|wqOh_lhzuI?|w+pHOxVE!PBYI^lhEQio@c{7!ynOnU-|2nH_DH4&xeS0+PR zal173SCl}QI#-_GBgtMDwbcBg)fSfOW~e2Biges6#l*n6s#ql&L(BOqvMPu)7DCze z9%$T2s!C+?9rEgo46o4Hsy2B>>2rctV9dnIy$l8QT0Gg9oxQ`md;tYU!~Uh0g!C)N_&=s?>0u_c)~>14qymp&j+lenvsB^K{;Pl^X2Wu)mtcS-oV8nTI1&i zpZ)5mnhi?=UAFDz=2s4H(?2>>pq)|1{2_eh)ADZgS!CHyZ|7t0Zx`c9)mx{Q^QMyM z9i>W_w(md;BN(_&x6D$SLG(LIq3-90X;KkJiaj0NGTkp2K_#>28%O2oLe7F7e#>?F zIt*!^vUPB*JD(6o!qC&ss!c|MI}lC1NKoQq!yEce$_wr zorb%2BIlnpu$EoeR1LVH;iXZ3%$#Bo>hTR?ZT)P$j|WygtLal4n=(XCemC%~ny=oZ zp}_WXR?O<;=QTRl-g!?1#_reApR1!>{VvV9d&>Rn?8TNkmdwBR_^a-ZeORf$vU%W2 z?`j_LNcvKFQ+`u`aC(*Kk>B+RS$fO{_`KmmvsF>sX=76MEF#c6yi!+YPcKadfw+Klqep0UlQnSE4J^0RuP`JSjf^O zGwZB-O;~>>j0tL5ywPB=vF~HFig10v9Ms$0ZJ0+H9^F0wxmo?yBfF}AtG%q--=820 zY6Dm`MWO;y4>4Vx65-m6?FRC;I4dvOTIJ)y!o;@)tBK*)5XEEM07rbM@pkZXsLmpf zp&4GMrCtr;HFt?%3cf%0S1W;idK!Nwq8vd|J>Ae}`tIp4ru(sp>`Nd{XYXX^QpH7a zFHhbd4U?+Y!E(3s>mI2Rs=siY##6m`qqHy0T-1cOyONhv1NJ{iYluRY#ferqIQ@RE zy4u=ivYHYm{G4UTY}b>Sb6cJdtlIVOZ(=f~I1dZT{z z=IAzgy%pFP$%svvdQFhBIO}zml_yQY$xhRuATKBFsMl+Xn;(|GpI}Gi7rpyfO>hFj z)&m5Npa=DIy*!HJm?p3C;)7Kt^5O3(9@s6G>? zPY6&xci3Brwpfn00T9|d{RVnN>9z_HfA0?M{4GGLN@Fiitn;_P<}Al-ldc?5xW+i3 zBrAyiG-*>wk|}PESM@znhzOS`WRM0h(JVz>1I11unFL6~uwP`3 zBQ#t@kQMRr%Uc2cb7OO~Z|=K0zoFTU&Otbxl~oLUy9mS@PvT^PjmRu+R#ukdc(KA| zK;nIiUc$A2W@{`CF;f(eL$C8+#$^@eIBddVO^rJ8}=efAL@-Va4Rs5zM>aT(u! zsWXYW=j!DpA-EbB(0a@5kd8DsZx?NMcz~y9=knCo)pJ4q+GC+;K&bvWx~9n{n43=# zFxAox^+08?k}E8)#|*XNRhghy?o$I7RMgU$*E;%GSzV%qDZ@EmSasBbT6Sp+0_t@d zNgRyQ&ePIP&QA9bm)@xW{c>w4w?;cP2lfw)hEK`WQh4#xv-g&3k5QRBK1I=?BacpU%&7XB=NV?S>Ziw^Q^DS(WZ}K zBbKo`jU0wHn!B->!xu7de|hbWelbqzR5wV)@^kZY*eapk5ZC>AlXOL;8> z_B-|zPu@R68;m||@aHcX?Z4AuBvi3@clmsIxpF)v zf#e3uk?=e^xqn6mw{tJ_6ip3MT2hp!jq>fm%TRrGe9J;n*ItTX?HfWO1lnBi%jECo z=^{+qCma@$ioQlwX9=wNk&I~o0XSy9D+jxhTIvSt?^}haFY?j|xR&3F_=#|^V}Y__ zi8f8^;UvlSZ7Q)JCbnr ziN5=%NySQ0gX580H5Z^ZE5nlKKexh9a?hMEC2y-ya$##L$=6Iy$-y+;Xy?nA|7gD8 zLH&4=Sa37UoI+`Y@)|5JJ(MU{spNL9yFX*U7XODJlp{!w1f;iic??bsT@;YaN?)=c z0KqilM^}`>LX-Euun9D~DkAYYu*jLIv&mv4_7{OUr9JEw+un3VCmm*^j#1KYi^l z3AgK`Mu~GJcp%Gb`GVj`CvjO3|LZXRU$o2ZxYIgYhSAaKuc*X0@qfW^sme`pvY?*? zJa`?*TVHUgLaP6>o5hx!?O(b(=+s()^qu-0@9aja{?=a#oVTlUofD9w{gCjc+7cpb z7v78V{Wrlkg)9}{E~_CUr4TMv$eCPlg{W7TkXgdNtE+<%g`(aJfG`n8zWu)zv{Jr} zF&(Rn@@pLWLPv_t)IfXWuJJL==>K zo{kOLz=af=SC>q5Y^iS|$TzVbf{U5LK!|wcEAM1CsQTk<=7>jObE3ui_lZOI#TNP4 zd2fwQrB72+a^VUxlwn0Z?@XE5q!lt}=sRlewffCC2&*gm_R!^M*P7oYir3-Sowws< z7O)$ydzD`jYSJU`wJr+X{!&(6;N$jb7oH9h3r0R+78 z``nJv5K$3!_4r(*r+ZcZ*-H6cwh@KLpp51sbgY(7^f~FkpoT;R! zAre>m8x`SOS@O7pglc|%9hDNgI)uHU_ zAe^q0aT{>aPLIiJckEyK-UtPeC@Qz#wa5|OYKRq0K8Y55hPSDoK%70;_|X??jA38@ z{)`DOLuTCbSNlc>&s70d<)-auA_;2t z#QqNLO&9eK_%J%gY!-DC=@ReWF-U$UqJ0-;0XWO#Do|OeD~fZ0_-P$w9EVrb z-~LkD-o|HFo3yoh+iPC@%-l6OsVLaDgJLmyQ^#rV5OYvxIuq;Td-9bm*O%6M?T%#} zyP{SuUyo|wTgo+lSB|UOKidX>IUWW0(Pi{(VsXG!jj)v$?!aUT^fmMDf^uKK9|wrsJr=K|MozHHvO zyH4#FT6Iz6PXrL6;3lhUs)gAJ&bAiEmZdfaf0qI6rdAavc+5vEXh8iPd@LvkDeT>H z&_|jPySn-VKJB}*`rK~nYA>F003SV@xk}$BiVIUFK@21FmF4RP)f*^+vYIgTh}NT7 zp7yr~(h0YJv3V)>tBJU*%0!9jJn82MM8Hn>@TH+I&DK*8jF& zryV9^peY->IKn zHnR%LB9=(PVVN+n)Jn>_)zk}GHJRbg$X5$XnAH=zaY$+d@_0KHo?_?5cjaP;g=FQe zVUIsf#@!?Jnqfr)uP2Yj$_}W$5jBO?7iG#(#4=WXC83ZaXscPQM7##?Y6vq(naw*r+x6Yd$(--_k0Jhl=7a^G=yjelkh@QUR^h+P_tM zFYG^m{&a`DLvewvds`e%7YvV#*t#EX&;}CsN60i$qNlOqP^0|e&YZEiK#Ws}mnc-g zGSa5Di_DAN%*hU+!uj_8fa6j?r|ZN*`F=DnkhhvFyC@n}HJ}C2xl(mtVz-iyOHTTJ zv~$aDoR}tc9Wc=DNH8B3U`Bebb2fb^XPWw&p1{!SmS!OSPu z3d8iuYQF3>BbDW~~__$Kay3dQ;_x?TJ8P_L@qI$lT@Bg-#vta*-cCVe18TeVH z+wMlmV8|uU;!{{}lG{RY)Yzz7dlw+m5Byk-kKQaMRp+7rU;db%N=LHBf4>Se zxLANewzKLxeAJtfOL9ViscK$YVJi~!JJ6XOwrbVEb??b9=BD9Mr67wLn=#IZ4ZY9j z4plk&YO7s-topU8811rDlZu%+0sm5H{y)sq^AEV0krQ}@UteDIVf9T-om+kpnQRgd zlfxH<1gmKM$QAZBTevfHAmncG6pnGsN8tar{GoO?;o%TrT~!V~`5mMe(3vGlUUP z@aO!mtD04-rwwXYizVj^d{6WKx^8NF%00jDWL5Rk90Tag(zeX+0~wEY7zgPX`V`I> zCoSJTpx_%IZ=9DfIxs@xbh(8nEihWLTvmXTzKRMX|MUAV#Sd=P5~O#Z>~hi~lWThe zS(AOoa3e4m;aH?(aarqJDbwl*$%B&{gm?^w-!IJz8XbY1yf1;YpT&4}EtwjWO_F8mzk&Q2nn)7(bK5uc!^}kEIvZ*WaXsail7tyLBtLP1CCK z+nM)poVU(j7aNw5a=KPaZMTzY*4#YL8ukv!AWM2nSJ7lL5X#b!-6m6;IJ#5~68wyx zp^gP_O)R;Ju)G~GaG&{<6d_c`wF*%Gtx7EhB@&j|T1uJ~fmcxjvWz^BMvk&kF`*dFt1 zb%1d9lbVT|AE+PWXu6N^$X@hU|7_Iu2;F$BGWxh=FO;fS{@E9{&(+D*N}e}ZW}?j6 z_;kel#l5EjWGiLN*2~JNm53`?zI;}uWbinW<1m_EdP1}^&R?GI>2f$SYMWSWI>X|_ z-9)l$y?OjG&sKcM`CrKTH>?m)=i_@8oyuv%&%E=l7p4`i^1z*%C&z7qzkw@DomEoj zl^SyH%PAtiv7oE|5{>#o*6b@RI%<972)eF%p}IH2aFxc-W|v7TcOx%l_XY_p?+Z1b z!F&LbXrE-aNryEa>N!qrAGIspHIF6TUv5|%LATug@MXKWmVhj|pASIktKnKut!_*o zjhM`>w(o}_!OSl{W=|xQ)ohEE%d)WKK6BUNtJHwyj%K@>Hg(emuj<>YGPH>STZA~z zxreS8Vb+b&(TC#=kEV&=&^%)u(D9@u%Sc_>r>A9?@TXHD(U19-WCON{*K z_fXFV%H3El^4UmwUX%p}W9JP=+lt#}rC|<2S2`Nx(7AyfmKvM~AeKQP7kO`MgMo{Z z&au=t5!{6}{XxIB6mvy(j6&`{)3qk-vAY=UtTKdb@dq-Q-(NqdHt1i|DQ5<6mH7K7 z0TO#O2X(_6rg^{ub*5vl8?zBw!>(;xjknz?_B z)%hh?X;EBA6d|;(SeXafi;mtn8k1nRKk)pw-V5j+a5yeN?N}@n^kHM2nG7l=WniJ* zNIYimnZe^(TN%Mr!8!Uh{^bi;09I+a)o;CLC;QFZmBI1Sae;8)rNVRsRDNucD)pcw`D-k#h{f8|?M4ib%jM>7~dz-qFc z(@d_Y>TE%5$TD2<-x{w42oU-rv4(zq3AMz}M*{APUVG$3LWho|7d!eM$1dt=h?(#6 zXtN0w%PZlqcOVP#ju6hG@gAr}`JT*c(EYWnJr7f#%`S37ZT`4gaj(FLbb`kz>7;8T z3E(;Klt^7Uvg7{#b-4|%`_u8$>nrHThZd^s&O`}RISEYl3t2>*w^Mc}3w8|)`p!WO zn~jf-uTU5Swi;LwbfOOOGwqO(Y0<*QLR3c-414od5*0@9^GDdaW#5Y!clNr&&t=0s zx+(Ra%K%3}xWAcGyopn%4p);lV%!{kam~zNIU^ZZ=I__`*lk&VhXuyP0hxaR2l>p z6@uDra`Le7i|5!WZ3kQRcH_#$#0EahH>b$fImrIl&LmLJ|CVoSXFKSRhB0&LA)_2C2K1+yez z(>VgOVSE5KS*Sek0wP}COBxd)m=za%iRLME(<8Nc1{tr4>tJmPGU;9vOc_sGu;3}x zoDEs;B>)DBVa+lFVH@{^O2&;lo+lZlMJs6cV_f%3G3!VrY4YwTro8)r@o&aNL>cO~ z3^fE+s*?LZex+qsUY$1f3pdc4oWDNnStWKzi<7L#K>a+c@lh+4J++s#R{)DrILrig zIp|-NwkFBEmA>6iYy#BT=kBH_iXTqw8eA6({pP%*U#@n08k_iMTPNxy3)dE-Bmm)e zh_i^31ujqTj+g_nymJWV9!x0L>*UV9^N7NFNa(X$x~o5IM4aU0RiRP^zd`u_8|IsW z`#`(5Mgt?dd1Hvl$FbFJdSFiL{weVD*UjY8&gi63@fvk>o&AheDwI@}QIpuR1FyExw|QB&R$9EOt(AIAR%Mk}y-fq-z|<|xgYp(XOYNfSr`rG$W4_WrJ!)RV zit6f%XQv$Uld4vb%5Zsqkb&7>zU*!*ZKwTE4_-vBx;R0~Qq33tfS0oqeX~3&J2rLd z!s{H3x_`W71oj^(-6HC&FPQ}h3PgsLnpop=T_zlDw>7}cnO4}V9=0qeq?knix4B=wXfCT3*T-1;q5qd>{>Pw}h){K6n|O;Vr~Z$* z;5P^pCc#^P>vLNDsDIll_x8JqXBaK%Kc|8vu8FAb7vN7(gf#!OiaM_zyagcN9*+1I ztJ82K)Ii=>vESkUb|6oDs(WoYfm-T+vC0$l_PfbMSK>G7e>)I4lA-6g93M(ZTpUJZ z)ogdjJMyMFod4yfZ)gZ&4_b$!gpFm6G&BUH#N=M$!vAwhDa4{Jf!X=lYyeAMt1Sgn zBRguaGOsnO;7t$6?-ak33eX&^E2^XTzda}s`d&8#)VA~@=s^Cw>vxjacZS)PPyRpe zuGJ0oI{6E>uv=}c+S%E`$5FrTUI4E@=)Y!zJRBf1rk>UPjU;!a+zYOTuq{3v{ropQ zpv5H!8RtJ<=d0;vXTVCWRcrzU8@i$1+nT`VM<#mu;uWe4plavh#zRXCW*TML=>*$s z#AZM-&MPoaC}*+iij#=2Tuq%}no!%;q+prI3c;mEbb!IpRd1zt&5$6wBRbkO^@=dN zeL&sS?Ng(MJ|9o}n;uXEe+lyc9jR{-u~BJj?3dW944Ni4NXg0BKuZ-rf8r7l5ZIn9 zR@Hu2E0m2d=X%rl)KQg+U=nhiKtv8WP!#`mW1EbSeR^(h^Aee7oJY&@S!3#wZ5m5tq1X*C=t5(k9t<(ne;l?t9sS#fqy9!FX&Wcd- zU$Y-GFAbbUF6=v=2U7jE$na3-IBz=-RUgksI-u>Oi})ki+!9z~x0}Z{5h0F25HU8E ztlvQ*-VHlS-6y#yXEP=y!peyoro}MkuBQdR<1WUu_>UE}R;LaaZ@-(w7bubcGvQRa zN!A-&cL%o`|NQwRBP&}j6^Tj0@026?&a}<@Tqj>FV7|p2V){6px|8#JIz4qUfL_e^ zI`(@H$mnRbI4aa{zw2d8rHum=AG3J&b1*x-Go-ba=fVnlLn!-ai5{>L!okARXsz6- z0m`sMFj>ScEdyZAm6~Lq7#Qg3 zn;03H8BJyJT(K<`MDD&jTPNkax0-->ZY5Wm>Jb3UpZZx^4TjeYkp`|BC_yJdwh?{= zS$rAY28NPY$xsxT0WY0&HzesY_o=X1HtPgXnEc#XEuz(sDT0go3fbRBD(Ee4!u25Al#-$(0V%)24BS`EKgV{=J`FJ)!|LX* zNS_QrZ5%6wj4vLMFGj799AU~ORg_Gk5Gq~ygz2r3;C%QO&8Amlto6om6`V{Sy;pbT zpL$bhBRzKRxKYy!Fn|DCmgaT2Q|x)JT!o6-CJ=q;aNDNNW9m6QD;Q919C-Snc*DPK zkTC-EiI%o6fhJP5hvNU>2s*wGx+iQ!JkrtfwRz)lx2CP{%m(FuTt@|A@e|0oi?^rz z#{fw zj&+`ZJ>~(2)yIp0@{D$=OcCv11K?;drFbDBNuGYV|47R{_IYMsvT=9Ur&of&!Izv@o?=?mra^I8q|Lq$^Yn^KH&@p15S8F4=@@tM=A4v&f! zD7ZpcYD$b7K#AEZlYZ-HpKiXsGyMG@XvT|Ia{&8KZtGO)nu$MLo`AZlQ)b@#)6>&y zuS_B%+A&L9RFr5ixY=ohf<=+C3T>1N^*o&J!SwSynk{DKv`3x)61)Xqo8F1cFQiu7T-?n2Yo2$f z`%N5rIY|v}_!Ls~&%&fmB_?J}D;xKxIdchhKK4xyNT1VdcA;sV9kfc@LbLDI17H#R zX9m1Mh-a0!DZ$*T{^;ICi~eu0T}QNKn>f)K`;F?KEJDi^0uFfec}-vO@W@UW1I#&i zeg)|28kYK7+8Mr;4dkunZ}ww^+N#wpMC#!kSw`sxvWN4 zp02fP21MT661nsTvf4-{di7xxE`ts&2B8i4+(^K%7?$eN4 z2uDRH*}3|&SD#4(myOZiV|RC~5!*L_vjVA6HjI&jXJb{7myquT4U>4c(^9YM>=&uo z*#>2my}gnI+!CyawU+?mhlTrt`F}F5+fNrSXNmP)pH{)rQi*n5Lk~5z{^2d`Yl%w2NUs+#z$D7x6uWY}3 zVB*U?ZBw4l9#Hh=o+Cw%%|;uccste&Gi3O+C1L9NrM^gb2w&J}**Hp^#^xJBL)bqeFl$Gka>Uc`t^neEEOW6OxQT}*`kU1Nt zTKNSGrJl2~q6g|FacpAeI{ydZmIQkc>td8Y+E*;@H7um2XLP4G^e4>Ihtl5oMi8Sc z&aJ3f&T1LfrZ`=VHy3$WW}^A)DL&p6#tgqmzTTQ_W&v78xeL1%vmEi{nwntO#h3r_ zQ64YvzXe{-qFIrcPz{~K$g?@H+`t3k_Ecz&2d8b8Y?Ng(UhJ-%7Hl0wYWw=mfLgB? zM3`+rE@xD3qH<DNRznCMqG0xmMLb z?X*0-1Z%6B?{H&oUe;#OuH3tp);#i&F>X*M->+9Ri1BCqt;Ej^8X`ad06{akqaW86JAvxqyBUnP2)#?U4d` zI>^wz8Y*hUf7e#N#`h#MAfG}`9X*@)>XzR4dcd@P7cZWX#&d~jB>Z{SlDK^2UBby` zSBLU>w!#Hv$Dji<+iuKjv(XXOi>5WZKM>5=-nE03m31ix{OrHN&69}C3y!EX2$@lB5b=LZR-iw=^nc1^vuDNFR?dwdD z`BwdXGJtDU$?b2B=g3JEv3%Z#D{tePFL+9O=4JAoq^-JsqSYdezHYz@SZeFy`11Pd zh4V{ORmH!Dl{=2s*TVrCv)A>K2o*{mM8wEVTg*ryLdoYTTDN@GR*ujb%-2^hDoee4 z=Jf-&Aan;Aq*7 zR7JfIs8B`jtbI*|pfvjLXIOzhShU#z*&WUJ-a5OEPUhgZ3ogCr$(rpgofj`&IO{Sx z{rg|T=pWtDy;o`qKt6Oa{T&DgM@7yJQ2j?>6%v!FZowq!K+m#O7b*HTr!IIsYMGPf z3A81#Ver*!FP4SEV>jL)=){f$bZ5>w!j6*pr54>4iGS^XvUI)H^?c3P-nd)mLo04} zGCJ_#(2}Wt{mCHAK=`1K*T3U6ORps7>EI8qQ}s_X@e2~40@{y43R^|QZxreJ&Sm%@ zaQ#AA?xT$x&vpEd?Uv88hLdj+*go>G3EB&u$uCOzfK4$AA;Tmn*@|Dq<0Csd41N%4 zMxFOtyG=}I+uDR0K=*iyfCpqjWHB-GKdC1~XsH}0z#9jOTwj#rQa4iX258)=LU#*^ zh_=y({E0Pancy&_xc`~Jt_`Ra&_#L_r3G(3#=mHe@H=6y8p+KvR2pXdyGL9L!!bB2 zbO_2=*!mP24CYk`%5h>3(tiRs2MmF4)bTfT*$L(OF|zvFMYQxlUW>&!ZvaD|?wAUa zXT|OYp?AIM9L+lf59^h9_fYVKre=I?p;y2S8klnDv(2ieyyAL_zuWOkoh*htw9{YT zUB03Csi9ZXJ)6rK0tCaYoK_+TA8t&+d^xyxy76t23|yeZuvi2?kuB0Jsu_H{XMl$w z-*L~;t^>xNW>kz|-@Z}{DtYtd$;d#Rzat%ix7*47($+A?e%7nXKIhJZOhRsN5-ZC~ z5lZL0l)cLf8CJ*AjmlfNhnLO2tB88B5%Q6|ihvY-47U=lH(V4~bkNxDN>+xeZm|D> z)F)69qEh(H3(`oC%RX3$SUO2_tJ3k0WfB};9b~%UMNE3=@@Oc5)6Plc>il`#R+W~P zt=umR6f>75@g?G3a`BJ6l#Qq2^aQ-&x>`Y6f2Vmp~7?O@f!jW^@~iHf!|EAQk+FT?d@RWc!dCC++HVjLseASlgxbQiPg8w&Z?ju zU7a6hkL3wPWb&{Hk%PWE4d5aBc-d)Y^KMr$oz2fNROR~Ouh1Nx)Ksl;B%uVs@E1Zx*WD zbs7T0VyMQ)vwR5oK?0vv_M|3<8030ooaX58H^Bx`3@?7W2G+~7=c~Q8UJG8D2rPX& z{4-BM!ujr-wT3i7vA0rpt$#dmkR)^xXesKUi{NG9-%(Byq8Qy$HtyPunV-JsPD4Oh z38S*lePKC=G`|ckE3oLhXlEClbIu*PN+kkzy2Ygx@k#SrH9s(DaH3(AECDYPss%C+ z8RPHxwYD_}BRb4ay)$c&lD7T`yczaLL`8*QI4ZmA_{2Lj;CN1~?`UK8wBeU|USJ=? zuG1>7J1~Ln%K9~dpMF_EY@)JPrQ9?{bI?gOtc9UTdZe~lftRwGh4;#d>hpaTpWX)!&RW)gdPcIDNeFGH_+R;_mRi!Jhhs?O zs`tSj5dj#m_?XVooOV9HB)8j&5Herzh4B` zQJ4}6kZ*~uhXc4?b9vn&r1BsUF*3(|lHhjTy>;h8f=nV=p1`ViJm?>ut!(LZ8o<12 zlh(DM<*~wq(&`;YDkA9W@JITws9Cn7Byf7=!xtvWPgoUBB>|^+N253=Y0CelqW+5N z+1EN?(?{=uWz4-$l&U*37CdGZ(fOu@ka;V{57w^tRN@GLrmSmL+0$ArcQqEPgd@te z4jK&E!y9NG^AkXYUx+@qZT`%K7&^FVH9iMd0hKS~H4S%7rQ(5SI2+nnz z>7@#_`j)Z4X?xg>J_Ow2&Yh|^-~Uee$`*_e-wH*=N|>^}I)%eeMZ;iyH_<#?F$BRI z;QgW@e?NsNAL^zM3hWnL7|mwtvc@dD&55^FcHvij#7)TSY{>3hR7Uz-?5Q0u?wQy= zB=}MadA-xL%G1-h?icYYR7uFC57kF#|@EbIp9@_X5oTX!xhDT8A4bgbJZ;|w31&mKfwFs~me z!b9))Oj~3-t1wwyTi6rj`oW4jwOv<8ENr0IlXhcqxP}itI1vg7Iyiy&+8*up%pt>y zfdY7!h6s|dvb&4$E|cyqE^3{hh5FNfL^4(3PE}kw#VIqWB4R?I{g!aqH4db6F$*Xb z%92thmLL3U5ask!I3WS1alM2hf^;11<@3a zLmsa4k5nsxy^UR_U*>{Nc^3lT$wqc=Q_iiY&A7S=@#78M4AZdvZ~gPAGMneFSB2Nx$8Lubdr7PFBX1SK)dK;lPtj^glusXidYu*KLSBiyAgZi%h z5WW?MUG&b@_ue~+Xk~9`#;Ip1Cgh=i2BvMU%WD4I&j5p4^x&tSfy;&j!yYffr4M-nfcqJ`?Y|np^Uo-ZYes11>y2PXB?G`ZLQ# z$IE|JSC8r%RQm>eErRwF2hn>c_!&UGFfqaO=)DlWt|9BO(^YR#WNd!Lc0P(Xgg#o* zq4JfgAN#N^(d@~j?GdD4nNU{BNJS_nwbq)=uPdj$TNc4jU__<^J>CaJTZGz&`5pfQ zIa@M)vHU@Vw^`bGI8opvw!tND9Rb^>iw>?@Ypo`k>F;+L`P@ZY-Xk_&u%F8wfmJ<$ zj@r0GK1nu1%<|Z=&G{9iP$qs1W%7P!OQ84hYYoJ)AFJb?d)^kFeuJoNO(f(ttV0Yh z?J`Z-?4=x}D_cm95ZC2BIYCREY8ozzR|K_XSAoGhpHY%AtB>wB0w$4WcG2j8k-9kl zz8nFsMvakNWLEX}UHj};=jvB*5xi*$>zY}a>DyiX^r03tn6#9kvAtWHW>oP zWrFj;p-^!)b<*_5>q?D);=+|3rXfFRKxI!OSHJijsOwT<^7iM$^T~45?$CHRi}d0A z5s!pj>`r#Fi?_Hr#|^aJ;T>D-KZzC#?8bFw*m+ad=`zM7o58O4n5Sdh)6j|KGIZY= zTb+q>0S~pJLsk(xqmw|l@$tN+8AVVOZTCd=+PpzvVV{}WfZ%sm(sejML*Fnm;0m=L zxb2fm?ax96PsR9tDstoHns0Qjr{=K7+oQTk{KJhTJ&cIH4aQ6e zC|icJ#LTlwK#e>kg4FpL+A11z$?dQ`k#+G1HxQE2ALJihVN+w!lp+G(N~pG4Gb?&7 z)iSfYU2l9fPFm&Xv>8CkG9#KN=J()TX#;Vt??_rRdqoR2egH+0geZgw#rX`O4y zXxN6ba-Q9F6*!@u4@tYJfa969X3%+3_4+#3TD3;gW&lnZl*M`@?S74BHbu#}8VI_u zApG|Es%GN+=v^xJc^*KtMXv=e(;if7(!xX4D9}F|D&&k|zS<~y)U#dhkAK^AS7Whn zMLTpSl;0v7vR=|=7be)UYFt7DbL|3P;CncxB)g~7GHOXoxJycVF)L3B3K{j>|>YqG8 z?>8f5hRnuVZiY`FP+X(M8j^`=c0xcF^~F9rx1j#1Y^Xlz%$KY8Z^_YcuLl9zuiH!K z{TBPCgZtZV`fp4c4DKQ&EMOWvZ_xo=80Dr3PlQ01Him&~zR^xU@MwgqMa1&p>>$6w z3JOU?FV%kUXACh-EKU?;UXZuK{lwONt6o0B_UX;;GE+kKNR_&P9eI=}vl$JepG#{s zpP%Kk*+DD^R2DzT#6?6#1+Zny1i!>n!NppPazFR)0wzWq!9^S=KwxBkSFUs%%g}?v zLum@40po)2r7&@^G#oJxwmu3I#Jmei zQrFKPh?HnmT6o`e9fes(bCHjAS1q)?DLKdEeP>RI(=9`7A~kYq`<7THBXl&)o9~PiHw<>gRj74awvm?`7x)HKbA4)2yfVoxAA>$` zNRh>HbX1obOEJ_J|Ke%b0|A(TDfy10?O-=h4TYVZ@>fOFp zQR})ym9!liHhfwmYC1!-t54g$#aMNtqw9AnQjwnd+3V_$^7cMF%4T^qUPHR*FT)0`u*K?uD)Qa$pmO^|GNutf~yq;~pFLflPmp!yB z`&;crf9gYNjV4t5-gC9}hKY^3Z|j!6Xg>@ii#fJ#@^bywDVE0Z_QDUc@#DIeS{9S1 zo;lcnz9s*!B{d;Oofn287|U9(G12UWxPI#XCkm^0z~YthEG|=`?CYq5r)}1cA@?xF zJ(e(go;w$G4VmyH`-XR6W(eRaXj;tUGi!z;NYBh=D0*S}{F;ytTFRaAokLCZ<(PMQ1=(=uEnbsuo@}s%9Np@0E;cJnN*rt++Gz>T!}-r-19;pZxXL zv|MA!PXgbqI`lGoRZ53$Q-Io>WJC_*DaQr-9p!+=(uYonE0o2YYktHDXWO`5LHjKG z{-_tFuy=_@!#vw6EN}_;vqD+OG!@!x*Bq6VTUiGObGi3REvRMFZMEm1kB^DKVF|8Fz1}Wx*cL;t3rSaYq53y0ivKWaO zF09d2jJ11@k8CuvNvWUCPg^X2z!hi73{OEPYnyZEa+p05kmVlhCg%NKqh*O9%f3?j zV$L*hHP>C_`>eM4Z+N7W7jUlCZIB`hRDj%R{UOs;n*6E|a~xH_f^*&%O?$(+UTX>+ z`RLWy8~N1mTjD!-D1>3v{==W&fhQ&6Nu$cajGbDlS1YbL!vxYC_OS{KU) z)y*FVmXYrkPKVN)y7u6lD-K%Xd2@&0UuPRmT%v)mcb#F|mq4G+q2=6^;wD9O&7tOc z-6XUw_H@6Vml;GF$M(wn^rzc6dZv|8oL{wWjaiS)uxvi?`H{osH`V-3upbn=ro3@KDR8qol&{3>IiJ-g!Egr<%Ve-a^y2a0XOn6e-s`t?k~q?ycXFXVC4%? z*%)>)JhDs?^vKIZ8Zo@vLMofkI-QsAmqu4@sh8(AF%8J`w&}^xp5Z(fm#*0hAWJ@$ zrr~~aw=}V#X5}tQC)}jV3hf`iHkrQOdHm8mLXa;=klv+xgo|znoQQ9bI*8*rG+uk( zvMhebp<%l!t6`v~1L9pgcK%X2;1fGNY?O2N7G=U@86;0R7w9JGXR>@w{TXv6X5u~{ zS8U_e;D`3~l_{$(f!pX@q27)vj)B*$@GABl4TLf)Q_XOBNDx{>Ym6<${0sJ`NnV z#qYGqieds?-8@A&l)qV!symh1H{ zG#*d$RY{EuS)UhF2D7PQCL*yc)w|C$Hh?GDGN0ZB<+$#o-wL^s1koE_VMq8fo%DDa z78^SZLWzX`EHStkRZ>o{BuKUm|FCDb0oLSCyzA*SvC7*#+oQFQXpDp68k*90Y{{g! zh1!BO>jre0Ap1s7lFfyG|2lAzubsO7;tF`E*U@=dKFt@n@gT%S6lbmL0}D{KTr?CL zg2IlzVXM4L9$W$w9x6ZMpyd?Ws08^A6K*y{@YYAKRNd`>JIGcy0E9f$s_% zI0j!`-%{+7ChIACG4s;gtJ6aYyQ41E+TKb%pf0g)_B}>5K}#`Vtiei9{PQ>@Tr6{r9chy0~8MjRz;;0H=%8I zyWYGj%3YYy!hq@Dz*VOtgMyOcvIQ?+EHEGhvyL2KF9WOQl>&|K% zsLbh%pHv_F?$gL#uY1LZnE#bYmblx}zkz2UGN{5dc(-|=Y0kNa4CtZgM;^XLkm$As zXLJ09VkcF$g~Sk`({In%OuOVcAUcRz93Omd8d^JK4P^YZGR+_9_;{YWMfE{LVaKspBK?>d?UIT79Ct?~Dc= z2<>&rm$>F-kp+gc(=jRW!=K3X8HIe=8Ye8|}@$c37GfY&8@%T|dwy zx)l-E+ZbW+u=ACn4F-frTJveL96+cLUf3`6Ptm*n~{HS^lBZj;b5ZP_0fQB zL+$&+bC{O|Q0*8ETnk3It^}IrYR#RX%iODA9ZS=UClY1`j3K7>+E+lT5HF&%mwAFH z^O+yHH_VDP3%Gb}Ar5`2`JJnEQ;g19sI^94x0fOGl6gXOSwm{XS#j4oV5_6F^*0Dn zq4Olu<3Ta^2o3SSmldLUc!pA!2)8HH4If8d>ww|JO5YHo`0Uwb_o^~|hzAI@QNDn# zhXan?RbvPd#RG5NFB%GM+{y|gAd=P<5ixReA@wdH;yNqlS_jO2lt!4KqL(DMLQzQW zCj{wG+Uwzfff5eKn}n=@|0_3wbX5s8d>uK7h>=+;O2fDRC4){o=D2(NWa0~1G#rZJ zT5#15P0&gC@`$8$>Ve5wr%p(Vc=@BMLYM!@r9kn`#0TT_>fe0!r}jkOIFZvhpOtjt zSkH>xjF{$~i`NHNpB7PYUnia&88dlW4viwY5Q$Tus}PVyhtw%J_#prf8tO5F-F64% zN_+{yGlYIlU7u>PSb)s)FN6&;%9Q+2@zP`dk9t~2qWFtSfTrp{o6rTFw`_xPQ5L2- z(C(7tEYBXFIgd^~4d$GJ+$x5Ro&bY)eS9QL#}mtTxXp7!ui(>ELr)3s-dhO|yu+fh z+rfOEnQc1X-j=M5+giQ>@H*KMo$&{! z+qn*)y6TXl;VYQb-vWA}PS3+G45T_fBO-fy2I~N(D=zcRrfyZY>O!KOek3Bgstr$; zeNDIdg)wCax|1}{=L@a9JyJ!%x*x^-^XH&BmUfqVmnZfcpUjg%*)xB7Y5?aLse7;d zlAQ9V3@yboJL7BXEY`q@^@mx%>!$C0VfToqOR$}GW6^A%6zH=fd0e`#eC3bH!26P@ z*7+a)XP(IsMHGMGjG7zj_(ub#-XQEVLhWdkx@j{tFi|l8G~C*RaUlno`BQ4TmDlqF zoDmPGPBzrkwzo+q`cc1uB|VMvUvlHnKyQ`$=6vZl+WD;&O_GUV8<&}yh}gu`xhVhM zCt@3;uWMA#|42dqJ`hcv32;Z%vY_N+iE5u~};h8~J!T`pM+z2zT6%nm4#^&jq;M*e44P{8e>nD?#i+|a&vC1m~1u`ix&lCv?4cw|79npNzQA$ysTOL|Q zL&Le}TivB>E?tP6i<)(1+7|C6+UDO87M`4MO;Br)wj~DpA|2w>svgUgt2b+vpVnBg zj1&#|I}S0hO@#^adiW0wq>N8(shl4%wQSwTEDn6EB^pcYsNfKRCoL#$mellU`#s1$ zWktcwFMHX^Pr2(Xqv4sqPdll!4o03S?#yM`k+$6xKK_;M)5#qZ+dWeh`6$7U&Tf5R z?IH|zea&2Lv2T<7Kf^f%dhZt*%8C9NB_LXsO7`#vENKsi1bA zUtY(O1RW=f_(=1Q6e^^}hS27_8?RHY7YQ_39QKCX?0c`z)tj}1NF zmNKLbG?F3Dlm%G62dBY(_8V9VxH(9jdjIHd@w+7{Mc3lTF4kO)tGfUu)j#Ytf9^|7 zGv2qhH<7}o1AUGa9I7l!Z23cHK*OIFv~SU6p-YA`SZFjxnN`$@lpAsmEq!duc4EYa4SD; z*r=8^D4HY=dTdma+regj(69~RUgIRC*h!m}4~bf+t{0>SE^V?*XP=Z_&Q-*@v24Jm zF#HLsO=BX!eMKQC&+E19rXF(e&{%B9ihHA;lZkswgOmxr#YDT|zOQi2*SSl@N&cEP z;zZuA#6aWXT4s88r^;ZE7SB<189YSMdGyoCrB|ybqiywzZFcr;8>o@VQNg_@Jn~Z; z+5J#Q4e5~hQTVntj#_fNBqI7$cptgDeH^QZNSR(A5QLbIFiI`m_T_gCF&lcEQod!N z%&VZC9&liDVwrGCJy|FE-?2N0#rtFc$cJ`D1D}TSY!sbmgp7^E-7A9m}gC zw^f5q3eD%Q@B5Bm4FP2(cQUrsR-I3{)Y2Y!1z9>7@jTX#M17R~s1mz7Hq@5zylDLk zRiL?78uR#SKeMiGltr$%resUm=GN%UV~P{7h8Ad+*n2+bDzk0j!6bdfmvH>Fw!}e| zT!KhwCbow(>%1r0#41Tv=+FmC8kg4Rj%|Il=8b3`CO67_W)hr(qu#WK1s(Q(I8Sz6 zk@{+C>Rr6T#^$i=b$NG6Q@$UPce0Er2$Kq`(A;atbbz?q8Wj)bHdi%DNkHE;1w4sO zJjv4bXj$33{|z$Acr2=LY9TRvZ+E1~a1B%7&HLYRm3r0d;Q&bOjJV@JeM#U>rVq62 zDCUKx--UYIDO`JD2{ArcC%;h6riDBdL{Ej_!_v&ZGX`gL3Mfaw0WI0Fnq7$1w<(* z$|Zok&7ajZAfc@DU(k>vY>ugI^!qN{31pFMHnP7t-T)rV^2v+hOs8J{M$!L4XT&p> zjP`LQ_EEr!pD9hfa_5J8tA0US+1P2ULjpDZnlD4vwrhmb+-ifFue;K84p<~8+cctV zt|b3)WAe<0-*QV$t5SXE4U*{Aje`#6N41LLDTx$Gw z;;wE-&wMw-e<7$+80{s^M2(*4zi_Q=+?{n-&XB7ntl^yX+<~D?T$R_uo_ov!8NXv= zc*R~j#Rr72$DvJa9sErX1Dd8KH5c9ejQ#x;Gst!zX9g{*BhTwpoDH5C)pnoL0SEb-Xn?P{n@~`ry`Aae>A<(aI>&}HU z&DF@VqzsmX_H9WeS44dJ_l z1QPhGe)<1f&BaPJ&I3Xv+{57vqR7ZdleXZdVCj5zc6Of$V+U?gQTQ}x{r6-5cDgMz zE>U02JDlv5Q{bOnO`v=SS^8LY-5PL^7KCnLqQKOoVW(T{;^3xNwFg^XNi2g0NGcbx z1?ttnG~_;0$i=pSWJ1vIXx!NE!^&NB*$z0Iuhe}?H_5^(R$}Bg-z20yt*U-`MqhP^ zXB*%i=64hK5aW>%I~D)GMc9v9Zxj_bTXx&Vs*UT81|@eL7urHZD!-r-E_#izZ59_7 z@1x$ik7+73!f15n?gp%+m%AC8Y6&!Q$>rU3$2WX?W-b`Imsyh%?5cY-ECuF1tTPUj z8Z(3@!tv!Bo4?hL^bKk`-|A7KJlhK_XWXP1AO8?7a$1Xb9j2 zo4izt7W4n;6i4sTWVSh6C=W?0bn3-inNN(?l2&Ua+zc{_6vxxT(+7Ofl@;?l~9T{l(v6X27oxi&M6etP&TV?-MRz)S|@)!nk!sCu{ zC|GD|Bn3mI>kM3^6160D#JB>?j5!fN)yjbdnmxWro7O8Xu;o?n=R)K?frDe3&iX#B zst3JpOH5Mxf#$v@nsp0RyB0wvY&-nqtp2BeoSHGJpl6&8_+Y8y5yhbT&uIk-57Lgn zebq)fG18zF6-4GX+jaYd^h__5Yu2-eg8~k}!x@fnQ8|{G<>v3|1lZ=d&m_KncJBrK zOl7+dK!vPFHe)_(fA$5=&{B*GRaA-EvmPb=!glI~9DTnyn5m|bnD-6b$3{+Dn0(QU zX+FSZi@*&_T1^M|BkHIfZPCTJrA1Hg-K}dv%bWKQheP7iI(Ho-eWv39m;bx_%R4nhElG7tsrjY%CW*)nI)&RH6T>l-lB&W9-+S<|SArM4c zC~m}wB+wo8g5`M!EYS~I_VS9#sUuDhgW0;(LNbB%$bEj_?Y8yJoWhD5TLULx>5vu` zpoUhxuO+X4ySq5yke-;z$CH@fVN+j3S5ICWZILEdyif##b1Ho!H6qCk$*An!c zkuSH;xAdi&Hfe?O4J)I7xp^XC73(F3K0|cns-%8AGSlQ4r8Bu-(Q}&qmx0ZJiffY{ zQIX#1>(xPJl|TEn?MT`NGd%0;Z(~aMDe_SL3hux^A7@0K)f=k6?<24F)kM5$)MT?> zZOVcn2Te-?IHH^t1wk!iFXDVwG~M)_*WmV#b(&YRvie-(hDOe>uDE)Y@0UrsXB6fo zw>0cQ#Eve3yH1PlplT!cmafRKez6_z*^SA~z-nDJU9#I)Zo`1|zpKWu~!6iiNDl9S;%b z7Zus~^jDu(FFDhJc?K?GlHQ$fB(@0X3T{v27{+(@2dLs@z}!W>p&Ml*4w~aXX^O{% z=Brjhg-+${3sw$Di_Z)bf3_Z~B#{idQP z*wW8`aJ=b6q(!1Sv%!{d?@K!ZPr8!LAQhzK+){B~P}PFVKs!0L5UB{Se+LS~0pZs2 zZjF461M0PT26qcb{7lv18S`0Q8;*yzANcJ4+>9GZGqCKR6@9>DZx}~n$N~J zon#4zL{sW_eVVz`=amN4*NsNcrf=vvP(BM21U~pQiVEf@OSG>Oi#oU7(dL_KGy;Wg zvEdF=G&hDcWlF(lHcIgHkqXM*02!b8t|rj9%Z9H^gYhZLkXBSval>Y4jP~Z4cC2{o zTn=gGiEEOb76j*N1W+#>rOZPXlVrY4? zHFfar)d?g~EuC*<=|?o?-dU{)%K4YqADFR|<~YQ+?s!-N6#XXS+4$YVlJ8YfSOEB4 zwbO(e*czN*b0c#GnCsN z8pxSKldE53vg)?J#8A5a+hBLvWm8~YmLrQ=4Vk*H?!qUsNt-B(3duu;^@btCjeJu> z?&dMAIWPQeP^%ejL5eN_&)V zSe~V_trnrNzn#|f#B9EDpt_8;M<`h!ZJxQs<#{f(B+K*NvSNsqE_jr<< z_DB%5j{xO>VBp4fM@LEZ-@su35gX{DCSAbXnY6vyltowPA|i8Br-G&Si`uXBv@UfY zq)T+Lx#rj|^npV-mBF1phytv�~&`)&U#a`Vk}CI7$M()hH#`7l^>jz#7Jgqj$dT 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 O0RR6Xxx!HZyb1ujJ*tEN literal 0 HcmV?d00001 From 223a18766ad4bc079d461ef145e9b2e3e9fa2469 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Tue, 15 Sep 2020 08:49:20 +0100 Subject: [PATCH 10/26] [Alerting] Improves performance of the authorization filter in AlertsClient.find by skipping KQL parsing (#77040) The Alerts Authorisation now manually builds the authorization filter instead of parsing a KQL string in order to get around the performance issue we recently identified in KQL. --- .../alerts/server/alerts_client.test.ts | 14 +- x-pack/plugins/alerts/server/alerts_client.ts | 16 +- .../alerts_authorization.test.ts | 46 +----- .../authorization/alerts_authorization.ts | 41 +---- .../alerts_authorization_kuery.test.ts | 144 ++++++++++++++++++ .../alerts_authorization_kuery.ts | 61 ++++++++ .../alerts/server/authorization/index.ts | 7 + 7 files changed, 238 insertions(+), 91 deletions(-) create mode 100644 x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts create mode 100644 x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.ts create mode 100644 x-pack/plugins/alerts/server/authorization/index.ts diff --git a/x-pack/plugins/alerts/server/alerts_client.test.ts b/x-pack/plugins/alerts/server/alerts_client.test.ts index 801c2c8775361..b20e6c6be2ebf 100644 --- a/x-pack/plugins/alerts/server/alerts_client.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client.test.ts @@ -7,6 +7,8 @@ import uuid from 'uuid'; import { schema } from '@kbn/config-schema'; import { AlertsClient, CreateOptions, ConstructorOptions } from './alerts_client'; import { savedObjectsClientMock, loggingSystemMock } from '../../../../src/core/server/mocks'; +import { nodeTypes } from '../../../../src/plugins/data/common'; +import { esKuery } from '../../../../src/plugins/data/server'; import { taskManagerMock } from '../../task_manager/server/task_manager.mock'; import { alertTypeRegistryMock } from './alert_type_registry.mock'; import { alertsAuthorizationMock } from './authorization/alerts_authorization.mock'; @@ -2722,6 +2724,7 @@ describe('find()', () => { Array [ Object { "fields": undefined, + "filter": undefined, "type": "alert", }, ] @@ -2730,9 +2733,11 @@ describe('find()', () => { describe('authorization', () => { test('ensures user is query filter types down to those the user is authorized to find', async () => { + const filter = esKuery.fromKueryExpression( + '((alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myOtherApp))' + ); authorization.getFindAuthorizationFilter.mockResolvedValue({ - filter: - '((alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myOtherApp))', + filter, ensureAlertTypeIsAuthorized() {}, logSuccessfulAuthorization() {}, }); @@ -2741,8 +2746,8 @@ describe('find()', () => { await alertsClient.find({ options: { filter: 'someTerm' } }); const [options] = unsecuredSavedObjectsClient.find.mock.calls[0]; - expect(options.filter).toMatchInlineSnapshot( - `"someTerm and ((alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myOtherApp))"` + expect(options.filter).toEqual( + nodeTypes.function.buildNode('and', [esKuery.fromKueryExpression('someTerm'), filter]) ); expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledTimes(1); }); @@ -2759,7 +2764,6 @@ describe('find()', () => { const ensureAlertTypeIsAuthorized = jest.fn(); const logSuccessfulAuthorization = jest.fn(); authorization.getFindAuthorizationFilter.mockResolvedValue({ - filter: '', ensureAlertTypeIsAuthorized, logSuccessfulAuthorization, }); diff --git a/x-pack/plugins/alerts/server/alerts_client.ts b/x-pack/plugins/alerts/server/alerts_client.ts index 0703a1e13937c..f8da17f4bf089 100644 --- a/x-pack/plugins/alerts/server/alerts_client.ts +++ b/x-pack/plugins/alerts/server/alerts_client.ts @@ -13,6 +13,7 @@ import { SavedObjectReference, SavedObject, } from 'src/core/server'; +import { esKuery } from '../../../../src/plugins/data/server'; import { ActionsClient, ActionsAuthorization } from '../../actions/server'; import { Alert, @@ -37,11 +38,7 @@ import { TaskManagerStartContract } from '../../task_manager/server'; import { taskInstanceToAlertTaskInstance } from './task_runner/alert_task_instance'; import { deleteTaskIfItExists } from './lib/delete_task_if_it_exists'; import { RegistryAlertType } from './alert_type_registry'; -import { - AlertsAuthorization, - WriteOperations, - ReadOperations, -} from './authorization/alerts_authorization'; +import { AlertsAuthorization, WriteOperations, ReadOperations, and } from './authorization'; import { IEventLogClient } from '../../../plugins/event_log/server'; import { parseIsoOrRelativeDate } from './lib/iso_or_relative_date'; import { alertInstanceSummaryFromEventLog } from './lib/alert_instance_summary_from_event_log'; @@ -339,11 +336,6 @@ export class AlertsClient { logSuccessfulAuthorization, } = await this.authorization.getFindAuthorizationFilter(); - if (authorizationFilter) { - options.filter = options.filter - ? `${options.filter} and ${authorizationFilter}` - : authorizationFilter; - } const { page, per_page: perPage, @@ -351,6 +343,10 @@ export class AlertsClient { saved_objects: data, } = await this.unsecuredSavedObjectsClient.find({ ...options, + filter: + (authorizationFilter && options.filter + ? and([esKuery.fromKueryExpression(options.filter), authorizationFilter]) + : authorizationFilter) ?? options.filter, fields: fields ? this.includeFieldsRequiredForAuthentication(fields) : fields, type: 'alert', }); diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts index c2506381b9df9..9515987af8dd9 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts @@ -6,17 +6,13 @@ import { KibanaRequest } from 'kibana/server'; import { alertTypeRegistryMock } from '../alert_type_registry.mock'; import { securityMock } from '../../../../plugins/security/server/mocks'; +import { esKuery } from '../../../../../src/plugins/data/server'; import { PluginStartContract as FeaturesStartContract, KibanaFeature, } from '../../../features/server'; import { featuresPluginMock } from '../../../features/server/mocks'; -import { - AlertsAuthorization, - ensureFieldIsSafeForQuery, - WriteOperations, - ReadOperations, -} from './alerts_authorization'; +import { AlertsAuthorization, WriteOperations, ReadOperations } from './alerts_authorization'; import { alertsAuthorizationAuditLoggerMock } from './audit_logger.mock'; import { AlertsAuthorizationAuditLogger, AuthorizationResult } from './audit_logger'; import uuid from 'uuid'; @@ -616,8 +612,10 @@ describe('AlertsAuthorization', () => { }); alertTypeRegistry.list.mockReturnValue(setOfAlertTypes); - expect((await alertAuthorization.getFindAuthorizationFilter()).filter).toMatchInlineSnapshot( - `"((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:myOtherAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:mySecondAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)))"` + expect((await alertAuthorization.getFindAuthorizationFilter()).filter).toEqual( + esKuery.fromKueryExpression( + `((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:myOtherAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:mySecondAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)))` + ) ); expect(auditLogger.alertsAuthorizationSuccess).not.toHaveBeenCalled(); @@ -1246,36 +1244,4 @@ describe('AlertsAuthorization', () => { `); }); }); - - describe('ensureFieldIsSafeForQuery', () => { - test('throws if field contains character that isnt safe in a KQL query', () => { - expect(() => ensureFieldIsSafeForQuery('id', 'alert-*')).toThrowError( - `expected id not to include invalid character: *` - ); - - expect(() => ensureFieldIsSafeForQuery('id', '<=""')).toThrowError( - `expected id not to include invalid character: <=` - ); - - expect(() => ensureFieldIsSafeForQuery('id', '>=""')).toThrowError( - `expected id not to include invalid character: >=` - ); - - expect(() => ensureFieldIsSafeForQuery('id', '1 or alertid:123')).toThrowError( - `expected id not to include whitespace and invalid character: :` - ); - - expect(() => ensureFieldIsSafeForQuery('id', ') or alertid:123')).toThrowError( - `expected id not to include whitespace and invalid characters: ), :` - ); - - expect(() => ensureFieldIsSafeForQuery('id', 'some space')).toThrowError( - `expected id not to include whitespace` - ); - }); - - test('doesnt throws if field is safe as part of a KQL query', () => { - expect(() => ensureFieldIsSafeForQuery('id', '123-0456-678')).not.toThrow(); - }); - }); }); diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts index 9dda006c1eb8e..20b9fecd601e6 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts @@ -5,7 +5,7 @@ */ import Boom from 'boom'; -import { map, mapValues, remove, fromPairs, has } from 'lodash'; +import { map, mapValues, fromPairs, has } from 'lodash'; import { KibanaRequest } from 'src/core/server'; import { ALERTS_FEATURE_ID } from '../../common'; import { AlertTypeRegistry } from '../types'; @@ -14,6 +14,8 @@ import { RegistryAlertType } from '../alert_type_registry'; import { PluginStartContract as FeaturesPluginStart } from '../../../features/server'; import { AlertsAuthorizationAuditLogger, ScopeType } from './audit_logger'; import { Space } from '../../../spaces/server'; +import { asFiltersByAlertTypeAndConsumer } from './alerts_authorization_kuery'; +import { KueryNode } from '../../../../../src/plugins/data/server'; export enum ReadOperations { Get = 'get', @@ -215,7 +217,7 @@ export class AlertsAuthorization { } public async getFindAuthorizationFilter(): Promise<{ - filter?: string; + filter?: KueryNode; ensureAlertTypeIsAuthorized: (alertTypeId: string, consumer: string) => void; logSuccessfulAuthorization: () => void; }> { @@ -244,7 +246,7 @@ export class AlertsAuthorization { const authorizedEntries: Map> = new Map(); return { - filter: `(${this.asFiltersByAlertTypeAndConsumer(authorizedAlertTypes).join(' or ')})`, + filter: asFiltersByAlertTypeAndConsumer(authorizedAlertTypes), ensureAlertTypeIsAuthorized: (alertTypeId: string, consumer: string) => { if (!authorizedAlertTypeIdsToConsumers.has(`${alertTypeId}/${consumer}`)) { throw Boom.forbidden( @@ -400,39 +402,6 @@ export class AlertsAuthorization { })) ); } - - private asFiltersByAlertTypeAndConsumer(alertTypes: Set): string[] { - return Array.from(alertTypes).reduce((filters, { id, authorizedConsumers }) => { - ensureFieldIsSafeForQuery('alertTypeId', id); - filters.push( - `(alert.attributes.alertTypeId:${id} and alert.attributes.consumer:(${Object.keys( - authorizedConsumers - ) - .map((consumer) => { - ensureFieldIsSafeForQuery('alertTypeId', id); - return consumer; - }) - .join(' or ')}))` - ); - return filters; - }, []); - } -} - -export function ensureFieldIsSafeForQuery(field: string, value: string): boolean { - const invalid = value.match(/([>=<\*:()]+|\s+)/g); - if (invalid) { - const whitespace = remove(invalid, (chars) => chars.trim().length === 0); - const errors = []; - if (whitespace.length) { - errors.push(`whitespace`); - } - if (invalid.length) { - errors.push(`invalid character${invalid.length > 1 ? `s` : ``}: ${invalid?.join(`, `)}`); - } - throw new Error(`expected ${field} not to include ${errors.join(' and ')}`); - } - return true; } function mergeHasPrivileges(left: HasPrivileges, right?: HasPrivileges): HasPrivileges { diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts new file mode 100644 index 0000000000000..e4b9f8c54c38d --- /dev/null +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts @@ -0,0 +1,144 @@ +/* + * 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 { esKuery } from '../../../../../src/plugins/data/server'; +import { + asFiltersByAlertTypeAndConsumer, + ensureFieldIsSafeForQuery, +} from './alerts_authorization_kuery'; + +describe('asFiltersByAlertTypeAndConsumer', () => { + test('constructs filter for single alert type with single authorized consumer', async () => { + expect( + asFiltersByAlertTypeAndConsumer( + new Set([ + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'myAppAlertType', + name: 'myAppAlertType', + producer: 'myApp', + authorizedConsumers: { + myApp: { read: true, all: true }, + }, + }, + ]) + ) + ).toEqual( + esKuery.fromKueryExpression( + `((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(myApp)))` + ) + ); + }); + + test('constructs filter for single alert type with multiple authorized consumer', async () => { + expect( + asFiltersByAlertTypeAndConsumer( + new Set([ + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'myAppAlertType', + name: 'myAppAlertType', + producer: 'myApp', + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + }, + }, + ]) + ) + ).toEqual( + esKuery.fromKueryExpression( + `((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp)))` + ) + ); + }); + + test('constructs filter for multiple alert types across authorized consumer', async () => { + expect( + asFiltersByAlertTypeAndConsumer( + new Set([ + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'myAppAlertType', + name: 'myAppAlertType', + producer: 'myApp', + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, + }, + }, + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'myOtherAppAlertType', + name: 'myOtherAppAlertType', + producer: 'alerts', + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, + }, + }, + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'mySecondAppAlertType', + name: 'mySecondAppAlertType', + producer: 'myApp', + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, + }, + }, + ]) + ) + ).toEqual( + esKuery.fromKueryExpression( + `((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:myOtherAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:mySecondAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)))` + ) + ); + }); +}); + +describe('ensureFieldIsSafeForQuery', () => { + test('throws if field contains character that isnt safe in a KQL query', () => { + expect(() => ensureFieldIsSafeForQuery('id', 'alert-*')).toThrowError( + `expected id not to include invalid character: *` + ); + + expect(() => ensureFieldIsSafeForQuery('id', '<=""')).toThrowError( + `expected id not to include invalid character: <=` + ); + + expect(() => ensureFieldIsSafeForQuery('id', '>=""')).toThrowError( + `expected id not to include invalid character: >=` + ); + + expect(() => ensureFieldIsSafeForQuery('id', '1 or alertid:123')).toThrowError( + `expected id not to include whitespace and invalid character: :` + ); + + expect(() => ensureFieldIsSafeForQuery('id', ') or alertid:123')).toThrowError( + `expected id not to include whitespace and invalid characters: ), :` + ); + + expect(() => ensureFieldIsSafeForQuery('id', 'some space')).toThrowError( + `expected id not to include whitespace` + ); + }); + + test('doesnt throws if field is safe as part of a KQL query', () => { + expect(() => ensureFieldIsSafeForQuery('id', '123-0456-678')).not.toThrow(); + }); +}); diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.ts new file mode 100644 index 0000000000000..f236ee7f3c258 --- /dev/null +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.ts @@ -0,0 +1,61 @@ +/* + * 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 { remove } from 'lodash'; +import { nodeTypes } from '../../../../../src/plugins/data/common'; +import { KueryNode } from '../../../../../src/plugins/data/server'; +import { RegistryAlertTypeWithAuth } from './alerts_authorization'; + +export const is = (fieldName: string, value: string | KueryNode) => + nodeTypes.function.buildNodeWithArgumentNodes('is', [ + nodeTypes.literal.buildNode(fieldName), + typeof value === 'string' ? nodeTypes.literal.buildNode(value) : value, + nodeTypes.literal.buildNode(false), + ]); + +export const or = ([first, ...args]: KueryNode[]): KueryNode => + args.length ? nodeTypes.function.buildNode('or', [first, or(args)]) : first; + +export const and = ([first, ...args]: KueryNode[]): KueryNode => + args.length ? nodeTypes.function.buildNode('and', [first, and(args)]) : first; + +export function asFiltersByAlertTypeAndConsumer( + alertTypes: Set +): KueryNode { + return or( + Array.from(alertTypes).reduce((filters, { id, authorizedConsumers }) => { + ensureFieldIsSafeForQuery('alertTypeId', id); + filters.push( + and([ + is(`alert.attributes.alertTypeId`, id), + or( + Object.keys(authorizedConsumers).map((consumer) => { + ensureFieldIsSafeForQuery('consumer', consumer); + return is(`alert.attributes.consumer`, consumer); + }) + ), + ]) + ); + return filters; + }, []) + ); +} + +export function ensureFieldIsSafeForQuery(field: string, value: string): boolean { + const invalid = value.match(/([>=<\*:()]+|\s+)/g); + if (invalid) { + const whitespace = remove(invalid, (chars) => chars.trim().length === 0); + const errors = []; + if (whitespace.length) { + errors.push(`whitespace`); + } + if (invalid.length) { + errors.push(`invalid character${invalid.length > 1 ? `s` : ``}: ${invalid?.join(`, `)}`); + } + throw new Error(`expected ${field} not to include ${errors.join(' and ')}`); + } + return true; +} diff --git a/x-pack/plugins/alerts/server/authorization/index.ts b/x-pack/plugins/alerts/server/authorization/index.ts new file mode 100644 index 0000000000000..66c7f0afd0122 --- /dev/null +++ b/x-pack/plugins/alerts/server/authorization/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +export * from './alerts_authorization'; +export * from './alerts_authorization_kuery'; From 280777dc099c3f2efd9c562f0f72bcfdf89e5f6b Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Tue, 15 Sep 2020 08:49:45 +0100 Subject: [PATCH 11/26] [Security Solution] Add unit tests for Network search strategy (#77416) * init tests * add unit tests for network * add more tests * remove reponse from inspect for hostDetails --- .../factory/hosts/details/__mocks__/index.ts | 1091 ++++------------- .../factory/hosts/details/index.ts | 2 - .../details/query.host_details.dsl.test.ts | 6 +- .../network/details/__mocks__/index.ts | 377 ++++++ .../factory/network/details/index.test.ts | 35 + .../details/query.details_network.dsl.test.ts | 13 + .../factory/network/dns/__mocks__/index.ts | 185 +++ .../factory/network/dns/index.test.ts | 35 + .../network/dns/query.dns_network.dsl.test.ts | 13 + .../factory/network/http/__mocks__/index.ts | 670 ++++++++++ .../factory/network/http/index.test.ts | 35 + .../http/query.http_network.dsl.test.ts | 13 + .../network/http/query.http_network.dsl.ts | 1 + .../factory/network/index.test.ts | 41 + .../network/overview/__mocks__/index.ts | 213 ++++ .../factory/network/overview/index.test.ts | 35 + .../query.overview_network.dsl.test.ts | 13 + .../factory/network/tls/__mocks__/index.ts | 109 ++ .../factory/network/tls/index.test.ts | 35 + .../network/tls/query.tls_network.dsl.test.ts | 13 + .../network/top_countries/__mocks__/index.ts | 109 ++ .../network/top_countries/index.test.ts | 35 + .../factory/network/top_countries/index.ts | 1 - .../query.top_countries_network.dsl.test.ts | 13 + .../network/top_n_flow/__mocks__/index.ts | 847 +++++++++++++ .../factory/network/top_n_flow/index.test.ts | 35 + .../query.top_n_flow_network.dsl.test.ts | 13 + .../factory/network/users/__mocks__/index.ts | 170 +++ .../factory/network/users/helpers.test.ts | 15 + .../factory/network/users/index.test.ts | 51 + .../users/query.users_network.dsl.test.ts | 13 + 31 files changed, 3345 insertions(+), 892 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/query.details_network.dsl.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/query.dns_network.dsl.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/query.overview_network.dsl.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/query.tls_network.dsl.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network.dsl.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network.dsl.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/__mocks__/index.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/helpers.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/query.users_network.dsl.test.ts diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/__mocks__/index.ts index 7403adfd9a659..dbd2591c8af7b 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/__mocks__/index.ts @@ -5,8 +5,11 @@ */ import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; import { + Direction, HostsQueries, HostDetailsRequestOptions, + SortField, + HostsFields, } from '../../../../../../../common/search_strategy'; export const mockOptions: HostDetailsRequestOptions = { @@ -421,8 +424,9 @@ export const mockOptions: HostDetailsRequestOptions = { format: 'date_time', }, ], - factoryQueryType: HostsQueries.authentications, - filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + factoryQueryType: HostsQueries.details, + filterQuery: + '{"bool":{"must":[],"filter":[{"match_all":{}},{"match_phrase":{"host.name":{"query":"bastion00.siem.estc.dev"}}}],"should":[],"must_not":[]}}', pagination: { activePage: 0, cursorStart: 0, @@ -434,860 +438,15 @@ export const mockOptions: HostDetailsRequestOptions = { from: '2020-09-02T15:17:13.678Z', to: '2020-09-03T15:17:13.678Z', }, - hostName: 'bastion00', -}; - -export const mockSearchStrategyResponse: IEsSearchResponse = { - isPartial: false, - isRunning: false, - rawResponse: { - took: 14, - timed_out: false, - _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, - hits: { total: -1, max_score: 0, hits: [] }, - aggregations: { - group_by_users: { - doc_count_error_upper_bound: -1, - sum_other_doc_count: 408, - buckets: [ - { - key: 'SYSTEM', - doc_count: 281, - failures: { - meta: {}, - doc_count: 0, - lastFailure: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - successes: { - meta: {}, - doc_count: 4, - lastSuccess: { - hits: { - total: 4, - max_score: 0, - hits: [ - { - _index: 'winlogbeat-8.0.0-2020.09.02-000001', - _id: 'zqY7WXQBA6bGZw2uLeKI', - _score: null, - _source: { - process: { - name: 'services.exe', - pid: 564, - executable: 'C:\\Windows\\System32\\services.exe', - }, - agent: { - build_date: '2020-07-16 09:16:27 +0000 UTC ', - name: 'siem-windows', - commit: '4dcbde39492bdc3843034bba8db811c68cb44b97 ', - id: '05e1bff7-d7a8-416a-8554-aa10288fa07d', - type: 'winlogbeat', - ephemeral_id: '655abd6c-6c33-435d-a2eb-79b2a01e6d61', - version: '8.0.0', - user: { name: 'inside_winlogbeat_user' }, - }, - winlog: { - computer_name: 'siem-windows', - process: { pid: 576, thread: { id: 880 } }, - keywords: ['Audit Success'], - logon: { id: '0x3e7', type: 'Service' }, - channel: 'Security', - event_data: { - LogonGuid: '{00000000-0000-0000-0000-000000000000}', - TargetOutboundDomainName: '-', - VirtualAccount: '%%1843', - LogonType: '5', - IpPort: '-', - TransmittedServices: '-', - SubjectLogonId: '0x3e7', - LmPackageName: '-', - TargetOutboundUserName: '-', - KeyLength: '0', - TargetLogonId: '0x3e7', - RestrictedAdminMode: '-', - SubjectUserName: 'SIEM-WINDOWS$', - TargetLinkedLogonId: '0x0', - ElevatedToken: '%%1842', - SubjectDomainName: 'WORKGROUP', - IpAddress: '-', - ImpersonationLevel: '%%1833', - TargetUserName: 'SYSTEM', - LogonProcessName: 'Advapi ', - TargetDomainName: 'NT AUTHORITY', - SubjectUserSid: 'S-1-5-18', - TargetUserSid: 'S-1-5-18', - AuthenticationPackageName: 'Negotiate', - }, - opcode: 'Info', - version: 2, - record_id: 57818, - task: 'Logon', - event_id: 4624, - provider_guid: '{54849625-5478-4994-a5ba-3e3b0328c30d}', - activity_id: '{d2485217-6bac-0000-8fbb-3f7e2571d601}', - api: 'wineventlog', - provider_name: 'Microsoft-Windows-Security-Auditing', - }, - log: { level: 'information' }, - source: { domain: '-' }, - message: - 'An account was successfully logged on.\n\nSubject:\n\tSecurity ID:\t\tS-1-5-18\n\tAccount Name:\t\tSIEM-WINDOWS$\n\tAccount Domain:\t\tWORKGROUP\n\tLogon ID:\t\t0x3E7\n\nLogon Information:\n\tLogon Type:\t\t5\n\tRestricted Admin Mode:\t-\n\tVirtual Account:\t\tNo\n\tElevated Token:\t\tYes\n\nImpersonation Level:\t\tImpersonation\n\nNew Logon:\n\tSecurity ID:\t\tS-1-5-18\n\tAccount Name:\t\tSYSTEM\n\tAccount Domain:\t\tNT AUTHORITY\n\tLogon ID:\t\t0x3E7\n\tLinked Logon ID:\t\t0x0\n\tNetwork Account Name:\t-\n\tNetwork Account Domain:\t-\n\tLogon GUID:\t\t{00000000-0000-0000-0000-000000000000}\n\nProcess Information:\n\tProcess ID:\t\t0x234\n\tProcess Name:\t\tC:\\Windows\\System32\\services.exe\n\nNetwork Information:\n\tWorkstation Name:\t-\n\tSource Network Address:\t-\n\tSource Port:\t\t-\n\nDetailed Authentication Information:\n\tLogon Process:\t\tAdvapi \n\tAuthentication Package:\tNegotiate\n\tTransited Services:\t-\n\tPackage Name (NTLM only):\t-\n\tKey Length:\t\t0\n\nThis event is generated when a logon session is created. It is generated on the computer that was accessed.\n\nThe subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe.\n\nThe logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network).\n\nThe New Logon fields indicate the account for whom the new logon was created, i.e. the account that was logged on.\n\nThe network fields indicate where a remote logon request originated. Workstation name is not always available and may be left blank in some cases.\n\nThe impersonation level field indicates the extent to which a process in the logon session can impersonate.\n\nThe authentication information fields provide detailed information about this specific logon request.\n\t- Logon GUID is a unique identifier that can be used to correlate this event with a KDC event.\n\t- Transited services indicate which intermediate services have participated in this logon request.\n\t- Package name indicates which sub-protocol was used among the NTLM protocols.\n\t- Key length indicates the length of the generated session key. This will be 0 if no session key was requested.', - cloud: { - availability_zone: 'us-central1-c', - instance: { name: 'siem-windows', id: '9156726559029788564' }, - provider: 'gcp', - machine: { type: 'g1-small' }, - project: { id: 'elastic-siem' }, - }, - '@timestamp': '2020-09-04T13:08:02.532Z', - related: { user: ['SYSTEM', 'SIEM-WINDOWS$'] }, - ecs: { version: '1.5.0' }, - host: { - hostname: 'siem-windows', - os: { - build: '17763.1397', - kernel: '10.0.17763.1397 (WinBuild.160101.0800)', - name: 'Windows Server 2019 Datacenter', - family: 'windows', - version: '10.0', - platform: 'windows', - }, - ip: ['fe80::ecf5:decc:3ec3:767e', '10.200.0.15'], - name: 'siem-windows', - id: 'ce1d3c9b-a815-4643-9641-ada0f2c00609', - mac: ['42:01:0a:c8:00:0f'], - architecture: 'x86_64', - }, - event: { - code: 4624, - provider: 'Microsoft-Windows-Security-Auditing', - created: '2020-09-04T13:08:03.638Z', - kind: 'event', - module: 'security', - action: 'logged-in', - category: 'authentication', - type: 'start', - outcome: 'success', - }, - user: { domain: 'NT AUTHORITY', name: 'SYSTEM', id: 'S-1-5-18' }, - }, - sort: [1599224882532], - }, - ], - }, - }, - }, - }, - { - key: 'tsg', - doc_count: 1, - failures: { - doc_count: 0, - lastFailure: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - successes: { - doc_count: 1, - lastSuccess: { - hits: { - total: 1, - max_score: 0, - hits: [ - { - _index: '.ds-logs-system.auth-default-000001', - _id: '9_sfWXQBc39KFIJbIsDh', - _score: null, - _source: { - agent: { - hostname: 'siem-kibana', - name: 'siem-kibana', - id: 'aa3d9dc7-fef1-4c2f-a68d-25785d624e35', - ephemeral_id: 'e503bd85-11c7-4bc9-ae7d-70be1d919fb7', - type: 'filebeat', - version: '7.9.1', - }, - process: { name: 'sshd', pid: 20764 }, - log: { file: { path: '/var/log/auth.log' }, offset: 552463 }, - source: { - geo: { - continent_name: 'Europe', - region_iso_code: 'DE-BE', - city_name: 'Berlin', - country_iso_code: 'DE', - region_name: 'Land Berlin', - location: { lon: 13.3512, lat: 52.5727 }, - }, - as: { number: 6805, organization: { name: 'Telefonica Germany' } }, - port: 57457, - ip: '77.183.42.188', - }, - cloud: { - availability_zone: 'us-east1-b', - instance: { name: 'siem-kibana', id: '5412578377715150143' }, - provider: 'gcp', - machine: { type: 'n1-standard-2' }, - project: { id: 'elastic-beats' }, - }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T11:49:21.000Z', - system: { - auth: { - ssh: { - method: 'publickey', - signature: 'RSA SHA256:vv64JNLzKZWYA9vonnGWuW7zxWhyZrL/BFxyIGbISx8', - event: 'Accepted', - }, - }, - }, - ecs: { version: '1.5.0' }, - data_stream: { namespace: 'default', type: 'logs', dataset: 'system.auth' }, - host: { - hostname: 'siem-kibana', - os: { - kernel: '4.9.0-8-amd64', - codename: 'stretch', - name: 'Debian GNU/Linux', - family: 'debian', - version: '9 (stretch)', - platform: 'debian', - }, - containerized: false, - ip: ['10.142.0.7', 'fe80::4001:aff:fe8e:7'], - name: 'siem-kibana', - id: 'aa7ca589f1b8220002f2fc61c64cfbf1', - mac: ['42:01:0a:8e:00:07'], - architecture: 'x86_64', - }, - event: { - timezone: '+00:00', - action: 'ssh_login', - type: 'authentication_success', - category: 'authentication', - dataset: 'system.auth', - outcome: 'success', - }, - user: { name: 'tsg' }, - }, - sort: [1599220161000], - }, - ], - }, - }, - }, - }, - { - key: 'admin', - doc_count: 23, - failures: { - doc_count: 23, - lastFailure: { - hits: { - total: 23, - max_score: 0, - hits: [ - { - _index: '.ds-logs-system.auth-default-000001', - _id: 'ZfxZWXQBc39KFIJbLN5U', - _score: null, - _source: { - agent: { - hostname: 'siem-kibana', - name: 'siem-kibana', - id: 'aa3d9dc7-fef1-4c2f-a68d-25785d624e35', - ephemeral_id: 'e503bd85-11c7-4bc9-ae7d-70be1d919fb7', - type: 'filebeat', - version: '7.9.1', - }, - process: { name: 'sshd', pid: 22913 }, - log: { file: { path: '/var/log/auth.log' }, offset: 562910 }, - source: { - geo: { - continent_name: 'Asia', - region_iso_code: 'KR-28', - city_name: 'Incheon', - country_iso_code: 'KR', - region_name: 'Incheon', - location: { lon: 126.7288, lat: 37.4562 }, - }, - as: { number: 4766, organization: { name: 'Korea Telecom' } }, - ip: '59.15.3.197', - }, - cloud: { - availability_zone: 'us-east1-b', - instance: { name: 'siem-kibana', id: '5412578377715150143' }, - provider: 'gcp', - machine: { type: 'n1-standard-2' }, - project: { id: 'elastic-beats' }, - }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T13:40:46.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - data_stream: { namespace: 'default', type: 'logs', dataset: 'system.auth' }, - host: { - hostname: 'siem-kibana', - os: { - kernel: '4.9.0-8-amd64', - codename: 'stretch', - name: 'Debian GNU/Linux', - family: 'debian', - version: '9 (stretch)', - platform: 'debian', - }, - containerized: false, - ip: ['10.142.0.7', 'fe80::4001:aff:fe8e:7'], - name: 'siem-kibana', - id: 'aa7ca589f1b8220002f2fc61c64cfbf1', - mac: ['42:01:0a:8e:00:07'], - architecture: 'x86_64', - }, - event: { - timezone: '+00:00', - action: 'ssh_login', - type: 'authentication_failure', - category: 'authentication', - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'admin' }, - }, - sort: [1599226846000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'user', - doc_count: 21, - failures: { - doc_count: 21, - lastFailure: { - hits: { - total: 21, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'M_xLWXQBc39KFIJbY7Cb', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - type: 'filebeat', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 20671 }, - log: { file: { path: '/var/log/auth.log' }, offset: 1028103 }, - source: { - geo: { - continent_name: 'North America', - region_iso_code: 'US-NY', - city_name: 'New York', - country_iso_code: 'US', - region_name: 'New York', - location: { lon: -74, lat: 40.7157 }, - }, - ip: '64.227.88.245', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T13:25:43.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['64.227.88.245'], user: ['user'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T13:25:47.034172Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'user' }, - }, - sort: [1599225943000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'ubuntu', - doc_count: 18, - failures: { - doc_count: 18, - lastFailure: { - hits: { - total: 18, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'nPxKWXQBc39KFIJb7q4w', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - type: 'filebeat', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 20665 }, - log: { file: { path: '/var/log/auth.log' }, offset: 1027372 }, - source: { - geo: { - continent_name: 'North America', - region_iso_code: 'US-NY', - city_name: 'New York', - country_iso_code: 'US', - region_name: 'New York', - location: { lon: -74, lat: 40.7157 }, - }, - ip: '64.227.88.245', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T13:25:07.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['64.227.88.245'], user: ['ubuntu'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T13:25:16.974606Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'ubuntu' }, - }, - sort: [1599225907000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'odoo', - doc_count: 17, - failures: { - doc_count: 17, - lastFailure: { - hits: { - total: 17, - max_score: 0, - hits: [ - { - _index: '.ds-logs-system.auth-default-000001', - _id: 'mPsfWXQBc39KFIJbI8HI', - _score: null, - _source: { - agent: { - hostname: 'siem-kibana', - name: 'siem-kibana', - id: 'aa3d9dc7-fef1-4c2f-a68d-25785d624e35', - type: 'filebeat', - ephemeral_id: 'e503bd85-11c7-4bc9-ae7d-70be1d919fb7', - version: '7.9.1', - }, - process: { name: 'sshd', pid: 21506 }, - log: { file: { path: '/var/log/auth.log' }, offset: 556761 }, - source: { - geo: { - continent_name: 'Asia', - region_iso_code: 'IN-DL', - city_name: 'New Delhi', - country_iso_code: 'IN', - region_name: 'National Capital Territory of Delhi', - location: { lon: 77.2245, lat: 28.6358 }, - }, - as: { number: 10029, organization: { name: 'SHYAM SPECTRA PVT LTD' } }, - ip: '180.151.228.166', - }, - cloud: { - availability_zone: 'us-east1-b', - instance: { name: 'siem-kibana', id: '5412578377715150143' }, - provider: 'gcp', - machine: { type: 'n1-standard-2' }, - project: { id: 'elastic-beats' }, - }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T12:26:36.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - data_stream: { namespace: 'default', type: 'logs', dataset: 'system.auth' }, - host: { - hostname: 'siem-kibana', - os: { - kernel: '4.9.0-8-amd64', - codename: 'stretch', - name: 'Debian GNU/Linux', - family: 'debian', - version: '9 (stretch)', - platform: 'debian', - }, - containerized: false, - ip: ['10.142.0.7', 'fe80::4001:aff:fe8e:7'], - name: 'siem-kibana', - id: 'aa7ca589f1b8220002f2fc61c64cfbf1', - mac: ['42:01:0a:8e:00:07'], - architecture: 'x86_64', - }, - event: { - timezone: '+00:00', - action: 'ssh_login', - type: 'authentication_failure', - category: 'authentication', - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'odoo' }, - }, - sort: [1599222396000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'pi', - doc_count: 17, - failures: { - doc_count: 17, - lastFailure: { - hits: { - total: 17, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'aaToWHQBA6bGZw2uR-St', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - type: 'filebeat', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 20475 }, - log: { file: { path: '/var/log/auth.log' }, offset: 1019218 }, - source: { - geo: { - continent_name: 'Europe', - region_iso_code: 'SE-AB', - city_name: 'Stockholm', - country_iso_code: 'SE', - region_name: 'Stockholm', - location: { lon: 17.7833, lat: 59.25 }, - }, - as: { number: 8473, organization: { name: 'Bahnhof AB' } }, - ip: '178.174.148.58', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T11:37:22.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['178.174.148.58'], user: ['pi'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T11:37:31.797423Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'pi' }, - }, - sort: [1599219442000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'demo', - doc_count: 14, - failures: { - doc_count: 14, - lastFailure: { - hits: { - total: 14, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'VaP_V3QBA6bGZw2upUbg', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - type: 'filebeat', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 19849 }, - log: { file: { path: '/var/log/auth.log' }, offset: 981036 }, - source: { - geo: { - continent_name: 'Europe', - country_iso_code: 'HR', - location: { lon: 15.5, lat: 45.1667 }, - }, - as: { - number: 42864, - organization: { name: 'Giganet Internet Szolgaltato Kft' }, - }, - ip: '45.95.168.157', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T07:23:22.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['45.95.168.157'], user: ['demo'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T07:23:26.046346Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'demo' }, - }, - sort: [1599204202000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'git', - doc_count: 13, - failures: { - doc_count: 13, - lastFailure: { - hits: { - total: 13, - max_score: 0, - hits: [ - { - _index: '.ds-logs-system.auth-default-000001', - _id: 'PqYfWXQBA6bGZw2uIhVU', - _score: null, - _source: { - agent: { - hostname: 'siem-kibana', - name: 'siem-kibana', - id: 'aa3d9dc7-fef1-4c2f-a68d-25785d624e35', - ephemeral_id: 'e503bd85-11c7-4bc9-ae7d-70be1d919fb7', - type: 'filebeat', - version: '7.9.1', - }, - process: { name: 'sshd', pid: 20396 }, - log: { file: { path: '/var/log/auth.log' }, offset: 550795 }, - source: { - geo: { - continent_name: 'Asia', - region_iso_code: 'CN-BJ', - city_name: 'Beijing', - country_iso_code: 'CN', - region_name: 'Beijing', - location: { lon: 116.3889, lat: 39.9288 }, - }, - as: { - number: 45090, - organization: { - name: 'Shenzhen Tencent Computer Systems Company Limited', - }, - }, - ip: '123.206.30.76', - }, - cloud: { - availability_zone: 'us-east1-b', - instance: { name: 'siem-kibana', id: '5412578377715150143' }, - provider: 'gcp', - machine: { type: 'n1-standard-2' }, - project: { id: 'elastic-beats' }, - }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T11:20:26.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - data_stream: { namespace: 'default', type: 'logs', dataset: 'system.auth' }, - host: { - hostname: 'siem-kibana', - os: { - kernel: '4.9.0-8-amd64', - codename: 'stretch', - name: 'Debian GNU/Linux', - family: 'debian', - version: '9 (stretch)', - platform: 'debian', - }, - containerized: false, - ip: ['10.142.0.7', 'fe80::4001:aff:fe8e:7'], - name: 'siem-kibana', - id: 'aa7ca589f1b8220002f2fc61c64cfbf1', - mac: ['42:01:0a:8e:00:07'], - architecture: 'x86_64', - }, - event: { - timezone: '+00:00', - action: 'ssh_login', - type: 'authentication_failure', - category: 'authentication', - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'git' }, - }, - sort: [1599218426000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'webadmin', - doc_count: 13, - failures: { - doc_count: 13, - lastFailure: { - hits: { - total: 13, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'iMABWHQBB-gskclyitP-', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - type: 'filebeat', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 19870 }, - log: { file: { path: '/var/log/auth.log' }, offset: 984133 }, - source: { - geo: { - continent_name: 'Europe', - country_iso_code: 'HR', - location: { lon: 15.5, lat: 45.1667 }, - }, - as: { - number: 42864, - organization: { name: 'Giganet Internet Szolgaltato Kft' }, - }, - ip: '45.95.168.157', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T07:25:28.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['45.95.168.157'], user: ['webadmin'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T07:25:30.236651Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'webadmin' }, - }, - sort: [1599204328000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - ], - }, - user_count: { value: 188 }, - }, - }, - total: 21, - loaded: 21, -}; + sort: ({ + direction: Direction.desc, + field: 'success', + } as unknown) as SortField, + params: {}, + hostName: 'bastion00.siem.estc.dev', +} as HostDetailsRequestOptions; -export const formattedSearchStrategyResponse = { +export const mockSearchStrategyResponse: IEsSearchResponse = { isPartial: false, isRunning: false, rawResponse: { @@ -2132,12 +1291,12 @@ export const formattedSearchStrategyResponse = { }, total: 21, loaded: 21, +}; + +export const formattedSearchStrategyResponse = { inspect: { dsl: [ - '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "host_architecture": {\n "terms": {\n "field": "host.architecture",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_id": {\n "terms": {\n "field": "host.id",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_ip": {\n "terms": {\n "field": "host.ip",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_mac": {\n "terms": {\n "field": "host.mac",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_name": {\n "terms": {\n "field": "host.name",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_family": {\n "terms": {\n "field": "host.os.family",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_name": {\n "terms": {\n "field": "host.os.name",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_platform": {\n "terms": {\n "field": "host.os.platform",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_version": {\n "terms": {\n "field": "host.os.version",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_instance_id": {\n "terms": {\n "field": "cloud.instance.id",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_machine_type": {\n "terms": {\n "field": "cloud.machine.type",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_provider": {\n "terms": {\n "field": "cloud.provider",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_region": {\n "terms": {\n "field": "cloud.region",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n {\n "term": {\n "host.name": "bastion00"\n }\n },\n {\n "range": {\n "@timestamp": {\n "format": "strict_date_optional_time",\n "gte": "2020-09-02T15:17:13.678Z",\n "lte": "2020-09-03T15:17:13.678Z"\n }\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', - ], - response: [ - '{\n "isPartial": false,\n "isRunning": false,\n "rawResponse": {\n "took": 14,\n "timed_out": false,\n "_shards": {\n "total": 21,\n "successful": 21,\n "skipped": 0,\n "failed": 0\n },\n "hits": {\n "total": -1,\n "max_score": 0,\n "hits": []\n },\n "aggregations": {\n "group_by_users": {\n "doc_count_error_upper_bound": -1,\n "sum_other_doc_count": 408,\n "buckets": [\n {\n "key": "SYSTEM",\n "doc_count": 281,\n "failures": {\n "meta": {},\n "doc_count": 0,\n "lastFailure": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n },\n "successes": {\n "meta": {},\n "doc_count": 4,\n "lastSuccess": {\n "hits": {\n "total": 4,\n "max_score": 0,\n "hits": [\n {\n "_index": "winlogbeat-8.0.0-2020.09.02-000001",\n "_id": "zqY7WXQBA6bGZw2uLeKI",\n "_score": null,\n "_source": {\n "process": {\n "name": "services.exe",\n "pid": 564,\n "executable": "C:\\\\Windows\\\\System32\\\\services.exe"\n },\n "agent": {\n "build_date": "2020-07-16 09:16:27 +0000 UTC ",\n "name": "siem-windows",\n "commit": "4dcbde39492bdc3843034bba8db811c68cb44b97 ",\n "id": "05e1bff7-d7a8-416a-8554-aa10288fa07d",\n "type": "winlogbeat",\n "ephemeral_id": "655abd6c-6c33-435d-a2eb-79b2a01e6d61",\n "version": "8.0.0",\n "user": {\n "name": "inside_winlogbeat_user"\n }\n },\n "winlog": {\n "computer_name": "siem-windows",\n "process": {\n "pid": 576,\n "thread": {\n "id": 880\n }\n },\n "keywords": [\n "Audit Success"\n ],\n "logon": {\n "id": "0x3e7",\n "type": "Service"\n },\n "channel": "Security",\n "event_data": {\n "LogonGuid": "{00000000-0000-0000-0000-000000000000}",\n "TargetOutboundDomainName": "-",\n "VirtualAccount": "%%1843",\n "LogonType": "5",\n "IpPort": "-",\n "TransmittedServices": "-",\n "SubjectLogonId": "0x3e7",\n "LmPackageName": "-",\n "TargetOutboundUserName": "-",\n "KeyLength": "0",\n "TargetLogonId": "0x3e7",\n "RestrictedAdminMode": "-",\n "SubjectUserName": "SIEM-WINDOWS$",\n "TargetLinkedLogonId": "0x0",\n "ElevatedToken": "%%1842",\n "SubjectDomainName": "WORKGROUP",\n "IpAddress": "-",\n "ImpersonationLevel": "%%1833",\n "TargetUserName": "SYSTEM",\n "LogonProcessName": "Advapi ",\n "TargetDomainName": "NT AUTHORITY",\n "SubjectUserSid": "S-1-5-18",\n "TargetUserSid": "S-1-5-18",\n "AuthenticationPackageName": "Negotiate"\n },\n "opcode": "Info",\n "version": 2,\n "record_id": 57818,\n "task": "Logon",\n "event_id": 4624,\n "provider_guid": "{54849625-5478-4994-a5ba-3e3b0328c30d}",\n "activity_id": "{d2485217-6bac-0000-8fbb-3f7e2571d601}",\n "api": "wineventlog",\n "provider_name": "Microsoft-Windows-Security-Auditing"\n },\n "log": {\n "level": "information"\n },\n "source": {\n "domain": "-"\n },\n "message": "An account was successfully logged on.\\n\\nSubject:\\n\\tSecurity ID:\\t\\tS-1-5-18\\n\\tAccount Name:\\t\\tSIEM-WINDOWS$\\n\\tAccount Domain:\\t\\tWORKGROUP\\n\\tLogon ID:\\t\\t0x3E7\\n\\nLogon Information:\\n\\tLogon Type:\\t\\t5\\n\\tRestricted Admin Mode:\\t-\\n\\tVirtual Account:\\t\\tNo\\n\\tElevated Token:\\t\\tYes\\n\\nImpersonation Level:\\t\\tImpersonation\\n\\nNew Logon:\\n\\tSecurity ID:\\t\\tS-1-5-18\\n\\tAccount Name:\\t\\tSYSTEM\\n\\tAccount Domain:\\t\\tNT AUTHORITY\\n\\tLogon ID:\\t\\t0x3E7\\n\\tLinked Logon ID:\\t\\t0x0\\n\\tNetwork Account Name:\\t-\\n\\tNetwork Account Domain:\\t-\\n\\tLogon GUID:\\t\\t{00000000-0000-0000-0000-000000000000}\\n\\nProcess Information:\\n\\tProcess ID:\\t\\t0x234\\n\\tProcess Name:\\t\\tC:\\\\Windows\\\\System32\\\\services.exe\\n\\nNetwork Information:\\n\\tWorkstation Name:\\t-\\n\\tSource Network Address:\\t-\\n\\tSource Port:\\t\\t-\\n\\nDetailed Authentication Information:\\n\\tLogon Process:\\t\\tAdvapi \\n\\tAuthentication Package:\\tNegotiate\\n\\tTransited Services:\\t-\\n\\tPackage Name (NTLM only):\\t-\\n\\tKey Length:\\t\\t0\\n\\nThis event is generated when a logon session is created. It is generated on the computer that was accessed.\\n\\nThe subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe.\\n\\nThe logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network).\\n\\nThe New Logon fields indicate the account for whom the new logon was created, i.e. the account that was logged on.\\n\\nThe network fields indicate where a remote logon request originated. Workstation name is not always available and may be left blank in some cases.\\n\\nThe impersonation level field indicates the extent to which a process in the logon session can impersonate.\\n\\nThe authentication information fields provide detailed information about this specific logon request.\\n\\t- Logon GUID is a unique identifier that can be used to correlate this event with a KDC event.\\n\\t- Transited services indicate which intermediate services have participated in this logon request.\\n\\t- Package name indicates which sub-protocol was used among the NTLM protocols.\\n\\t- Key length indicates the length of the generated session key. This will be 0 if no session key was requested.",\n "cloud": {\n "availability_zone": "us-central1-c",\n "instance": {\n "name": "siem-windows",\n "id": "9156726559029788564"\n },\n "provider": "gcp",\n "machine": {\n "type": "g1-small"\n },\n "project": {\n "id": "elastic-siem"\n }\n },\n "@timestamp": "2020-09-04T13:08:02.532Z",\n "related": {\n "user": [\n "SYSTEM",\n "SIEM-WINDOWS$"\n ]\n },\n "ecs": {\n "version": "1.5.0"\n },\n "host": {\n "hostname": "siem-windows",\n "os": {\n "build": "17763.1397",\n "kernel": "10.0.17763.1397 (WinBuild.160101.0800)",\n "name": "Windows Server 2019 Datacenter",\n "family": "windows",\n "version": "10.0",\n "platform": "windows"\n },\n "ip": [\n "fe80::ecf5:decc:3ec3:767e",\n "10.200.0.15"\n ],\n "name": "siem-windows",\n "id": "ce1d3c9b-a815-4643-9641-ada0f2c00609",\n "mac": [\n "42:01:0a:c8:00:0f"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "code": 4624,\n "provider": "Microsoft-Windows-Security-Auditing",\n "created": "2020-09-04T13:08:03.638Z",\n "kind": "event",\n "module": "security",\n "action": "logged-in",\n "category": "authentication",\n "type": "start",\n "outcome": "success"\n },\n "user": {\n "domain": "NT AUTHORITY",\n "name": "SYSTEM",\n "id": "S-1-5-18"\n }\n },\n "sort": [\n 1599224882532\n ]\n }\n ]\n }\n }\n }\n },\n {\n "key": "tsg",\n "doc_count": 1,\n "failures": {\n "doc_count": 0,\n "lastFailure": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n },\n "successes": {\n "doc_count": 1,\n "lastSuccess": {\n "hits": {\n "total": 1,\n "max_score": 0,\n "hits": [\n {\n "_index": ".ds-logs-system.auth-default-000001",\n "_id": "9_sfWXQBc39KFIJbIsDh",\n "_score": null,\n "_source": {\n "agent": {\n "hostname": "siem-kibana",\n "name": "siem-kibana",\n "id": "aa3d9dc7-fef1-4c2f-a68d-25785d624e35",\n "ephemeral_id": "e503bd85-11c7-4bc9-ae7d-70be1d919fb7",\n "type": "filebeat",\n "version": "7.9.1"\n },\n "process": {\n "name": "sshd",\n "pid": 20764\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 552463\n },\n "source": {\n "geo": {\n "continent_name": "Europe",\n "region_iso_code": "DE-BE",\n "city_name": "Berlin",\n "country_iso_code": "DE",\n "region_name": "Land Berlin",\n "location": {\n "lon": 13.3512,\n "lat": 52.5727\n }\n },\n "as": {\n "number": 6805,\n "organization": {\n "name": "Telefonica Germany"\n }\n },\n "port": 57457,\n "ip": "77.183.42.188"\n },\n "cloud": {\n "availability_zone": "us-east1-b",\n "instance": {\n "name": "siem-kibana",\n "id": "5412578377715150143"\n },\n "provider": "gcp",\n "machine": {\n "type": "n1-standard-2"\n },\n "project": {\n "id": "elastic-beats"\n }\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T11:49:21.000Z",\n "system": {\n "auth": {\n "ssh": {\n "method": "publickey",\n "signature": "RSA SHA256:vv64JNLzKZWYA9vonnGWuW7zxWhyZrL/BFxyIGbISx8",\n "event": "Accepted"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "data_stream": {\n "namespace": "default",\n "type": "logs",\n "dataset": "system.auth"\n },\n "host": {\n "hostname": "siem-kibana",\n "os": {\n "kernel": "4.9.0-8-amd64",\n "codename": "stretch",\n "name": "Debian GNU/Linux",\n "family": "debian",\n "version": "9 (stretch)",\n "platform": "debian"\n },\n "containerized": false,\n "ip": [\n "10.142.0.7",\n "fe80::4001:aff:fe8e:7"\n ],\n "name": "siem-kibana",\n "id": "aa7ca589f1b8220002f2fc61c64cfbf1",\n "mac": [\n "42:01:0a:8e:00:07"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "timezone": "+00:00",\n "action": "ssh_login",\n "type": "authentication_success",\n "category": "authentication",\n "dataset": "system.auth",\n "outcome": "success"\n },\n "user": {\n "name": "tsg"\n }\n },\n "sort": [\n 1599220161000\n ]\n }\n ]\n }\n }\n }\n },\n {\n "key": "admin",\n "doc_count": 23,\n "failures": {\n "doc_count": 23,\n "lastFailure": {\n "hits": {\n "total": 23,\n "max_score": 0,\n "hits": [\n {\n "_index": ".ds-logs-system.auth-default-000001",\n "_id": "ZfxZWXQBc39KFIJbLN5U",\n "_score": null,\n "_source": {\n "agent": {\n "hostname": "siem-kibana",\n "name": "siem-kibana",\n "id": "aa3d9dc7-fef1-4c2f-a68d-25785d624e35",\n "ephemeral_id": "e503bd85-11c7-4bc9-ae7d-70be1d919fb7",\n "type": "filebeat",\n "version": "7.9.1"\n },\n "process": {\n "name": "sshd",\n "pid": 22913\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 562910\n },\n "source": {\n "geo": {\n "continent_name": "Asia",\n "region_iso_code": "KR-28",\n "city_name": "Incheon",\n "country_iso_code": "KR",\n "region_name": "Incheon",\n "location": {\n "lon": 126.7288,\n "lat": 37.4562\n }\n },\n "as": {\n "number": 4766,\n "organization": {\n "name": "Korea Telecom"\n }\n },\n "ip": "59.15.3.197"\n },\n "cloud": {\n "availability_zone": "us-east1-b",\n "instance": {\n "name": "siem-kibana",\n "id": "5412578377715150143"\n },\n "provider": "gcp",\n "machine": {\n "type": "n1-standard-2"\n },\n "project": {\n "id": "elastic-beats"\n }\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T13:40:46.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "data_stream": {\n "namespace": "default",\n "type": "logs",\n "dataset": "system.auth"\n },\n "host": {\n "hostname": "siem-kibana",\n "os": {\n "kernel": "4.9.0-8-amd64",\n "codename": "stretch",\n "name": "Debian GNU/Linux",\n "family": "debian",\n "version": "9 (stretch)",\n "platform": "debian"\n },\n "containerized": false,\n "ip": [\n "10.142.0.7",\n "fe80::4001:aff:fe8e:7"\n ],\n "name": "siem-kibana",\n "id": "aa7ca589f1b8220002f2fc61c64cfbf1",\n "mac": [\n "42:01:0a:8e:00:07"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "timezone": "+00:00",\n "action": "ssh_login",\n "type": "authentication_failure",\n "category": "authentication",\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "admin"\n }\n },\n "sort": [\n 1599226846000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "user",\n "doc_count": 21,\n "failures": {\n "doc_count": 21,\n "lastFailure": {\n "hits": {\n "total": 21,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "M_xLWXQBc39KFIJbY7Cb",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "type": "filebeat",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 20671\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 1028103\n },\n "source": {\n "geo": {\n "continent_name": "North America",\n "region_iso_code": "US-NY",\n "city_name": "New York",\n "country_iso_code": "US",\n "region_name": "New York",\n "location": {\n "lon": -74,\n "lat": 40.7157\n }\n },\n "ip": "64.227.88.245"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T13:25:43.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "64.227.88.245"\n ],\n "user": [\n "user"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T13:25:47.034172Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "user"\n }\n },\n "sort": [\n 1599225943000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "ubuntu",\n "doc_count": 18,\n "failures": {\n "doc_count": 18,\n "lastFailure": {\n "hits": {\n "total": 18,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "nPxKWXQBc39KFIJb7q4w",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "type": "filebeat",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 20665\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 1027372\n },\n "source": {\n "geo": {\n "continent_name": "North America",\n "region_iso_code": "US-NY",\n "city_name": "New York",\n "country_iso_code": "US",\n "region_name": "New York",\n "location": {\n "lon": -74,\n "lat": 40.7157\n }\n },\n "ip": "64.227.88.245"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T13:25:07.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "64.227.88.245"\n ],\n "user": [\n "ubuntu"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T13:25:16.974606Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "ubuntu"\n }\n },\n "sort": [\n 1599225907000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "odoo",\n "doc_count": 17,\n "failures": {\n "doc_count": 17,\n "lastFailure": {\n "hits": {\n "total": 17,\n "max_score": 0,\n "hits": [\n {\n "_index": ".ds-logs-system.auth-default-000001",\n "_id": "mPsfWXQBc39KFIJbI8HI",\n "_score": null,\n "_source": {\n "agent": {\n "hostname": "siem-kibana",\n "name": "siem-kibana",\n "id": "aa3d9dc7-fef1-4c2f-a68d-25785d624e35",\n "type": "filebeat",\n "ephemeral_id": "e503bd85-11c7-4bc9-ae7d-70be1d919fb7",\n "version": "7.9.1"\n },\n "process": {\n "name": "sshd",\n "pid": 21506\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 556761\n },\n "source": {\n "geo": {\n "continent_name": "Asia",\n "region_iso_code": "IN-DL",\n "city_name": "New Delhi",\n "country_iso_code": "IN",\n "region_name": "National Capital Territory of Delhi",\n "location": {\n "lon": 77.2245,\n "lat": 28.6358\n }\n },\n "as": {\n "number": 10029,\n "organization": {\n "name": "SHYAM SPECTRA PVT LTD"\n }\n },\n "ip": "180.151.228.166"\n },\n "cloud": {\n "availability_zone": "us-east1-b",\n "instance": {\n "name": "siem-kibana",\n "id": "5412578377715150143"\n },\n "provider": "gcp",\n "machine": {\n "type": "n1-standard-2"\n },\n "project": {\n "id": "elastic-beats"\n }\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T12:26:36.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "data_stream": {\n "namespace": "default",\n "type": "logs",\n "dataset": "system.auth"\n },\n "host": {\n "hostname": "siem-kibana",\n "os": {\n "kernel": "4.9.0-8-amd64",\n "codename": "stretch",\n "name": "Debian GNU/Linux",\n "family": "debian",\n "version": "9 (stretch)",\n "platform": "debian"\n },\n "containerized": false,\n "ip": [\n "10.142.0.7",\n "fe80::4001:aff:fe8e:7"\n ],\n "name": "siem-kibana",\n "id": "aa7ca589f1b8220002f2fc61c64cfbf1",\n "mac": [\n "42:01:0a:8e:00:07"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "timezone": "+00:00",\n "action": "ssh_login",\n "type": "authentication_failure",\n "category": "authentication",\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "odoo"\n }\n },\n "sort": [\n 1599222396000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "pi",\n "doc_count": 17,\n "failures": {\n "doc_count": 17,\n "lastFailure": {\n "hits": {\n "total": 17,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "aaToWHQBA6bGZw2uR-St",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "type": "filebeat",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 20475\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 1019218\n },\n "source": {\n "geo": {\n "continent_name": "Europe",\n "region_iso_code": "SE-AB",\n "city_name": "Stockholm",\n "country_iso_code": "SE",\n "region_name": "Stockholm",\n "location": {\n "lon": 17.7833,\n "lat": 59.25\n }\n },\n "as": {\n "number": 8473,\n "organization": {\n "name": "Bahnhof AB"\n }\n },\n "ip": "178.174.148.58"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T11:37:22.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "178.174.148.58"\n ],\n "user": [\n "pi"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T11:37:31.797423Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "pi"\n }\n },\n "sort": [\n 1599219442000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "demo",\n "doc_count": 14,\n "failures": {\n "doc_count": 14,\n "lastFailure": {\n "hits": {\n "total": 14,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "VaP_V3QBA6bGZw2upUbg",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "type": "filebeat",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 19849\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 981036\n },\n "source": {\n "geo": {\n "continent_name": "Europe",\n "country_iso_code": "HR",\n "location": {\n "lon": 15.5,\n "lat": 45.1667\n }\n },\n "as": {\n "number": 42864,\n "organization": {\n "name": "Giganet Internet Szolgaltato Kft"\n }\n },\n "ip": "45.95.168.157"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T07:23:22.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "45.95.168.157"\n ],\n "user": [\n "demo"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T07:23:26.046346Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "demo"\n }\n },\n "sort": [\n 1599204202000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "git",\n "doc_count": 13,\n "failures": {\n "doc_count": 13,\n "lastFailure": {\n "hits": {\n "total": 13,\n "max_score": 0,\n "hits": [\n {\n "_index": ".ds-logs-system.auth-default-000001",\n "_id": "PqYfWXQBA6bGZw2uIhVU",\n "_score": null,\n "_source": {\n "agent": {\n "hostname": "siem-kibana",\n "name": "siem-kibana",\n "id": "aa3d9dc7-fef1-4c2f-a68d-25785d624e35",\n "ephemeral_id": "e503bd85-11c7-4bc9-ae7d-70be1d919fb7",\n "type": "filebeat",\n "version": "7.9.1"\n },\n "process": {\n "name": "sshd",\n "pid": 20396\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 550795\n },\n "source": {\n "geo": {\n "continent_name": "Asia",\n "region_iso_code": "CN-BJ",\n "city_name": "Beijing",\n "country_iso_code": "CN",\n "region_name": "Beijing",\n "location": {\n "lon": 116.3889,\n "lat": 39.9288\n }\n },\n "as": {\n "number": 45090,\n "organization": {\n "name": "Shenzhen Tencent Computer Systems Company Limited"\n }\n },\n "ip": "123.206.30.76"\n },\n "cloud": {\n "availability_zone": "us-east1-b",\n "instance": {\n "name": "siem-kibana",\n "id": "5412578377715150143"\n },\n "provider": "gcp",\n "machine": {\n "type": "n1-standard-2"\n },\n "project": {\n "id": "elastic-beats"\n }\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T11:20:26.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "data_stream": {\n "namespace": "default",\n "type": "logs",\n "dataset": "system.auth"\n },\n "host": {\n "hostname": "siem-kibana",\n "os": {\n "kernel": "4.9.0-8-amd64",\n "codename": "stretch",\n "name": "Debian GNU/Linux",\n "family": "debian",\n "version": "9 (stretch)",\n "platform": "debian"\n },\n "containerized": false,\n "ip": [\n "10.142.0.7",\n "fe80::4001:aff:fe8e:7"\n ],\n "name": "siem-kibana",\n "id": "aa7ca589f1b8220002f2fc61c64cfbf1",\n "mac": [\n "42:01:0a:8e:00:07"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "timezone": "+00:00",\n "action": "ssh_login",\n "type": "authentication_failure",\n "category": "authentication",\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "git"\n }\n },\n "sort": [\n 1599218426000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "webadmin",\n "doc_count": 13,\n "failures": {\n "doc_count": 13,\n "lastFailure": {\n "hits": {\n "total": 13,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "iMABWHQBB-gskclyitP-",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "type": "filebeat",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 19870\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 984133\n },\n "source": {\n "geo": {\n "continent_name": "Europe",\n "country_iso_code": "HR",\n "location": {\n "lon": 15.5,\n "lat": 45.1667\n }\n },\n "as": {\n "number": 42864,\n "organization": {\n "name": "Giganet Internet Szolgaltato Kft"\n }\n },\n "ip": "45.95.168.157"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T07:25:28.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "45.95.168.157"\n ],\n "user": [\n "webadmin"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T07:25:30.236651Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "webadmin"\n }\n },\n "sort": [\n 1599204328000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n }\n ]\n },\n "user_count": {\n "value": 188\n }\n }\n },\n "total": 21,\n "loaded": 21\n}', + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "host_architecture": {\n "terms": {\n "field": "host.architecture",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_id": {\n "terms": {\n "field": "host.id",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_ip": {\n "terms": {\n "field": "host.ip",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_mac": {\n "terms": {\n "field": "host.mac",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_name": {\n "terms": {\n "field": "host.name",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_family": {\n "terms": {\n "field": "host.os.family",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_name": {\n "terms": {\n "field": "host.os.name",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_platform": {\n "terms": {\n "field": "host.os.platform",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_version": {\n "terms": {\n "field": "host.os.version",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_instance_id": {\n "terms": {\n "field": "cloud.instance.id",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_machine_type": {\n "terms": {\n "field": "cloud.machine.type",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_provider": {\n "terms": {\n "field": "cloud.provider",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_region": {\n "terms": {\n "field": "cloud.region",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n {\n "term": {\n "host.name": "bastion00.siem.estc.dev"\n }\n },\n {\n "range": {\n "@timestamp": {\n "format": "strict_date_optional_time",\n "gte": "2020-09-02T15:17:13.678Z",\n "lte": "2020-09-03T15:17:13.678Z"\n }\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', ], }, hostDetails: {}, @@ -2158,62 +1317,222 @@ export const expectedDsl = { body: { aggregations: { host_architecture: { - terms: { field: 'host.architecture', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.architecture', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_id: { - terms: { field: 'host.id', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.id', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_ip: { - terms: { field: 'host.ip', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.ip', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_mac: { - terms: { field: 'host.mac', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.mac', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_name: { - terms: { field: 'host.name', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.name', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_os_family: { - terms: { field: 'host.os.family', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.os.family', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_os_name: { - terms: { field: 'host.os.name', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.os.name', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_os_platform: { - terms: { field: 'host.os.platform', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.os.platform', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_os_version: { - terms: { field: 'host.os.version', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.os.version', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, cloud_instance_id: { - terms: { field: 'cloud.instance.id', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'cloud.instance.id', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, cloud_machine_type: { - terms: { field: 'cloud.machine.type', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'cloud.machine.type', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, cloud_provider: { - terms: { field: 'cloud.provider', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'cloud.provider', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, cloud_region: { - terms: { field: 'cloud.region', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'cloud.region', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, }, query: { bool: { filter: [ - { term: { 'host.name': 'bastion00' } }, + { + term: { + 'host.name': 'bastion00.siem.estc.dev', + }, + }, { range: { '@timestamp': { diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.ts index 616e4ed0bac38..8913f72aad61e 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.ts @@ -29,10 +29,8 @@ export const hostDetails: SecuritySolutionFactory = { const aggregations: HostAggEsItem = get('aggregations', response.rawResponse) || {}; const inspect = { dsl: [inspectStringifyObject(buildHostDetailsQuery(options))], - response: [inspectStringifyObject(response)], }; const formattedHostItem = formatHostItem(aggregations); - return { ...response, inspect, hostDetails: formattedHostItem }; }, }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.test.ts index eab1966434859..ad1fabd156fad 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.test.ts @@ -3,11 +3,11 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { buildHostDetailsQuery as buildQuery } from './query.host_details.dsl'; +import { buildHostDetailsQuery } from './query.host_details.dsl'; import { mockOptions, expectedDsl } from './__mocks__/'; -describe('buildQuery', () => { +describe('buildHostDetailsQuery', () => { test('build query from options correctly', () => { - expect(buildQuery(mockOptions)).toEqual(expectedDsl); + expect(buildHostDetailsQuery(mockOptions)).toEqual(expectedDsl); }); }); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/__mocks__/index.ts new file mode 100644 index 0000000000000..fbe007622005c --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/__mocks__/index.ts @@ -0,0 +1,377 @@ +/* + * 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 { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + NetworkDetailsRequestOptions, + NetworkQueries, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkDetailsRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + docValueFields: [ + { field: '@timestamp', format: 'date_time' }, + { field: 'event.created', format: 'date_time' }, + { field: 'event.end', format: 'date_time' }, + { field: 'event.ingested', format: 'date_time' }, + { field: 'event.start', format: 'date_time' }, + { field: 'file.accessed', format: 'date_time' }, + { field: 'file.created', format: 'date_time' }, + { field: 'file.ctime', format: 'date_time' }, + { field: 'file.mtime', format: 'date_time' }, + { field: 'package.installed', format: 'date_time' }, + { field: 'process.parent.start', format: 'date_time' }, + { field: 'process.start', format: 'date_time' }, + { field: 'system.audit.host.boottime', format: 'date_time' }, + { field: 'system.audit.package.installtime', format: 'date_time' }, + { field: 'system.audit.user.password.last_changed', format: 'date_time' }, + { field: 'tls.client.not_after', format: 'date_time' }, + { field: 'tls.client.not_before', format: 'date_time' }, + { field: 'tls.server.not_after', format: 'date_time' }, + { field: 'tls.server.not_before', format: 'date_time' }, + { field: 'aws.cloudtrail.user_identity.session_context.creation_date', format: 'date_time' }, + { field: 'azure.auditlogs.properties.activity_datetime', format: 'date_time' }, + { field: 'azure.enqueued_time', format: 'date_time' }, + { field: 'azure.signinlogs.properties.created_at', format: 'date_time' }, + { field: 'cef.extensions.agentReceiptTime', format: 'date_time' }, + { field: 'cef.extensions.deviceCustomDate1', format: 'date_time' }, + { field: 'cef.extensions.deviceCustomDate2', format: 'date_time' }, + { field: 'cef.extensions.deviceReceiptTime', format: 'date_time' }, + { field: 'cef.extensions.endTime', format: 'date_time' }, + { field: 'cef.extensions.fileCreateTime', format: 'date_time' }, + { field: 'cef.extensions.fileModificationTime', format: 'date_time' }, + { field: 'cef.extensions.flexDate1', format: 'date_time' }, + { field: 'cef.extensions.managerReceiptTime', format: 'date_time' }, + { field: 'cef.extensions.oldFileCreateTime', format: 'date_time' }, + { field: 'cef.extensions.oldFileModificationTime', format: 'date_time' }, + { field: 'cef.extensions.startTime', format: 'date_time' }, + { field: 'checkpoint.subs_exp', format: 'date_time' }, + { field: 'crowdstrike.event.EndTimestamp', format: 'date_time' }, + { field: 'crowdstrike.event.IncidentEndTime', format: 'date_time' }, + { field: 'crowdstrike.event.IncidentStartTime', format: 'date_time' }, + { field: 'crowdstrike.event.ProcessEndTime', format: 'date_time' }, + { field: 'crowdstrike.event.ProcessStartTime', format: 'date_time' }, + { field: 'crowdstrike.event.StartTimestamp', format: 'date_time' }, + { field: 'crowdstrike.event.Timestamp', format: 'date_time' }, + { field: 'crowdstrike.event.UTCTimestamp', format: 'date_time' }, + { field: 'crowdstrike.metadata.eventCreationTime', format: 'date_time' }, + { field: 'gsuite.admin.email.log_search_filter.end_date', format: 'date_time' }, + { field: 'gsuite.admin.email.log_search_filter.start_date', format: 'date_time' }, + { field: 'gsuite.admin.user.birthdate', format: 'date_time' }, + { field: 'kafka.block_timestamp', format: 'date_time' }, + { field: 'microsoft.defender_atp.lastUpdateTime', format: 'date_time' }, + { field: 'microsoft.defender_atp.resolvedTime', format: 'date_time' }, + { field: 'misp.campaign.first_seen', format: 'date_time' }, + { field: 'misp.campaign.last_seen', format: 'date_time' }, + { field: 'misp.intrusion_set.first_seen', format: 'date_time' }, + { field: 'misp.intrusion_set.last_seen', format: 'date_time' }, + { field: 'misp.observed_data.first_observed', format: 'date_time' }, + { field: 'misp.observed_data.last_observed', format: 'date_time' }, + { field: 'misp.report.published', format: 'date_time' }, + { field: 'misp.threat_indicator.valid_from', format: 'date_time' }, + { field: 'misp.threat_indicator.valid_until', format: 'date_time' }, + { field: 'netflow.collection_time_milliseconds', format: 'date_time' }, + { field: 'netflow.exporter.timestamp', format: 'date_time' }, + { field: 'netflow.flow_end_microseconds', format: 'date_time' }, + { field: 'netflow.flow_end_milliseconds', format: 'date_time' }, + { field: 'netflow.flow_end_nanoseconds', format: 'date_time' }, + { field: 'netflow.flow_end_seconds', format: 'date_time' }, + { field: 'netflow.flow_start_microseconds', format: 'date_time' }, + { field: 'netflow.flow_start_milliseconds', format: 'date_time' }, + { field: 'netflow.flow_start_nanoseconds', format: 'date_time' }, + { field: 'netflow.flow_start_seconds', format: 'date_time' }, + { field: 'netflow.max_export_seconds', format: 'date_time' }, + { field: 'netflow.max_flow_end_microseconds', format: 'date_time' }, + { field: 'netflow.max_flow_end_milliseconds', format: 'date_time' }, + { field: 'netflow.max_flow_end_nanoseconds', format: 'date_time' }, + { field: 'netflow.max_flow_end_seconds', format: 'date_time' }, + { field: 'netflow.min_export_seconds', format: 'date_time' }, + { field: 'netflow.min_flow_start_microseconds', format: 'date_time' }, + { field: 'netflow.min_flow_start_milliseconds', format: 'date_time' }, + { field: 'netflow.min_flow_start_nanoseconds', format: 'date_time' }, + { field: 'netflow.min_flow_start_seconds', format: 'date_time' }, + { field: 'netflow.monitoring_interval_end_milli_seconds', format: 'date_time' }, + { field: 'netflow.monitoring_interval_start_milli_seconds', format: 'date_time' }, + { field: 'netflow.observation_time_microseconds', format: 'date_time' }, + { field: 'netflow.observation_time_milliseconds', format: 'date_time' }, + { field: 'netflow.observation_time_nanoseconds', format: 'date_time' }, + { field: 'netflow.observation_time_seconds', format: 'date_time' }, + { field: 'netflow.system_init_time_milliseconds', format: 'date_time' }, + { field: 'rsa.internal.lc_ctime', format: 'date_time' }, + { field: 'rsa.internal.time', format: 'date_time' }, + { field: 'rsa.time.effective_time', format: 'date_time' }, + { field: 'rsa.time.endtime', format: 'date_time' }, + { field: 'rsa.time.event_queue_time', format: 'date_time' }, + { field: 'rsa.time.event_time', format: 'date_time' }, + { field: 'rsa.time.expire_time', format: 'date_time' }, + { field: 'rsa.time.recorded_time', format: 'date_time' }, + { field: 'rsa.time.stamp', format: 'date_time' }, + { field: 'rsa.time.starttime', format: 'date_time' }, + { field: 'sophos.xg.date', format: 'date_time' }, + { field: 'sophos.xg.eventtime', format: 'date_time' }, + { field: 'sophos.xg.start_time', format: 'date_time' }, + ], + factoryQueryType: NetworkQueries.details, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + ip: '35.196.65.164', +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 2620, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { total: 0, max_score: 0, hits: [] }, + aggregations: { + host: { + doc_count: 0, + results: { hits: { total: { value: 0, relation: 'eq' }, max_score: null, hits: [] } }, + }, + destination: { + meta: {}, + doc_count: 5, + geo: { + meta: {}, + doc_count: 5, + results: { + hits: { + total: { value: 5, relation: 'eq' }, + max_score: null, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1523631609876537', + _score: null, + _source: { + destination: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + }, + sort: [1599703212208], + }, + ], + }, + }, + }, + as: { + meta: {}, + doc_count: 5, + results: { + hits: { + total: { value: 5, relation: 'eq' }, + max_score: null, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1523631609876537', + _score: null, + _source: { + destination: { as: { number: 15169, organization: { name: 'Google LLC' } } }, + }, + sort: [1599703212208], + }, + ], + }, + }, + }, + lastSeen: { value: 1599703212208, value_as_string: '2020-09-10T02:00:12.208Z' }, + firstSeen: { value: 1598802015355, value_as_string: '2020-08-30T15:40:15.355Z' }, + }, + source: { + meta: {}, + doc_count: 5, + geo: { + meta: {}, + doc_count: 5, + results: { + hits: { + total: { value: 5, relation: 'eq' }, + max_score: null, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1523631486500511', + _score: null, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + }, + sort: [1599703214494], + }, + ], + }, + }, + }, + as: { + meta: {}, + doc_count: 5, + results: { + hits: { + total: { value: 5, relation: 'eq' }, + max_score: null, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1523631486500511', + _score: null, + _source: { + source: { as: { number: 15169, organization: { name: 'Google LLC' } } }, + }, + sort: [1599703214494], + }, + ], + }, + }, + }, + lastSeen: { value: 1599703214494, value_as_string: '2020-09-10T02:00:14.494Z' }, + firstSeen: { value: 1598802015107, value_as_string: '2020-08-30T15:40:15.107Z' }, + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggs": {\n "source": {\n "filter": {\n "term": {\n "source.ip": "35.196.65.164"\n }\n },\n "aggs": {\n "firstSeen": {\n "min": {\n "field": "@timestamp"\n }\n },\n "lastSeen": {\n "max": {\n "field": "@timestamp"\n }\n },\n "as": {\n "filter": {\n "exists": {\n "field": "source.as"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "source.as"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n },\n "geo": {\n "filter": {\n "exists": {\n "field": "source.geo"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "source.geo"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n }\n }\n },\n "destination": {\n "filter": {\n "term": {\n "destination.ip": "35.196.65.164"\n }\n },\n "aggs": {\n "firstSeen": {\n "min": {\n "field": "@timestamp"\n }\n },\n "lastSeen": {\n "max": {\n "field": "@timestamp"\n }\n },\n "as": {\n "filter": {\n "exists": {\n "field": "destination.as"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "destination.as"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n },\n "geo": {\n "filter": {\n "exists": {\n "field": "destination.geo"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "destination.geo"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n }\n }\n },\n "host": {\n "filter": {\n "term": {\n "host.ip": "35.196.65.164"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "host"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "should": []\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', + ], + }, + networkDetails: { + source: { + firstSeen: '2020-08-30T15:40:15.107Z', + lastSeen: '2020-09-10T02:00:14.494Z', + autonomousSystem: { number: 15169, organization: { name: 'Google LLC' } }, + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + destination: { + firstSeen: '2020-08-30T15:40:15.355Z', + lastSeen: '2020-09-10T02:00:12.208Z', + autonomousSystem: { number: 15169, organization: { name: 'Google LLC' } }, + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + host: {}, + }, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggs: { + source: { + filter: { term: { 'source.ip': '35.196.65.164' } }, + aggs: { + firstSeen: { min: { field: '@timestamp' } }, + lastSeen: { max: { field: '@timestamp' } }, + as: { + filter: { exists: { field: 'source.as' } }, + aggs: { + results: { + top_hits: { size: 1, _source: ['source.as'], sort: [{ '@timestamp': 'desc' }] }, + }, + }, + }, + geo: { + filter: { exists: { field: 'source.geo' } }, + aggs: { + results: { + top_hits: { size: 1, _source: ['source.geo'], sort: [{ '@timestamp': 'desc' }] }, + }, + }, + }, + }, + }, + destination: { + filter: { term: { 'destination.ip': '35.196.65.164' } }, + aggs: { + firstSeen: { min: { field: '@timestamp' } }, + lastSeen: { max: { field: '@timestamp' } }, + as: { + filter: { exists: { field: 'destination.as' } }, + aggs: { + results: { + top_hits: { + size: 1, + _source: ['destination.as'], + sort: [{ '@timestamp': 'desc' }], + }, + }, + }, + }, + geo: { + filter: { exists: { field: 'destination.geo' } }, + aggs: { + results: { + top_hits: { + size: 1, + _source: ['destination.geo'], + sort: [{ '@timestamp': 'desc' }], + }, + }, + }, + }, + }, + }, + host: { + filter: { term: { 'host.ip': '35.196.65.164' } }, + aggs: { + results: { top_hits: { size: 1, _source: ['host'], sort: [{ '@timestamp': 'desc' }] } }, + }, + }, + }, + query: { bool: { should: [] } }, + size: 0, + track_total_hits: false, + }, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/index.test.ts new file mode 100644 index 0000000000000..6f54097a76fe7 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.details_network.dsl'; +import { networkDetails } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkDetails search strategy', () => { + const buildNetworkDetailsQuery = jest.spyOn(buildQuery, 'buildNetworkDetailsQuery'); + + afterEach(() => { + buildNetworkDetailsQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkDetails.buildDsl(mockOptions); + expect(buildNetworkDetailsQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkDetails.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/query.details_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/query.details_network.dsl.test.ts new file mode 100644 index 0000000000000..93dca8ee03978 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/query.details_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * 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 { buildNetworkDetailsQuery } from './query.details_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildNetworkDetailsQuery', () => { + test('build query from options correctly', () => { + expect(buildNetworkDetailsQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/__mocks__/index.ts new file mode 100644 index 0000000000000..f0605c5523fd9 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/__mocks__/index.ts @@ -0,0 +1,185 @@ +/* + * 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 { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkDnsFields, + NetworkDnsRequestOptions, + NetworkQueries, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkDnsRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.dns, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + isPtrIncluded: false, + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkDnsFields.uniqueDomains, direction: Direction.desc }, + timerange: { interval: '12h', from: '2020-09-13T09:00:43.249Z', to: '2020-09-14T09:00:43.249Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 28, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { max_score: 0, hits: [], total: 0 }, + aggregations: { + dns_count: { value: 2 }, + dns_name_query_count: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'google.com', + doc_count: 1, + unique_domains: { value: 1 }, + dns_bytes_in: { value: 0 }, + dns_bytes_out: { value: 0 }, + }, + { + key: 'google.internal', + doc_count: 1, + unique_domains: { value: 1 }, + dns_bytes_in: { value: 0 }, + dns_bytes_out: { value: 0 }, + }, + ], + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 28, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { max_score: 0, hits: [] }, + aggregations: { + dns_count: { value: 2 }, + dns_name_query_count: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'google.com', + doc_count: 1, + unique_domains: { value: 1 }, + dns_bytes_in: { value: 0 }, + dns_bytes_out: { value: 0 }, + }, + { + key: 'google.internal', + doc_count: 1, + unique_domains: { value: 1 }, + dns_bytes_in: { value: 0 }, + dns_bytes_out: { value: 0 }, + }, + ], + }, + }, + }, + total: 21, + loaded: 21, + edges: [ + { + node: { + _id: 'google.com', + dnsBytesIn: 0, + dnsBytesOut: 0, + dnsName: 'google.com', + queryCount: 1, + uniqueDomains: 1, + }, + cursor: { value: 'google.com', tiebreaker: null }, + }, + { + node: { + _id: 'google.internal', + dnsBytesIn: 0, + dnsBytesOut: 0, + dnsName: 'google.internal', + queryCount: 1, + uniqueDomains: 1, + }, + cursor: { value: 'google.internal', tiebreaker: null }, + }, + ], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "dns_count": {\n "cardinality": {\n "field": "dns.question.registered_domain"\n }\n },\n "dns_name_query_count": {\n "terms": {\n "field": "dns.question.registered_domain",\n "size": 10,\n "order": {\n "unique_domains": "desc"\n }\n },\n "aggs": {\n "unique_domains": {\n "cardinality": {\n "field": "dns.question.name"\n }\n },\n "dns_bytes_in": {\n "sum": {\n "field": "source.bytes"\n }\n },\n "dns_bytes_out": {\n "sum": {\n "field": "destination.bytes"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T09:00:43.249Z",\n "lte": "2020-09-14T09:00:43.249Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ],\n "must_not": [\n {\n "term": {\n "dns.question.type": {\n "value": "PTR"\n }\n }\n }\n ]\n }\n }\n },\n "size": 0,\n "track_total_hits": false\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 2, showMorePagesIndicator: false }, + totalCount: 2, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggregations: { + dns_count: { cardinality: { field: 'dns.question.registered_domain' } }, + dns_name_query_count: { + terms: { + field: 'dns.question.registered_domain', + size: 10, + order: { unique_domains: 'desc' }, + }, + aggs: { + unique_domains: { cardinality: { field: 'dns.question.name' } }, + dns_bytes_in: { sum: { field: 'source.bytes' } }, + dns_bytes_out: { sum: { field: 'destination.bytes' } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T09:00:43.249Z', + lte: '2020-09-14T09:00:43.249Z', + format: 'strict_date_optional_time', + }, + }, + }, + ], + must_not: [{ term: { 'dns.question.type': { value: 'PTR' } } }], + }, + }, + }, + size: 0, + track_total_hits: false, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/index.test.ts new file mode 100644 index 0000000000000..22906a1ea138c --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.dns_network.dsl'; +import { networkDns } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkDns search strategy', () => { + const mockBuildDnsQuery = jest.spyOn(buildQuery, 'buildDnsQuery'); + + afterEach(() => { + mockBuildDnsQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkDns.buildDsl(mockOptions); + expect(mockBuildDnsQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkDns.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/query.dns_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/query.dns_network.dsl.test.ts new file mode 100644 index 0000000000000..9e95990d13a44 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/query.dns_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * 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 { buildDnsQuery } from './query.dns_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildDnsQuery', () => { + test('build query from options correctly', () => { + expect(buildDnsQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/__mocks__/index.ts new file mode 100644 index 0000000000000..9991d267707b7 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/__mocks__/index.ts @@ -0,0 +1,670 @@ +/* + * 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 { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkDnsFields, + NetworkDnsRequestOptions, + NetworkQueries, + SortField, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkDnsRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.http, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { direction: Direction.desc } as SortField, + timerange: { interval: '12h', from: '2020-09-13T09:00:43.249Z', to: '2020-09-14T09:00:43.249Z' }, +} as NetworkDnsRequestOptions; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 422, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { max_score: 0, hits: [], total: 0 }, + aggregations: { + http_count: { value: 1404 }, + url: { + doc_count_error_upper_bound: 1440, + sum_other_doc_count: 98077, + buckets: [ + { + key: '/_nodes?filter_path=nodes.*.version%2Cnodes.*.http.publish_address%2Cnodes.*.ip', + doc_count: 106704, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'GET', doc_count: 106704 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 68983 }, + { key: 'es.siem.estc.dev', doc_count: 37721 }, + ], + }, + source: { + hits: { + total: { value: 106704, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'L4wXh3QBc39KFIJbgXrN', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '67.173.227.94' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 200, doc_count: 72174 }, + { key: 401, doc_count: 34530 }, + ], + }, + }, + { + key: '/_bulk', + doc_count: 76744, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 76744 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 76737 }, + { key: 'es.siem.estc.dev', doc_count: 7 }, + ], + }, + source: { + hits: { + total: { value: 76744, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'tEIXh3QBB-gskclyiT2g', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '35.227.65.114' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 200, doc_count: 75394 }, + { key: 401, doc_count: 1350 }, + ], + }, + }, + { + key: '/.reporting-*/_search', + doc_count: 58746, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 58746 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 56305 }, + { key: 'es.siem.estc.dev', doc_count: 2441 }, + ], + }, + source: { + hits: { + total: { value: 58746, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'MYwXh3QBc39KFIJbgXrN', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '67.173.227.94' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 58746 }], + }, + }, + { + key: + '/.kibana-task-manager-xavier-m/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + doc_count: 28715, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 28715 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'es.siem.estc.dev:9200', doc_count: 28715 }], + }, + source: { + hits: { + total: { value: 28715, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'MIwXh3QBc39KFIJbgXrN', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '24.168.52.229' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 28715 }], + }, + }, + { + key: + '/.kibana-task-manager-andrewg-local-testing-7-9-ff/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + doc_count: 28161, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 28161 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'es.siem.estc.dev:9200', doc_count: 28161 }], + }, + source: { + hits: { + total: { value: 28161, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'MowXh3QBc39KFIJbgXrN', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '67.173.227.94' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 28161 }], + }, + }, + { + key: '/_security/user/_has_privileges', + doc_count: 23283, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 23283 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 21601 }, + { key: 'es.siem.estc.dev', doc_count: 1682 }, + ], + }, + source: { + hits: { + total: { value: 23283, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: '6Ywch3QBc39KFIJbVY_k', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '67.173.227.94' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 23283 }], + }, + }, + { + key: '/_xpack', + doc_count: 20724, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'GET', doc_count: 20724 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 17289 }, + { key: 'es.siem.estc.dev', doc_count: 3435 }, + ], + }, + source: { + hits: { + total: { value: 20724, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'rkIXh3QBB-gskclyiT2g', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '35.226.77.71' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 200, doc_count: 12084 }, + { key: 401, doc_count: 8640 }, + ], + }, + }, + { + key: '/', + doc_count: 18306, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'GET', doc_count: 18274 }, + { key: 'HEAD', doc_count: 29 }, + { key: 'POST', doc_count: 3 }, + ], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 37, + buckets: [ + { key: 'es.siem.estc.dev', doc_count: 8631 }, + { key: 'es.siem.estc.dev:9200', doc_count: 5757 }, + { key: 'es.siem.estc.dev:443', doc_count: 3858 }, + { key: '35.232.239.42', doc_count: 20 }, + ], + }, + source: { + hits: { + total: { value: 18306, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'JEIYh3QBB-gskclyYEfA', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '35.171.72.245' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 3, + buckets: [ + { key: 401, doc_count: 18220 }, + { key: 404, doc_count: 30 }, + { key: 302, doc_count: 27 }, + { key: 200, doc_count: 26 }, + ], + }, + }, + { + key: '/_monitoring/bulk?system_id=kibana&system_api_version=7&interval=10000ms', + doc_count: 18048, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 18048 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 17279 }, + { key: 'es.siem.estc.dev', doc_count: 769 }, + ], + }, + source: { + hits: { + total: { value: 18048, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'sUIXh3QBB-gskclyiT2g', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '24.168.52.229' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 18048 }], + }, + }, + { + key: '/s/row-renderer-checking/api/reporting/jobs/count', + doc_count: 14046, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'GET', doc_count: 14046 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'kibana.siem.estc.dev', doc_count: 14046 }], + }, + source: { + hits: { + total: { value: 14046, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 's0IXh3QBB-gskclyiT2g', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '75.134.244.183' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 14046 }], + }, + }, + ], + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + edges: [ + { + node: { + _id: '/_nodes?filter_path=nodes.*.version%2Cnodes.*.http.publish_address%2Cnodes.*.ip', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['GET'], + statuses: ['200', '401'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '67.173.227.94', + path: '/_nodes?filter_path=nodes.*.version%2Cnodes.*.http.publish_address%2Cnodes.*.ip', + requestCount: 106704, + }, + cursor: { + value: '/_nodes?filter_path=nodes.*.version%2Cnodes.*.http.publish_address%2Cnodes.*.ip', + tiebreaker: null, + }, + }, + { + node: { + _id: '/_bulk', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['POST'], + statuses: ['200', '401'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '35.227.65.114', + path: '/_bulk', + requestCount: 76744, + }, + cursor: { value: '/_bulk', tiebreaker: null }, + }, + { + node: { + _id: '/.reporting-*/_search', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '67.173.227.94', + path: '/.reporting-*/_search', + requestCount: 58746, + }, + cursor: { value: '/.reporting-*/_search', tiebreaker: null }, + }, + { + node: { + _id: + '/.kibana-task-manager-xavier-m/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + domains: ['es.siem.estc.dev:9200'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '24.168.52.229', + path: + '/.kibana-task-manager-xavier-m/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + requestCount: 28715, + }, + cursor: { + value: + '/.kibana-task-manager-xavier-m/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + tiebreaker: null, + }, + }, + { + node: { + _id: + '/.kibana-task-manager-andrewg-local-testing-7-9-ff/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + domains: ['es.siem.estc.dev:9200'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '67.173.227.94', + path: + '/.kibana-task-manager-andrewg-local-testing-7-9-ff/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + requestCount: 28161, + }, + cursor: { + value: + '/.kibana-task-manager-andrewg-local-testing-7-9-ff/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + tiebreaker: null, + }, + }, + { + node: { + _id: '/_security/user/_has_privileges', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '67.173.227.94', + path: '/_security/user/_has_privileges', + requestCount: 23283, + }, + cursor: { value: '/_security/user/_has_privileges', tiebreaker: null }, + }, + { + node: { + _id: '/_xpack', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['GET'], + statuses: ['200', '401'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '35.226.77.71', + path: '/_xpack', + requestCount: 20724, + }, + cursor: { value: '/_xpack', tiebreaker: null }, + }, + { + node: { + _id: '/', + domains: [ + 'es.siem.estc.dev', + 'es.siem.estc.dev:9200', + 'es.siem.estc.dev:443', + '35.232.239.42', + ], + methods: ['GET', 'HEAD', 'POST'], + statuses: ['401', '404', '302', '200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '35.171.72.245', + path: '/', + requestCount: 18306, + }, + cursor: { value: '/', tiebreaker: null }, + }, + { + node: { + _id: '/_monitoring/bulk?system_id=kibana&system_api_version=7&interval=10000ms', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '24.168.52.229', + path: '/_monitoring/bulk?system_id=kibana&system_api_version=7&interval=10000ms', + requestCount: 18048, + }, + cursor: { + value: '/_monitoring/bulk?system_id=kibana&system_api_version=7&interval=10000ms', + tiebreaker: null, + }, + }, + { + node: { + _id: '/s/row-renderer-checking/api/reporting/jobs/count', + domains: ['kibana.siem.estc.dev'], + methods: ['GET'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '75.134.244.183', + path: '/s/row-renderer-checking/api/reporting/jobs/count', + requestCount: 14046, + }, + cursor: { value: '/s/row-renderer-checking/api/reporting/jobs/count', tiebreaker: null }, + }, + ], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "http_count": {\n "cardinality": {\n "field": "url.path"\n }\n },\n "url": {\n "terms": {\n "field": "url.path",\n "size": 10,\n "order": {\n "_count": "desc"\n }\n },\n "aggs": {\n "methods": {\n "terms": {\n "field": "http.request.method",\n "size": 4\n }\n },\n "domains": {\n "terms": {\n "field": "url.domain",\n "size": 4\n }\n },\n "status": {\n "terms": {\n "field": "http.response.status_code",\n "size": 4\n }\n },\n "source": {\n "top_hits": {\n "size": 1,\n "_source": {\n "includes": [\n "host.name",\n "source.ip"\n ]\n }\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T09:00:43.249Z",\n "lte": "2020-09-14T09:00:43.249Z",\n "format": "strict_date_optional_time"\n }\n }\n },\n {\n "exists": {\n "field": "http.request.method"\n }\n }\n ]\n }\n }\n },\n "size": 0,\n "track_total_hits": false\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 50, showMorePagesIndicator: true }, + totalCount: 1404, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggregations: { + http_count: { cardinality: { field: 'url.path' } }, + url: { + terms: { field: 'url.path', size: 10, order: { _count: 'desc' } }, + aggs: { + methods: { terms: { field: 'http.request.method', size: 4 } }, + domains: { terms: { field: 'url.domain', size: 4 } }, + status: { terms: { field: 'http.response.status_code', size: 4 } }, + source: { top_hits: { size: 1, _source: { includes: ['host.name', 'source.ip'] } } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T09:00:43.249Z', + lte: '2020-09-14T09:00:43.249Z', + format: 'strict_date_optional_time', + }, + }, + }, + { exists: { field: 'http.request.method' } }, + ], + }, + }, + }, + size: 0, + track_total_hits: false, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.test.ts new file mode 100644 index 0000000000000..47946ee3ed20b --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.http_network.dsl'; +import { networkHttp } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkHttp search strategy', () => { + const buildHttpQuery = jest.spyOn(buildQuery, 'buildHttpQuery'); + + afterEach(() => { + buildHttpQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkHttp.buildDsl(mockOptions); + expect(buildHttpQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkHttp.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.test.ts new file mode 100644 index 0000000000000..1d10b60374a2f --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * 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 { buildHttpQuery } from './query.http_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildHttpQuery', () => { + test('build query from options correctly', () => { + expect(buildHttpQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.ts index feffe7f70afd9..dcffa60d8aa3c 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.ts @@ -69,6 +69,7 @@ export const buildHttpQuery = ({ size: 0, track_total_hits: false, }; + return dslQuery; }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts new file mode 100644 index 0000000000000..f901d9f3dab5d --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts @@ -0,0 +1,41 @@ +/* + * 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 { NetworkQueries } from '../../../../../common/search_strategy/security_solution'; + +import { networkFactory } from '.'; +import { networkDetails } from './details'; +import { networkDns } from './dns'; +import { networkHttp } from './http'; +import { networkOverview } from './overview'; +import { networkTls } from './tls'; +import { networkTopCountries } from './top_countries'; +import { networkTopNFlow } from './top_n_flow'; +import { networkUsers } from './users'; + +jest.mock('./details'); +jest.mock('./dns'); +jest.mock('./http'); +jest.mock('./overview'); +jest.mock('./tls'); +jest.mock('./top_countries'); +jest.mock('./top_n_flow'); +jest.mock('./users'); + +describe('networkFactory', () => { + test('should include correct apis', () => { + const expectedNetworkFactory = { + [NetworkQueries.details]: networkDetails, + [NetworkQueries.dns]: networkDns, + [NetworkQueries.http]: networkHttp, + [NetworkQueries.overview]: networkOverview, + [NetworkQueries.tls]: networkTls, + [NetworkQueries.topCountries]: networkTopCountries, + [NetworkQueries.topNFlow]: networkTopNFlow, + [NetworkQueries.users]: networkUsers, + }; + expect(networkFactory).toEqual(expectedNetworkFactory); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/__mocks__/index.ts new file mode 100644 index 0000000000000..8f34d31e49e1d --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/__mocks__/index.ts @@ -0,0 +1,213 @@ +/* + * 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 { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + NetworkOverviewRequestOptions, + NetworkQueries, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkOverviewRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.overview, + filterQuery: + '{"bool":{"must":[],"filter":[{"match_all":{}},{"bool":{"filter":[{"bool":{"should":[{"bool":{"should":[{"exists":{"field":"source.ip"}}],"minimum_should_match":1}},{"bool":{"should":[{"exists":{"field":"destination.ip"}}],"minimum_should_match":1}}],"minimum_should_match":1}}]}}],"should":[],"must_not":[]}}', + timerange: { interval: '12h', from: '2020-09-13T12:54:24.685Z', to: '2020-09-14T12:54:24.685Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 141, + timed_out: false, + _shards: { + total: 21, + successful: 21, + skipped: 0, + failed: 0, + }, + hits: { + total: 1349108, + max_score: 0, + hits: [], + }, + aggregations: { + unique_zeek_count: { + meta: {}, + doc_count: 0, + }, + unique_packetbeat_count: { + meta: {}, + doc_count: 0, + unique_tls_count: { + meta: {}, + doc_count: 0, + }, + }, + unique_filebeat_count: { + meta: {}, + doc_count: 1278559, + unique_netflow_count: { + doc_count: 0, + }, + unique_cisco_count: { + meta: {}, + doc_count: 0, + }, + unique_panw_count: { + meta: {}, + doc_count: 0, + }, + }, + unique_dns_count: { + meta: {}, + doc_count: 0, + }, + unique_flow_count: { + meta: {}, + doc_count: 0, + }, + unique_socket_count: { + doc_count: 0, + }, + unique_suricata_count: { + meta: {}, + doc_count: 0, + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "unique_flow_count": {\n "filter": {\n "term": {\n "type": "flow"\n }\n }\n },\n "unique_dns_count": {\n "filter": {\n "term": {\n "type": "dns"\n }\n }\n },\n "unique_suricata_count": {\n "filter": {\n "term": {\n "service.type": "suricata"\n }\n }\n },\n "unique_zeek_count": {\n "filter": {\n "term": {\n "service.type": "zeek"\n }\n }\n },\n "unique_socket_count": {\n "filter": {\n "term": {\n "event.dataset": "socket"\n }\n }\n },\n "unique_filebeat_count": {\n "filter": {\n "term": {\n "agent.type": "filebeat"\n }\n },\n "aggs": {\n "unique_netflow_count": {\n "filter": {\n "term": {\n "input.type": "netflow"\n }\n }\n },\n "unique_panw_count": {\n "filter": {\n "term": {\n "event.module": "panw"\n }\n }\n },\n "unique_cisco_count": {\n "filter": {\n "term": {\n "event.module": "cisco"\n }\n }\n }\n }\n },\n "unique_packetbeat_count": {\n "filter": {\n "term": {\n "agent.type": "packetbeat"\n }\n },\n "aggs": {\n "unique_tls_count": {\n "filter": {\n "term": {\n "network.protocol": "tls"\n }\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}},{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"exists\\":{\\"field\\":\\"source.ip\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"exists\\":{\\"field\\":\\"destination.ip\\"}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}}]}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T12:54:24.685Z",\n "lte": "2020-09-14T12:54:24.685Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', + ], + }, + overviewNetwork: { + auditbeatSocket: 0, + filebeatCisco: 0, + filebeatNetflow: 0, + filebeatPanw: 0, + filebeatSuricata: 0, + filebeatZeek: 0, + packetbeatDNS: 0, + packetbeatFlow: 0, + packetbeatTLS: 0, + }, +}; + +export const expectedDsl = { + allowNoIndices: true, + ignoreUnavailable: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + body: { + aggregations: { + unique_flow_count: { + filter: { + term: { + type: 'flow', + }, + }, + }, + unique_dns_count: { + filter: { + term: { + type: 'dns', + }, + }, + }, + unique_suricata_count: { + filter: { + term: { + 'service.type': 'suricata', + }, + }, + }, + unique_zeek_count: { + filter: { + term: { + 'service.type': 'zeek', + }, + }, + }, + unique_socket_count: { + filter: { + term: { + 'event.dataset': 'socket', + }, + }, + }, + unique_filebeat_count: { + filter: { + term: { + 'agent.type': 'filebeat', + }, + }, + aggs: { + unique_netflow_count: { + filter: { + term: { + 'input.type': 'netflow', + }, + }, + }, + unique_panw_count: { + filter: { + term: { + 'event.module': 'panw', + }, + }, + }, + unique_cisco_count: { + filter: { + term: { + 'event.module': 'cisco', + }, + }, + }, + }, + }, + unique_packetbeat_count: { + filter: { + term: { + 'agent.type': 'packetbeat', + }, + }, + aggs: { + unique_tls_count: { + filter: { + term: { + 'network.protocol': 'tls', + }, + }, + }, + }, + }, + }, + }, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/index.test.ts new file mode 100644 index 0000000000000..14b9fb3c71933 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.overview_network.dsl'; +import { networkOverview } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkOverview search strategy', () => { + const buildOverviewNetworkQuery = jest.spyOn(buildQuery, 'buildOverviewNetworkQuery'); + + afterEach(() => { + buildOverviewNetworkQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkOverview.buildDsl(mockOptions); + expect(buildOverviewNetworkQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkOverview.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/query.overview_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/query.overview_network.dsl.test.ts new file mode 100644 index 0000000000000..553df2ab80e58 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/query.overview_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * 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 { buildOverviewNetworkQuery } from './query.overview_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildOverviewNetworkQuery', () => { + test('build query from options correctly', () => { + expect(buildOverviewNetworkQuery(mockOptions)).toMatchObject(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/__mocks__/index.ts new file mode 100644 index 0000000000000..15e2ac3cc0f69 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/__mocks__/index.ts @@ -0,0 +1,109 @@ +/* + * 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 { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkTlsFields, + NetworkTlsRequestOptions, + NetworkQueries, + FlowTargetSourceDest, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkTlsRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.tls, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + flowTarget: FlowTargetSourceDest.source, + ip: '', + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkTlsFields._id, direction: Direction.desc }, + timerange: { interval: '12h', from: '2020-09-13T09:58:58.637Z', to: '2020-09-14T09:58:58.637Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 62, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { total: 0, max_score: 0, hits: [] }, + aggregations: { + sha1: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + count: { value: 0 }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + edges: [], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggs": {\n "count": {\n "cardinality": {\n "field": "tls.server.hash.sha1"\n }\n },\n "sha1": {\n "terms": {\n "field": "tls.server.hash.sha1",\n "size": 10,\n "order": {\n "_key": "desc"\n }\n },\n "aggs": {\n "issuers": {\n "terms": {\n "field": "tls.server.issuer"\n }\n },\n "subjects": {\n "terms": {\n "field": "tls.server.subject"\n }\n },\n "not_after": {\n "terms": {\n "field": "tls.server.not_after"\n }\n },\n "ja3": {\n "terms": {\n "field": "tls.server.ja3s"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T09:58:58.637Z",\n "lte": "2020-09-14T09:58:58.637Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 0, showMorePagesIndicator: false }, + totalCount: 0, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggs: { + count: { cardinality: { field: 'tls.server.hash.sha1' } }, + sha1: { + terms: { field: 'tls.server.hash.sha1', size: 10, order: { _key: 'desc' } }, + aggs: { + issuers: { terms: { field: 'tls.server.issuer' } }, + subjects: { terms: { field: 'tls.server.subject' } }, + not_after: { terms: { field: 'tls.server.not_after' } }, + ja3: { terms: { field: 'tls.server.ja3s' } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T09:58:58.637Z', + lte: '2020-09-14T09:58:58.637Z', + format: 'strict_date_optional_time', + }, + }, + }, + ], + }, + }, + size: 0, + track_total_hits: false, + }, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/index.test.ts new file mode 100644 index 0000000000000..b8c2be5bc61f8 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.tls_network.dsl'; +import { networkTls } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkTls search strategy', () => { + const buildNetworkTlsQuery = jest.spyOn(buildQuery, 'buildNetworkTlsQuery'); + + afterEach(() => { + buildNetworkTlsQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkTls.buildDsl(mockOptions); + expect(buildNetworkTlsQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkTls.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/query.tls_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/query.tls_network.dsl.test.ts new file mode 100644 index 0000000000000..39cfcc7ab462e --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/query.tls_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * 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 { buildNetworkTlsQuery } from './query.tls_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildNetworkTlsQuery', () => { + test('build query from options correctly', () => { + expect(buildNetworkTlsQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/__mocks__/index.ts new file mode 100644 index 0000000000000..0578d99accbf5 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/__mocks__/index.ts @@ -0,0 +1,109 @@ +/* + * 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 { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkTopCountriesRequestOptions, + NetworkQueries, + FlowTargetSourceDest, + NetworkTopTablesFields, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkTopCountriesRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.topCountries, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + flowTarget: FlowTargetSourceDest.destination, + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkTopTablesFields.bytes_in, direction: Direction.desc }, + timerange: { interval: '12h', from: '2020-09-13T09:58:58.637Z', to: '2020-09-14T09:58:58.637Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 62, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { total: 0, max_score: 0, hits: [] }, + aggregations: { + sha1: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + count: { value: 0 }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + edges: [], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "top_countries_count": {\n "cardinality": {\n "field": "destination.geo.country_iso_code"\n }\n },\n "destination": {\n "terms": {\n "field": "destination.geo.country_iso_code",\n "size": 10,\n "order": {\n "bytes_in": "desc"\n }\n },\n "aggs": {\n "bytes_in": {\n "sum": {\n "field": "source.bytes"\n }\n },\n "bytes_out": {\n "sum": {\n "field": "destination.bytes"\n }\n },\n "flows": {\n "cardinality": {\n "field": "network.community_id"\n }\n },\n "source_ips": {\n "cardinality": {\n "field": "source.ip"\n }\n },\n "destination_ips": {\n "cardinality": {\n "field": "destination.ip"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T09:58:58.637Z",\n "lte": "2020-09-14T09:58:58.637Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ]\n }\n }\n },\n "size": 0,\n "track_total_hits": false\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 0, showMorePagesIndicator: false }, + totalCount: 0, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggregations: { + top_countries_count: { cardinality: { field: 'destination.geo.country_iso_code' } }, + destination: { + terms: { field: 'destination.geo.country_iso_code', size: 10, order: { bytes_in: 'desc' } }, + aggs: { + bytes_in: { sum: { field: 'source.bytes' } }, + bytes_out: { sum: { field: 'destination.bytes' } }, + flows: { cardinality: { field: 'network.community_id' } }, + source_ips: { cardinality: { field: 'source.ip' } }, + destination_ips: { cardinality: { field: 'destination.ip' } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T09:58:58.637Z', + lte: '2020-09-14T09:58:58.637Z', + format: 'strict_date_optional_time', + }, + }, + }, + ], + }, + }, + }, + size: 0, + track_total_hits: false, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.test.ts new file mode 100644 index 0000000000000..65d1306b6946e --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.top_countries_network.dsl'; +import { networkTopCountries } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkTopCountries search strategy', () => { + const buildTopCountriesQuery = jest.spyOn(buildQuery, 'buildTopCountriesQuery'); + + afterEach(() => { + buildTopCountriesQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkTopCountries.buildDsl(mockOptions); + expect(buildTopCountriesQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkTopCountries.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts index 5b0ced06f2ee9..ba4565b068eb4 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts @@ -43,7 +43,6 @@ export const networkTopCountries: SecuritySolutionFactory fakeTotalCount; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network.dsl.test.ts new file mode 100644 index 0000000000000..cba2988aa240e --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * 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 { buildTopCountriesQuery } from './query.top_countries_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildTopCountriesQuery', () => { + test('build query from options correctly', () => { + expect(buildTopCountriesQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/__mocks__/index.ts new file mode 100644 index 0000000000000..84c1ca129ecac --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/__mocks__/index.ts @@ -0,0 +1,847 @@ +/* + * 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 { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkTopNFlowRequestOptions, + NetworkQueries, + NetworkTopTablesFields, + FlowTargetSourceDest, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkTopNFlowRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.topNFlow, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + flowTarget: FlowTargetSourceDest.source, + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkTopTablesFields.bytes_out, direction: Direction.desc }, + timerange: { interval: '12h', from: '2020-09-13T10:16:46.870Z', to: '2020-09-14T10:16:46.870Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 191, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { max_score: 0, hits: [], total: 0 }, + aggregations: { + source: { + meta: {}, + doc_count_error_upper_bound: -1, + sum_other_doc_count: 500330, + buckets: [ + { + key: '10.142.0.7', + doc_count: 12116, + bytes_out: { value: 2581835370 }, + flows: { value: 1967 }, + bytes_in: { value: 0 }, + domain: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'siem-kibana', + doc_count: 3221, + timestamp: { value: 1600078221017, value_as_string: '2020-09-14T10:10:21.017Z' }, + }, + ], + }, + autonomous_system: { + meta: {}, + doc_count: 0, + top_as: { hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] } }, + }, + location: { + doc_count: 0, + top_geo: { hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] } }, + }, + destination_ips: { value: 264 }, + }, + { + key: '35.232.239.42', + doc_count: 2119, + bytes_out: { value: 86968388 }, + flows: { value: 922 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 2119, + top_as: { + hits: { + total: { value: 2119, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526378075029582', + _score: 0, + _source: { + source: { as: { number: 15169, organization: { name: 'Google LLC' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 2119, + top_geo: { + hits: { + total: { value: 2119, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526378075029582', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '151.101.200.204', + doc_count: 2, + bytes_out: { value: 1394839 }, + flows: { value: 2 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 2, + top_as: { + hits: { + total: { value: 2, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1527252060367158', + _score: 0, + _source: { + source: { as: { number: 54113, organization: { name: 'Fastly' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 2, + top_geo: { + hits: { + total: { value: 2, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1527252060367158', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + city_name: 'Ashburn', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.4728, lat: 39.0481 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '91.189.92.39', + doc_count: 1, + bytes_out: { value: 570550 }, + flows: { value: 1 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 1, + top_as: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526971840437636', + _score: 0, + _source: { + source: { + as: { number: 41231, organization: { name: 'Canonical Group Limited' } }, + }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 1, + top_geo: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526971840437636', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'Europe', + region_iso_code: 'GB-ENG', + city_name: 'London', + country_iso_code: 'GB', + region_name: 'England', + location: { lon: -0.0961, lat: 51.5132 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '10.142.0.5', + doc_count: 514, + bytes_out: { value: 565933 }, + flows: { value: 486 }, + bytes_in: { value: 0 }, + domain: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'infraops-docker-data', + doc_count: 514, + timestamp: { value: 1600078218215, value_as_string: '2020-09-14T10:10:18.215Z' }, + }, + ], + }, + autonomous_system: { + doc_count: 0, + top_as: { hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] } }, + }, + location: { + doc_count: 0, + top_geo: { hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] } }, + }, + destination_ips: { value: 343 }, + }, + { + key: '151.101.248.204', + doc_count: 6, + bytes_out: { value: 260903 }, + flows: { value: 6 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 6, + top_as: { + hits: { + total: { value: 6, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1527003062069535', + _score: 0, + _source: { + source: { as: { number: 54113, organization: { name: 'Fastly' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 6, + top_geo: { + hits: { + total: { value: 6, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1527003062069535', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + city_name: 'Ashburn', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.539, lat: 39.018 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '35.196.129.83', + doc_count: 1, + bytes_out: { value: 164079 }, + flows: { value: 1 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 1, + top_as: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526557113311472', + _score: 0, + _source: { + source: { as: { number: 15169, organization: { name: 'Google LLC' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 1, + top_geo: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526557113311472', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '151.101.2.217', + doc_count: 24, + bytes_out: { value: 158407 }, + flows: { value: 24 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 24, + top_as: { + hits: { + total: { value: 24, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526379128390241', + _score: 0, + _source: { + source: { as: { number: 54113, organization: { name: 'Fastly' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 24, + top_geo: { + hits: { + total: { value: 24, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526379128390241', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + country_iso_code: 'US', + location: { lon: -97.822, lat: 37.751 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '91.189.91.38', + doc_count: 1, + bytes_out: { value: 89031 }, + flows: { value: 1 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 1, + top_as: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526555996515551', + _score: 0, + _source: { + source: { + as: { number: 41231, organization: { name: 'Canonical Group Limited' } }, + }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 1, + top_geo: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526555996515551', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-MA', + city_name: 'Boston', + country_iso_code: 'US', + region_name: 'Massachusetts', + location: { lon: -71.0631, lat: 42.3562 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '193.228.91.123', + doc_count: 33, + bytes_out: { value: 32170 }, + flows: { value: 33 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 33, + top_as: { + hits: { + total: { value: 33, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526584379144248', + _score: 0, + _source: { + source: { as: { number: 133766, organization: { name: 'YHSRV.LLC' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 33, + top_geo: { + hits: { + total: { value: 33, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526584379144248', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + country_iso_code: 'US', + location: { lon: -97.822, lat: 37.751 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 2 }, + }, + ], + }, + top_n_flow_count: { value: 738 }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + edges: [ + { + node: { + _id: '10.142.0.7', + source: { + domain: ['siem-kibana'], + ip: '10.142.0.7', + location: null, + autonomous_system: null, + flows: 1967, + destination_ips: 264, + }, + network: { bytes_in: 0, bytes_out: 2581835370 }, + }, + cursor: { value: '10.142.0.7', tiebreaker: null }, + }, + { + node: { + _id: '35.232.239.42', + source: { + domain: [], + ip: '35.232.239.42', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 15169, name: 'Google LLC' }, + flows: 922, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 86968388 }, + }, + cursor: { value: '35.232.239.42', tiebreaker: null }, + }, + { + node: { + _id: '151.101.200.204', + source: { + domain: [], + ip: '151.101.200.204', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + city_name: 'Ashburn', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.4728, lat: 39.0481 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 54113, name: 'Fastly' }, + flows: 2, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 1394839 }, + }, + cursor: { value: '151.101.200.204', tiebreaker: null }, + }, + { + node: { + _id: '91.189.92.39', + source: { + domain: [], + ip: '91.189.92.39', + location: { + geo: { + continent_name: 'Europe', + region_iso_code: 'GB-ENG', + city_name: 'London', + country_iso_code: 'GB', + region_name: 'England', + location: { lon: -0.0961, lat: 51.5132 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 41231, name: 'Canonical Group Limited' }, + flows: 1, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 570550 }, + }, + cursor: { value: '91.189.92.39', tiebreaker: null }, + }, + { + node: { + _id: '10.142.0.5', + source: { + domain: ['infraops-docker-data'], + ip: '10.142.0.5', + location: null, + autonomous_system: null, + flows: 486, + destination_ips: 343, + }, + network: { bytes_in: 0, bytes_out: 565933 }, + }, + cursor: { value: '10.142.0.5', tiebreaker: null }, + }, + { + node: { + _id: '151.101.248.204', + source: { + domain: [], + ip: '151.101.248.204', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + city_name: 'Ashburn', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.539, lat: 39.018 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 54113, name: 'Fastly' }, + flows: 6, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 260903 }, + }, + cursor: { value: '151.101.248.204', tiebreaker: null }, + }, + { + node: { + _id: '35.196.129.83', + source: { + domain: [], + ip: '35.196.129.83', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 15169, name: 'Google LLC' }, + flows: 1, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 164079 }, + }, + cursor: { value: '35.196.129.83', tiebreaker: null }, + }, + { + node: { + _id: '151.101.2.217', + source: { + domain: [], + ip: '151.101.2.217', + location: { + geo: { + continent_name: 'North America', + country_iso_code: 'US', + location: { lon: -97.822, lat: 37.751 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 54113, name: 'Fastly' }, + flows: 24, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 158407 }, + }, + cursor: { value: '151.101.2.217', tiebreaker: null }, + }, + { + node: { + _id: '91.189.91.38', + source: { + domain: [], + ip: '91.189.91.38', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-MA', + city_name: 'Boston', + country_iso_code: 'US', + region_name: 'Massachusetts', + location: { lon: -71.0631, lat: 42.3562 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 41231, name: 'Canonical Group Limited' }, + flows: 1, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 89031 }, + }, + cursor: { value: '91.189.91.38', tiebreaker: null }, + }, + { + node: { + _id: '193.228.91.123', + source: { + domain: [], + ip: '193.228.91.123', + location: { + geo: { + continent_name: 'North America', + country_iso_code: 'US', + location: { lon: -97.822, lat: 37.751 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 133766, name: 'YHSRV.LLC' }, + flows: 33, + destination_ips: 2, + }, + network: { bytes_in: 0, bytes_out: 32170 }, + }, + cursor: { value: '193.228.91.123', tiebreaker: null }, + }, + ], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "top_n_flow_count": {\n "cardinality": {\n "field": "source.ip"\n }\n },\n "source": {\n "terms": {\n "field": "source.ip",\n "size": 10,\n "order": {\n "bytes_out": "desc"\n }\n },\n "aggs": {\n "bytes_in": {\n "sum": {\n "field": "destination.bytes"\n }\n },\n "bytes_out": {\n "sum": {\n "field": "source.bytes"\n }\n },\n "domain": {\n "terms": {\n "field": "source.domain",\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "location": {\n "filter": {\n "exists": {\n "field": "source.geo"\n }\n },\n "aggs": {\n "top_geo": {\n "top_hits": {\n "_source": "source.geo.*",\n "size": 1\n }\n }\n }\n },\n "autonomous_system": {\n "filter": {\n "exists": {\n "field": "source.as"\n }\n },\n "aggs": {\n "top_as": {\n "top_hits": {\n "_source": "source.as.*",\n "size": 1\n }\n }\n }\n },\n "flows": {\n "cardinality": {\n "field": "network.community_id"\n }\n },\n "destination_ips": {\n "cardinality": {\n "field": "destination.ip"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T10:16:46.870Z",\n "lte": "2020-09-14T10:16:46.870Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ]\n }\n }\n },\n "size": 0,\n "track_total_hits": false\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 50, showMorePagesIndicator: true }, + totalCount: 738, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggregations: { + top_n_flow_count: { cardinality: { field: 'source.ip' } }, + source: { + terms: { field: 'source.ip', size: 10, order: { bytes_out: 'desc' } }, + aggs: { + bytes_in: { sum: { field: 'destination.bytes' } }, + bytes_out: { sum: { field: 'source.bytes' } }, + domain: { + terms: { field: 'source.domain', order: { timestamp: 'desc' } }, + aggs: { timestamp: { max: { field: '@timestamp' } } }, + }, + location: { + filter: { exists: { field: 'source.geo' } }, + aggs: { top_geo: { top_hits: { _source: 'source.geo.*', size: 1 } } }, + }, + autonomous_system: { + filter: { exists: { field: 'source.as' } }, + aggs: { top_as: { top_hits: { _source: 'source.as.*', size: 1 } } }, + }, + flows: { cardinality: { field: 'network.community_id' } }, + destination_ips: { cardinality: { field: 'destination.ip' } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T10:16:46.870Z', + lte: '2020-09-14T10:16:46.870Z', + format: 'strict_date_optional_time', + }, + }, + }, + ], + }, + }, + }, + size: 0, + track_total_hits: false, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.test.ts new file mode 100644 index 0000000000000..fe3213a4e5388 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.top_n_flow_network.dsl'; +import { networkTopNFlow } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkTopNFlow search strategy', () => { + const buildTopNFlowQuery = jest.spyOn(buildQuery, 'buildTopNFlowQuery'); + + afterEach(() => { + buildTopNFlowQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkTopNFlow.buildDsl(mockOptions); + expect(buildTopNFlowQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkTopNFlow.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network.dsl.test.ts new file mode 100644 index 0000000000000..902769ae9a30b --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * 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 { buildTopNFlowQuery } from './query.top_n_flow_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildTopNFlowQuery', () => { + test('build query from options correctly', () => { + expect(buildTopNFlowQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/__mocks__/index.ts new file mode 100644 index 0000000000000..3f57de7c78d1a --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/__mocks__/index.ts @@ -0,0 +1,170 @@ +/* + * 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 { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkUsersRequestOptions, + NetworkQueries, + NetworkUsersFields, + FlowTarget, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkUsersRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.users, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + flowTarget: FlowTarget.source, + ip: '10.142.0.7', + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkUsersFields.name, direction: Direction.asc }, + timerange: { interval: '12h', from: '2020-09-13T10:16:46.870Z', to: '2020-09-14T10:16:46.870Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 12, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { total: 0, max_score: 0, hits: [] }, + aggregations: { + user_count: { value: 3 }, + users: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: '_apt', + doc_count: 34, + groupName: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + groupId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + id: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: '104', doc_count: 34 }], + }, + }, + { + key: 'root', + doc_count: 8852, + groupName: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + groupId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + id: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: '0', doc_count: 8852 }], + }, + }, + { + key: 'tsg', + doc_count: 16, + groupName: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + groupId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + id: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: '1005', doc_count: 16 }], + }, + }, + ], + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + edges: [ + { + node: { + _id: '_apt', + user: { id: ['104'], name: '_apt', groupId: [], groupName: [], count: 34 }, + }, + cursor: { value: '_apt', tiebreaker: null }, + }, + { + node: { + _id: 'root', + user: { id: ['0'], name: 'root', groupId: [], groupName: [], count: 8852 }, + }, + cursor: { value: 'root', tiebreaker: null }, + }, + { + node: { + _id: 'tsg', + user: { id: ['1005'], name: 'tsg', groupId: [], groupName: [], count: 16 }, + }, + cursor: { value: 'tsg', tiebreaker: null }, + }, + ], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggs": {\n "user_count": {\n "cardinality": {\n "field": "user.name"\n }\n },\n "users": {\n "terms": {\n "field": "user.name",\n "size": 10,\n "order": {\n "_key": "asc"\n }\n },\n "aggs": {\n "id": {\n "terms": {\n "field": "user.id"\n }\n },\n "groupId": {\n "terms": {\n "field": "user.group.id"\n }\n },\n "groupName": {\n "terms": {\n "field": "user.group.name"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T10:16:46.870Z",\n "lte": "2020-09-14T10:16:46.870Z",\n "format": "strict_date_optional_time"\n }\n }\n },\n {\n "term": {\n "source.ip": "10.142.0.7"\n }\n }\n ],\n "must_not": [\n {\n "term": {\n "event.category": "authentication"\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 3, showMorePagesIndicator: false }, + totalCount: 3, +}; + +export const expectedDsl = { + allowNoIndices: true, + body: { + aggs: { + user_count: { cardinality: { field: 'user.name' } }, + users: { + aggs: { + groupId: { terms: { field: 'user.group.id' } }, + groupName: { terms: { field: 'user.group.name' } }, + id: { terms: { field: 'user.id' } }, + }, + terms: { field: 'user.name', order: { _key: 'asc' }, size: 10 }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + format: 'strict_date_optional_time', + gte: '2020-09-13T10:16:46.870Z', + lte: '2020-09-14T10:16:46.870Z', + }, + }, + }, + { term: { 'source.ip': '10.142.0.7' } }, + ], + must_not: [{ term: { 'event.category': 'authentication' } }], + }, + }, + size: 0, + track_total_hits: false, + }, + ignoreUnavailable: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/helpers.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/helpers.test.ts new file mode 100644 index 0000000000000..19ce687cd3f07 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/helpers.test.ts @@ -0,0 +1,15 @@ +/* + * 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 { getUsersEdges } from './helpers'; +import { mockSearchStrategyResponse, formattedSearchStrategyResponse } from './__mocks__'; + +describe('#getUsers', () => { + test('will format edges correctly', () => { + const edges = getUsersEdges(mockSearchStrategyResponse); + expect(edges).toEqual(formattedSearchStrategyResponse.edges); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/index.test.ts new file mode 100644 index 0000000000000..bd98ec0947b35 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/index.test.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 { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../../../common/constants'; +import { NetworkUsersRequestOptions } from '../../../../../../common/search_strategy/security_solution/network'; + +import * as buildQuery from './query.users_network.dsl'; +import { networkUsers } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkUsers search strategy', () => { + const buildUsersQuery = jest.spyOn(buildQuery, 'buildUsersQuery'); + + afterEach(() => { + buildUsersQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkUsers.buildDsl(mockOptions); + expect(buildUsersQuery).toHaveBeenCalledWith(mockOptions); + }); + + test('should throw error if query size is greater equal than DEFAULT_MAX_TABLE_QUERY_SIZE ', () => { + const overSizeOptions = { + ...mockOptions, + pagination: { + ...mockOptions.pagination, + querySize: DEFAULT_MAX_TABLE_QUERY_SIZE, + }, + } as NetworkUsersRequestOptions; + + expect(() => { + networkUsers.buildDsl(overSizeOptions); + }).toThrowError(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkUsers.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/query.users_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/query.users_network.dsl.test.ts new file mode 100644 index 0000000000000..ce43e1fb49e9f --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/query.users_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * 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 { buildUsersQuery } from './query.users_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildUsersQuery', () => { + test('build query from options correctly', () => { + expect(buildUsersQuery(mockOptions)).toEqual(expectedDsl); + }); +}); From b2ff5b43697125170f678f1c8b9afaab70111d86 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Tue, 15 Sep 2020 11:10:03 +0300 Subject: [PATCH 12/26] Fix tsvb filter ration for table (#77272) Co-authored-by: Elastic Machine --- .../request_processors/table/filter_ratios.js | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js index 707ccd1e55bb0..13874166bc558 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js @@ -18,22 +18,27 @@ */ const filter = (metric) => metric.type === 'filter_ratio'; +import { esQuery } from '../../../../../../data/server'; import { bucketTransform } from '../../helpers/bucket_transform'; import { overwrite } from '../../helpers'; import { calculateAggRoot } from './calculate_agg_root'; -export function ratios(req, panel) { +export function ratios(req, panel, esQueryConfig, indexPatternObject) { return (next) => (doc) => { panel.series.forEach((column) => { const aggRoot = calculateAggRoot(doc, column); if (column.metrics.some(filter)) { column.metrics.filter(filter).forEach((metric) => { - overwrite(doc, `${aggRoot}.timeseries.aggs.${metric.id}-numerator.filter`, { - query_string: { query: metric.numerator || '*', analyze_wildcard: true }, - }); - overwrite(doc, `${aggRoot}.timeseries.aggs.${metric.id}-denominator.filter`, { - query_string: { query: metric.denominator || '*', analyze_wildcard: true }, - }); + overwrite( + doc, + `${aggRoot}.timeseries.aggs.${metric.id}-numerator.filter`, + esQuery.buildEsQuery(indexPatternObject, metric.numerator, [], esQueryConfig) + ); + overwrite( + doc, + `${aggRoot}.timeseries.aggs.${metric.id}-denominator.filter`, + esQuery.buildEsQuery(indexPatternObject, metric.denominator, [], esQueryConfig) + ); let numeratorPath = `${metric.id}-numerator>_count`; let denominatorPath = `${metric.id}-denominator>_count`; @@ -46,7 +51,7 @@ export function ratios(req, panel) { }), }; overwrite(doc, `${aggRoot}.timeseries.aggs.${metric.id}-numerator.aggs`, aggBody); - overwrite(doc, `${aggBody}.timeseries.aggs.${metric.id}-denominator.aggs`, aggBody); + overwrite(doc, `${aggRoot}.timeseries.aggs.${metric.id}-denominator.aggs`, aggBody); numeratorPath = `${metric.id}-numerator>metric`; denominatorPath = `${metric.id}-denominator>metric`; } From e6e7187b03554b8b4f3c8846ae2bfec8052fc5f8 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Tue, 15 Sep 2020 10:18:40 +0100 Subject: [PATCH 13/26] Implementing ReferenceOrValueEmbeddable for visualize embeddable (#76088) * Adding dashboard as dependency to visualize * Making visualize embeddable as ReferenceOrValueEmbeddable * Adding attribute service to visualize embeddable * Binding createFromSavedObject method * Add/remove visualize embeddable from library * Removing debugger statement * Using custom save method on attribute service * Reverting to not using attribute service * Resetting flag value * Fix i18n title and update title * Using custom save method on attribute service * Fixing eslint * Using custom save method in visualize embeddable factory * Making getInputAsValueType return Promise as it should * Better error handling when saving a visualization fails Co-authored-by: Elastic Machine --- .../attribute_service/attribute_service.tsx | 8 +- src/plugins/dashboard/public/mocks.tsx | 35 +++++++ .../default_embeddable_factory_provider.ts | 10 +- src/plugins/visualizations/kibana.json | 2 +- .../create_vis_embeddable_from_object.ts | 19 +++- .../public/embeddable/visualize_embeddable.ts | 81 +++++++++++++++- .../visualize_embeddable_factory.tsx | 93 ++++++++++++++++++- src/plugins/visualizations/public/mocks.ts | 3 + src/plugins/visualizations/public/plugin.ts | 5 +- 9 files changed, 240 insertions(+), 16 deletions(-) create mode 100644 src/plugins/dashboard/public/mocks.tsx diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index a36363d22d87d..84df05154fb63 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -57,7 +57,7 @@ export interface AttributeServiceOptions { type: string, attributes: A, savedObjectId?: string - ) => Promise<{ id: string }>; + ) => Promise<{ id?: string } | { error: Error }>; customUnwrapMethod?: (savedObject: SimpleSavedObject) => A; } @@ -124,7 +124,10 @@ export class AttributeService< newAttributes, savedObjectId ); - return { ...originalInput, savedObjectId: savedItem.id } as RefType; + if ('id' in savedItem) { + return { ...originalInput, savedObjectId: savedItem.id } as RefType; + } + return { ...originalInput } as RefType; } if (savedObjectId) { @@ -208,7 +211,6 @@ export class AttributeService< return { error }; } }; - if (saveOptions && (saveOptions as { showSaveModal: boolean }).showSaveModal) { this.showSaveModal( ; + +const createStartContract = (): DashboardStart => { + // @ts-ignore + const startContract: DashboardStart = { + getAttributeService: jest.fn(), + }; + + return startContract; +}; + +export const dashboardPluginMock = { + createStartContract, +}; diff --git a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts index 570a78fc41ea9..b22f16c94aff8 100644 --- a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts +++ b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts @@ -37,11 +37,11 @@ export const defaultEmbeddableFactoryProvider = < getExplicitInput: def.getExplicitInput ? def.getExplicitInput.bind(def) : () => Promise.resolve({}), - createFromSavedObject: - def.createFromSavedObject ?? - ((savedObjectId: string, input: Partial, parent?: IContainer) => { - throw new Error(`Creation from saved object not supported by type ${def.type}`); - }), + createFromSavedObject: def.createFromSavedObject + ? def.createFromSavedObject.bind(def) + : (savedObjectId: string, input: Partial, parent?: IContainer) => { + throw new Error(`Creation from saved object not supported by type ${def.type}`); + }, create: def.create.bind(def), type: def.type, isEditable: def.isEditable.bind(def), diff --git a/src/plugins/visualizations/kibana.json b/src/plugins/visualizations/kibana.json index da3edfbdd3bf5..0bd5de1d9ee15 100644 --- a/src/plugins/visualizations/kibana.json +++ b/src/plugins/visualizations/kibana.json @@ -3,6 +3,6 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection", "inspector"], + "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection", "inspector", "dashboard"], "requiredBundles": ["kibanaUtils", "discover", "savedObjects"] } diff --git a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts index 194deef82a5f0..b27d24d980e8d 100644 --- a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts +++ b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts @@ -18,7 +18,13 @@ */ import { Vis } from '../types'; -import { VisualizeInput, VisualizeEmbeddable } from './visualize_embeddable'; +import { + VisualizeInput, + VisualizeEmbeddable, + VisualizeByValueInput, + VisualizeByReferenceInput, + VisualizeSavedObjectAttributes, +} from './visualize_embeddable'; import { IContainer, ErrorEmbeddable } from '../../../../plugins/embeddable/public'; import { DisabledLabEmbeddable } from './disabled_lab_embeddable'; import { @@ -30,10 +36,18 @@ import { } from '../services'; import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory'; import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants'; +import { SavedVisualizationsLoader } from '../saved_visualizations'; +import { AttributeService } from '../../../dashboard/public'; export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDeps) => async ( vis: Vis, input: Partial & { id: string }, + savedVisualizationsLoader?: SavedVisualizationsLoader, + attributeService?: AttributeService< + VisualizeSavedObjectAttributes, + VisualizeByValueInput, + VisualizeByReferenceInput + >, parent?: IContainer ): Promise => { const savedVisualizations = getSavedVisualizationsLoader(); @@ -55,6 +69,7 @@ export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDe const indexPattern = vis.data.indexPattern; const indexPatterns = indexPattern ? [indexPattern] : []; const editable = getCapabilities().visualize.save as boolean; + return new VisualizeEmbeddable( getTimeFilter(), { @@ -66,6 +81,8 @@ export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDe deps, }, input, + attributeService, + savedVisualizationsLoader, parent ); } catch (e) { diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index cc278a6ee9b3d..18ae68ec40fe5 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -20,6 +20,7 @@ import _, { get } from 'lodash'; import { Subscription } from 'rxjs'; import * as Rx from 'rxjs'; +import { i18n } from '@kbn/i18n'; import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; import { IIndexPattern, @@ -35,6 +36,8 @@ import { Embeddable, IContainer, Adapters, + SavedObjectEmbeddableInput, + ReferenceOrValueEmbeddable, } from '../../../../plugins/embeddable/public'; import { IExpressionLoaderParams, @@ -47,6 +50,10 @@ import { getExpressions, getUiActions } from '../services'; import { VIS_EVENT_TO_TRIGGER } from './events'; import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory'; import { TriggerId } from '../../../ui_actions/public'; +import { SavedObjectAttributes } from '../../../../core/types'; +import { AttributeService } from '../../../dashboard/public'; +import { SavedVisualizationsLoader } from '../saved_visualizations'; +import { VisSavedObject } from '../types'; const getKeys = (o: T): Array => Object.keys(o) as Array; @@ -75,9 +82,19 @@ export interface VisualizeOutput extends EmbeddableOutput { visTypeName: string; } +export type VisualizeSavedObjectAttributes = SavedObjectAttributes & { + title: string; + vis?: Vis; + savedVis?: VisSavedObject; +}; +export type VisualizeByValueInput = { attributes: VisualizeSavedObjectAttributes } & VisualizeInput; +export type VisualizeByReferenceInput = SavedObjectEmbeddableInput & VisualizeInput; + type ExpressionLoader = InstanceType; -export class VisualizeEmbeddable extends Embeddable { +export class VisualizeEmbeddable + extends Embeddable + implements ReferenceOrValueEmbeddable { private handler?: ExpressionLoader; private timefilter: TimefilterContract; private timeRange?: TimeRange; @@ -93,11 +110,23 @@ export class VisualizeEmbeddable extends Embeddable; + private savedVisualizationsLoader?: SavedVisualizationsLoader; constructor( timefilter: TimefilterContract, { vis, editPath, editUrl, indexPatterns, editable, deps }: VisualizeEmbeddableConfiguration, initialInput: VisualizeInput, + attributeService?: AttributeService< + VisualizeSavedObjectAttributes, + VisualizeByValueInput, + VisualizeByReferenceInput + >, + savedVisualizationsLoader?: SavedVisualizationsLoader, parent?: IContainer ) { super( @@ -118,6 +147,8 @@ export class VisualizeEmbeddable extends Embeddable { + if (!this.attributeService) { + throw new Error('AttributeService must be defined for getInputAsRefType'); + } + return this.attributeService.inputIsRefType(input as VisualizeByReferenceInput); + }; + + getInputAsValueType = async (): Promise => { + const input = { + savedVis: this.vis.serialize(), + }; + if (this.getTitle()) { + input.savedVis.title = this.getTitle(); + } + delete input.savedVis.id; + return new Promise((resolve) => { + resolve({ ...(input as VisualizeByValueInput) }); + }); + }; + + getInputAsRefType = async (): Promise => { + const savedVis = await this.savedVisualizationsLoader?.get({}); + if (!savedVis) { + throw new Error('Error creating a saved vis object'); + } + if (!this.attributeService) { + throw new Error('AttributeService must be defined for getInputAsRefType'); + } + const saveModalTitle = this.getTitle() + ? this.getTitle() + : i18n.translate('visualizations.embeddable.placeholderTitle', { + defaultMessage: 'Placeholder Title', + }); + // @ts-ignore + const attributes: VisualizeSavedObjectAttributes = { + savedVis, + vis: this.vis, + title: this.vis.title, + }; + return this.attributeService.getInputAsRefType( + { + id: this.id, + attributes, + }, + { showSaveModal: true, saveModalTitle } + ); + }; } diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index b81ff5c166183..75e53e8e92dbe 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -28,7 +28,14 @@ import { IContainer, } from '../../../embeddable/public'; import { DisabledLabEmbeddable } from './disabled_lab_embeddable'; -import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable'; +import { + VisualizeByReferenceInput, + VisualizeByValueInput, + VisualizeEmbeddable, + VisualizeInput, + VisualizeOutput, + VisualizeSavedObjectAttributes, +} from './visualize_embeddable'; import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; import { SerializedVis, Vis } from '../vis'; import { @@ -43,13 +50,16 @@ import { createVisEmbeddableFromObject } from './create_vis_embeddable_from_obje import { StartServicesGetter } from '../../../kibana_utils/public'; import { VisualizationsStartDeps } from '../plugin'; import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants'; +import { AttributeService } from '../../../dashboard/public'; interface VisualizationAttributes extends SavedObjectAttributes { visState: string; } export interface VisualizeEmbeddableFactoryDeps { - start: StartServicesGetter>; + start: StartServicesGetter< + Pick + >; } export class VisualizeEmbeddableFactory @@ -62,6 +72,12 @@ export class VisualizeEmbeddableFactory > { public readonly type = VISUALIZE_EMBEDDABLE_TYPE; + private attributeService?: AttributeService< + VisualizeSavedObjectAttributes, + VisualizeByValueInput, + VisualizeByReferenceInput + >; + public readonly savedObjectMetaData: SavedObjectMetaData = { name: i18n.translate('visualizations.savedObjectName', { defaultMessage: 'Visualization' }), includeFields: ['visState'], @@ -105,6 +121,19 @@ export class VisualizeEmbeddableFactory return await this.deps.start().core.application.currentAppId$.pipe(first()).toPromise(); } + private async getAttributeService() { + if (!this.attributeService) { + this.attributeService = await this.deps + .start() + .plugins.dashboard.getAttributeService< + VisualizeSavedObjectAttributes, + VisualizeByValueInput, + VisualizeByReferenceInput + >(this.type, { customSaveMethod: this.onSave }); + } + return this.attributeService!; + } + public async createFromSavedObject( savedObjectId: string, input: Partial & { id: string }, @@ -117,7 +146,13 @@ export class VisualizeEmbeddableFactory const visState = convertToSerializedVis(savedObject); const vis = new Vis(savedObject.visState.type, visState); await vis.setState(visState); - return createVisEmbeddableFromObject(this.deps)(vis, input, parent); + return createVisEmbeddableFromObject(this.deps)( + vis, + input, + savedVisualizations, + await this.getAttributeService(), + parent + ); } catch (e) { console.error(e); // eslint-disable-line no-console return new ErrorEmbeddable(e, input, parent); @@ -131,7 +166,14 @@ export class VisualizeEmbeddableFactory const visState = input.savedVis; const vis = new Vis(visState.type, visState); await vis.setState(visState); - return createVisEmbeddableFromObject(this.deps)(vis, input, parent); + const savedVisualizations = getSavedVisualizationsLoader(); + return createVisEmbeddableFromObject(this.deps)( + vis, + input, + savedVisualizations, + await this.getAttributeService(), + parent + ); } else { showNewVisModal({ originatingApp: await this.getCurrentAppId(), @@ -140,4 +182,47 @@ export class VisualizeEmbeddableFactory return undefined; } } + + private async onSave( + type: string, + attributes: VisualizeSavedObjectAttributes + ): Promise<{ id: string }> { + try { + const { title, savedVis } = attributes; + const visObj = attributes.vis; + if (!savedVis) { + throw new Error('No Saved Vis'); + } + const saveOptions = { + confirmOverwrite: false, + returnToOrigin: true, + }; + savedVis.title = title; + savedVis.copyOnSave = false; + savedVis.description = ''; + savedVis.searchSourceFields = visObj?.data.searchSource?.getSerializedFields(); + const serializedVis = ((visObj as unknown) as Vis).serialize(); + const { params, data } = serializedVis; + savedVis.visState = { + title, + type: serializedVis.type, + params, + aggs: data.aggs, + }; + if (visObj) { + savedVis.uiStateJSON = visObj?.uiState.toString(); + } + const id = await savedVis.save(saveOptions); + if (!id || id === '') { + throw new Error( + i18n.translate('visualizations.savingVisualizationFailed.errorMsg', { + defaultMessage: 'Saving a visualization failed', + }) + ); + } + return { id }; + } catch (error) { + throw error; + } + } } diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts index e0ec4801b3caf..646acc49a6a83 100644 --- a/src/plugins/visualizations/public/mocks.ts +++ b/src/plugins/visualizations/public/mocks.ts @@ -27,6 +27,7 @@ import { dataPluginMock } from '../../../plugins/data/public/mocks'; import { usageCollectionPluginMock } from '../../../plugins/usage_collection/public/mocks'; import { uiActionsPluginMock } from '../../../plugins/ui_actions/public/mocks'; import { inspectorPluginMock } from '../../../plugins/inspector/public/mocks'; +import { dashboardPluginMock } from '../../../plugins/dashboard/public/mocks'; const createSetupContract = (): VisualizationsSetup => ({ createBaseVisualization: jest.fn(), @@ -69,6 +70,8 @@ const createInstance = async () => { uiActions: uiActionsPluginMock.createStartContract(), application: applicationServiceMock.createStartContract(), embeddable: embeddablePluginMock.createStartContract(), + dashboard: dashboardPluginMock.createStartContract(), + getAttributeService: jest.fn(), }); return { diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 3546fa4056491..0ba80887b513f 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -76,6 +76,7 @@ import { convertToSerializedVis, } from './saved_visualizations/_saved_vis'; import { createSavedSearchesLoader } from '../../discover/public'; +import { DashboardStart } from '../../dashboard/public'; /** * Interface for this plugin's returned setup/start contracts. @@ -109,6 +110,8 @@ export interface VisualizationsStartDeps { inspector: InspectorStart; uiActions: UiActionsStart; application: ApplicationStart; + dashboard: DashboardStart; + getAttributeService: DashboardStart['getAttributeService']; } /** @@ -155,7 +158,7 @@ export class VisualizationsPlugin public start( core: CoreStart, - { data, expressions, uiActions, embeddable }: VisualizationsStartDeps + { data, expressions, uiActions, embeddable, dashboard }: VisualizationsStartDeps ): VisualizationsStart { const types = this.types.start(); setI18n(core.i18n); From 63f0cc051980530b7ab29ebc1324debedf34fe8a Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 15 Sep 2020 11:24:02 +0200 Subject: [PATCH 14/26] [Lens] Stack as percentage (#70703) --- .../plugins/lens/public/app_plugin/_app.scss | 14 ++ .../plugins/lens/public/assets/chart_area.svg | 6 - .../plugins/lens/public/assets/chart_area.tsx | 30 +++ .../public/assets/chart_area_percentage.tsx | 34 +++ .../lens/public/assets/chart_area_stacked.svg | 6 - .../lens/public/assets/chart_area_stacked.tsx | 34 +++ .../plugins/lens/public/assets/chart_bar.svg | 6 - .../plugins/lens/public/assets/chart_bar.tsx | 30 +++ .../public/assets/chart_bar_horizontal.svg | 6 - .../public/assets/chart_bar_horizontal.tsx | 34 +++ .../chart_bar_horizontal_percentage.tsx | 34 +++ .../assets/chart_bar_horizontal_stacked.svg | 6 - .../assets/chart_bar_horizontal_stacked.tsx | 34 +++ .../public/assets/chart_bar_percentage.tsx | 34 +++ .../lens/public/assets/chart_bar_stacked.svg | 6 - .../lens/public/assets/chart_bar_stacked.tsx | 34 +++ .../lens/public/assets/chart_datatable.svg | 6 - .../lens/public/assets/chart_datatable.tsx | 34 +++ .../lens/public/assets/chart_donut.svg | 4 - .../lens/public/assets/chart_donut.tsx | 30 +++ .../plugins/lens/public/assets/chart_line.svg | 6 - .../plugins/lens/public/assets/chart_line.tsx | 30 +++ .../lens/public/assets/chart_metric.svg | 4 - .../lens/public/assets/chart_metric.tsx | 30 +++ .../lens/public/assets/chart_mixed_xy.svg | 7 - .../lens/public/assets/chart_mixed_xy.tsx | 34 +++ .../plugins/lens/public/assets/chart_pie.svg | 4 - .../plugins/lens/public/assets/chart_pie.tsx | 30 +++ .../lens/public/assets/chart_treemap.svg | 5 - .../lens/public/assets/chart_treemap.tsx | 34 +++ .../expression.test.tsx | 3 +- .../datatable_visualization/expression.tsx | 4 +- .../datatable_visualization/visualization.tsx | 9 +- .../editor_frame/_suggestion_panel.scss | 5 +- .../config_panel/layer_panel.scss | 8 + .../editor_frame/config_panel/layer_panel.tsx | 2 +- .../editor_frame/suggestion_panel.test.tsx | 6 +- .../workspace_panel/chart_switch.scss | 1 + .../workspace_panel/chart_switch.tsx | 4 +- .../metric_suggestions.test.ts | 2 +- .../metric_suggestions.ts | 4 +- .../metric_visualization.tsx | 7 +- .../public/pie_visualization/constants.ts | 14 +- .../pie_visualization/pie_visualization.tsx | 6 +- .../render_function.test.tsx | 3 +- .../pie_visualization/render_function.tsx | 5 +- .../lens/public/pie_visualization/toolbar.tsx | 4 +- x-pack/plugins/lens/public/types.ts | 3 +- .../__snapshots__/xy_expression.test.tsx.snap | 231 ++++++++++++++++++ .../xy_visualization/axes_configuration.ts | 13 +- .../public/xy_visualization/state_helpers.ts | 6 +- .../xy_visualization/to_expression.test.ts | 39 +-- .../public/xy_visualization/to_expression.ts | 4 +- .../lens/public/xy_visualization/types.ts | 80 ++++-- .../xy_visualization/xy_config_panel.test.tsx | 10 +- .../xy_visualization/xy_config_panel.tsx | 1 - .../public/xy_visualization/xy_expression.tsx | 37 ++- .../xy_visualization/xy_suggestions.test.ts | 77 +++++- .../public/xy_visualization/xy_suggestions.ts | 133 ++++++++-- .../xy_visualization/xy_visualization.test.ts | 5 +- .../xy_visualization/xy_visualization.tsx | 44 ++-- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 63 files changed, 1149 insertions(+), 229 deletions(-) delete mode 100644 x-pack/plugins/lens/public/assets/chart_area.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_area.tsx create mode 100644 x-pack/plugins/lens/public/assets/chart_area_percentage.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_area_stacked.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_area_stacked.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_bar.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_bar.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_bar_stacked.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_datatable.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_datatable.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_donut.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_donut.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_line.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_line.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_metric.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_metric.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_mixed_xy.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_pie.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_pie.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_treemap.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_treemap.tsx diff --git a/x-pack/plugins/lens/public/app_plugin/_app.scss b/x-pack/plugins/lens/public/app_plugin/_app.scss index 4ad8dd360bac6..8416577a60421 100644 --- a/x-pack/plugins/lens/public/app_plugin/_app.scss +++ b/x-pack/plugins/lens/public/app_plugin/_app.scss @@ -26,3 +26,17 @@ flex-direction: column; flex-grow: 1; } + +.lensChartIcon__subdued { + fill: $euiTextSubduedColor; + + // Not great, but the easiest way to fix the gray fill when stuck in a button with a fill + // Like when selected in a button group + .euiButton--fill & { + fill: currentColor; + } +} + +.lensChartIcon__accent { + fill: $euiColorVis0; +} diff --git a/x-pack/plugins/lens/public/assets/chart_area.svg b/x-pack/plugins/lens/public/assets/chart_area.svg deleted file mode 100644 index d291a084028db..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_area.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_area.tsx b/x-pack/plugins/lens/public/assets/chart_area.tsx new file mode 100644 index 0000000000000..ae817e9794dc5 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_area.tsx @@ -0,0 +1,30 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartArea = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_area_percentage.tsx b/x-pack/plugins/lens/public/assets/chart_area_percentage.tsx new file mode 100644 index 0000000000000..45c208d5d634b --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_area_percentage.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartAreaPercentage = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_area_stacked.svg b/x-pack/plugins/lens/public/assets/chart_area_stacked.svg deleted file mode 100644 index 6ae48bf6a640b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_area_stacked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_area_stacked.tsx b/x-pack/plugins/lens/public/assets/chart_area_stacked.tsx new file mode 100644 index 0000000000000..0320ad7e9afa5 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_area_stacked.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartAreaStacked = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar.svg b/x-pack/plugins/lens/public/assets/chart_bar.svg deleted file mode 100644 index 44553960a5cce..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar.tsx b/x-pack/plugins/lens/public/assets/chart_bar.tsx new file mode 100644 index 0000000000000..9408f77bd4237 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar.tsx @@ -0,0 +1,30 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBar = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg deleted file mode 100644 index e0d9dc8385971..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx new file mode 100644 index 0000000000000..7ec48b107e2fb --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarHorizontal = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx new file mode 100644 index 0000000000000..6ce09265d4894 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarHorizontalPercentage = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg deleted file mode 100644 index 602a06e696ecd..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx new file mode 100644 index 0000000000000..c862121fd04f2 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarHorizontalStacked = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx b/x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx new file mode 100644 index 0000000000000..b7d6a0ed604af --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarPercentage = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg b/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg deleted file mode 100644 index a954cce83873d..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx b/x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx new file mode 100644 index 0000000000000..edf8e675178f0 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarStacked = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_datatable.svg b/x-pack/plugins/lens/public/assets/chart_datatable.svg deleted file mode 100644 index aba1f104264cb..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_datatable.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_datatable.tsx b/x-pack/plugins/lens/public/assets/chart_datatable.tsx new file mode 100644 index 0000000000000..48cc844ea2805 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_datatable.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartDatatable = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_donut.svg b/x-pack/plugins/lens/public/assets/chart_donut.svg deleted file mode 100644 index 5e0d8b7ea83bf..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_donut.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_donut.tsx b/x-pack/plugins/lens/public/assets/chart_donut.tsx new file mode 100644 index 0000000000000..9482161de9d9e --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_donut.tsx @@ -0,0 +1,30 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartDonut = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_line.svg b/x-pack/plugins/lens/public/assets/chart_line.svg deleted file mode 100644 index 412c9f88f652b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_line.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_line.tsx b/x-pack/plugins/lens/public/assets/chart_line.tsx new file mode 100644 index 0000000000000..5b57e1fe28c16 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_line.tsx @@ -0,0 +1,30 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartLine = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_metric.svg b/x-pack/plugins/lens/public/assets/chart_metric.svg deleted file mode 100644 index 84f0dc181587b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_metric.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_metric.tsx b/x-pack/plugins/lens/public/assets/chart_metric.tsx new file mode 100644 index 0000000000000..9faa4d6584258 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_metric.tsx @@ -0,0 +1,30 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartMetric = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg b/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg deleted file mode 100644 index 943d5a08bcc0b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx b/x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx new file mode 100644 index 0000000000000..08eac8eb1605d --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartMixedXy = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_pie.svg b/x-pack/plugins/lens/public/assets/chart_pie.svg deleted file mode 100644 index 22faaf5d97661..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_pie.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_pie.tsx b/x-pack/plugins/lens/public/assets/chart_pie.tsx new file mode 100644 index 0000000000000..cc26df4419caf --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_pie.tsx @@ -0,0 +1,30 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartPie = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_treemap.svg b/x-pack/plugins/lens/public/assets/chart_treemap.svg deleted file mode 100644 index b0ee04d02b2a6..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_treemap.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_treemap.tsx b/x-pack/plugins/lens/public/assets/chart_treemap.tsx new file mode 100644 index 0000000000000..57205e94137a8 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_treemap.tsx @@ -0,0 +1,34 @@ +/* + * 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 { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartTreemap = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + + +); diff --git a/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx b/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx index b9bdea5522f32..eb00cf93ccd34 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx @@ -15,6 +15,7 @@ import { IFieldFormat } from '../../../../../src/plugins/data/public'; import { IAggType } from 'src/plugins/data/public'; const onClickValue = jest.fn(); import { EmptyPlaceholder } from '../shared_components'; +import { LensIconChartDatatable } from '../assets/chart_datatable'; function sampleArgs() { const data: LensMultiTable = { @@ -219,7 +220,7 @@ describe('datatable_expression', () => { )} /> ); - expect(component.find(EmptyPlaceholder).prop('icon')).toEqual('visTable'); + expect(component.find(EmptyPlaceholder).prop('icon')).toEqual(LensIconChartDatatable); }); }); }); diff --git a/x-pack/plugins/lens/public/datatable_visualization/expression.tsx b/x-pack/plugins/lens/public/datatable_visualization/expression.tsx index 87ac2d1710b19..dac3b23b98e3b 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/expression.tsx @@ -23,6 +23,8 @@ import { import { VisualizationContainer } from '../visualization_container'; import { EmptyPlaceholder } from '../shared_components'; import { desanitizeFilterContext } from '../utils'; +import { LensIconChartDatatable } from '../assets/chart_datatable'; + export interface DatatableColumns { columnIds: string[]; } @@ -199,7 +201,7 @@ export function DatatableComponent(props: DatatableRenderProps) { )); if (isEmpty) { - return ; + return ; } return ( diff --git a/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx b/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx index 836ffcb15cfa1..5b462f44b3dd5 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx @@ -7,7 +7,7 @@ import { Ast } from '@kbn/interpreter/common'; import { i18n } from '@kbn/i18n'; import { SuggestionRequest, Visualization, VisualizationSuggestion, Operation } from '../types'; -import chartTableSVG from '../assets/chart_datatable.svg'; +import { LensIconChartDatatable } from '../assets/chart_datatable'; export interface LayerState { layerId: string; @@ -31,8 +31,7 @@ export const datatableVisualization: Visualization visualizationTypes: [ { id: 'lnsDatatable', - icon: 'visTable', - largeIcon: chartTableSVG, + icon: LensIconChartDatatable, label: i18n.translate('xpack.lens.datatable.label', { defaultMessage: 'Data table', }), @@ -55,7 +54,7 @@ export const datatableVisualization: Visualization getDescription() { return { - icon: chartTableSVG, + icon: LensIconChartDatatable, label: i18n.translate('xpack.lens.datatable.label', { defaultMessage: 'Data table', }), @@ -121,7 +120,7 @@ export const datatableVisualization: Visualization }, ], }, - previewIcon: chartTableSVG, + previewIcon: LensIconChartDatatable, // tables are hidden from suggestion bar, but used for drag & drop and chart switching hide: true, }, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss index 1d088e2ec86f9..9d018076dc320 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss @@ -42,9 +42,8 @@ justify-content: center; padding: $euiSizeS; - // Targeting img as this won't target normal EuiIcon's only the custom svgs's - > img { - @include size($euiSize * 4); + &:not(:only-child) { + height: calc(100% - #{$euiSizeL}); } } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss index 34cefd7d1b101..b85c3e843613d 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss @@ -6,6 +6,14 @@ max-width: calc(100% - #{$euiSize * 3.625}); } +.lnsLayerPanel__settingsFlexItem:empty + .lnsLayerPanel__sourceFlexItem { + max-width: calc(100% - #{$euiSizeS}); +} + +.lnsLayerPanel__settingsFlexItem:empty { + margin: 0; +} + .lnsLayerPanel__row { background: $euiColorLightestShade; padding: $euiSizeS; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index 258aadc82fbf2..46cd0292f2459 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -101,7 +101,7 @@ export function LayerPanel( - + { getSuggestionsMock.mockReturnValue([ { datasourceState: {}, - previewIcon: chartTableSVG, + previewIcon: LensIconChartDatatable, score: 0.5, visualizationState: suggestion1State, visualizationId: 'vis', @@ -288,6 +288,6 @@ describe('suggestion_panel', () => { const wrapper = mount(); expect(wrapper.find(EuiIcon)).toHaveLength(1); - expect(wrapper.find(EuiIcon).prop('type')).toEqual(chartTableSVG); + expect(wrapper.find(EuiIcon).prop('type')).toEqual(LensIconChartDatatable); }); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss index 8a44d59ff1c0d..f84191e1bfb1a 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss @@ -8,6 +8,7 @@ .lnsChartSwitch__summaryIcon { margin-right: $euiSizeS; transform: translateY(-1px); + color: $euiTextSubduedColor; } // Targeting img as this won't target normal EuiIcon's only the custom svgs's diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx index 5640c52ac4325..82983862e7c03 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx @@ -66,7 +66,7 @@ function VisualizationSummary(props: Props) { return ( <> {description.icon && ( - + )} {description.label} @@ -181,7 +181,7 @@ export function ChartSwitch(props: Props) { v.visualizationTypes.map((t) => ({ visualizationId: v.id, ...t, - icon: t.largeIcon || t.icon, + icon: t.icon, })) ) ).map((visualizationType) => ({ diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts index ecb1f07214ac6..2a659e5fe10c4 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts +++ b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts @@ -100,7 +100,7 @@ describe('metric_suggestions', () => { expect(rest).toHaveLength(0); expect(suggestion).toMatchInlineSnapshot(` Object { - "previewIcon": "test-file-stub", + "previewIcon": [Function], "score": 0.1, "state": Object { "accessor": "bytes", diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts index 0caac7dd0d092..c95467ab04e11 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts +++ b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts @@ -6,7 +6,7 @@ import { SuggestionRequest, VisualizationSuggestion, TableSuggestion } from '../types'; import { State } from './types'; -import chartMetricSVG from '../assets/chart_metric.svg'; +import { LensIconChartMetric } from '../assets/chart_metric'; /** * Generate suggestions for the metric chart. @@ -44,7 +44,7 @@ function getSuggestion(table: TableSuggestion): VisualizationSuggestion { return { title, score: 0.1, - previewIcon: chartMetricSVG, + previewIcon: LensIconChartMetric, state: { layerId: table.layerId, accessor: col.columnId, diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx b/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx index 5f1ce5334dd36..72c07bed1acb2 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx +++ b/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx @@ -7,9 +7,9 @@ import { i18n } from '@kbn/i18n'; import { Ast } from '@kbn/interpreter/target/common'; import { getSuggestions } from './metric_suggestions'; +import { LensIconChartMetric } from '../assets/chart_metric'; import { Visualization, OperationMetadata, DatasourcePublicAPI } from '../types'; import { State } from './types'; -import chartMetricSVG from '../assets/chart_metric.svg'; const toExpression = ( state: State, @@ -45,8 +45,7 @@ export const metricVisualization: Visualization = { visualizationTypes: [ { id: 'lnsMetric', - icon: 'visMetric', - largeIcon: chartMetricSVG, + icon: LensIconChartMetric, label: i18n.translate('xpack.lens.metric.label', { defaultMessage: 'Metric', }), @@ -70,7 +69,7 @@ export const metricVisualization: Visualization = { getDescription() { return { - icon: chartMetricSVG, + icon: LensIconChartMetric, label: i18n.translate('xpack.lens.metric.label', { defaultMessage: 'Metric', }), diff --git a/x-pack/plugins/lens/public/pie_visualization/constants.ts b/x-pack/plugins/lens/public/pie_visualization/constants.ts index 10672f91a81c7..ab5e64ea84029 100644 --- a/x-pack/plugins/lens/public/pie_visualization/constants.ts +++ b/x-pack/plugins/lens/public/pie_visualization/constants.ts @@ -5,25 +5,25 @@ */ import { i18n } from '@kbn/i18n'; -import chartDonutSVG from '../assets/chart_donut.svg'; -import chartPieSVG from '../assets/chart_pie.svg'; -import chartTreemapSVG from '../assets/chart_treemap.svg'; +import { LensIconChartDonut } from '../assets/chart_donut'; +import { LensIconChartPie } from '../assets/chart_pie'; +import { LensIconChartTreemap } from '../assets/chart_treemap'; export const CHART_NAMES = { donut: { - icon: chartDonutSVG, + icon: LensIconChartDonut, label: i18n.translate('xpack.lens.pie.donutLabel', { defaultMessage: 'Donut', }), }, pie: { - icon: chartPieSVG, + icon: LensIconChartPie, label: i18n.translate('xpack.lens.pie.pielabel', { defaultMessage: 'Pie', }), }, treemap: { - icon: chartTreemapSVG, + icon: LensIconChartTreemap, label: i18n.translate('xpack.lens.pie.treemaplabel', { defaultMessage: 'Treemap', }), @@ -33,4 +33,4 @@ export const CHART_NAMES = { export const MAX_PIE_BUCKETS = 3; export const MAX_TREEMAP_BUCKETS = 2; -export const DEFAULT_PERCENT_DECIMALS = 3; +export const DEFAULT_PERCENT_DECIMALS = 2; diff --git a/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx index 855bacd4f794c..dd1b36e00ebb9 100644 --- a/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx @@ -37,17 +37,17 @@ export const pieVisualization: Visualization = { visualizationTypes: [ { id: 'donut', - largeIcon: CHART_NAMES.donut.icon, + icon: CHART_NAMES.donut.icon, label: CHART_NAMES.donut.label, }, { id: 'pie', - largeIcon: CHART_NAMES.pie.icon, + icon: CHART_NAMES.pie.icon, label: CHART_NAMES.pie.label, }, { id: 'treemap', - largeIcon: CHART_NAMES.treemap.icon, + icon: CHART_NAMES.treemap.icon, label: CHART_NAMES.treemap.label, }, ], diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx index 38ef44a2fef18..ac952e307758b 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx @@ -12,6 +12,7 @@ import { PieComponent } from './render_function'; import { PieExpressionArgs } from './types'; import { EmptyPlaceholder } from '../shared_components'; import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks'; +import { LensIconChartDonut } from '../assets/chart_donut'; const chartsThemeService = chartPluginMock.createSetupContract().theme; @@ -189,7 +190,7 @@ describe('PieVisualization component', () => { const component = shallow( ); - expect(component.find(EmptyPlaceholder).prop('icon')).toEqual('visPie'); + expect(component.find(EmptyPlaceholder).prop('icon')).toEqual(LensIconChartDonut); }); }); }); diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx index 4e813494d7d32..d97ab146e000d 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx @@ -33,6 +33,7 @@ import { EmptyPlaceholder } from '../shared_components'; import './visualization.scss'; import { desanitizeFilterContext } from '../utils'; import { ChartsPluginSetup } from '../../../../../src/plugins/charts/public'; +import { LensIconChartDonut } from '../assets/chart_donut'; const EMPTY_SLICE = Symbol('empty_slice'); @@ -186,7 +187,7 @@ export function PieComponent( const percentFormatter = props.formatFactory({ id: 'percent', params: { - pattern: `0,0.${'0'.repeat(percentDecimals ?? DEFAULT_PERCENT_DECIMALS)}%`, + pattern: `0,0.[${'0'.repeat(percentDecimals ?? DEFAULT_PERCENT_DECIMALS)}]%`, }, }); @@ -210,7 +211,7 @@ export function PieComponent( ); if (isEmpty) { - return ; + return ; } if (hasNegative) { diff --git a/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx b/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx index 501a2de24d9ad..9ee37fdf53a92 100644 --- a/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx @@ -188,10 +188,10 @@ export function PieToolbar(props: VisualizationToolbarProps yAxisConfig.forAccessor === accessor)?.axisMode || 'auto'; - const formatter: SerializedFieldFormat = table.columns.find( - (column) => column.id === accessor - )?.formatHint || { id: 'number' }; + let formatter: SerializedFieldFormat = table.columns.find((column) => column.id === accessor) + ?.formatHint || { id: 'number' }; + if (layer.seriesType.includes('percentage') && formatter.id !== 'percent') { + formatter = { + id: 'percent', + params: { + pattern: '0.[00]%', + }, + }; + } series[mode].push({ layer: layer.layerId, accessor, diff --git a/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts b/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts index 2ddb9418abad9..41d18e5199e4c 100644 --- a/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts +++ b/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts @@ -8,7 +8,11 @@ import { EuiIconType } from '@elastic/eui/src/components/icon/icon'; import { SeriesType, visualizationTypes, LayerConfig, YConfig } from './types'; export function isHorizontalSeries(seriesType: SeriesType) { - return seriesType === 'bar_horizontal' || seriesType === 'bar_horizontal_stacked'; + return ( + seriesType === 'bar_horizontal' || + seriesType === 'bar_horizontal_stacked' || + seriesType === 'bar_horizontal_percentage_stacked' + ); } export function isHorizontalChart(layers: Array<{ seriesType: SeriesType }>) { diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts index f579085646f6f..825281d6d88c2 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts @@ -100,25 +100,26 @@ describe('#toExpression', () => { expect(expression.chain[0].arguments.showYAxisTitle[0]).toBe(true); }); - it('should not generate an expression when missing x', () => { - expect( - xyVisualization.toExpression( - { - legend: { position: Position.Bottom, isVisible: true }, - preferredSeriesType: 'bar', - layers: [ - { - layerId: 'first', - seriesType: 'area', - splitAccessor: undefined, - xAccessor: undefined, - accessors: ['a'], - }, - ], - }, - frame.datasourceLayers - ) - ).toBeNull(); + it('should generate an expression without x accessor', () => { + const expression = xyVisualization.toExpression( + { + legend: { position: Position.Bottom, isVisible: true }, + preferredSeriesType: 'bar', + layers: [ + { + layerId: 'first', + seriesType: 'area', + splitAccessor: undefined, + xAccessor: undefined, + accessors: ['a'], + }, + ], + }, + frame.datasourceLayers + ) as Ast; + expect((expression.chain[0].arguments.layers[0] as Ast).chain[0].arguments.xAccessor).toEqual( + [] + ); }); it('should not generate an expression when missing y', () => { diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts index cd32d4f94c3e5..f64624776186d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts @@ -84,7 +84,7 @@ export const buildExpression = ( datasourceLayers?: Record ): Ast | null => { const validLayers = state.layers.filter((layer): layer is ValidLayer => - Boolean(layer.xAccessor && layer.accessors.length) + Boolean(layer.accessors.length) ); if (!validLayers.length) { return null; @@ -187,7 +187,7 @@ export const buildExpression = ( hide: [Boolean(layer.hide)], - xAccessor: [layer.xAccessor], + xAccessor: layer.xAccessor ? [layer.xAccessor] : [], yScaleType: [ getScaleType(metadata[layer.layerId][layer.accessors[0]], ScaleType.Ordinal), ], diff --git a/x-pack/plugins/lens/public/xy_visualization/types.ts b/x-pack/plugins/lens/public/xy_visualization/types.ts index 2739ffe42f13f..8438b1f27dd0d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/types.ts +++ b/x-pack/plugins/lens/public/xy_visualization/types.ts @@ -7,13 +7,16 @@ import { Position } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; import { ArgumentType, ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; -import chartAreaSVG from '../assets/chart_area.svg'; -import chartAreaStackedSVG from '../assets/chart_area_stacked.svg'; -import chartBarSVG from '../assets/chart_bar.svg'; -import chartBarStackedSVG from '../assets/chart_bar_stacked.svg'; -import chartBarHorizontalSVG from '../assets/chart_bar_horizontal.svg'; -import chartBarHorizontalStackedSVG from '../assets/chart_bar_horizontal_stacked.svg'; -import chartLineSVG from '../assets/chart_line.svg'; +import { LensIconChartArea } from '../assets/chart_area'; +import { LensIconChartAreaStacked } from '../assets/chart_area_stacked'; +import { LensIconChartAreaPercentage } from '../assets/chart_area_percentage'; +import { LensIconChartBar } from '../assets/chart_bar'; +import { LensIconChartBarStacked } from '../assets/chart_bar_stacked'; +import { LensIconChartBarPercentage } from '../assets/chart_bar_percentage'; +import { LensIconChartBarHorizontal } from '../assets/chart_bar_horizontal'; +import { LensIconChartBarHorizontalStacked } from '../assets/chart_bar_horizontal_stacked'; +import { LensIconChartBarHorizontalPercentage } from '../assets/chart_bar_horizontal_percentage'; +import { LensIconChartLine } from '../assets/chart_line'; import { VisualizationType } from '../index'; import { FittingFunction } from './fitting_functions'; @@ -230,7 +233,15 @@ export const layerConfig: ExpressionFunctionDefinition< }, seriesType: { types: ['string'], - options: ['bar', 'line', 'area', 'bar_stacked', 'area_stacked'], + options: [ + 'bar', + 'line', + 'area', + 'bar_stacked', + 'area_stacked', + 'bar_percentage_stacked', + 'area_percentage_stacked', + ], help: 'The type of chart to display.', }, xScaleType: { @@ -283,8 +294,11 @@ export type SeriesType = | 'line' | 'area' | 'bar_stacked' + | 'bar_percentage_stacked' | 'bar_horizontal_stacked' - | 'area_stacked'; + | 'bar_horizontal_percentage_stacked' + | 'area_stacked' + | 'area_percentage_stacked'; export type YAxisMode = 'auto' | 'left' | 'right'; @@ -343,58 +357,72 @@ export type State = XYState; export const visualizationTypes: VisualizationType[] = [ { id: 'bar', - icon: 'visBarVertical', - largeIcon: chartBarSVG, + icon: LensIconChartBar, label: i18n.translate('xpack.lens.xyVisualization.barLabel', { defaultMessage: 'Bar', }), }, { id: 'bar_horizontal', - icon: 'visBarHorizontal', - largeIcon: chartBarHorizontalSVG, + icon: LensIconChartBarHorizontal, label: i18n.translate('xpack.lens.xyVisualization.barHorizontalLabel', { defaultMessage: 'Horizontal bar', }), }, { id: 'bar_stacked', - icon: 'visBarVerticalStacked', - largeIcon: chartBarStackedSVG, + icon: LensIconChartBarStacked, label: i18n.translate('xpack.lens.xyVisualization.stackedBarLabel', { defaultMessage: 'Stacked bar', }), }, + { + id: 'bar_percentage_stacked', + icon: LensIconChartBarPercentage, + label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarLabel', { + defaultMessage: 'Bar percentage', + }), + }, { id: 'bar_horizontal_stacked', - icon: 'visBarHorizontalStacked', - largeIcon: chartBarHorizontalStackedSVG, + icon: LensIconChartBarHorizontalStacked, label: i18n.translate('xpack.lens.xyVisualization.stackedBarHorizontalLabel', { defaultMessage: 'Stacked horizontal bar', }), }, { - id: 'line', - icon: 'visLine', - largeIcon: chartLineSVG, - label: i18n.translate('xpack.lens.xyVisualization.lineLabel', { - defaultMessage: 'Line', + id: 'bar_horizontal_percentage_stacked', + icon: LensIconChartBarHorizontalPercentage, + label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarHorizontalLabel', { + defaultMessage: 'Horizontal bar percentage', }), }, { id: 'area', - icon: 'visArea', - largeIcon: chartAreaSVG, + icon: LensIconChartArea, label: i18n.translate('xpack.lens.xyVisualization.areaLabel', { defaultMessage: 'Area', }), }, { id: 'area_stacked', - icon: 'visAreaStacked', - largeIcon: chartAreaStackedSVG, + icon: LensIconChartAreaStacked, label: i18n.translate('xpack.lens.xyVisualization.stackedAreaLabel', { defaultMessage: 'Stacked area', }), }, + { + id: 'area_percentage_stacked', + icon: LensIconChartAreaPercentage, + label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageAreaLabel', { + defaultMessage: 'Area percentage', + }), + }, + { + id: 'line', + icon: LensIconChartLine, + label: i18n.translate('xpack.lens.xyVisualization.lineLabel', { + defaultMessage: 'Line', + }), + }, ]; diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx index e80bb22c04a69..89a2574026ced 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx @@ -59,9 +59,11 @@ describe('XY Config panels', () => { expect(options!.map(({ id }) => id)).toEqual([ 'bar', 'bar_stacked', - 'line', + 'bar_percentage_stacked', 'area', 'area_stacked', + 'area_percentage_stacked', + 'line', ]); expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]); @@ -83,7 +85,11 @@ describe('XY Config panels', () => { .first() .prop('options') as EuiButtonGroupProps['options']; - expect(options!.map(({ id }) => id)).toEqual(['bar_horizontal', 'bar_horizontal_stacked']); + expect(options!.map(({ id }) => id)).toEqual([ + 'bar_horizontal', + 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', + ]); expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]); }); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx index a2488d123e13a..62fd6e013f20d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx @@ -114,7 +114,6 @@ export function LayerContextMenu(props: VisualizationLayerWidgetProps) { ); }} isIconOnly - buttonSize="compressed" /> ); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx index 31873228fb394..a8c7c8daaf58b 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx @@ -17,6 +17,7 @@ import { Position, GeometryValue, XYChartSeriesIdentifier, + StackMode, } from '@elastic/charts'; import { I18nProvider } from '@kbn/i18n/react'; import { @@ -229,11 +230,10 @@ export function XYChart({ const filteredLayers = layers.filter(({ layerId, xAccessor, accessors }) => { return !( - !xAccessor || !accessors.length || !data.tables[layerId] || data.tables[layerId].rows.length === 0 || - data.tables[layerId].rows.every((row) => typeof row[xAccessor] === 'undefined') + (xAccessor && data.tables[layerId].rows.every((row) => typeof row[xAccessor] === 'undefined')) ); }); @@ -425,7 +425,7 @@ export function XYChart({ visible: gridlinesVisibilitySettings?.x, strokeWidth: 2, }} - hide={filteredLayers[0].hide} + hide={filteredLayers[0].hide || !filteredLayers[0].xAccessor} tickFormat={(d) => xAxisFormatter.convert(d)} style={{ tickLabel: { @@ -483,8 +483,7 @@ export function XYChart({ // To not display them in the legend, they need to be filtered out. const rows = table.rows.filter( (row) => - xAccessor && - typeof row[xAccessor] !== 'undefined' && + !(xAccessor && typeof row[xAccessor] === 'undefined') && !( splitAccessor && typeof row[splitAccessor] === 'undefined' && @@ -492,21 +491,42 @@ export function XYChart({ ) ); + if (!xAccessor) { + rows.forEach((row) => { + row.unifiedX = i18n.translate('xpack.lens.xyChart.emptyXLabel', { + defaultMessage: '(empty)', + }); + }); + } + const seriesProps: SeriesSpec = { splitSeriesAccessors: splitAccessor ? [splitAccessor] : [], stackAccessors: seriesType.includes('stacked') ? [xAccessor as string] : [], id: `${splitAccessor}-${accessor}`, - xAccessor, + xAccessor: xAccessor || 'unifiedX', yAccessors: [accessor], data: rows, - xScaleType, + xScaleType: xAccessor ? xScaleType : 'ordinal', yScaleType, color: () => getSeriesColor(layer, accessor), groupId: yAxesConfiguration.find((axisConfiguration) => axisConfiguration.series.find((currentSeries) => currentSeries.accessor === accessor) )?.groupId, enableHistogramMode: isHistogram && (seriesType.includes('stacked') || !splitAccessor), + stackMode: seriesType.includes('percentage') ? StackMode.Percentage : undefined, timeZone, + areaSeriesStyle: { + point: { + visible: !xAccessor, + radius: 5, + }, + }, + lineSeriesStyle: { + point: { + visible: !xAccessor, + radius: 5, + }, + }, name(d) { const splitHint = table.columns.find((col) => col.id === splitAccessor)?.formatHint; @@ -545,10 +565,13 @@ export function XYChart({ ); case 'bar': case 'bar_stacked': + case 'bar_percentage_stacked': case 'bar_horizontal': case 'bar_horizontal_stacked': + case 'bar_horizontal_percentage_stacked': return ; case 'area_stacked': + case 'area_percentage_stacked': return ( ); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts index 79e4ed6958193..ea5cff80695a3 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts @@ -119,6 +119,51 @@ describe('xy_suggestions', () => { ); }); + test('suggests all xy charts without changes to the state when switching among xy charts with malformed table', () => { + (generateId as jest.Mock).mockReturnValueOnce('aaa'); + const suggestions = getSuggestions({ + table: { + isMultiRow: false, + columns: [numCol('bytes')], + layerId: 'first', + changeType: 'unchanged', + }, + keptLayerIds: [], + state: { + legend: { isVisible: true, position: 'bottom' }, + preferredSeriesType: 'bar', + layers: [ + { + layerId: 'first', + seriesType: 'bar', + accessors: ['bytes'], + splitAccessor: undefined, + }, + { + layerId: 'second', + seriesType: 'bar', + accessors: ['bytes'], + splitAccessor: undefined, + }, + ], + }, + }); + + expect(suggestions).toHaveLength(visualizationTypes.length); + expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([ + 'bar', + 'bar_horizontal', + 'bar_stacked', + 'bar_percentage_stacked', + 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', + 'area', + 'area_stacked', + 'area_percentage_stacked', + 'line', + ]); + }); + test('suggests all basic x y charts when switching from another vis', () => { (generateId as jest.Mock).mockReturnValueOnce('aaa'); const suggestions = getSuggestions({ @@ -134,10 +179,13 @@ describe('xy_suggestions', () => { expect(suggestions).toHaveLength(visualizationTypes.length); expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([ 'bar_stacked', + 'line', + 'area_percentage_stacked', 'area_stacked', 'area', - 'line', + 'bar_horizontal_percentage_stacked', 'bar_horizontal_stacked', + 'bar_percentage_stacked', 'bar_horizontal', 'bar', ]); @@ -157,13 +205,27 @@ describe('xy_suggestions', () => { }); expect(suggestions).toHaveLength(visualizationTypes.length); - expect(suggestions.map(({ state }) => state.layers.length)).toEqual([1, 1, 1, 1, 1, 1, 1]); + expect(suggestions.map(({ state }) => state.layers.length)).toEqual([ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + ]); expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([ 'bar_stacked', + 'line', + 'area_percentage_stacked', 'area_stacked', 'area', - 'line', + 'bar_horizontal_percentage_stacked', 'bar_horizontal_stacked', + 'bar_percentage_stacked', 'bar_horizontal', 'bar', ]); @@ -200,9 +262,12 @@ describe('xy_suggestions', () => { 'bar', 'bar_horizontal', 'bar_stacked', + 'bar_percentage_stacked', 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', 'area', 'area_stacked', + 'area_percentage_stacked', ]); }); @@ -244,9 +309,12 @@ describe('xy_suggestions', () => { 'bar', 'bar_horizontal', 'bar_stacked', + 'bar_percentage_stacked', 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', 'area', 'area_stacked', + 'area_percentage_stacked', ]); expect(suggestions.map(({ state }) => state.layers.map((l) => l.layerId))).toEqual([ ['first', 'second'], @@ -256,6 +324,9 @@ describe('xy_suggestions', () => { ['first', 'second'], ['first', 'second'], ['first', 'second'], + ['first', 'second'], + ['first', 'second'], + ['first', 'second'], ]); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts index 75dd5a7a579b8..42fc538874b93 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts @@ -45,6 +45,24 @@ export function getSuggestions({ table.columns.every((col) => col.operation.dataType !== 'number') || table.columns.some((col) => !columnSortOrder.hasOwnProperty(col.operation.dataType)) ) { + if (table.changeType === 'unchanged' && state) { + // this isn't a table we would switch to, but we have a state already. In this case, just use the current state for all series types + return visualizationTypes.map((visType) => { + const seriesType = visType.id as SeriesType; + return { + seriesType, + score: 0, + state: { + ...state, + preferredSeriesType: seriesType, + layers: state.layers.map((layer) => ({ ...layer, seriesType })), + }, + previewIcon: getIconForSeries(seriesType), + title: visType.label, + hide: true, + }; + }); + } return []; } @@ -91,6 +109,25 @@ function getSuggestionForColumns( } } +function flipSeriesType(seriesType: SeriesType) { + switch (seriesType) { + case 'bar_horizontal': + return 'bar'; + case 'bar_horizontal_stacked': + return 'bar_stacked'; + case 'bar': + return 'bar_horizontal'; + case 'bar_horizontal_stacked': + return 'bar_stacked'; + case 'bar_horizontal_percentage_stacked': + return 'bar_percentage_stacked'; + case 'bar_percentage_stacked': + return 'bar_horizontal_percentage_stacked'; + default: + return 'bar_horizontal'; + } +} + function getBucketMappings(table: TableSuggestion, currentState?: State) { const currentLayer = currentState && currentState.layers.find(({ layerId }) => layerId === table.layerId); @@ -156,7 +193,7 @@ function getSuggestionsForLayer({ }: { layerId: string; changeType: TableChangeType; - xValue: TableSuggestionColumn; + xValue?: TableSuggestionColumn; yValues: TableSuggestionColumn[]; splitBy?: TableSuggestionColumn; currentState?: State; @@ -164,7 +201,7 @@ function getSuggestionsForLayer({ keptLayerIds: string[]; }): VisualizationSuggestion | Array> { const title = getSuggestionTitle(yValues, xValue, tableLabel); - const seriesType: SeriesType = getSeriesType(currentState, layerId, xValue, changeType); + const seriesType: SeriesType = getSeriesType(currentState, layerId, xValue); const options = { currentState, @@ -182,11 +219,13 @@ function getSuggestionsForLayer({ if (!currentState && changeType === 'unchanged') { // Chart switcher needs to include every chart type return visualizationTypes - .map((visType) => ({ - ...buildSuggestion({ ...options, seriesType: visType.id as SeriesType }), - title: visType.label, - hide: visType.id !== 'bar_stacked', - })) + .map((visType) => { + return { + ...buildSuggestion({ ...options, seriesType: visType.id as SeriesType }), + title: visType.label, + hide: visType.id !== 'bar_stacked', + }; + }) .sort((a, b) => (a.state.preferredSeriesType === 'bar_stacked' ? -1 : 1)); } @@ -199,18 +238,13 @@ function getSuggestionsForLayer({ const sameStateSuggestions: Array> = []; // if current state is using the same data, suggest same chart with different presentational configuration - if (seriesType !== 'line' && xValue.operation.scale === 'ordinal') { + if (seriesType.includes('bar') && (!xValue || xValue.operation.scale === 'ordinal')) { // flip between horizontal/vertical for ordinal scales sameStateSuggestions.push( buildSuggestion({ ...options, title: i18n.translate('xpack.lens.xySuggestions.flipTitle', { defaultMessage: 'Flip' }), - seriesType: - seriesType === 'bar_horizontal' - ? 'bar' - : seriesType === 'bar_horizontal_stacked' - ? 'bar_stacked' - : 'bar_horizontal', + seriesType: flipSeriesType(seriesType), }) ); } else { @@ -231,7 +265,7 @@ function getSuggestionsForLayer({ ); } - if (seriesType !== 'line' && splitBy) { + if (seriesType !== 'line' && splitBy && !seriesType.includes('percentage')) { // flip between stacked/unstacked sameStateSuggestions.push( buildSuggestion({ @@ -248,6 +282,30 @@ function getSuggestionsForLayer({ ); } + if ( + seriesType !== 'line' && + seriesType.includes('stacked') && + !seriesType.includes('percentage') + ) { + const percentageOptions = { ...options }; + if (percentageOptions.xValue?.operation.scale === 'ordinal' && !percentageOptions.splitBy) { + percentageOptions.splitBy = percentageOptions.xValue; + delete percentageOptions.xValue; + } + // percentage suggestion + sameStateSuggestions.push( + buildSuggestion({ + ...options, + // hide the suggestion if split by is missing + hide: !percentageOptions.splitBy, + seriesType: asPercentageSeriesType(seriesType), + title: i18n.translate('xpack.lens.xySuggestions.asPercentageTitle', { + defaultMessage: 'Percentage', + }), + }) + ); + } + // Combine all pre-built suggestions with hidden suggestions for remaining chart types return sameStateSuggestions.concat( visualizationTypes @@ -280,6 +338,19 @@ function toggleStackSeriesType(oldSeriesType: SeriesType) { } } +function asPercentageSeriesType(oldSeriesType: SeriesType) { + switch (oldSeriesType) { + case 'area_stacked': + return 'area_percentage_stacked'; + case 'bar_stacked': + return 'bar_percentage_stacked'; + case 'bar_horizontal_stacked': + return 'bar_horizontal_percentage_stacked'; + default: + return oldSeriesType; + } +} + // Until the area chart rendering bug is fixed, avoid suggesting area charts // https://github.com/elastic/elastic-charts/issues/388 function altSeriesType(oldSeriesType: SeriesType) { @@ -301,8 +372,7 @@ function altSeriesType(oldSeriesType: SeriesType) { function getSeriesType( currentState: XYState | undefined, layerId: string, - xValue: TableSuggestionColumn, - changeType: TableChangeType + xValue?: TableSuggestionColumn ): SeriesType { const defaultType = 'bar_stacked'; @@ -314,7 +384,7 @@ function getSeriesType( // Attempt to keep the seriesType consistent on initial add of a layer // Ordinal scales should always use a bar because there is no interpolation between buckets - if (xValue.operation.scale && xValue.operation.scale === 'ordinal') { + if (xValue && xValue.operation.scale && xValue.operation.scale === 'ordinal') { return closestSeriesType.startsWith('bar') ? closestSeriesType : defaultType; } @@ -323,7 +393,7 @@ function getSeriesType( function getSuggestionTitle( yValues: TableSuggestionColumn[], - xValue: TableSuggestionColumn, + xValue: TableSuggestionColumn | undefined, tableLabel: string | undefined ) { const yTitle = yValues @@ -335,10 +405,14 @@ function getSuggestionTitle( 'A character that can be used for conjunction of multiple enumarated items. Make sure to include spaces around it if needed.', }) ); - const xTitle = xValue.operation.label; + const xTitle = + xValue?.operation.label || + i18n.translate('xpack.lens.xySuggestions.emptyAxisTitle', { + defaultMessage: '(empty)', + }); const title = tableLabel || - (xValue.operation.dataType === 'date' + (xValue?.operation.dataType === 'date' ? i18n.translate('xpack.lens.xySuggestions.dateSuggestion', { defaultMessage: '{yTitle} over {xTitle}', description: @@ -364,24 +438,30 @@ function buildSuggestion({ changeType, xValue, keptLayerIds, + hide, }: { currentState: XYState | undefined; seriesType: SeriesType; title: string; yValues: TableSuggestionColumn[]; - xValue: TableSuggestionColumn; + xValue?: TableSuggestionColumn; splitBy: TableSuggestionColumn | undefined; layerId: string; changeType: TableChangeType; keptLayerIds: string[]; + hide?: boolean; }) { + if (seriesType.includes('percentage') && xValue?.operation.scale === 'ordinal' && !splitBy) { + splitBy = xValue; + xValue = undefined; + } const existingLayer: LayerConfig | {} = getExistingLayer(currentState, layerId) || {}; const accessors = yValues.map((col) => col.columnId); const newLayer = { ...existingLayer, layerId, seriesType, - xAccessor: xValue.columnId, + xAccessor: xValue?.columnId, splitAccessor: splitBy?.columnId, accessors, yConfig: @@ -427,10 +507,11 @@ function buildSuggestion({ title, score: getScore(yValues, splitBy, changeType), hide: + hide ?? // Only advertise very clear changes when XY chart is not active - (!currentState && changeType !== 'unchanged' && changeType !== 'extended') || - // Don't advertise removing dimensions - (currentState && changeType === 'reduced'), + ((!currentState && changeType !== 'unchanged' && changeType !== 'extended') || + // Don't advertise removing dimensions + (currentState && changeType === 'reduced')), state, previewIcon: getIconForSeries(seriesType), }; diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts index 53f7a23dcae98..7cf1830cdc2fa 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts @@ -9,6 +9,7 @@ import { Position } from '@elastic/charts'; import { Operation } from '../types'; import { State, SeriesType } from './types'; import { createMockDatasource, createMockFramePublicAPI } from '../editor_frame_service/mocks'; +import { LensIconChartBar } from '../assets/chart_bar'; function exampleState(): State { return { @@ -49,9 +50,7 @@ describe('xy_visualization', () => { it('should show the preferredSeriesType if there are no layers', () => { const desc = xyVisualization.getDescription(mixedState()); - // 'test-file-stub' is a hack, but it at least means we aren't using - // a standard icon here. - expect(desc.icon).toEqual('test-file-stub'); + expect(desc.icon).toEqual(LensIconChartBar); expect(desc.label).toEqual('Bar chart'); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx index 8c551c575764e..0b8f7e2ed0f11 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx @@ -14,12 +14,13 @@ import { getSuggestions } from './xy_suggestions'; import { LayerContextMenu, XyToolbar, DimensionEditor } from './xy_config_panel'; import { Visualization, OperationMetadata, VisualizationType } from '../types'; import { State, SeriesType, visualizationTypes, LayerConfig } from './types'; -import chartBarStackedSVG from '../assets/chart_bar_stacked.svg'; -import chartMixedSVG from '../assets/chart_mixed_xy.svg'; import { isHorizontalChart } from './state_helpers'; import { toExpression, toPreviewExpression } from './to_expression'; +import { LensIconChartBarStacked } from '../assets/chart_bar_stacked'; +import { LensIconChartMixedXy } from '../assets/chart_mixed_xy'; +import { LensIconChartBarHorizontal } from '../assets/chart_bar_horizontal'; -const defaultIcon = chartBarStackedSVG; +const defaultIcon = LensIconChartBarStacked; const defaultSeriesType = 'bar_stacked'; const isNumericMetric = (op: OperationMetadata) => !op.isBucketed && op.dataType === 'number'; const isBucketed = (op: OperationMetadata) => op.isBucketed; @@ -48,29 +49,27 @@ function getDescription(state?: State) { const visualizationType = getVisualizationType(state); - if (!state.layers.length) { - const preferredType = visualizationType as VisualizationType; + if (visualizationType === 'mixed' && isHorizontalChart(state.layers)) { + return { + icon: LensIconChartBarHorizontal, + label: i18n.translate('xpack.lens.xyVisualization.mixedBarHorizontalLabel', { + defaultMessage: 'Mixed horizontal bar', + }), + }; + } + + if (visualizationType === 'mixed') { return { - icon: preferredType.largeIcon || preferredType.icon, - label: preferredType.label, + icon: LensIconChartMixedXy, + label: i18n.translate('xpack.lens.xyVisualization.mixedLabel', { + defaultMessage: 'Mixed XY', + }), }; } return { - icon: - visualizationType === 'mixed' - ? chartMixedSVG - : visualizationType.largeIcon || visualizationType.icon, - label: - visualizationType === 'mixed' - ? isHorizontalChart(state.layers) - ? i18n.translate('xpack.lens.xyVisualization.mixedBarHorizontalLabel', { - defaultMessage: 'Mixed horizontal bar', - }) - : i18n.translate('xpack.lens.xyVisualization.mixedLabel', { - defaultMessage: 'Mixed XY', - }) - : visualizationType.label, + icon: visualizationType.icon, + label: visualizationType.label, }; } @@ -172,7 +171,7 @@ export const xyVisualization: Visualization = { filterOperations: isBucketed, suggestedPriority: 1, supportsMoreColumns: !layer.xAccessor, - required: true, + required: !layer.seriesType.includes('percentage'), dataTestSubj: 'lnsXY_xDimensionPanel', }, { @@ -197,6 +196,7 @@ export const xyVisualization: Visualization = { suggestedPriority: 0, supportsMoreColumns: !layer.splitAccessor, dataTestSubj: 'lnsXY_splitDimensionPanel', + required: layer.seriesType.includes('percentage'), }, ], }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a0aa285b43848..0977e99fa0c3c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9691,7 +9691,6 @@ "xpack.lens.pieChart.legendDisplayLegend": "凡例表示", "xpack.lens.pieChart.nestedLegendLabel": "ネストされた凡例", "xpack.lens.pieChart.numberLabels": "ラベル値", - "xpack.lens.pieChart.percentDecimalsLabel": "割合の小数点桁数", "xpack.lens.pieChart.showCategoriesLabel": "内部または外部", "xpack.lens.pieChart.showFormatterValuesLabel": "値を表示", "xpack.lens.pieChart.showPercentValuesLabel": "割合を表示", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 01cd7f569d13b..7f8f2a98abae3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9697,7 +9697,6 @@ "xpack.lens.pieChart.legendDisplayLegend": "图例显示", "xpack.lens.pieChart.nestedLegendLabel": "嵌套图例", "xpack.lens.pieChart.numberLabels": "标签值", - "xpack.lens.pieChart.percentDecimalsLabel": "百分比的小数位数", "xpack.lens.pieChart.showCategoriesLabel": "内部或外部", "xpack.lens.pieChart.showFormatterValuesLabel": "显示值", "xpack.lens.pieChart.showPercentValuesLabel": "显示百分比", From aae704ab41cd5fa9cdfae0f2f162df4d6e2b63c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Tue, 15 Sep 2020 12:39:35 +0200 Subject: [PATCH 15/26] [Index management] Unskip jest tests (#76672) Co-authored-by: Elastic Machine --- .../helpers/http_requests.ts | 12 + .../helpers/setup_environment.tsx | 16 +- .../index_template_wizard/constants.ts | 2 - .../template_clone.test.tsx | 67 ++-- .../template_create.test.tsx | 347 ++++++++++++------ .../template_edit.test.tsx | 116 +++--- .../template_form.helpers.ts | 249 +++++++++---- .../client_integration/helpers/index.ts | 2 +- .../helpers/setup_environment.tsx | 2 +- .../component_templates/__jest__/index.ts | 7 + .../component_templates.tsx | 4 +- .../component_templates_list.tsx | 4 +- .../component_templates_list_item.tsx | 5 +- .../component_templates_selector.tsx | 3 +- .../components/filter_list_button.tsx | 2 +- .../datatypes/shape_datatype.test.tsx | 20 +- .../datatypes/text_datatype.test.tsx | 79 ++-- .../client_integration/edit_field.test.tsx | 41 ++- .../helpers/mappings_editor.helpers.tsx | 53 +-- .../mappings_editor.test.tsx | 179 +++++---- .../field_parameters/analyzer_parameter.tsx | 3 +- .../analyzer_parameter_selects.tsx | 5 +- .../index_settings_context.tsx | 25 +- .../mappings_editor/mappings_editor.tsx | 80 ++-- .../mappings_editor_context.tsx | 7 +- .../components/mappings_editor/reducer.ts | 8 + .../test/fixtures/template.ts | 36 ++ 27 files changed, 858 insertions(+), 516 deletions(-) create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/__jest__/index.ts diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts index 12cf7ccac6c59..20b1e0878a730 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts @@ -103,6 +103,17 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setLoadComponentTemplatesResponse = (response?: HttpResponse, error?: any) => { + const status = error ? error.status || 400 : 200; + const body = error ? error.body : response; + + server.respondWith('GET', `${API_BASE_PATH}/component_templates`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + return { setLoadTemplatesResponse, setLoadIndicesResponse, @@ -114,6 +125,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { setCreateTemplateResponse, setUpdateTemplateResponse, setSimulateTemplateResponse, + setLoadComponentTemplatesResponse, }; }; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx index 910d9be842da8..e221c3d421e02 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx @@ -24,7 +24,11 @@ import { ExtensionsService } from '../../../public/services'; import { UiMetricService } from '../../../public/application/services/ui_metric'; import { setUiMetricService } from '../../../public/application/services/api'; import { setExtensionsService } from '../../../public/application/store/selectors'; -import { MappingsEditorProvider } from '../../../public/application/components'; +import { + MappingsEditorProvider, + ComponentTemplatesProvider, +} from '../../../public/application/components'; +import { componentTemplatesMockDependencies } from '../../../public/application/components/component_templates/__jest__'; import { init as initHttpRequests } from './http_requests'; const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); @@ -34,9 +38,11 @@ export const services = { extensionsService: new ExtensionsService(), uiMetricService: new UiMetricService('index_management'), }; + services.uiMetricService.setup({ reportUiStats() {} } as any); setExtensionsService(services.extensionsService); setUiMetricService(services.uiMetricService); + const appDependencies = { services, core: { getUrlForApp: () => {} }, @@ -66,9 +72,11 @@ export const WithAppDependencies = (Comp: any, overridingDependencies: any = {}) return ( - - - + + + + + ); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/constants.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/constants.ts index 3f6e5d7d4dab2..ef5cffc05d8d7 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/constants.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/constants.ts @@ -26,7 +26,5 @@ export const ALIASES = { }; export const MAPPINGS = { - _source: {}, - _meta: {}, properties: {}, }; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_clone.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_clone.test.tsx index ccb729db44f9b..8b74e9fb0cdf8 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_clone.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_clone.test.tsx @@ -7,8 +7,8 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { getTemplate } from '../../../test/fixtures'; -import { setupEnvironment, nextTick } from '../helpers'; +import { getComposableTemplate } from '../../../test/fixtures'; +import { setupEnvironment } from '../helpers'; import { TEMPLATE_NAME, INDEX_PATTERNS as DEFAULT_INDEX_PATTERNS, MAPPINGS } from './constants'; import { setup } from './template_clone.helpers'; @@ -41,32 +41,35 @@ jest.mock('@elastic/eui', () => { }; }); -// FLAKY: https://github.com/elastic/kibana/issues/59849 -describe.skip('', () => { +const templateToClone = getComposableTemplate({ + name: TEMPLATE_NAME, + indexPatterns: ['indexPattern1'], + template: { + mappings: MAPPINGS, + }, +}); + +describe('', () => { let testBed: TemplateFormTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); - afterAll(() => { - server.restore(); + beforeAll(() => { + jest.useFakeTimers(); + httpRequestsMockHelpers.setLoadComponentTemplatesResponse([]); + httpRequestsMockHelpers.setLoadTemplateResponse(templateToClone); }); - const templateToClone = getTemplate({ - name: TEMPLATE_NAME, - indexPatterns: ['indexPattern1'], - template: { - mappings: MAPPINGS, - }, - isLegacy: true, + afterAll(() => { + server.restore(); + jest.useRealTimers(); }); beforeEach(async () => { - httpRequestsMockHelpers.setLoadTemplateResponse(templateToClone); - await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); }); + testBed.component.update(); }); test('should set the correct page title', () => { @@ -80,30 +83,26 @@ describe.skip('', () => { beforeEach(async () => { const { actions } = testBed; - await act(async () => { - // Complete step 1 (logistics) - // Specify index patterns, but do not change name (keep default) - await actions.completeStepOne({ - indexPatterns: DEFAULT_INDEX_PATTERNS, - }); - - // Bypass step 2 (index settings) - await actions.completeStepTwo(); - - // Bypass step 3 (mappings) - await actions.completeStepThree(); - - // Bypass step 4 (aliases) - await actions.completeStepFour(); + // Logistics + // Specify index patterns, but do not change name (keep default) + await actions.completeStepOne({ + indexPatterns: DEFAULT_INDEX_PATTERNS, }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree(); + // Mappings + await actions.completeStepFour(); + // Aliases + await actions.completeStepFive(); }); it('should send the correct payload', async () => { const { actions } = testBed; await act(async () => { - actions.clickSubmitButton(); - await nextTick(); + actions.clickNextButton(); }); const latestRequest = server.requests[server.requests.length - 1]; @@ -113,6 +112,8 @@ describe.skip('', () => { name: `${templateToClone.name}-copy`, indexPatterns: DEFAULT_INDEX_PATTERNS, }; + // @ts-expect-error + delete expected.template; // As no settings, mappings or aliases have been defined, no "template" param is sent expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual(expected); }); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_create.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_create.test.tsx index 76b6c34f999d5..b67e503f8d3e2 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_create.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_create.test.tsx @@ -7,12 +7,11 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { setupEnvironment, nextTick } from '../helpers'; +import { setupEnvironment } from '../helpers'; import { TEMPLATE_NAME, SETTINGS, - MAPPINGS, ALIASES, INDEX_PATTERNS as DEFAULT_INDEX_PATTERNS, } from './constants'; @@ -61,21 +60,50 @@ const KEYWORD_MAPPING_FIELD = { type: 'keyword', }; -// FLAKY: https://github.com/elastic/kibana/issues/67833 -describe.skip('', () => { +const componentTemplate1 = { + name: 'test_component_template_1', + hasMappings: true, + hasAliases: false, + hasSettings: false, + usedBy: [], + isManaged: false, +}; + +const componentTemplate2 = { + name: 'test_component_template_2', + hasMappings: false, + hasAliases: false, + hasSettings: true, + usedBy: ['test_index_template_1'], + isManaged: false, +}; + +const componentTemplates = [componentTemplate1, componentTemplate2]; + +describe('', () => { let testBed: TemplateFormTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); + beforeAll(() => { + jest.useFakeTimers(); + + httpRequestsMockHelpers.setLoadComponentTemplatesResponse(componentTemplates); + + // disable all react-beautiful-dnd development warnings + (window as any)['__react-beautiful-dnd-disable-dev-warnings'] = true; + }); + afterAll(() => { server.restore(); + jest.useRealTimers(); + (window as any)['__react-beautiful-dnd-disable-dev-warnings'] = false; }); describe('on component mount', () => { beforeEach(async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); }); }); @@ -93,9 +121,8 @@ describe.skip('', () => { await act(async () => { actions.clickNextButton(); - await nextTick(); - component.update(); }); + component.update(); expect(find('nextButton').props().disabled).toEqual(true); }); @@ -105,21 +132,131 @@ describe.skip('', () => { beforeEach(async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); }); + testBed.component.update(); }); - describe('index settings (step 2)', () => { + describe('component templates (step 2)', () => { beforeEach(async () => { const { actions } = testBed; + await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + }); + + it('should set the correct page title', async () => { + const { exists, find } = testBed; + + expect(exists('stepComponents')).toBe(true); + expect(find('stepTitle').text()).toEqual('Component templates (optional)'); + }); + + it('should list the available component templates', () => { + const { + actions: { + componentTemplates: { getComponentTemplatesInList }, + }, + } = testBed; + const componentsFound = getComponentTemplatesInList(); + expect(componentsFound).toEqual(componentTemplates.map((c) => c.name)); + }); + + it('should allow to search for a component', async () => { + const { + component, + form: { setInputValue }, + actions: { + componentTemplates: { getComponentTemplatesInList }, + }, + } = testBed; await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + setInputValue('componentTemplateSearchBox', 'template_2'); }); + component.update(); + + const componentsFound = getComponentTemplatesInList(); + expect(componentsFound).toEqual(['test_component_template_2']); }); - it('should set the correct page title', () => { + it('should allow to filter component by Index settings, mappings and aliases', async () => { + const { + find, + exists, + actions: { + componentTemplates: { showFilters, selectFilter, getComponentTemplatesInList }, + }, + } = testBed; + + showFilters(); + + expect(find('filterList.filterItem').map((wrapper) => wrapper.text())).toEqual([ + 'Index settings', + 'Mappings', + 'Aliases', + ]); + + await selectFilter('settings'); + expect(getComponentTemplatesInList()).toEqual(['test_component_template_2']); // only this one has settings + + await selectFilter('mappings'); + expect(exists('componentTemplatesList')).toBe(false); // no component has **both** settings and mappings + expect(exists('componentTemplates.emptySearchResult')).toBe(true); + expect(find('componentTemplates.emptySearchResult').text()).toContain( + 'No components match your search' + ); + + await selectFilter('settings'); // unselect settings + expect(getComponentTemplatesInList()).toEqual(['test_component_template_1']); // only this one has mappings + + await selectFilter('mappings'); // unselect mappings (back to start) + expect(getComponentTemplatesInList()).toEqual([ + 'test_component_template_1', + 'test_component_template_2', + ]); + + await selectFilter('aliases'); + expect(exists('componentTemplatesList')).toBe(false); // no component has aliases defined. + }); + + it('should allow to select and unselect a component template', async () => { + const { + find, + exists, + actions: { + componentTemplates: { + selectComponentAt, + unSelectComponentAt, + getComponentTemplatesSelected, + }, + }, + } = testBed; + + // Start with empty selection + expect(exists('componentTemplatesSelection.emptyPrompt')).toBe(true); + expect(find('componentTemplatesSelection.emptyPrompt').text()).toContain( + 'Add component template building blocks to this template.' + ); + + // Select first component in the list + await selectComponentAt(0); + expect(exists('componentTemplatesSelection.emptyPrompt')).toBe(false); + expect(getComponentTemplatesSelected()).toEqual(['test_component_template_1']); + + // Unselect the component + await unSelectComponentAt(0); + expect(exists('componentTemplatesSelection.emptyPrompt')).toBe(true); + }); + }); + + describe('index settings (step 3)', () => { + beforeEach(async () => { + const { actions } = testBed; + // Logistics + await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + // Component templates + await actions.completeStepTwo(); + }); + + it('should set the correct page title', async () => { const { exists, find } = testBed; expect(exists('stepSettings')).toBe(true); @@ -130,24 +267,22 @@ describe.skip('', () => { const { form, actions } = testBed; await act(async () => { - actions.completeStepTwo('{ invalidJsonString '); + actions.completeStepThree('{ invalidJsonString '); }); expect(form.getErrorsMessages()).toContain('Invalid JSON format.'); }); }); - describe('mappings (step 3)', () => { + describe('mappings (step 4)', () => { beforeEach(async () => { const { actions } = testBed; - - await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); - - // Complete step 2 (index settings) - await actions.completeStepTwo('{}'); - }); + // Logistics + await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree('{}'); }); it('should set the correct page title', () => { @@ -160,11 +295,9 @@ describe.skip('', () => { it('should allow the user to define document fields for a mapping', async () => { const { actions, find } = testBed; - await act(async () => { - await actions.addMappingField('field_1', 'text'); - await actions.addMappingField('field_2', 'text'); - await actions.addMappingField('field_3', 'text'); - }); + await actions.mappings.addField('field_1', 'text'); + await actions.mappings.addField('field_2', 'text'); + await actions.mappings.addField('field_3', 'text'); expect(find('fieldsListItem').length).toBe(3); }); @@ -172,10 +305,8 @@ describe.skip('', () => { it('should allow the user to remove a document field from a mapping', async () => { const { actions, find } = testBed; - await act(async () => { - await actions.addMappingField('field_1', 'text'); - await actions.addMappingField('field_2', 'text'); - }); + await actions.mappings.addField('field_1', 'text'); + await actions.mappings.addField('field_2', 'text'); expect(find('fieldsListItem').length).toBe(2); @@ -187,20 +318,17 @@ describe.skip('', () => { }); }); - describe('aliases (step 4)', () => { + describe('aliases (step 5)', () => { beforeEach(async () => { const { actions } = testBed; - - await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); - - // Complete step 2 (index settings) - await actions.completeStepTwo('{}'); - - // Complete step 3 (mappings) - await actions.completeStepThree(); - }); + // Logistics + await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree('{}'); + // Mappings + await actions.completeStepFour(); }); it('should set the correct page title', () => { @@ -213,39 +341,35 @@ describe.skip('', () => { it('should not allow invalid json', async () => { const { actions, form } = testBed; - await act(async () => { - // Complete step 4 (aliases) with invalid json - await actions.completeStepFour('{ invalidJsonString ', false); - }); + // Complete step 5 (aliases) with invalid json + await actions.completeStepFive('{ invalidJsonString '); expect(form.getErrorsMessages()).toContain('Invalid JSON format.'); }); }); }); - describe('review (step 5)', () => { + describe('review (step 6)', () => { beforeEach(async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); - - const { actions } = testBed; - - // Complete step 1 (logistics) - await actions.completeStepOne({ - name: TEMPLATE_NAME, - indexPatterns: DEFAULT_INDEX_PATTERNS, - }); - - // Complete step 2 (index settings) - await actions.completeStepTwo(JSON.stringify(SETTINGS)); - - // Complete step 3 (mappings) - await actions.completeStepThree(); + }); + testBed.component.update(); - // Complete step 4 (aliases) - await actions.completeStepFour(JSON.stringify(ALIASES)); + const { actions } = testBed; + // Logistics + await actions.completeStepOne({ + name: TEMPLATE_NAME, + indexPatterns: DEFAULT_INDEX_PATTERNS, }); + // Component templates + await actions.completeStepTwo('test_component_template_1'); + // Index settings + await actions.completeStepThree(JSON.stringify(SETTINGS)); + // Mappings + await actions.completeStepFour(); + // Aliases + await actions.completeStepFive(JSON.stringify(ALIASES)); }); it('should set the correct step title', () => { @@ -255,26 +379,30 @@ describe.skip('', () => { }); describe('tabs', () => { - test('should have 2 tabs', () => { + test('should have 3 tabs', () => { const { find } = testBed; - expect(find('summaryTabContent').find('.euiTab').length).toBe(2); + expect(find('summaryTabContent').find('.euiTab').length).toBe(3); expect( find('summaryTabContent') .find('.euiTab') .map((t) => t.text()) - ).toEqual(['Summary', 'Request']); + ).toEqual(['Summary', 'Preview', 'Request']); }); - test('should navigate to the Request tab', async () => { + test('should navigate to the preview and request tab', async () => { const { exists, actions } = testBed; expect(exists('summaryTab')).toBe(true); expect(exists('requestTab')).toBe(false); + expect(exists('previewTab')).toBe(false); - actions.selectSummaryTab('request'); - + await actions.review.selectTab('preview'); expect(exists('summaryTab')).toBe(false); + expect(exists('previewTab')).toBe(true); + + await actions.review.selectTab('request'); + expect(exists('previewTab')).toBe(false); expect(exists('requestTab')).toBe(true); }); }); @@ -282,24 +410,23 @@ describe.skip('', () => { it('should render a warning message if a wildcard is used as an index pattern', async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); - - const { actions } = testBed; - // Complete step 1 (logistics) - await actions.completeStepOne({ - name: TEMPLATE_NAME, - indexPatterns: ['*'], // Set wildcard index pattern - }); - - // Complete step 2 (index settings) - await actions.completeStepTwo(JSON.stringify({})); - - // Complete step 3 (mappings) - await actions.completeStepThree(); + }); + testBed.component.update(); - // Complete step 4 (aliases) - await actions.completeStepFour(JSON.stringify({})); + const { actions } = testBed; + // Logistics + await actions.completeStepOne({ + name: TEMPLATE_NAME, + indexPatterns: ['*'], // Set wildcard index pattern }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree(JSON.stringify({})); + // Mappings + await actions.completeStepFour(); + // Aliases + await actions.completeStepFive(JSON.stringify({})); const { exists, find } = testBed; @@ -316,32 +443,32 @@ describe.skip('', () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); - - const { actions } = testBed; - // Complete step 1 (logistics) - await actions.completeStepOne({ - name: TEMPLATE_NAME, - indexPatterns: DEFAULT_INDEX_PATTERNS, - }); - - // Complete step 2 (index settings) - await actions.completeStepTwo(JSON.stringify(SETTINGS)); - - // Complete step 3 (mappings) - await actions.completeStepThree(MAPPING_FIELDS); + }); + testBed.component.update(); - // Complete step 4 (aliases) - await actions.completeStepFour(JSON.stringify(ALIASES)); + const { actions } = testBed; + // Logistics + await actions.completeStepOne({ + name: TEMPLATE_NAME, + indexPatterns: DEFAULT_INDEX_PATTERNS, }); + // Component templates + await actions.completeStepTwo('test_component_template_1'); + // Index settings + await actions.completeStepThree(JSON.stringify(SETTINGS)); + // Mappings + await actions.completeStepFour(MAPPING_FIELDS); + // Aliases + await actions.completeStepFive(JSON.stringify(ALIASES)); }); it('should send the correct payload', async () => { - const { actions } = testBed; + const { actions, find } = testBed; + + expect(find('stepTitle').text()).toEqual(`Review details for '${TEMPLATE_NAME}'`); await act(async () => { - actions.clickSubmitButton(); - await nextTick(); + actions.clickNextButton(); }); const latestRequest = server.requests[server.requests.length - 1]; @@ -349,10 +476,10 @@ describe.skip('', () => { const expected = { name: TEMPLATE_NAME, indexPatterns: DEFAULT_INDEX_PATTERNS, + composedOf: ['test_component_template_1'], template: { settings: SETTINGS, mappings: { - ...MAPPINGS, properties: { [BOOLEAN_MAPPING_FIELD.name]: { type: BOOLEAN_MAPPING_FIELD.type, @@ -370,6 +497,7 @@ describe.skip('', () => { _kbnMeta: { type: 'default', isLegacy: false, + hasDatastream: false, }, }; @@ -388,10 +516,9 @@ describe.skip('', () => { httpRequestsMockHelpers.setCreateTemplateResponse(undefined, { body: error }); await act(async () => { - actions.clickSubmitButton(); - await nextTick(); - component.update(); + actions.clickNextButton(); }); + component.update(); expect(exists('saveTemplateError')).toBe(true); expect(find('saveTemplateError').text()).toContain(error.message); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx index de66013241236..37d489b6afe72 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import * as fixtures from '../../../test/fixtures'; -import { setupEnvironment, nextTick } from '../helpers'; +import { setupEnvironment } from '../helpers'; import { TEMPLATE_NAME, SETTINGS, ALIASES, MAPPINGS as DEFAULT_MAPPING } from './constants'; import { setup } from './template_edit.helpers'; @@ -52,51 +52,51 @@ jest.mock('@elastic/eui', () => { }; }); -// FLAKY: https://github.com/elastic/kibana/issues/65567 -describe.skip('', () => { +describe('', () => { let testBed: TemplateFormTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); + beforeAll(() => { + jest.useFakeTimers(); + httpRequestsMockHelpers.setLoadComponentTemplatesResponse([]); + }); + afterAll(() => { server.restore(); + jest.useRealTimers(); }); describe('without mappings', () => { const templateToEdit = fixtures.getTemplate({ name: 'index_template_without_mappings', indexPatterns: ['indexPattern1'], - isLegacy: true, }); - beforeEach(async () => { + beforeAll(() => { httpRequestsMockHelpers.setLoadTemplateResponse(templateToEdit); + }); - testBed = await setup(); - + beforeEach(async () => { await act(async () => { - await nextTick(); - testBed.component.update(); + testBed = await setup(); }); + + testBed.component.update(); }); it('allows you to add mappings', async () => { const { actions, find } = testBed; - - await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne(); - - // Step 2 (index settings) - await actions.completeStepTwo(); - - // Step 3 (mappings) - await act(async () => { - await actions.addMappingField('field_1', 'text'); - }); - - expect(find('fieldsListItem').length).toBe(1); - }); + // Logistics + await actions.completeStepOne(); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree(); + // Mappings + await actions.mappings.addField('field_1', 'text'); + + expect(find('fieldsListItem').length).toBe(1); }); }); @@ -107,16 +107,17 @@ describe.skip('', () => { template: { mappings: MAPPING, }, - isLegacy: true, }); - beforeEach(async () => { + beforeAll(() => { httpRequestsMockHelpers.setLoadTemplateResponse(templateToEdit); + }); + beforeEach(async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); }); + testBed.component.update(); }); test('should set the correct page title', () => { @@ -138,64 +139,64 @@ describe.skip('', () => { beforeEach(async () => { const { actions } = testBed; - await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne({ - indexPatterns: UPDATED_INDEX_PATTERN, - }); - - // Step 2 (index settings) - await actions.completeStepTwo(JSON.stringify(SETTINGS)); + // Logistics + await actions.completeStepOne({ + indexPatterns: UPDATED_INDEX_PATTERN, + priority: 3, }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree(JSON.stringify(SETTINGS)); }); it('should send the correct payload with changed values', async () => { - const { actions, component, find, form } = testBed; + const { actions, component, exists, form } = testBed; + // Make some changes to the mappings await act(async () => { - // Make some changes to the mappings (step 3) - actions.clickEditButtonAtField(0); // Select the first field to edit - await nextTick(); - component.update(); }); + component.update(); - // verify edit field flyout - expect(find('mappingsEditorFieldEdit').length).toEqual(1); + // Verify that the edit field flyout is opened + expect(exists('mappingsEditorFieldEdit')).toBe(true); + // Change the field name await act(async () => { - // change the field name form.setInputValue('nameParameterInput', UPDATED_MAPPING_TEXT_FIELD_NAME); + }); - // Save changes + // Save changes on the field + await act(async () => { actions.clickEditFieldUpdateButton(); - await nextTick(); - component.update(); + }); + component.update(); - // Proceed to the next step + // Proceed to the next step + await act(async () => { actions.clickNextButton(); - await nextTick(50); - component.update(); + }); + component.update(); - // Step 4 (aliases) - await actions.completeStepFour(JSON.stringify(ALIASES)); + // Aliases + await actions.completeStepFive(JSON.stringify(ALIASES)); - // Submit the form - actions.clickSubmitButton(); - await nextTick(); + // Submit the form + await act(async () => { + actions.clickNextButton(); }); const latestRequest = server.requests[server.requests.length - 1]; - const { version, order } = templateToEdit; + const { version } = templateToEdit; const expected = { name: TEMPLATE_NAME, version, - order, + priority: 3, indexPatterns: UPDATED_INDEX_PATTERN, template: { mappings: { - ...MAPPING, properties: { [UPDATED_MAPPING_TEXT_FIELD_NAME]: { type: 'text', @@ -215,6 +216,7 @@ describe.skip('', () => { _kbnMeta: { type: 'default', isLegacy: templateToEdit._kbnMeta.isLegacy, + hasDatastream: false, }, }; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_form.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_form.helpers.ts index fdf837a914cf1..025410129a002 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_form.helpers.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_form.helpers.ts @@ -3,10 +3,10 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { act } from 'react-dom/test-utils'; import { TestBed, SetupFunc, UnwrapPromise } from '../../../../../test_utils'; import { TemplateDeserialized } from '../../../common'; -import { nextTick } from '../helpers'; interface MappingField { name: string; @@ -30,10 +30,6 @@ export const formSetup = async (initTestBed: SetupFunc) => { testBed.find('backButton').simulate('click'); }; - const clickSubmitButton = () => { - testBed.find('submitButton').simulate('click'); - }; - const clickEditButtonAtField = (index: number) => { testBed.find('editFieldButton').at(index).simulate('click'); }; @@ -52,16 +48,100 @@ export const formSetup = async (initTestBed: SetupFunc) => { testBed.find('createFieldForm.cancelButton').simulate('click'); }; + // Step component templates actions + const componentTemplates = { + getComponentTemplatesInList() { + const { find } = testBed; + return find('componentTemplatesList.item.name').map((wrapper) => wrapper.text()); + }, + getComponentTemplatesSelected() { + const { find } = testBed; + return find('componentTemplatesSelection.item.name').map((wrapper) => wrapper.text()); + }, + showFilters() { + const { find, component } = testBed; + act(() => { + find('componentTemplates.filterButton').simulate('click'); + }); + component.update(); + }, + async selectFilter(filter: 'settings' | 'mappings' | 'aliases') { + const { find, component } = testBed; + const filters = ['settings', 'mappings', 'aliases']; + const index = filters.indexOf(filter); + + await act(async () => { + find('filterList.filterItem').at(index).simulate('click'); + }); + component.update(); + }, + async selectComponentAt(index: number) { + const { find, component } = testBed; + + await act(async () => { + find('componentTemplatesList.item.action-plusInCircle').at(index).simulate('click'); + }); + component.update(); + }, + async unSelectComponentAt(index: number) { + const { find, component } = testBed; + + await act(async () => { + find('componentTemplatesSelection.item.action-minusInCircle').at(index).simulate('click'); + }); + component.update(); + }, + }; + + // Step Mappings actions + const mappings = { + async addField(name: string, type: string) { + const { find, form, component } = testBed; + + await act(async () => { + form.setInputValue('nameParameterInput', name); + find('createFieldForm.mockComboBox').simulate('change', [ + { + label: type, + value: type, + }, + ]); + }); + + await act(async () => { + find('createFieldForm.addButton').simulate('click'); + }); + + component.update(); + }, + }; + + // Step Review actions + const review = { + async selectTab(tab: 'summary' | 'preview' | 'request') { + const tabs = ['summary', 'preview', 'request']; + + await act(async () => { + testBed.find('summaryTabContent').find('.euiTab').at(tabs.indexOf(tab)).simulate('click'); + }); + + testBed.component.update(); + }, + }; + const completeStepOne = async ({ name, indexPatterns, order, + priority, version, }: Partial = {}) => { - const { form, find, waitFor } = testBed; + const { component, form, find } = testBed; if (name) { - form.setInputValue('nameField.input', name); + act(() => { + form.setInputValue('nameField.input', name); + }); } if (indexPatterns) { @@ -70,94 +150,104 @@ export const formSetup = async (initTestBed: SetupFunc) => { value: pattern, })); - find('mockComboBox').simulate('change', indexPatternsFormatted); // Using mocked EuiComboBox - await nextTick(); + act(() => { + find('mockComboBox').simulate('change', indexPatternsFormatted); // Using mocked EuiComboBox + }); } - if (order) { - form.setInputValue('orderField.input', JSON.stringify(order)); - } + await act(async () => { + if (order) { + form.setInputValue('orderField.input', JSON.stringify(order)); + } - if (version) { - form.setInputValue('versionField.input', JSON.stringify(version)); - } + if (priority) { + form.setInputValue('priorityField.input', JSON.stringify(priority)); + } - clickNextButton(); - await waitFor('stepSettings'); + if (version) { + form.setInputValue('versionField.input', JSON.stringify(version)); + } + + clickNextButton(); + }); + + component.update(); }; - const completeStepTwo = async (settings?: string) => { - const { find, component, waitFor } = testBed; + const completeStepTwo = async (componentName?: string) => { + const { find, component } = testBed; + + if (componentName) { + // Find the index of the template in the list + const allComponents = find('componentTemplatesList.item.name').map((wrapper) => + wrapper.text() + ); + const index = allComponents.indexOf(componentName); + if (index < 0) { + throw new Error( + `Could not find component "${componentName}" in the list ${JSON.stringify(allComponents)}` + ); + } - if (settings) { - find('mockCodeEditor').simulate('change', { - jsonString: settings, - }); // Using mocked EuiCodeEditor - await nextTick(); - component.update(); + await componentTemplates.selectComponentAt(index); } - clickNextButton(); - await waitFor('stepMappings'); + await act(async () => { + clickNextButton(); + }); + + component.update(); + }; + + const completeStepThree = async (settings?: string) => { + const { find, component } = testBed; + + await act(async () => { + if (settings) { + find('mockCodeEditor').simulate('change', { + jsonString: settings, + }); // Using mocked EuiCodeEditor + } + + clickNextButton(); + }); + + component.update(); }; - const completeStepThree = async (mappingFields?: MappingField[]) => { - const { waitFor } = testBed; + const completeStepFour = async (mappingFields?: MappingField[]) => { + const { component } = testBed; if (mappingFields) { for (const field of mappingFields) { const { name, type } = field; - await addMappingField(name, type); + await mappings.addField(name, type); } } - clickNextButton(); - await waitFor('stepAliases'); + await act(async () => { + clickNextButton(); + }); + + component.update(); }; - const completeStepFour = async (aliases?: string, waitForNextStep = true) => { - const { find, component, waitFor } = testBed; + const completeStepFive = async (aliases?: string) => { + const { find, component } = testBed; if (aliases) { - find('mockCodeEditor').simulate('change', { - jsonString: aliases, - }); // Using mocked EuiCodeEditor - await nextTick(); + await act(async () => { + find('mockCodeEditor').simulate('change', { + jsonString: aliases, + }); // Using mocked EuiCodeEditor + }); component.update(); } - clickNextButton(); - - if (waitForNextStep) { - await waitFor('summaryTab'); - } else { - component.update(); - } - }; - - const selectSummaryTab = (tab: 'summary' | 'request') => { - const tabs = ['summary', 'request']; - - testBed.find('summaryTabContent').find('.euiTab').at(tabs.indexOf(tab)).simulate('click'); - }; - - const addMappingField = async (name: string, type: string) => { - const { find, form, component } = testBed; - - form.setInputValue('nameParameterInput', name); - find('createFieldForm.mockComboBox').simulate('change', [ - { - label: type, - value: type, - }, - ]); - - await nextTick(50); - component.update(); - - find('createFieldForm.addButton').simulate('click'); + await act(async () => { + clickNextButton(); + }); - await nextTick(); component.update(); }; @@ -166,7 +256,6 @@ export const formSetup = async (initTestBed: SetupFunc) => { actions: { clickNextButton, clickBackButton, - clickSubmitButton, clickEditButtonAtField, clickEditFieldUpdateButton, deleteMappingsFieldAt, @@ -175,8 +264,10 @@ export const formSetup = async (initTestBed: SetupFunc) => { completeStepTwo, completeStepThree, completeStepFour, - selectSummaryTab, - addMappingField, + completeStepFive, + componentTemplates, + mappings, + review, }, }; }; @@ -187,6 +278,17 @@ export type TestSubjects = | 'backButton' | 'codeEditorContainer' | 'confirmModalConfirmButton' + | 'componentTemplates.filterButton' + | 'componentTemplates.emptySearchResult' + | 'filterList.filterItem' + | 'componentTemplatesList' + | 'componentTemplatesList.item.name' + | 'componentTemplatesList.item.action-plusInCircle' + | 'componentTemplatesSelection' + | 'componentTemplatesSelection.item.name' + | 'componentTemplatesSelection.item.action-minusInCircle' + | 'componentTemplatesSelection.emptyPrompt' + | 'componentTemplateSearchBox' | 'createFieldForm.addPropertyButton' | 'createFieldForm.addButton' | 'createFieldForm.addFieldButton' @@ -209,12 +311,15 @@ export type TestSubjects = | 'nextButton' | 'orderField' | 'orderField.input' + | 'priorityField.input' | 'pageTitle' + | 'previewTab' | 'removeFieldButton' | 'requestTab' | 'saveTemplateError' | 'settingsEditor' | 'systemTemplateEditCallout' + | 'stepComponents' | 'stepAliases' | 'stepMappings' | 'stepSettings' diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts index 93eb65aac0761..4b92235993e26 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts @@ -9,7 +9,7 @@ import { setup as componentTemplateDetailsSetup } from './component_template_det export { nextTick, getRandomString, findTestSubject } from '../../../../../../../../../test_utils'; -export { setupEnvironment } from './setup_environment'; +export { setupEnvironment, appDependencies } from './setup_environment'; export const pageHelpers = { componentTemplateList: { setup: componentTemplatesListSetup }, diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx index 79e213229fc51..ac748e1b7dc2c 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx @@ -24,7 +24,7 @@ import { API_BASE_PATH } from './constants'; const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); const { GlobalFlyoutProvider } = GlobalFlyout; -const appDependencies = { +export const appDependencies = { httpClient: (mockHttpClient as unknown) as HttpSetup, apiBasePath: API_BASE_PATH, trackMetric: () => {}, diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/index.ts new file mode 100644 index 0000000000000..ebd2cd9392568 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { appDependencies as componentTemplatesMockDependencies } from './client_integration/helpers'; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.tsx index b07279c57d2be..3c10ef2cc7edc 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.tsx @@ -145,12 +145,13 @@ export const ComponentTemplates = ({ isLoading, components, listItemProps }: Pro /> } + data-test-subj="emptySearchResult" /> ); }; return ( -
      +
      @@ -162,6 +163,7 @@ export const ComponentTemplates = ({ isLoading, components, listItemProps }: Pro }} aria-label={i18nTexts.searchBoxPlaceholder} className="componentTemplates__searchBox" + data-test-subj="componentTemplateSearchBox" /> diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list.tsx index 0c64c38c8963f..519f2482c9323 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list.tsx @@ -19,10 +19,10 @@ interface Props { export const ComponentTemplatesList = ({ components, listItemProps }: Props) => { return ( - <> +
      {components.map((component) => ( ))} - +
      ); }; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.tsx index ad75c8dcbcc54..40bb062f5ddf3 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.tsx @@ -48,6 +48,7 @@ export const ComponentTemplatesListItem = ({ className={classNames('componentTemplatesListItem', { 'componentTemplatesListItem--selected': isSelectedValue, })} + data-test-subj="item" > @@ -59,7 +60,7 @@ export const ComponentTemplatesListItem = ({
      )} - + {/* {component.name} */} onViewDetail(component)}>{component.name} @@ -83,7 +84,7 @@ export const ComponentTemplatesListItem = ({ action.handler(component)} - data-test-subj="addPropertyButton" + data-test-subj={`action-${action.icon}`} aria-label={action.label} /> diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx index ff871b8b79247..f2fd5048931de 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx @@ -160,6 +160,7 @@ export const ComponentTemplatesSelector = ({ // eslint-disable-next-line @typescript-eslint/naming-convention 'componentTemplatesSelector__selection--is-empty': !hasSelection, })} + data-test-subj="componentTemplatesSelection" > {hasSelection ? ( <> @@ -200,7 +201,7 @@ export const ComponentTemplatesSelector = ({
      ) : ( - +

      0} numActiveFilters={activeFilters.length} - data-test-subj="viewButton" + data-test-subj="filterButton" > { - let testBed: MappingsEditorTestBed; - /** * Variable to store the mappings data forwarded to the consumer component */ let data: any; + let onChangeHandler: jest.Mock = jest.fn(); + let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); + let testBed: MappingsEditorTestBed; beforeAll(() => { jest.useFakeTimers(); @@ -34,6 +34,11 @@ describe('Mappings editor: shape datatype', () => { jest.useRealTimers(); }); + beforeEach(() => { + onChangeHandler = jest.fn(); + getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); + }); + test('initial view and default parameters values', async () => { const defaultMappings = { properties: { @@ -45,7 +50,10 @@ describe('Mappings editor: shape datatype', () => { const updatedMappings = { ...defaultMappings }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { component, @@ -53,7 +61,7 @@ describe('Mappings editor: shape datatype', () => { } = testBed; // Open the flyout to edit the field - startEditField('myField'); + await startEditField('myField'); // Save the field and close the flyout await updateFieldAndCloseFlyout(); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/datatypes/text_datatype.test.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/datatypes/text_datatype.test.tsx index 66989baa2dc67..1832bedee0143 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/datatypes/text_datatype.test.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/datatypes/text_datatype.test.tsx @@ -9,8 +9,6 @@ import { componentHelpers, MappingsEditorTestBed } from '../helpers'; import { getFieldConfig } from '../../../lib'; const { setup, getMappingsEditorDataFactory } = componentHelpers.mappingsEditor; -const onChangeHandler = jest.fn(); -const getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); // Parameters automatically added to the text datatype when saved (with the default values) export const defaultTextParameters = { @@ -24,14 +22,14 @@ export const defaultTextParameters = { store: false, }; -// FLAKY: https://github.com/elastic/kibana/issues/66669 -describe.skip('Mappings editor: text datatype', () => { - let testBed: MappingsEditorTestBed; - +describe('Mappings editor: text datatype', () => { /** * Variable to store the mappings data forwarded to the consumer component */ let data: any; + let onChangeHandler: jest.Mock = jest.fn(); + let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); + let testBed: MappingsEditorTestBed; beforeAll(() => { jest.useFakeTimers(); @@ -41,8 +39,9 @@ describe.skip('Mappings editor: text datatype', () => { jest.useRealTimers(); }); - afterEach(() => { - onChangeHandler.mockReset(); + beforeEach(() => { + onChangeHandler = jest.fn(); + getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); }); test('initial view and default parameters values', async () => { @@ -56,7 +55,10 @@ describe.skip('Mappings editor: text datatype', () => { const updatedMappings = { ...defaultMappings }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { component, @@ -64,7 +66,7 @@ describe.skip('Mappings editor: text datatype', () => { } = testBed; // Open the flyout to edit the field - startEditField('myField'); + await startEditField('myField'); // It should have searchable ("index" param) active by default const indexFieldConfig = getFieldConfig('index'); @@ -80,7 +82,7 @@ describe.skip('Mappings editor: text datatype', () => { ({ data } = await getMappingsEditorData(component)); expect(data).toEqual(updatedMappings); - }, 10000); + }); test('analyzer parameter: default values', async () => { const defaultMappings = { @@ -96,7 +98,10 @@ describe.skip('Mappings editor: text datatype', () => { }, }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { component, @@ -113,8 +118,8 @@ describe.skip('Mappings editor: text datatype', () => { const fieldToEdit = 'myField'; // Start edit and immediately save to have all the default values - startEditField(fieldToEdit); - showAdvancedSettings(); + await startEditField(fieldToEdit); + await showAdvancedSettings(); await updateFieldAndCloseFlyout(); expect(exists('mappingsEditorFieldEdit')).toBe(false); @@ -133,8 +138,8 @@ describe.skip('Mappings editor: text datatype', () => { expect(data).toEqual(updatedMappings); // Re-open the edit panel - startEditField(fieldToEdit); - showAdvancedSettings(); + await startEditField(fieldToEdit); + await showAdvancedSettings(); // When no analyzer is defined, defaults to "Index default" let indexAnalyzerValue = find('indexAnalyzer.select').props().value; @@ -158,9 +163,8 @@ describe.skip('Mappings editor: text datatype', () => { expect(exists('searchAnalyzer')).toBe(false); // Uncheck the "Use same analyzer for search" checkbox and make sure the dedicated select appears - selectCheckBox('useSameAnalyzerForSearchCheckBox.input', false); - act(() => { - jest.advanceTimersByTime(1000); + await act(async () => { + selectCheckBox('useSameAnalyzerForSearchCheckBox.input', false); }); component.update(); @@ -169,7 +173,6 @@ describe.skip('Mappings editor: text datatype', () => { let searchAnalyzerValue = find('searchAnalyzer.select').props().value; expect(searchAnalyzerValue).toEqual('index_default'); - // Change the value of the 3 analyzers await act(async () => { // Change the value of the 3 analyzers setSelectValue('indexAnalyzer.select', 'standard', false); @@ -195,8 +198,8 @@ describe.skip('Mappings editor: text datatype', () => { expect(data).toEqual(updatedMappings); // Re-open the flyout and make sure the select have the correct updated value - startEditField('myField'); - showAdvancedSettings(); + await startEditField('myField'); + await showAdvancedSettings(); isUseSameAnalyzerForSearchChecked = getCheckboxValue('useSameAnalyzerForSearchCheckBox.input'); expect(isUseSameAnalyzerForSearchChecked).toBe(false); @@ -208,7 +211,7 @@ describe.skip('Mappings editor: text datatype', () => { expect(indexAnalyzerValue).toBe('standard'); expect(searchAnalyzerValue).toBe('simple'); expect(searchQuoteAnalyzerValue).toBe('whitespace'); - }, 50000); + }); test('analyzer parameter: custom analyzer (external plugin)', async () => { const defaultMappings = { @@ -234,7 +237,10 @@ describe.skip('Mappings editor: text datatype', () => { }, }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { find, @@ -245,8 +251,8 @@ describe.skip('Mappings editor: text datatype', () => { } = testBed; const fieldToEdit = 'myField'; - startEditField(fieldToEdit); - showAdvancedSettings(); + await startEditField(fieldToEdit); + await showAdvancedSettings(); expect(exists('indexAnalyzer-custom')).toBe(true); expect(exists('searchAnalyzer-custom')).toBe(true); @@ -301,7 +307,7 @@ describe.skip('Mappings editor: text datatype', () => { }; expect(data).toEqual(updatedMappings); - }, 100000); + }); test('analyzer parameter: custom analyzer (from index settings)', async () => { const indexSettings = { @@ -320,8 +326,6 @@ describe.skip('Mappings editor: text datatype', () => { const customAnalyzers = Object.keys(indexSettings.analysis.analyzer); const defaultMappings = { - _meta: {}, - _source: {}, properties: { myField: { type: 'text', @@ -340,11 +344,14 @@ describe.skip('Mappings editor: text datatype', () => { }, }; - testBed = setup({ - value: defaultMappings, - onChange: onChangeHandler, - indexSettings, + await act(async () => { + testBed = setup({ + value: defaultMappings, + onChange: onChangeHandler, + indexSettings, + }); }); + testBed.component.update(); const { component, @@ -354,8 +361,8 @@ describe.skip('Mappings editor: text datatype', () => { } = testBed; const fieldToEdit = 'myField'; - startEditField(fieldToEdit); - showAdvancedSettings(); + await startEditField(fieldToEdit); + await showAdvancedSettings(); // It should have 2 selects const indexAnalyzerSelects = find('indexAnalyzer.select'); @@ -395,5 +402,5 @@ describe.skip('Mappings editor: text datatype', () => { }; expect(data).toEqual(updatedMappings); - }, 50000); + }); }); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/edit_field.test.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/edit_field.test.tsx index c146c7704911f..9634817835101 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/edit_field.test.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/edit_field.test.tsx @@ -8,10 +8,14 @@ import { act } from 'react-dom/test-utils'; import { componentHelpers, MappingsEditorTestBed } from './helpers'; import { defaultTextParameters, defaultShapeParameters } from './datatypes'; const { setup, getMappingsEditorDataFactory } = componentHelpers.mappingsEditor; -const onChangeHandler = jest.fn(); -const getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); describe('Mappings editor: edit field', () => { + /** + * Variable to store the mappings data forwarded to the consumer component + */ + let data: any; + let onChangeHandler: jest.Mock = jest.fn(); + let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); let testBed: MappingsEditorTestBed; beforeAll(() => { @@ -22,8 +26,9 @@ describe('Mappings editor: edit field', () => { jest.useRealTimers(); }); - afterEach(() => { - onChangeHandler.mockReset(); + beforeEach(() => { + onChangeHandler = jest.fn(); + getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); }); test('should open a flyout with the correct field to edit', async () => { @@ -43,7 +48,11 @@ describe('Mappings editor: edit field', () => { }, }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); + await testBed.actions.expandAllFieldsAndReturnMetadata(); const { @@ -51,7 +60,7 @@ describe('Mappings editor: edit field', () => { actions: { startEditField }, } = testBed; // Open the flyout to edit the field - startEditField('user.address.street'); + await startEditField('user.address.street'); // It should have the correct title expect(find('mappingsEditorFieldEdit.flyoutTitle').text()).toEqual(`Edit field 'street'`); @@ -72,7 +81,10 @@ describe('Mappings editor: edit field', () => { }, }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { find, @@ -83,19 +95,18 @@ describe('Mappings editor: edit field', () => { expect(exists('userNameField' as any)).toBe(true); // Open the flyout, change the field type and save it - startEditField('userName'); + await startEditField('userName'); // Change the field type - find('mappingsEditorFieldEdit.fieldType').simulate('change', [ - { label: 'Shape', value: defaultShapeParameters.type }, - ]); - act(() => { - jest.advanceTimersByTime(1000); + await act(async () => { + find('mappingsEditorFieldEdit.fieldType').simulate('change', [ + { label: 'Shape', value: defaultShapeParameters.type }, + ]); }); await updateFieldAndCloseFlyout(); - const { data } = await getMappingsEditorData(component); + ({ data } = await getMappingsEditorData(component)); const updatedMappings = { ...defaultMappings, @@ -107,5 +118,5 @@ describe('Mappings editor: edit field', () => { }; expect(data).toEqual(updatedMappings); - }, 50000); + }); }); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.tsx index a6558b28a1273..2a4af89c46559 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.tsx @@ -149,22 +149,28 @@ const createActions = (testBed: TestBed) => { return { field: find(testSubject as TestSubjects), testSubject }; }; - const addField = (name: string, type: string) => { - form.setInputValue('nameParameterInput', name); - find('createFieldForm.fieldType').simulate('change', [ - { - label: type, - value: type, - }, - ]); - find('createFieldForm.addButton').simulate('click'); + const addField = async (name: string, type: string) => { + await act(async () => { + form.setInputValue('nameParameterInput', name); + find('createFieldForm.fieldType').simulate('change', [ + { + label: type, + value: type, + }, + ]); + }); + + await act(async () => { + find('createFieldForm.addButton').simulate('click'); + }); + + component.update(); }; - const startEditField = (path: string) => { + const startEditField = async (path: string) => { const { testSubject } = getFieldAt(path); - find(`${testSubject}.editFieldButton` as TestSubjects).simulate('click'); - act(() => { - jest.advanceTimersByTime(1000); + await act(async () => { + find(`${testSubject}.editFieldButton` as TestSubjects).simulate('click'); }); component.update(); }; @@ -174,34 +180,33 @@ const createActions = (testBed: TestBed) => { find('mappingsEditorFieldEdit.editFieldUpdateButton').simulate('click'); }); component.update(); - - act(() => { - jest.advanceTimersByTime(1000); - }); }; - const showAdvancedSettings = () => { + const showAdvancedSettings = async () => { if (find('mappingsEditorFieldEdit.advancedSettings').props().style.display === 'block') { // Already opened, nothing else to do return; } - find('mappingsEditorFieldEdit.toggleAdvancedSetting').simulate('click'); - - act(() => { - jest.advanceTimersByTime(1000); + await act(async () => { + find('mappingsEditorFieldEdit.toggleAdvancedSetting').simulate('click'); }); + component.update(); }; - const selectTab = (tab: 'fields' | 'templates' | 'advanced') => { + const selectTab = async (tab: 'fields' | 'templates' | 'advanced') => { const index = ['fields', 'templates', 'advanced'].indexOf(tab); const tabElement = find('formTab').at(index); if (tabElement.length === 0) { throw new Error(`Tab not found: "${tab}"`); } - tabElement.simulate('click'); + + await act(async () => { + tabElement.simulate('click'); + }); + component.update(); }; const updateJsonEditor = (testSubject: TestSubjects, value: object) => { diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx index 0743211a2b7bf..68933ddc9a935 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx @@ -8,15 +8,15 @@ import { act } from 'react-dom/test-utils'; import { componentHelpers, MappingsEditorTestBed } from './helpers'; const { setup, getMappingsEditorDataFactory } = componentHelpers.mappingsEditor; -const onChangeHandler = jest.fn(); -const getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); -// FLAKY: https://github.com/elastic/kibana/issues/66457 -describe.skip('Mappings editor: core', () => { +describe('Mappings editor: core', () => { /** * Variable to store the mappings data forwarded to the consumer component */ let data: any; + let onChangeHandler: jest.Mock = jest.fn(); + let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); + let testBed: MappingsEditorTestBed; beforeAll(() => { jest.useFakeTimers(); @@ -26,8 +26,9 @@ describe.skip('Mappings editor: core', () => { jest.useRealTimers(); }); - afterEach(() => { - onChangeHandler.mockReset(); + beforeEach(() => { + onChangeHandler = jest.fn(); + getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); }); test('default behaviour', async () => { @@ -42,11 +43,14 @@ describe.skip('Mappings editor: core', () => { }, }; - const { component } = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + + const { component } = testBed; + component.update(); const expectedMappings = { - _meta: {}, // Was not defined so an empty object is returned - _source: {}, // Was not defined so an empty object is returned ...defaultMappings, properties: { user: { @@ -78,8 +82,13 @@ describe.skip('Mappings editor: core', () => { }, }, }; - const testBed = setup({ onChange: onChangeHandler, value }); - const { exists } = testBed; + + await act(async () => { + testBed = setup({ onChange: onChangeHandler, value }); + }); + + const { component, exists } = testBed; + component.update(); expect(exists('mappingsEditor')).toBe(true); expect(exists('mappingTypesDetectedCallout')).toBe(true); @@ -94,8 +103,12 @@ describe.skip('Mappings editor: core', () => { }, }, }; - const testBed = setup({ onChange: onChangeHandler, value }); - const { exists } = testBed; + await act(async () => { + testBed = setup({ onChange: onChangeHandler, value }); + }); + + const { component, exists } = testBed; + component.update(); expect(exists('mappingsEditor')).toBe(true); expect(exists('mappingTypesDetectedCallout')).toBe(false); @@ -108,10 +121,12 @@ describe.skip('Mappings editor: core', () => { properties: {}, dynamic_templates: [{ before: 'foo' }], }; - let testBed: MappingsEditorTestBed; beforeEach(async () => { - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); }); test('should keep the changes when switching tabs', async () => { @@ -129,10 +144,7 @@ describe.skip('Mappings editor: core', () => { expect(find('fieldsListItem').length).toEqual(0); // Check that we start with an empty list const newField = { name: 'John', type: 'text' }; - await act(async () => { - addField(newField.name, newField.type); - }); - component.update(); + await addField(newField.name, newField.type); expect(find('fieldsListItem').length).toEqual(1); @@ -142,10 +154,7 @@ describe.skip('Mappings editor: core', () => { // ------------------------------------- // Navigate to dynamic templates tab // ------------------------------------- - await act(async () => { - selectTab('templates'); - }); - component.update(); + await selectTab('templates'); let templatesValue = getJsonEditorValue('dynamicTemplatesEditor'); expect(templatesValue).toEqual(defaultMappings.dynamic_templates); @@ -163,10 +172,7 @@ describe.skip('Mappings editor: core', () => { // ------------------------------------------------------ // Switch to advanced settings tab and make some changes // ------------------------------------------------------ - await act(async () => { - selectTab('advanced'); - }); - component.update(); + await selectTab('advanced'); let isDynamicMappingsEnabled = getToggleValue( 'advancedConfiguration.dynamicMappingsToggle.input' @@ -194,10 +200,7 @@ describe.skip('Mappings editor: core', () => { // ---------------------------------------------------------------------------- // Go back to dynamic templates tab and make sure our changes are still there // ---------------------------------------------------------------------------- - await act(async () => { - selectTab('templates'); - }); - component.update(); + await selectTab('templates'); templatesValue = getJsonEditorValue('dynamicTemplatesEditor'); expect(templatesValue).toEqual(updatedValueTemplates); @@ -205,18 +208,13 @@ describe.skip('Mappings editor: core', () => { // ----------------------------------------------------------- // Go back to fields and make sure our created field is there // ----------------------------------------------------------- - await act(async () => { - selectTab('fields'); - }); - component.update(); + await selectTab('fields'); + field = find('fieldsListItem').at(0); expect(find('fieldName', field).text()).toEqual(newField.name); // Go back to advanced settings tab make sure dynamic mappings is disabled - await act(async () => { - selectTab('advanced'); - }); - component.update(); + await selectTab('advanced'); isDynamicMappingsEnabled = getToggleValue( 'advancedConfiguration.dynamicMappingsToggle.input' @@ -231,46 +229,47 @@ describe.skip('Mappings editor: core', () => { /** * Note: the "indexSettings" prop will be tested along with the "analyzer" parameter on a text datatype field, * as it is the only place where it is consumed by the mappings editor. - * - * The test that covers it is text_datatype.test.tsx: "analyzer parameter: custom analyzer (from index settings)" + * The test that covers it is in the "text_datatype.test.tsx": "analyzer parameter: custom analyzer (from index settings)" */ - const defaultMappings: any = { - dynamic: true, - numeric_detection: false, - date_detection: true, - properties: { - title: { type: 'text' }, - address: { - type: 'object', - properties: { - street: { type: 'text' }, - city: { type: 'text' }, + let defaultMappings: any; + + beforeEach(async () => { + defaultMappings = { + dynamic: true, + numeric_detection: false, + date_detection: true, + properties: { + title: { type: 'text' }, + address: { + type: 'object', + properties: { + street: { type: 'text' }, + city: { type: 'text' }, + }, }, }, - }, - dynamic_templates: [{ initial: 'value' }], - _source: { - enabled: true, - includes: ['field1', 'field2'], - excludes: ['field3'], - }, - _meta: { - some: 'metaData', - }, - _routing: { - required: false, - }, - }; - - let testBed: MappingsEditorTestBed; + dynamic_templates: [{ initial: 'value' }], + _source: { + enabled: true, + includes: ['field1', 'field2'], + excludes: ['field3'], + }, + _meta: { + some: 'metaData', + }, + _routing: { + required: false, + }, + }; - beforeEach(async () => { - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); }); test('props.value => should prepopulate the editor data', async () => { const { - component, actions: { selectTab, getJsonEditorValue, getComboBoxValue, getToggleValue }, find, } = testBed; @@ -285,10 +284,7 @@ describe.skip('Mappings editor: core', () => { /** * Dynamic templates */ - await act(async () => { - selectTab('templates'); - }); - component.update(); + await selectTab('templates'); // Test that dynamic templates JSON is rendered in the templates editor const templatesValue = getJsonEditorValue('dynamicTemplatesEditor'); @@ -297,10 +293,7 @@ describe.skip('Mappings editor: core', () => { /** * Advanced settings */ - await act(async () => { - selectTab('advanced'); - }); - component.update(); + await selectTab('advanced'); const isDynamicMappingsEnabled = getToggleValue( 'advancedConfiguration.dynamicMappingsToggle.input' @@ -339,7 +332,14 @@ describe.skip('Mappings editor: core', () => { /** * Mapped fields */ + await act(async () => { + find('addFieldButton').simulate('click'); + }); + component.update(); + const newField = { name: 'someNewField', type: 'text' }; + await addField(newField.name, newField.type); + updatedMappings = { ...updatedMappings, properties: { @@ -348,26 +348,14 @@ describe.skip('Mappings editor: core', () => { }, }; - await act(async () => { - find('addFieldButton').simulate('click'); - }); - component.update(); - - await act(async () => { - addField(newField.name, newField.type); - }); - component.update(); - ({ data } = await getMappingsEditorData(component)); + expect(data).toEqual(updatedMappings); /** * Dynamic templates */ - await act(async () => { - await selectTab('templates'); - }); - component.update(); + await selectTab('templates'); const updatedTemplatesValue = [{ someTemplateProp: 'updated' }]; updatedMappings = { @@ -385,10 +373,7 @@ describe.skip('Mappings editor: core', () => { /** * Advanced settings */ - await act(async () => { - selectTab('advanced'); - }); - component.update(); + await selectTab('advanced'); // Disbable dynamic mappings await act(async () => { diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx index dc52a362008c6..1457c4583aa0e 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx @@ -71,9 +71,8 @@ export const AnalyzerParameter = ({ allowsIndexDefaultOption = true, 'data-test-subj': dataTestSubj, }: Props) => { - const indexSettings = useIndexSettings(); + const { value: indexSettings } = useIndexSettings(); const customAnalyzers = getCustomAnalyzers(indexSettings); - const analyzerOptions = allowsIndexDefaultOption ? ANALYZER_OPTIONS : ANALYZER_OPTIONS_WITHOUT_DEFAULT; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx index 17d3ea0909bfb..c966df82fb507 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx @@ -49,16 +49,17 @@ export const AnalyzerParameterSelects = ({ 'data-test-subj': dataTestSubj, }: Props) => { const { form } = useForm({ defaultValue: { main: mainDefaultValue, sub: subDefaultValue } }); + const { subscribe } = form; useEffect(() => { - const subscription = form.subscribe((updateData) => { + const subscription = subscribe((updateData) => { const formData = updateData.data.raw; const value = formData.sub ? formData.sub : formData.main; onChange(value); }); return subscription.unsubscribe; - }, [form, onChange]); + }, [subscribe, onChange]); const getSubOptionsMeta = useCallback( (mainValue: string) => diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx index 411193f10b24a..bd84c3a905ec8 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx @@ -3,23 +3,32 @@ * 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, { createContext, useContext } from 'react'; +import React, { createContext, useContext, useState } from 'react'; import { IndexSettings } from './types'; -const IndexSettingsContext = createContext(undefined); +const IndexSettingsContext = createContext< + { value: IndexSettings; update: (value: IndexSettings) => void } | undefined +>(undefined); interface Props { - indexSettings: IndexSettings | undefined; children: React.ReactNode; } -export const IndexSettingsProvider = ({ indexSettings = {}, children }: Props) => ( - {children} -); +export const IndexSettingsProvider = ({ children }: Props) => { + const [state, setState] = useState({}); + + return ( + + {children} + + ); +}; export const useIndexSettings = () => { const ctx = useContext(IndexSettingsContext); - - return ctx === undefined ? {} : ctx; + if (ctx === undefined) { + throw new Error('useIndexSettings must be used within a '); + } + return ctx; }; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx index 39451639bfb86..39c4a2885efa5 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx @@ -25,7 +25,7 @@ import { import { extractMappingsDefinition } from './lib'; import { useMappingsState } from './mappings_state_context'; import { useMappingsStateListener } from './use_state_listener'; -import { IndexSettingsProvider } from './index_settings_context'; +import { useIndexSettings } from './index_settings_context'; type TabName = 'fields' | 'advanced' | 'templates'; @@ -94,6 +94,12 @@ export const MappingsEditor = React.memo(({ onChange, value, indexSettings }: Pr */ useMappingsStateListener({ onChange, value: parsedDefaultValue }); + // Update the Index settings context so it is available in the Global flyout + const { update: updateIndexSettings } = useIndexSettings(); + if (indexSettings !== undefined) { + updateIndexSettings(indexSettings); + } + const state = useMappingsState(); const [selectedTab, selectTab] = useState('fields'); @@ -141,43 +147,41 @@ export const MappingsEditor = React.memo(({ onChange, value, indexSettings }: Pr {multipleMappingsDeclared ? ( ) : ( - -

      - - changeTab('fields')} - isSelected={selectedTab === 'fields'} - data-test-subj="formTab" - > - {i18n.translate('xpack.idxMgmt.mappingsEditor.fieldsTabLabel', { - defaultMessage: 'Mapped fields', - })} - - changeTab('templates')} - isSelected={selectedTab === 'templates'} - data-test-subj="formTab" - > - {i18n.translate('xpack.idxMgmt.mappingsEditor.templatesTabLabel', { - defaultMessage: 'Dynamic templates', - })} - - changeTab('advanced')} - isSelected={selectedTab === 'advanced'} - data-test-subj="formTab" - > - {i18n.translate('xpack.idxMgmt.mappingsEditor.advancedTabLabel', { - defaultMessage: 'Advanced options', - })} - - - - - - {tabToContentMap[selectedTab]} -
      - +
      + + changeTab('fields')} + isSelected={selectedTab === 'fields'} + data-test-subj="formTab" + > + {i18n.translate('xpack.idxMgmt.mappingsEditor.fieldsTabLabel', { + defaultMessage: 'Mapped fields', + })} + + changeTab('templates')} + isSelected={selectedTab === 'templates'} + data-test-subj="formTab" + > + {i18n.translate('xpack.idxMgmt.mappingsEditor.templatesTabLabel', { + defaultMessage: 'Dynamic templates', + })} + + changeTab('advanced')} + isSelected={selectedTab === 'advanced'} + data-test-subj="formTab" + > + {i18n.translate('xpack.idxMgmt.mappingsEditor.advancedTabLabel', { + defaultMessage: 'Advanced options', + })} + + + + + + {tabToContentMap[selectedTab]} +
      )}
      ); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor_context.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor_context.tsx index 596b49cc89ee8..8e30d07c2262f 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor_context.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor_context.tsx @@ -6,7 +6,12 @@ import React from 'react'; import { StateProvider } from './mappings_state_context'; +import { IndexSettingsProvider } from './index_settings_context'; export const MappingsEditorProvider: React.FC = ({ children }) => { - return {children}; + return ( + + {children} + + ); }; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/reducer.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/reducer.ts index 2a8368c666859..e7efd6f28343b 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/reducer.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/reducer.ts @@ -175,10 +175,18 @@ export const reducer = (state: State, action: Action): State => { fields: action.value.fields, configuration: { ...state.configuration, + data: { + raw: action.value.configuration, + format: () => action.value.configuration, + }, defaultValue: action.value.configuration, }, templates: { ...state.templates, + data: { + raw: action.value.templates, + format: () => action.value.templates, + }, defaultValue: action.value.templates, }, documentFields: { diff --git a/x-pack/plugins/index_management/test/fixtures/template.ts b/x-pack/plugins/index_management/test/fixtures/template.ts index 3b9de2b3409b6..ac6e8b7879a26 100644 --- a/x-pack/plugins/index_management/test/fixtures/template.ts +++ b/x-pack/plugins/index_management/test/fixtures/template.ts @@ -11,6 +11,42 @@ const objHasProperties = (obj?: Record): boolean => { return obj === undefined || Object.keys(obj).length === 0 ? false : true; }; +export const getComposableTemplate = ({ + name = getRandomString(), + version = getRandomNumber(), + priority = getRandomNumber(), + indexPatterns = [], + template: { settings, aliases, mappings } = {}, + hasDatastream = false, + isLegacy = false, + type = 'default', +}: Partial< + TemplateDeserialized & { + isLegacy?: boolean; + type?: TemplateType; + hasDatastream: boolean; + } +> = {}): TemplateDeserialized => { + const indexTemplate = { + name, + version, + priority, + indexPatterns, + template: { + aliases, + mappings, + settings, + }, + _kbnMeta: { + type, + hasDatastream, + isLegacy, + }, + }; + + return indexTemplate; +}; + export const getTemplate = ({ name = getRandomString(), version = getRandomNumber(), From e7d8ea3927a7255b14f92f790c02aa1d16ee6004 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 15 Sep 2020 13:41:27 +0300 Subject: [PATCH 16/26] Extract src/core in a separate TS project (#76785) * break dependency on data plugin TS code * move global typings to @kbn/utility-types * import types from @kbn/utility-types * remove type dependency on plugins * add intermediate js files to break dependency on outter TS code * temp type declaration for query-string * declare src/core project * export types to reference in the built d.ts files * reference core project * move jest types out of kbn/utility-types due to a clash with mocha types * fix wrong es_kuery path and ts project paths * reference core from packages consuming it * x-pack & oss should use the same lodash version * Revert "x-pack & oss should use the same lodash version" This reverts commit 79cec5781ed5e6a7320afe7cd4fe649ceba0bc68. * use the same lodash version * fix @types/lodash TS2300: Duplicate identifier error * fix wrong imports * update docs * update docs * add a comment why file is needed --- examples/alerting_example/tsconfig.json | 5 +- examples/bfetch_explorer/tsconfig.json | 5 +- .../tsconfig.json | 5 +- examples/developer_examples/tsconfig.json | 5 +- examples/embeddable_examples/tsconfig.json | 5 +- examples/embeddable_explorer/tsconfig.json | 5 +- examples/routing_example/tsconfig.json | 5 +- examples/search_examples/tsconfig.json | 5 +- .../state_containers_examples/tsconfig.json | 5 +- examples/ui_action_examples/tsconfig.json | 5 +- examples/ui_actions_explorer/tsconfig.json | 5 +- .../url_generators_examples/tsconfig.json | 5 +- .../url_generators_explorer/tsconfig.json | 5 +- packages/kbn-utility-types/index.ts | 12 ++++ packages/kbn-utility-types/tsconfig.json | 1 - .../capabilities/capabilities_service.mock.ts | 1 + src/core/public/application/test_types.ts | 2 +- src/core/public/chrome/chrome_service.mock.ts | 1 + .../public/context/context_service.mock.ts | 2 +- src/core/public/core_app/core_app.mock.ts | 2 +- .../doc_links/doc_links_service.mock.ts | 2 +- .../fatal_errors/fatal_errors_service.mock.ts | 1 + src/core/public/http/http_service.mock.ts | 2 +- .../public/http/loading_count_service.mock.ts | 1 + src/core/public/i18n/i18n_service.mock.ts | 2 + .../injected_metadata_service.mock.ts | 1 + .../integrations/integrations_service.mock.ts | 2 +- .../notifications_service.mock.ts | 1 + .../overlays/banners/banners_service.mock.ts | 2 +- .../overlays/flyout/flyout_service.mock.ts | 2 +- .../overlays/modal/modal_service.mock.ts | 2 +- .../public/overlays/overlay_service.mock.ts | 1 + .../public/plugins/plugins_service.mock.ts | 2 +- src/core/public/public.api.md | 4 +- .../rendering/rendering_service.mock.ts | 2 +- .../saved_objects/saved_objects_client.ts | 1 + .../ui_settings/ui_settings_service.mock.ts | 1 + .../audit_trail/audit_trail_service.mock.ts | 2 +- .../capabilities/capabilities_service.mock.ts | 2 +- src/core/server/config/config_service.ts | 2 +- .../server/config/raw_config_service.mock.ts | 2 +- .../server/context/context_service.mock.ts | 1 + src/core/server/core_context.mock.ts | 1 - src/core/server/elasticsearch/client/mocks.ts | 3 +- .../elasticsearch_service.mock.ts | 4 +- .../environment/environment_service.mock.ts | 1 + src/core/server/http/http_service.mock.ts | 2 + .../lifecycle_handlers.test.ts | 4 +- src/core/server/legacy/cli.js | 20 +++++++ src/core/server/legacy/cluster_manager.js | 20 +++++++ src/core/server/legacy/legacy_service.mock.ts | 2 +- src/core/server/legacy/legacy_service.test.ts | 6 +- src/core/server/legacy/legacy_service.ts | 6 +- .../legacy/plugins/collect_ui_exports.js | 21 +++++++ .../plugins/find_legacy_plugin_specs.ts | 8 +-- .../server/logging/logging_service.mock.ts | 1 + src/core/server/logging/logging_system.ts | 1 + .../server/metrics/metrics_service.mock.ts | 2 + .../server/plugins/plugins_service.mock.ts | 2 +- .../rendering/__mocks__/rendering_service.ts | 2 +- src/core/server/saved_objects/es_query.js | 21 +++++++ .../migrations/kibana/kibana_migrator.mock.ts | 1 + .../saved_objects_service.mock.ts | 1 + .../service/lib/filter_utils.test.ts | 4 +- .../saved_objects/service/lib/filter_utils.ts | 5 +- .../service/lib/repository.test.js | 4 +- .../lib/search_dsl/query_params.test.ts | 5 +- .../service/lib/search_dsl/query_params.ts | 5 +- .../service/lib/search_dsl/search_dsl.ts | 4 +- src/core/server/saved_objects/types.ts | 3 +- src/core/server/server.api.md | 3 - src/core/server/status/status_service.mock.ts | 2 +- .../ui_settings/ui_settings_service.mock.ts | 2 +- src/core/tsconfig.json | 22 ++++++++ src/core/typings.ts | 55 +++++++++++++++++++ src/dev/typescript/projects.ts | 1 + src/legacy/server/i18n/index.ts | 6 +- src/legacy/server/kbn_server.d.ts | 6 -- src/plugins/data/public/public.api.md | 1 + .../plugins/kbn_tp_run_pipeline/tsconfig.json | 5 +- .../plugins/app_link_test/tsconfig.json | 5 +- .../plugins/core_plugin_a/tsconfig.json | 5 +- .../core_plugin_appleave/tsconfig.json | 5 +- .../plugins/core_plugin_b/tsconfig.json | 5 +- .../core_plugin_chromeless/tsconfig.json | 5 +- .../core_plugin_route_timeouts/tsconfig.json | 5 +- .../core_plugin_static_assets/tsconfig.json | 5 +- .../core_provider_plugin/tsconfig.json | 5 +- .../plugins/doc_views_plugin/tsconfig.json | 5 +- .../elasticsearch_client_plugin/tsconfig.json | 5 +- .../plugins/index_patterns/tsconfig.json | 5 +- .../kbn_sample_panel_action/tsconfig.json | 5 +- .../plugins/kbn_top_nav/tsconfig.json | 5 +- .../tsconfig.json | 5 +- .../management_test_plugin/tsconfig.json | 5 +- .../plugins/rendering_plugin/tsconfig.json | 5 +- .../plugins/ui_settings_plugin/tsconfig.json | 5 +- test/tsconfig.json | 3 + tsconfig.json | 8 ++- tsconfig.refs.json | 3 +- .../tsconfig.json | 5 +- x-pack/package.json | 3 +- x-pack/test/tsconfig.json | 3 + x-pack/tsconfig.json | 5 +- 104 files changed, 399 insertions(+), 102 deletions(-) create mode 100644 src/core/server/legacy/cli.js create mode 100644 src/core/server/legacy/cluster_manager.js create mode 100644 src/core/server/legacy/plugins/collect_ui_exports.js create mode 100644 src/core/server/saved_objects/es_query.js create mode 100644 src/core/tsconfig.json create mode 100644 src/core/typings.ts diff --git a/examples/alerting_example/tsconfig.json b/examples/alerting_example/tsconfig.json index 09c130aca4642..214e4b78a9a70 100644 --- a/examples/alerting_example/tsconfig.json +++ b/examples/alerting_example/tsconfig.json @@ -11,5 +11,8 @@ "common/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/bfetch_explorer/tsconfig.json b/examples/bfetch_explorer/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/bfetch_explorer/tsconfig.json +++ b/examples/bfetch_explorer/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/dashboard_embeddable_examples/tsconfig.json b/examples/dashboard_embeddable_examples/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/dashboard_embeddable_examples/tsconfig.json +++ b/examples/dashboard_embeddable_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/developer_examples/tsconfig.json b/examples/developer_examples/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/developer_examples/tsconfig.json +++ b/examples/developer_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/embeddable_examples/tsconfig.json b/examples/embeddable_examples/tsconfig.json index caeed2c1a434f..78098339c16f5 100644 --- a/examples/embeddable_examples/tsconfig.json +++ b/examples/embeddable_examples/tsconfig.json @@ -12,5 +12,8 @@ "server/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/embeddable_explorer/tsconfig.json b/examples/embeddable_explorer/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/embeddable_explorer/tsconfig.json +++ b/examples/embeddable_explorer/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/routing_example/tsconfig.json b/examples/routing_example/tsconfig.json index 761a5c4da65ba..54ac800019f82 100644 --- a/examples/routing_example/tsconfig.json +++ b/examples/routing_example/tsconfig.json @@ -12,5 +12,8 @@ "common/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/search_examples/tsconfig.json b/examples/search_examples/tsconfig.json index 8bec69ca40ccc..2b7d86d76a8a5 100644 --- a/examples/search_examples/tsconfig.json +++ b/examples/search_examples/tsconfig.json @@ -12,5 +12,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/state_containers_examples/tsconfig.json b/examples/state_containers_examples/tsconfig.json index 007322e2d9525..6cfb9f9dc2321 100644 --- a/examples/state_containers_examples/tsconfig.json +++ b/examples/state_containers_examples/tsconfig.json @@ -12,5 +12,8 @@ "common/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/ui_action_examples/tsconfig.json b/examples/ui_action_examples/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/ui_action_examples/tsconfig.json +++ b/examples/ui_action_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/ui_actions_explorer/tsconfig.json b/examples/ui_actions_explorer/tsconfig.json index 119209114a7bb..782b9cd57fa7b 100644 --- a/examples/ui_actions_explorer/tsconfig.json +++ b/examples/ui_actions_explorer/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/url_generators_examples/tsconfig.json b/examples/url_generators_examples/tsconfig.json index 327b4642a8e7f..8aef3328b4222 100644 --- a/examples/url_generators_examples/tsconfig.json +++ b/examples/url_generators_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/url_generators_explorer/tsconfig.json b/examples/url_generators_explorer/tsconfig.json index 327b4642a8e7f..8aef3328b4222 100644 --- a/examples/url_generators_explorer/tsconfig.json +++ b/examples/url_generators_explorer/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 6ccfeb8ab052c..d3fb5bdf36194 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -98,3 +98,15 @@ export type PublicKeys = keyof T; * Returns an object with public keys only. */ export type PublicContract = Pick>; + +/** + * Returns public method names + */ +export type MethodKeysOf = { + [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; +}[keyof T]; + +/** + * Returns an object with public methods only. + */ +export type PublicMethodsOf = Pick>; diff --git a/packages/kbn-utility-types/tsconfig.json b/packages/kbn-utility-types/tsconfig.json index 03cace5b9cb2c..79cf423fe78ac 100644 --- a/packages/kbn-utility-types/tsconfig.json +++ b/packages/kbn-utility-types/tsconfig.json @@ -7,7 +7,6 @@ "stripInternal": true, "declarationMap": true, "types": [ - "jest", "node" ] }, diff --git a/src/core/public/application/capabilities/capabilities_service.mock.ts b/src/core/public/application/capabilities/capabilities_service.mock.ts index 54aaa31e08859..d7b0c27879aad 100644 --- a/src/core/public/application/capabilities/capabilities_service.mock.ts +++ b/src/core/public/application/capabilities/capabilities_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CapabilitiesService, CapabilitiesStart } from './capabilities_service'; import { deepFreeze } from '../../../utils'; diff --git a/src/core/public/application/test_types.ts b/src/core/public/application/test_types.ts index 64012f0c0b6c1..6d29b77d92f36 100644 --- a/src/core/public/application/test_types.ts +++ b/src/core/public/application/test_types.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AppUnmount, Mounter } from './types'; import { ApplicationService } from './application_service'; diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 0ae8b132f1d86..9cd96763d2e79 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -17,6 +17,7 @@ * under the License. */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ChromeBadge, ChromeBrand, ChromeBreadcrumb, ChromeService, InternalChromeStart } from './'; const createStartContractMock = () => { diff --git a/src/core/public/context/context_service.mock.ts b/src/core/public/context/context_service.mock.ts index eb55ced69dc04..3f9f647e1f7d0 100644 --- a/src/core/public/context/context_service.mock.ts +++ b/src/core/public/context/context_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ContextService, ContextSetup } from './context_service'; import { contextMock } from '../../utils/context.mock'; diff --git a/src/core/public/core_app/core_app.mock.ts b/src/core/public/core_app/core_app.mock.ts index b0e3871a40bf5..b2af81b3630a3 100644 --- a/src/core/public/core_app/core_app.mock.ts +++ b/src/core/public/core_app/core_app.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CoreApp } from './core_app'; type CoreAppContract = PublicMethodsOf; diff --git a/src/core/public/doc_links/doc_links_service.mock.ts b/src/core/public/doc_links/doc_links_service.mock.ts index 105c13f96cef6..07e29edad8974 100644 --- a/src/core/public/doc_links/doc_links_service.mock.ts +++ b/src/core/public/doc_links/doc_links_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; import { DocLinksService, DocLinksStart } from './doc_links_service'; diff --git a/src/core/public/fatal_errors/fatal_errors_service.mock.ts b/src/core/public/fatal_errors/fatal_errors_service.mock.ts index 6d9876f787fa9..326ce9a3923e9 100644 --- a/src/core/public/fatal_errors/fatal_errors_service.mock.ts +++ b/src/core/public/fatal_errors/fatal_errors_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FatalErrorsService, FatalErrorsSetup } from './fatal_errors_service'; const createSetupContractMock = () => { diff --git a/src/core/public/http/http_service.mock.ts b/src/core/public/http/http_service.mock.ts index 1111fd39ec78e..68533159765fb 100644 --- a/src/core/public/http/http_service.mock.ts +++ b/src/core/public/http/http_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { HttpService } from './http_service'; import { HttpSetup } from './types'; import { BehaviorSubject } from 'rxjs'; diff --git a/src/core/public/http/loading_count_service.mock.ts b/src/core/public/http/loading_count_service.mock.ts index 79928aa4b160d..2ff635e815296 100644 --- a/src/core/public/http/loading_count_service.mock.ts +++ b/src/core/public/http/loading_count_service.mock.ts @@ -19,6 +19,7 @@ import { LoadingCountSetup, LoadingCountService } from './loading_count_service'; import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; const createSetupContractMock = () => { const setupContract: jest.Mocked = { diff --git a/src/core/public/i18n/i18n_service.mock.ts b/src/core/public/i18n/i18n_service.mock.ts index 1a9ca0869d7c1..a91710fbed780 100644 --- a/src/core/public/i18n/i18n_service.mock.ts +++ b/src/core/public/i18n/i18n_service.mock.ts @@ -18,6 +18,8 @@ */ import React from 'react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { I18nService, I18nStart } from './i18n_service'; const PassThroughComponent = ({ children }: { children: React.ReactNode }) => children; diff --git a/src/core/public/injected_metadata/injected_metadata_service.mock.ts b/src/core/public/injected_metadata/injected_metadata_service.mock.ts index 3bb4358406246..33d04eedebb07 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.mock.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { InjectedMetadataService, InjectedMetadataSetup } from './injected_metadata_service'; const createSetupContractMock = () => { diff --git a/src/core/public/integrations/integrations_service.mock.ts b/src/core/public/integrations/integrations_service.mock.ts index 4f6ca0fb68459..88458ebb747fe 100644 --- a/src/core/public/integrations/integrations_service.mock.ts +++ b/src/core/public/integrations/integrations_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { IntegrationsService } from './integrations_service'; type IntegrationsServiceContract = PublicMethodsOf; diff --git a/src/core/public/notifications/notifications_service.mock.ts b/src/core/public/notifications/notifications_service.mock.ts index 464f47e20aa3b..990ab479d35c3 100644 --- a/src/core/public/notifications/notifications_service.mock.ts +++ b/src/core/public/notifications/notifications_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsService, NotificationsSetup, diff --git a/src/core/public/overlays/banners/banners_service.mock.ts b/src/core/public/overlays/banners/banners_service.mock.ts index 14041b2720877..acd38af383d67 100644 --- a/src/core/public/overlays/banners/banners_service.mock.ts +++ b/src/core/public/overlays/banners/banners_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { OverlayBannersStart, OverlayBannersService } from './banners_service'; const createStartContractMock = () => { diff --git a/src/core/public/overlays/flyout/flyout_service.mock.ts b/src/core/public/overlays/flyout/flyout_service.mock.ts index 91544500713d6..90dcb308de1b9 100644 --- a/src/core/public/overlays/flyout/flyout_service.mock.ts +++ b/src/core/public/overlays/flyout/flyout_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FlyoutService, OverlayFlyoutStart } from './flyout_service'; const createStartContractMock = () => { diff --git a/src/core/public/overlays/modal/modal_service.mock.ts b/src/core/public/overlays/modal/modal_service.mock.ts index 5ac49874dcf93..0af207d168fae 100644 --- a/src/core/public/overlays/modal/modal_service.mock.ts +++ b/src/core/public/overlays/modal/modal_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ModalService, OverlayModalStart } from './modal_service'; const createStartContractMock = () => { diff --git a/src/core/public/overlays/overlay_service.mock.ts b/src/core/public/overlays/overlay_service.mock.ts index e29247494034f..66ba36b20b45c 100644 --- a/src/core/public/overlays/overlay_service.mock.ts +++ b/src/core/public/overlays/overlay_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { OverlayService, OverlayStart } from './overlay_service'; import { overlayBannersServiceMock } from './banners/banners_service.mock'; import { overlayFlyoutServiceMock } from './flyout/flyout_service.mock'; diff --git a/src/core/public/plugins/plugins_service.mock.ts b/src/core/public/plugins/plugins_service.mock.ts index 900f20422b826..0625d2c3ec4b2 100644 --- a/src/core/public/plugins/plugins_service.mock.ts +++ b/src/core/public/plugins/plugins_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { PluginsService, PluginsServiceSetup } from './plugins_service'; const createSetupContractMock = () => { diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index a9bea7bcfdef1..a4f9234b539d6 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -7,7 +7,6 @@ import { Action } from 'history'; import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; import Boom from 'boom'; -import { ErrorToastOptions as ErrorToastOptions_2 } from 'src/core/public/notifications'; import { EuiBreadcrumb } from '@elastic/eui'; import { EuiButtonEmptyProps } from '@elastic/eui'; import { EuiConfirmModalProps } from '@elastic/eui'; @@ -24,13 +23,12 @@ import { MaybePromise } from '@kbn/utility-types'; import { Observable } from 'rxjs'; import { ParsedQuery } from 'query-string'; import { Path } from 'history'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { PublicUiSettingsParams as PublicUiSettingsParams_2 } from 'src/core/server/types'; import React from 'react'; import { RecursiveReadonly } from '@kbn/utility-types'; import * as Rx from 'rxjs'; -import { SavedObject as SavedObject_2 } from 'src/core/server'; import { ShallowPromise } from '@kbn/utility-types'; -import { ToastInputFields as ToastInputFields_2 } from 'src/core/public/notifications'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; diff --git a/src/core/public/rendering/rendering_service.mock.ts b/src/core/public/rendering/rendering_service.mock.ts index bb4723e69ab5e..803a7dae91a40 100644 --- a/src/core/public/rendering/rendering_service.mock.ts +++ b/src/core/public/rendering/rendering_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RenderingService } from './rendering_service'; type RenderingServiceContract = PublicMethodsOf; diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts index 351020004b0e7..5a8949ca2f55f 100644 --- a/src/core/public/saved_objects/saved_objects_client.ts +++ b/src/core/public/saved_objects/saved_objects_client.ts @@ -19,6 +19,7 @@ import { cloneDeep, pick, throttle } from 'lodash'; import { resolve as resolveUrl } from 'url'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObject, diff --git a/src/core/public/ui_settings/ui_settings_service.mock.ts b/src/core/public/ui_settings/ui_settings_service.mock.ts index e1f7eeff93471..1921c26e57971 100644 --- a/src/core/public/ui_settings/ui_settings_service.mock.ts +++ b/src/core/public/ui_settings/ui_settings_service.mock.ts @@ -17,6 +17,7 @@ * under the License. */ import * as Rx from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { UiSettingsService } from './'; import { IUiSettingsClient } from './types'; diff --git a/src/core/server/audit_trail/audit_trail_service.mock.ts b/src/core/server/audit_trail/audit_trail_service.mock.ts index d63b3539e5cdc..4c9c064840750 100644 --- a/src/core/server/audit_trail/audit_trail_service.mock.ts +++ b/src/core/server/audit_trail/audit_trail_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AuditTrailSetup, AuditTrailStart, Auditor } from './types'; import { AuditTrailService } from './audit_trail_service'; diff --git a/src/core/server/capabilities/capabilities_service.mock.ts b/src/core/server/capabilities/capabilities_service.mock.ts index 3f31eca8339d8..7d134f9592dc7 100644 --- a/src/core/server/capabilities/capabilities_service.mock.ts +++ b/src/core/server/capabilities/capabilities_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CapabilitiesService, CapabilitiesSetup, CapabilitiesStart } from './capabilities_service'; const createSetupContractMock = () => { diff --git a/src/core/server/config/config_service.ts b/src/core/server/config/config_service.ts index bceba420bb6ce..d77ee980b0491 100644 --- a/src/core/server/config/config_service.ts +++ b/src/core/server/config/config_service.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Type } from '@kbn/config-schema'; import { isEqual } from 'lodash'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; diff --git a/src/core/server/config/raw_config_service.mock.ts b/src/core/server/config/raw_config_service.mock.ts index fdcb17395aaad..73a3b5cc9e4d0 100644 --- a/src/core/server/config/raw_config_service.mock.ts +++ b/src/core/server/config/raw_config_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RawConfigService } from './raw_config_service'; import { Observable, of } from 'rxjs'; diff --git a/src/core/server/context/context_service.mock.ts b/src/core/server/context/context_service.mock.ts index eb55ced69dc04..a8d895acad624 100644 --- a/src/core/server/context/context_service.mock.ts +++ b/src/core/server/context/context_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ContextService, ContextSetup } from './context_service'; import { contextMock } from '../../utils/context.mock'; diff --git a/src/core/server/core_context.mock.ts b/src/core/server/core_context.mock.ts index f870d30528df4..2b887358818e3 100644 --- a/src/core/server/core_context.mock.ts +++ b/src/core/server/core_context.mock.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { CoreContext } from './core_context'; import { getEnvOptions } from './config/__mocks__/env'; import { Env, IConfigService } from './config'; diff --git a/src/core/server/elasticsearch/client/mocks.ts b/src/core/server/elasticsearch/client/mocks.ts index 2f2ca08fee6f2..6fb3dc090bfb4 100644 --- a/src/core/server/elasticsearch/client/mocks.ts +++ b/src/core/server/elasticsearch/client/mocks.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { Client, ApiResponse } from '@elastic/elasticsearch'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; import { ElasticsearchClient } from './types'; @@ -75,7 +74,7 @@ export type ElasticsearchClientMock = DeeplyMockedKeys; const createClientMock = (): ElasticsearchClientMock => (createInternalClientMock() as unknown) as ElasticsearchClientMock; -interface ScopedClusterClientMock { +export interface ScopedClusterClientMock { asInternalUser: ElasticsearchClientMock; asCurrentUser: ElasticsearchClientMock; } diff --git a/src/core/server/elasticsearch/elasticsearch_service.mock.ts b/src/core/server/elasticsearch/elasticsearch_service.mock.ts index 26186efc286bf..ad80928d2fe5e 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.mock.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.mock.ts @@ -18,6 +18,8 @@ */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { ILegacyClusterClient, ILegacyCustomClusterClient } from './legacy'; import { elasticsearchClientMock, @@ -32,7 +34,7 @@ import { InternalElasticsearchServiceSetup, ElasticsearchStatusMeta } from './ty import { NodesVersionCompatibility } from './version_check/ensure_es_version'; import { ServiceStatus, ServiceStatusLevels } from '../status'; -interface MockedElasticSearchServiceSetup { +export interface MockedElasticSearchServiceSetup { legacy: { config$: BehaviorSubject; createClient: jest.Mock; diff --git a/src/core/server/environment/environment_service.mock.ts b/src/core/server/environment/environment_service.mock.ts index 8bf726b4a6388..a956e369ba4a7 100644 --- a/src/core/server/environment/environment_service.mock.ts +++ b/src/core/server/environment/environment_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { EnvironmentService, InternalEnvironmentServiceSetup } from './environment_service'; diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index 676cee1954c59..3e38f6a6d384d 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -18,6 +18,8 @@ */ import { Server } from 'hapi'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { CspConfig } from '../csp'; import { mockRouter, RouterMock } from './router/router.mock'; import { configMock } from '../config/config.mock'; diff --git a/src/core/server/http/integration_tests/lifecycle_handlers.test.ts b/src/core/server/http/integration_tests/lifecycle_handlers.test.ts index a1401ba73813b..8d70b5c3ad119 100644 --- a/src/core/server/http/integration_tests/lifecycle_handlers.test.ts +++ b/src/core/server/http/integration_tests/lifecycle_handlers.test.ts @@ -20,7 +20,6 @@ import supertest from 'supertest'; import { BehaviorSubject } from 'rxjs'; import { ByteSizeValue } from '@kbn/config-schema'; -import pkg from '../../../../../package.json'; import { createHttpServer } from '../test_utils'; import { HttpService } from '../http_service'; @@ -30,6 +29,9 @@ import { IRouter, RouteRegistrar } from '../router'; import { configServiceMock } from '../../config/config_service.mock'; import { contextServiceMock } from '../../context/context_service.mock'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pkg = require('../../../../../package.json'); + const actualVersion = pkg.version; const versionHeader = 'kbn-version'; const xsrfHeader = 'kbn-xsrf'; diff --git a/src/core/server/legacy/cli.js b/src/core/server/legacy/cli.js new file mode 100644 index 0000000000000..28e14d28eecd3 --- /dev/null +++ b/src/core/server/legacy/cli.js @@ -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 { startRepl } from '../../../cli/repl'; diff --git a/src/core/server/legacy/cluster_manager.js b/src/core/server/legacy/cluster_manager.js new file mode 100644 index 0000000000000..3c51fd6869a09 --- /dev/null +++ b/src/core/server/legacy/cluster_manager.js @@ -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 { ClusterManager } from '../../../cli/cluster/cluster_manager'; diff --git a/src/core/server/legacy/legacy_service.mock.ts b/src/core/server/legacy/legacy_service.mock.ts index c27f5be04d965..ab501bd6bb53b 100644 --- a/src/core/server/legacy/legacy_service.mock.ts +++ b/src/core/server/legacy/legacy_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { LegacyService } from './legacy_service'; import { LegacyConfig, LegacyServiceDiscoverPlugins, LegacyServiceSetupDeps } from './types'; diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index d0492ea88c5e8..f3ce89f83a610 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -18,8 +18,7 @@ */ jest.mock('../../../legacy/server/kbn_server'); -jest.mock('../../../cli/cluster/cluster_manager'); - +jest.mock('./cluster_manager'); import { findLegacyPluginSpecsMock, logLegacyThirdPartyPluginDeprecationWarningMock, @@ -27,7 +26,8 @@ import { import { BehaviorSubject, throwError } from 'rxjs'; -import { ClusterManager as MockClusterManager } from '../../../cli/cluster/cluster_manager'; +// @ts-expect-error js file to remove TS dependency on cli +import { ClusterManager as MockClusterManager } from './cluster_manager'; import KbnServer from '../../../legacy/server/kbn_server'; import { Config, Env, ObjectToConfigAdapter } from '../config'; import { getEnvOptions } from '../config/__mocks__/env'; diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index 6e6d5cfc24340..d07c81b8b5ebe 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { combineLatest, ConnectableObservable, EMPTY, Observable, Subscription } from 'rxjs'; import { first, map, publishReplay, tap } from 'rxjs/operators'; @@ -233,7 +233,7 @@ export class LegacyService implements CoreService { : EMPTY; // eslint-disable-next-line @typescript-eslint/no-var-requires - const { ClusterManager } = require('../../../cli/cluster/cluster_manager'); + const { ClusterManager } = require('./cluster_manager'); return new ClusterManager( this.coreContext.env.cliArgs, config, @@ -368,7 +368,7 @@ export class LegacyService implements CoreService { // We only want one REPL. if (this.coreContext.env.cliArgs.repl && process.env.kbnWorkerType === 'server') { // eslint-disable-next-line @typescript-eslint/no-var-requires - require('../../../cli/repl').startRepl(kbnServer); + require('./cli').startRepl(kbnServer); } const { autoListen } = await this.httpConfig$.pipe(first()).toPromise(); diff --git a/src/core/server/legacy/plugins/collect_ui_exports.js b/src/core/server/legacy/plugins/collect_ui_exports.js new file mode 100644 index 0000000000000..842ab554d79d1 --- /dev/null +++ b/src/core/server/legacy/plugins/collect_ui_exports.js @@ -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. + */ + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export { collectUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports'; diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts index 82e04496ffc3e..cb4277b130a88 100644 --- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts +++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts @@ -25,12 +25,12 @@ import { defaultConfig, // @ts-expect-error } from '../../../../legacy/plugin_discovery/find_plugin_specs.js'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { collectUiExports as collectLegacyUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports'; +// @ts-expect-error +import { collectUiExports as collectLegacyUiExports } from './collect_ui_exports'; import { LoggerFactory } from '../../logging'; import { PackageInfo } from '../../config'; -import { LegacyPluginSpec, LegacyPluginPack, LegacyConfig } from '../types'; +import { LegacyUiExports, LegacyPluginSpec, LegacyPluginPack, LegacyConfig } from '../types'; export async function findLegacyPluginSpecs( settings: unknown, @@ -123,7 +123,7 @@ export async function findLegacyPluginSpecs( spec$.pipe(toArray()), log$.pipe(toArray()) ).toPromise(); - const uiExports = collectLegacyUiExports(pluginSpecs); + const uiExports: LegacyUiExports = collectLegacyUiExports(pluginSpecs); return { disabledPluginSpecs, diff --git a/src/core/server/logging/logging_service.mock.ts b/src/core/server/logging/logging_service.mock.ts index 21edbe670eaec..6a721e134feed 100644 --- a/src/core/server/logging/logging_service.mock.ts +++ b/src/core/server/logging/logging_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { LoggingService, diff --git a/src/core/server/logging/logging_system.ts b/src/core/server/logging/logging_system.ts index 8aadab83bf716..a3970b1720950 100644 --- a/src/core/server/logging/logging_system.ts +++ b/src/core/server/logging/logging_system.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Appenders, DisposableAppender } from './appenders/appenders'; import { BufferAppender } from './appenders/buffer/buffer_appender'; import { LogLevel } from './log_level'; diff --git a/src/core/server/metrics/metrics_service.mock.ts b/src/core/server/metrics/metrics_service.mock.ts index 2af653004a479..caa7acc001db3 100644 --- a/src/core/server/metrics/metrics_service.mock.ts +++ b/src/core/server/metrics/metrics_service.mock.ts @@ -17,6 +17,8 @@ * under the License. */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { MetricsService } from './metrics_service'; import { InternalMetricsServiceSetup, diff --git a/src/core/server/plugins/plugins_service.mock.ts b/src/core/server/plugins/plugins_service.mock.ts index a40566767ddae..14d6de889dd42 100644 --- a/src/core/server/plugins/plugins_service.mock.ts +++ b/src/core/server/plugins/plugins_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { PluginsService, PluginsServiceSetup } from './plugins_service'; type PluginsServiceMock = jest.Mocked>; diff --git a/src/core/server/rendering/__mocks__/rendering_service.ts b/src/core/server/rendering/__mocks__/rendering_service.ts index 2e35568873c9a..179a09b8619b0 100644 --- a/src/core/server/rendering/__mocks__/rendering_service.ts +++ b/src/core/server/rendering/__mocks__/rendering_service.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RenderingService as Service } from '../rendering_service'; import { InternalRenderingServiceSetup } from '../types'; import { mockRenderingServiceParams } from './params'; diff --git a/src/core/server/saved_objects/es_query.js b/src/core/server/saved_objects/es_query.js new file mode 100644 index 0000000000000..68d582e3cae09 --- /dev/null +++ b/src/core/server/saved_objects/es_query.js @@ -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. + */ +// a temporary file to remove circular deps in TS code between platform & data plugin +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export { esKuery } from '../../../plugins/data/server'; diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts index fae33bc050dee..23d8c4518d3ab 100644 --- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts +++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { KibanaMigrator, KibanaMigratorStatus } from './kibana_migrator'; import { buildActiveMappings } from '../core'; diff --git a/src/core/server/saved_objects/saved_objects_service.mock.ts b/src/core/server/saved_objects/saved_objects_service.mock.ts index e3d44c20dd190..bd76658c21731 100644 --- a/src/core/server/saved_objects/saved_objects_service.mock.ts +++ b/src/core/server/saved_objects/saved_objects_service.mock.ts @@ -18,6 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObjectsService, diff --git a/src/core/server/saved_objects/service/lib/filter_utils.test.ts b/src/core/server/saved_objects/service/lib/filter_utils.test.ts index 60e8aa0afdda4..0608035ce51a2 100644 --- a/src/core/server/saved_objects/service/lib/filter_utils.test.ts +++ b/src/core/server/saved_objects/service/lib/filter_utils.test.ts @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery } from '../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../es_query'; import { validateFilterKueryNode, validateConvertFilterToKueryNode } from './filter_utils'; diff --git a/src/core/server/saved_objects/service/lib/filter_utils.ts b/src/core/server/saved_objects/service/lib/filter_utils.ts index d19f06d74e419..be36807f0d02b 100644 --- a/src/core/server/saved_objects/service/lib/filter_utils.ts +++ b/src/core/server/saved_objects/service/lib/filter_utils.ts @@ -21,8 +21,9 @@ import { set } from '@elastic/safer-lodash-set'; import { get } from 'lodash'; import { SavedObjectsErrorHelpers } from './errors'; import { IndexMapping } from '../../mappings'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery, KueryNode } from '../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../es_query'; +type KueryNode = any; const astFunctionType = ['is', 'range', 'nested']; diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 7d30875b90796..352ce4c1c16eb 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -25,8 +25,8 @@ import { encodeHitVersion } from '../../version'; import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry'; import { DocumentMigrator } from '../../migrations/core/document_migrator'; import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { nodeTypes } from '../../../../../plugins/data/common/es_query'; +import { esKuery } from '../../es_query'; +const { nodeTypes } = esKuery; jest.mock('./search_dsl/search_dsl', () => ({ getSearchDsl: jest.fn() })); diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts index 85c47029e36d5..4adc92df31805 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts @@ -17,8 +17,9 @@ * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery, KueryNode } from '../../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../../es_query'; +type KueryNode = any; import { typeRegistryMock } from '../../../saved_objects_type_registry.mock'; import { getQueryParams } from './query_params'; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts index 3ff72a86c2f89..642d51c70766e 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts @@ -16,8 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery, KueryNode } from '../../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../../es_query'; +type KueryNode = any; import { getRootPropertiesObjects, IndexMapping } from '../../../mappings'; import { ISavedObjectTypeRegistry } from '../../../saved_objects_type_registry'; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts index ddf20606800c8..aa79a10b2a9be 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts @@ -22,10 +22,10 @@ import Boom from 'boom'; import { IndexMapping } from '../../../mappings'; import { getQueryParams } from './query_params'; import { getSortingParams } from './sorting_params'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { KueryNode } from '../../../../../../plugins/data/server'; import { ISavedObjectTypeRegistry } from '../../../saved_objects_type_registry'; +type KueryNode = any; + interface GetSearchDslOptions { type: string | string[]; search?: string; diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index 50c118ca64ffb..1885f5ec50139 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -35,8 +35,7 @@ export { import { SavedObject } from '../../types'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { KueryNode } from '../../../plugins/data/common'; +type KueryNode = any; export { SavedObjectAttributes, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index ec457704e89c7..d6572ee8e7d3e 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -40,7 +40,6 @@ import { DeleteScriptParams } from 'elasticsearch'; import { DeleteTemplateParams } from 'elasticsearch'; import { DetailedPeerCertificate } from 'tls'; import { Duration } from 'moment'; -import { ErrorToastOptions } from 'src/core/public/notifications'; import { ExistsParams } from 'elasticsearch'; import { ExplainParams } from 'elasticsearch'; import { FieldStatsParams } from 'elasticsearch'; @@ -119,7 +118,6 @@ import { RenderSearchTemplateParams } from 'elasticsearch'; import { Request } from 'hapi'; import { ResponseObject } from 'hapi'; import { ResponseToolkit } from 'hapi'; -import { SavedObject as SavedObject_2 } from 'src/core/server'; import { SchemaTypeError } from '@kbn/config-schema'; import { ScrollParams } from 'elasticsearch'; import { SearchParams } from 'elasticsearch'; @@ -143,7 +141,6 @@ import { TasksCancelParams } from 'elasticsearch'; import { TasksGetParams } from 'elasticsearch'; import { TasksListParams } from 'elasticsearch'; import { TermvectorsParams } from 'elasticsearch'; -import { ToastInputFields } from 'src/core/public/notifications'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; diff --git a/src/core/server/status/status_service.mock.ts b/src/core/server/status/status_service.mock.ts index 42b3eecdca310..930ee2970cf55 100644 --- a/src/core/server/status/status_service.mock.ts +++ b/src/core/server/status/status_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { StatusService } from './status_service'; import { InternalStatusServiceSetup, diff --git a/src/core/server/ui_settings/ui_settings_service.mock.ts b/src/core/server/ui_settings/ui_settings_service.mock.ts index 83cea6d7ab3e2..b1ed0dd188cde 100644 --- a/src/core/server/ui_settings/ui_settings_service.mock.ts +++ b/src/core/server/ui_settings/ui_settings_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { IUiSettingsClient, InternalUiSettingsServiceSetup, diff --git a/src/core/tsconfig.json b/src/core/tsconfig.json new file mode 100644 index 0000000000000..b8780321e11dd --- /dev/null +++ b/src/core/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*", + "server/**/*", + "types/**/*", + "test_helpers/**/*", + "utils/**/*", + "index.ts", + "typings.ts" + ], + "references": [ + { "path": "../test_utils/" } + ] +} diff --git a/src/core/typings.ts b/src/core/typings.ts new file mode 100644 index 0000000000000..a84e1c01d2bd2 --- /dev/null +++ b/src/core/typings.ts @@ -0,0 +1,55 @@ +/* + * 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. + */ + +declare module 'query-string' { + type ArrayFormat = 'bracket' | 'index' | 'none'; + + export interface ParseOptions { + arrayFormat?: ArrayFormat; + sort: ((itemLeft: string, itemRight: string) => number) | false; + } + + export interface ParsedQuery { + [key: string]: T | T[] | null | undefined; + } + + export function parse(str: string, options?: ParseOptions): ParsedQuery; + + export function parseUrl(str: string, options?: ParseOptions): { url: string; query: any }; + + export interface StringifyOptions { + strict?: boolean; + encode?: boolean; + arrayFormat?: ArrayFormat; + sort: ((itemLeft: string, itemRight: string) => number) | false; + } + + export function stringify(obj: object, options?: StringifyOptions): string; + + export function extract(str: string): string; +} + +type DeeplyMockedKeys = { + [P in keyof T]: T[P] extends (...args: any[]) => any + ? jest.MockInstance, Parameters> + : DeeplyMockedKeys; +} & + T; + +type MockedKeys = { [P in keyof T]: jest.Mocked }; diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index e18c82b5b9e96..6fa07190dc43e 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -25,6 +25,7 @@ import { Project } from './project'; export const PROJECTS = [ new Project(resolve(REPO_ROOT, 'tsconfig.json')), new Project(resolve(REPO_ROOT, 'src/test_utils/tsconfig.json')), + new Project(resolve(REPO_ROOT, 'src/core/tsconfig.json')), new Project(resolve(REPO_ROOT, 'test/tsconfig.json'), { name: 'kibana/test' }), new Project(resolve(REPO_ROOT, 'x-pack/tsconfig.json')), new Project(resolve(REPO_ROOT, 'x-pack/test/tsconfig.json'), { name: 'x-pack/test' }), diff --git a/src/legacy/server/i18n/index.ts b/src/legacy/server/i18n/index.ts index e895f83fe6901..cb86c3220bec1 100644 --- a/src/legacy/server/i18n/index.ts +++ b/src/legacy/server/i18n/index.ts @@ -21,6 +21,7 @@ import { i18n, i18nLoader } from '@kbn/i18n'; import { basename } from 'path'; import { Server } from 'hapi'; import { fromRoot } from '../../../core/server/utils'; +import type { UsageCollectionSetup } from '../../../plugins/usage_collection/server'; import { getTranslationPaths } from './get_translations_path'; import { I18N_RC } from './constants'; import KbnServer, { KibanaConfig } from '../kbn_server'; @@ -64,7 +65,10 @@ export async function i18nMixin(kbnServer: KbnServer, server: Server, config: Ki server.decorate('server', 'getTranslationsFilePaths', getTranslationsFilePaths); if (kbnServer.newPlatform.setup.plugins.usageCollection) { - registerLocalizationUsageCollector(kbnServer.newPlatform.setup.plugins.usageCollection, { + const { usageCollection } = kbnServer.newPlatform.setup.plugins as { + usageCollection: UsageCollectionSetup; + }; + registerLocalizationUsageCollector(usageCollection, { getLocale: () => config.get('i18n.locale') as string, getTranslationsFilePaths, }); diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts index 663542618375a..8827dc53c5275 100644 --- a/src/legacy/server/kbn_server.d.ts +++ b/src/legacy/server/kbn_server.d.ts @@ -19,7 +19,6 @@ import { Server } from 'hapi'; -import { TelemetryCollectionManagerPluginSetup } from 'src/plugins/telemetry_collection_manager/server'; import { CoreSetup, CoreStart, @@ -35,8 +34,6 @@ import { LegacyConfig, ILegacyInternals } from '../../core/server/legacy'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { UiPlugins } from '../../core/server/plugins'; import { ElasticsearchPlugin } from '../core_plugins/elasticsearch'; -import { UsageCollectionSetup } from '../../plugins/usage_collection/server'; -import { HomeServerPluginSetup } from '../../plugins/home/server'; // lot of legacy code was assuming this type only had these two methods export type KibanaConfig = Pick; @@ -60,9 +57,6 @@ declare module 'hapi' { type KbnMixinFunc = (kbnServer: KbnServer, server: Server, config: any) => Promise | void; export interface PluginsSetup { - usageCollection: UsageCollectionSetup; - telemetryCollectionManager: TelemetryCollectionManagerPluginSetup; - home: HomeServerPluginSetup; [key: string]: object; } diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index fa5d3cd85f430..09da0f462a3cc 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -49,6 +49,7 @@ import { Path } from 'history'; import { Plugin as Plugin_2 } from 'src/core/public'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public'; import { PopoverAnchorPosition } from '@elastic/eui'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { PublicUiSettingsParams } from 'src/core/server/types'; import React from 'react'; import * as React_2 from 'react'; diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/tsconfig.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/tsconfig.json +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/app_link_test/tsconfig.json b/test/plugin_functional/plugins/app_link_test/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/app_link_test/tsconfig.json +++ b/test/plugin_functional/plugins/app_link_test/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_a/tsconfig.json b/test/plugin_functional/plugins/core_plugin_a/tsconfig.json index ccbffc34bce4a..3d9d8ca9451d4 100644 --- a/test/plugin_functional/plugins/core_plugin_a/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_a/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_appleave/tsconfig.json b/test/plugin_functional/plugins/core_plugin_appleave/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/core_plugin_appleave/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_appleave/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_b/tsconfig.json b/test/plugin_functional/plugins/core_plugin_b/tsconfig.json index ccbffc34bce4a..3d9d8ca9451d4 100644 --- a/test/plugin_functional/plugins/core_plugin_b/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_b/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_chromeless/tsconfig.json b/test/plugin_functional/plugins/core_plugin_chromeless/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/core_plugin_chromeless/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_chromeless/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_route_timeouts/tsconfig.json b/test/plugin_functional/plugins/core_plugin_route_timeouts/tsconfig.json index 0e27246a49980..72793a327d97e 100644 --- a/test/plugin_functional/plugins/core_plugin_route_timeouts/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_route_timeouts/tsconfig.json @@ -8,5 +8,8 @@ "server/**/*.ts", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json b/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json index 433b041b9af3f..f9b0443e0a8bf 100644 --- a/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_provider_plugin/tsconfig.json b/test/plugin_functional/plugins/core_provider_plugin/tsconfig.json index 0aac2eb570987..eacd2f5e9aee3 100644 --- a/test/plugin_functional/plugins/core_provider_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/core_provider_plugin/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.ts", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/doc_views_plugin/tsconfig.json b/test/plugin_functional/plugins/doc_views_plugin/tsconfig.json index 433b041b9af3f..f9b0443e0a8bf 100644 --- a/test/plugin_functional/plugins/doc_views_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/doc_views_plugin/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/elasticsearch_client_plugin/tsconfig.json b/test/plugin_functional/plugins/elasticsearch_client_plugin/tsconfig.json index 0e27246a49980..72793a327d97e 100644 --- a/test/plugin_functional/plugins/elasticsearch_client_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/elasticsearch_client_plugin/tsconfig.json @@ -8,5 +8,8 @@ "server/**/*.ts", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/index_patterns/tsconfig.json b/test/plugin_functional/plugins/index_patterns/tsconfig.json index d5ccf7adddb2d..9d11a9850f151 100644 --- a/test/plugin_functional/plugins/index_patterns/tsconfig.json +++ b/test/plugin_functional/plugins/index_patterns/tsconfig.json @@ -10,5 +10,8 @@ "server/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/kbn_sample_panel_action/tsconfig.json b/test/plugin_functional/plugins/kbn_sample_panel_action/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/kbn_sample_panel_action/tsconfig.json +++ b/test/plugin_functional/plugins/kbn_sample_panel_action/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/kbn_top_nav/tsconfig.json b/test/plugin_functional/plugins/kbn_top_nav/tsconfig.json index ccbffc34bce4a..3d9d8ca9451d4 100644 --- a/test/plugin_functional/plugins/kbn_top_nav/tsconfig.json +++ b/test/plugin_functional/plugins/kbn_top_nav/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/tsconfig.json index 7e2f7c97eb058..b704274a58aa4 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/tsconfig.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/tsconfig.json @@ -15,5 +15,8 @@ "public/**/*.tsx", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/management_test_plugin/tsconfig.json b/test/plugin_functional/plugins/management_test_plugin/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/management_test_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/management_test_plugin/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/rendering_plugin/tsconfig.json b/test/plugin_functional/plugins/rendering_plugin/tsconfig.json index ccbffc34bce4a..3d9d8ca9451d4 100644 --- a/test/plugin_functional/plugins/rendering_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/rendering_plugin/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/ui_settings_plugin/tsconfig.json b/test/plugin_functional/plugins/ui_settings_plugin/tsconfig.json index 33b2d6c0f64ad..05b1c2c11da03 100644 --- a/test/plugin_functional/plugins/ui_settings_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/ui_settings_plugin/tsconfig.json @@ -8,5 +8,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/tsconfig.json b/test/tsconfig.json index 325db48978022..6e846690d54d9 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -16,5 +16,8 @@ "exclude": [ "plugin_functional/plugins/**/*", "interpreter_functional/plugins/**/*" + ], + "references": [ + { "path": "../src/core/tsconfig.json" } ] } diff --git a/tsconfig.json b/tsconfig.json index 21a817213c62f..11838627c5319 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "./tsconfig.base.json", "compilerOptions": { - "tsBuildInfoFile": "./build/tsbuildinfo/kibana", + "tsBuildInfoFile": "./build/tsbuildinfo/kibana" }, "include": [ "kibana.d.ts", @@ -11,7 +11,8 @@ ], "exclude": [ "src/**/__fixtures__/**/*", - "src/test_utils/**/*" + "src/test_utils/**/*", + "src/core/**/*" // In the build we actually exclude **/public/**/* from this config so that // we can run the TSC on both this and the .browser version of this config // file, but if we did it during development IDEs would not be able to find @@ -19,6 +20,7 @@ // "src/**/public/**/*" ], "references": [ - { "path": "./src/test_utils/tsconfig.json" } + { "path": "./src/test_utils/tsconfig.json" }, + { "path": "./src/core/tsconfig.json" } ] } diff --git a/tsconfig.refs.json b/tsconfig.refs.json index 0e4cc1bd32da3..66282687f633b 100644 --- a/tsconfig.refs.json +++ b/tsconfig.refs.json @@ -1,6 +1,7 @@ { "include": [], "references": [ - { "path": "./src/test_utils" } + { "path": "./src/test_utils" }, + { "path": "./src/core" }, ] } diff --git a/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json b/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json index cae75bb81c723..9f4f010c20fec 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json +++ b/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../src/core/tsconfig.json" } + ] } diff --git a/x-pack/package.json b/x-pack/package.json index 1e2fa4d7ee550..3e1e1173be2d7 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -95,7 +95,6 @@ "@types/jsdom": "^16.2.3", "@types/json-stable-stringify": "^1.0.32", "@types/jsonwebtoken": "^7.2.8", - "@types/lodash": "^4.14.159", "@types/mapbox-gl": "^1.9.1", "@types/memoize-one": "^4.1.0", "@types/mime": "^2.0.1", @@ -338,7 +337,7 @@ "js-yaml": "3.13.1", "json-stable-stringify": "^1.0.1", "jsonwebtoken": "^8.5.1", - "lodash": "^4.17.15", + "lodash": "^4.17.20", "markdown-it": "^10.0.0", "mime": "^2.4.4", "moment": "^2.24.0", diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index d0e2ea952e108..e8af79b9e84e0 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -14,5 +14,8 @@ ], "exclude": [ "../typings/jest.d.ts" + ], + "references": [ + { "path": "../../src/core/tsconfig.json" } ] } diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index b5080f83f2eda..38851653898a8 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -35,5 +35,8 @@ }, // overhead is too significant "incremental": false, - } + }, + "references": [ + { "path": "../src/core/tsconfig.json" } + ] } From 1eb44e18132fdd6ebebde4bca795af41c7c94bc3 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Tue, 15 Sep 2020 06:48:58 -0400 Subject: [PATCH 17/26] Allow passwords to be visible on security screens (#77394) --- .../account_management_page.test.tsx | 4 ++-- .../__snapshots__/login_form.test.tsx.snap | 1 + .../login/components/login_form/login_form.tsx | 1 + .../change_password_form.test.tsx | 8 ++++---- .../change_password_form/change_password_form.tsx | 14 +++++++------- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/security/public/account_management/account_management_page.test.tsx b/x-pack/plugins/security/public/account_management/account_management_page.test.tsx index e58d8e8421547..b677f6a1fe8bb 100644 --- a/x-pack/plugins/security/public/account_management/account_management_page.test.tsx +++ b/x-pack/plugins/security/public/account_management/account_management_page.test.tsx @@ -115,8 +115,8 @@ describe('', () => { wrapper.update(); }); - expect(wrapper.find('EuiFieldText[data-test-subj="currentPassword"]')).toHaveLength(1); - expect(wrapper.find('EuiFieldText[data-test-subj="newPassword"]')).toHaveLength(1); + expect(wrapper.find('EuiFieldPassword[data-test-subj="currentPassword"]')).toHaveLength(1); + expect(wrapper.find('EuiFieldPassword[data-test-subj="newPassword"]')).toHaveLength(1); }); it(`does not display change password form for users in the saml realm`, async () => { diff --git a/x-pack/plugins/security/public/authentication/login/components/login_form/__snapshots__/login_form.test.tsx.snap b/x-pack/plugins/security/public/authentication/login/components/login_form/__snapshots__/login_form.test.tsx.snap index 08f8034538ac3..99780542b97f4 100644 --- a/x-pack/plugins/security/public/authentication/login/components/login_form/__snapshots__/login_form.test.tsx.snap +++ b/x-pack/plugins/security/public/authentication/login/components/login_form/__snapshots__/login_form.test.tsx.snap @@ -166,6 +166,7 @@ exports[`LoginForm renders as expected 1`] = ` isLoading={false} name="password" onChange={[Function]} + type="dual" value="" /> diff --git a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx index a929b50fa1ffa..901d43adb659d 100644 --- a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx +++ b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx @@ -221,6 +221,7 @@ export class LoginForm extends Component { id="password" name="password" data-test-subj="loginPassword" + type={'dual'} value={this.state.password} onChange={this.onPasswordChange} disabled={!this.isLoadingState(LoadingStateType.None)} diff --git a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx index d41a05e00e53c..43eb32853cf63 100644 --- a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx +++ b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx @@ -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 { EuiFieldText } from '@elastic/eui'; +import { EuiFieldPassword } from '@elastic/eui'; import { ReactWrapper } from 'enzyme'; import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; @@ -14,15 +14,15 @@ import { coreMock } from '../../../../../../../../src/core/public/mocks'; import { userAPIClientMock } from '../../index.mock'; function getCurrentPasswordField(wrapper: ReactWrapper) { - return wrapper.find(EuiFieldText).filter('[data-test-subj="currentPassword"]'); + return wrapper.find(EuiFieldPassword).filter('[data-test-subj="currentPassword"]'); } function getNewPasswordField(wrapper: ReactWrapper) { - return wrapper.find(EuiFieldText).filter('[data-test-subj="newPassword"]'); + return wrapper.find(EuiFieldPassword).filter('[data-test-subj="newPassword"]'); } function getConfirmPasswordField(wrapper: ReactWrapper) { - return wrapper.find(EuiFieldText).filter('[data-test-subj="confirmNewPassword"]'); + return wrapper.find(EuiFieldPassword).filter('[data-test-subj="confirmNewPassword"]'); } describe('', () => { diff --git a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx index 296a8f6c8693f..5d889abdf46ce 100644 --- a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx +++ b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx @@ -6,7 +6,7 @@ import { EuiButton, EuiButtonEmpty, - EuiFieldText, + EuiFieldPassword, EuiFlexGroup, EuiFlexItem, EuiForm, @@ -72,10 +72,10 @@ export class ChangePasswordForm extends Component { /> } > - { /> } > - { /> } > - Date: Tue, 15 Sep 2020 19:14:39 +0800 Subject: [PATCH 18/26] [APM] update index pattern (#77452) --- src/plugins/apm_oss/server/tutorial/index_pattern.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/apm_oss/server/tutorial/index_pattern.json b/src/plugins/apm_oss/server/tutorial/index_pattern.json index 1d061f9e11e61..bb42b223c85ed 100644 --- a/src/plugins/apm_oss/server/tutorial/index_pattern.json +++ b/src/plugins/apm_oss/server/tutorial/index_pattern.json @@ -1,11 +1,11 @@ { "attributes": { - "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", - "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.url\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.author\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"child.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.histogram\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", + "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.limit.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.usage.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.stats.inactive_file.bytes\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", + "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.url\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.author\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.limit.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.usage.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.stats.inactive_file.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"child.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.cls\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.fid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.tbt\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.histogram\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"metricset.period\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", "sourceFilters": "[{\"value\":\"sourcemap.sourcemap\"}]", "timeFieldName": "@timestamp" }, "id": "apm-*", "type": "index-pattern", "version": "1" -} \ No newline at end of file +} From ba4d4a9fc27011ceb637f444c8cb987b91dbd903 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Tue, 15 Sep 2020 14:08:30 +0200 Subject: [PATCH 19/26] [docs] High-level Routing, Navigation and URL overview (#76888) --- .../images/state_inside_the_link.png | Bin 0 -> 165374 bytes docs/developer/best-practices/index.asciidoc | 10 + .../best-practices/navigation.asciidoc | 226 ++++++++++++++++++ src/plugins/kibana_react/README.md | 73 +++--- .../common/state_containers/README.md | 2 + .../kibana_utils/docs/state_sync/README.md | 16 +- .../kibana_utils/public/state_sync/README.md | 3 + 7 files changed, 283 insertions(+), 47 deletions(-) create mode 100644 docs/developer/best-practices/images/state_inside_the_link.png create mode 100644 docs/developer/best-practices/navigation.asciidoc create mode 100644 src/plugins/kibana_utils/common/state_containers/README.md create mode 100644 src/plugins/kibana_utils/public/state_sync/README.md diff --git a/docs/developer/best-practices/images/state_inside_the_link.png b/docs/developer/best-practices/images/state_inside_the_link.png new file mode 100644 index 0000000000000000000000000000000000000000..833478ccbda6875ceb33c3af92e2019853900402 GIT binary patch literal 165374 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
      `k_ycci);Unl>XP%U#K)hIK3 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 to get an idea of available tools and common approaches for handling routing and browser navigation. + [discrete] === Testing & stability @@ -131,6 +139,8 @@ Review: * <> * <> +include::navigation.asciidoc[leveloffset=+1] + include::stability.asciidoc[leveloffset=+1] include::security.asciidoc[leveloffset=+1] diff --git a/docs/developer/best-practices/navigation.asciidoc b/docs/developer/best-practices/navigation.asciidoc new file mode 100644 index 0000000000000..d01f2c2aa0f95 --- /dev/null +++ b/docs/developer/best-practices/navigation.asciidoc @@ -0,0 +1,226 @@ +[[kibana-navigation]] +== Routing, Navigation and URL + +The {kib} platform provides a set of tools to help developers build consistent experience around routing and browser navigation. +Some of that tooling is inside `core`, some is available as part of various plugins. + +The purpose of this guide is to give a high-level overview of available tools and to explain common approaches for handling routing and browser navigation. + +This guide covers following topics: + +* <> +* <> +* <> +* <> +* <> +* <> + +[[deep-linking]] +=== Deep-linking into {kib} apps + +Assuming you want to link from your app to *Discover*. When building such URL there are two things to consider: + +1. Prepending a proper `basePath`. +2. Specifying *Discover* state. + +==== Prepending a proper `basePath` + +To prepend {kib}'s `basePath` use {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.ibasepath.prepend.md[core.http.basePath.prepend] helper: + +[source,typescript jsx] +---- +const discoverUrl = core.http.basePath.prepend(`/discover`); + +console.log(discoverUrl); // http://localhost:5601/bpr/s/space/app/discover +---- + +==== Specifying state + +**Consider a {kib} app URL a part of app's plugin contract:** + +. Avoid hardcoding other app's URL in your app's code. +. Avoid generating other app's state and serializing it into URL query params. + +[source,typescript jsx] +---- +// Avoid relying on other app's state structure in your app's code: +const discoverUrlWithSomeState = core.http.basePath.prepend(`/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2020-09-10T11:39:50.203Z',to:'2020-09-10T11:40:20.249Z'))&_a=(columns:!(_source),filters:!(),index:'90943e30-9a47-11e8-b64d-95841ca0b247',interval:auto,query:(language:kuery,query:''),sort:!())`); +---- + +Instead, each app should expose {kib-repo}tree/{branch}/src/plugins/share/public/url_generators/README.md[a URL generator]. +Other apps should use those URL generators for creating URLs. + +[source,typescript jsx] +---- +// Properly generated URL to *Discover* app. Generator code is owned by *Discover* app and available on *Discover*'s plugin contract. +const discoverUrl = discoverUrlGenerator.createUrl({filters, timeRange}); +---- + +To get a better idea, take a look at *Discover* URL generator {kib-repo}tree/{branch}/src/plugins/discover/public/url_generator.ts[implementation]. +It allows specifying various **Discover** app state pieces like: index pattern, filters, query, time range and more. + +There are two ways to access other's app URL generator in your code: + +1. From a plugin contract of a destination app *(preferred)*. +2. Using URL generator service instance on `share` plugin contract (in case an explicit plugin dependency is not possible). + +In case you want other apps to link to your app, then you should create a URL generator and expose it on your plugin's contract. + + +[[navigating-between-kibana-apps]] +=== Navigating between {kib} apps + +{kib} is a single page application and there is a set of simple rules developers should follow +to make sure there is no page reload when navigating from one place in {kib} to another. + +For example, navigation using native browser APIs would cause a full page reload. + +[source,js] +---- +const urlToADashboard = core.http.basePath.prepend(`/dashboard/my-dashboard`); + +// this would cause a full page reload: +window.location.href = urlToADashboard; +---- + +To navigate between different {kib} apps without a page reload there are APIs in `core`: + +* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetoapp.md[core.application.navigateToApp] +* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md[core.application.navigateToUrl] + +*Rendering a link to a different {kib} app on its own would also cause a full page reload:* + +[source,typescript jsx] +---- +const myLink = () => + Go to Dashboard; +---- + +A workaround could be to handle a click, prevent browser navigation and use `core.application.navigateToApp` API: + +[source,typescript jsx] +---- +const MySPALink = () => + { + e.preventDefault(); + core.application.navigateToApp('dashboard', { path: '/my-dashboard' }); + }} + > + Go to Dashboard + ; +---- + +As it would be too much boilerplate to do this for each {kib} link in your app, there is a handy wrapper that helps with it: +{kib-repo}tree/{branch}/src/plugins/kibana_react/public/app_links/redirect_app_link.tsx#L49[RedirectAppLinks]. + +[source,typescript jsx] +---- +const MyApp = () => + + {/*...*/} + {/* navigations using this link will happen in SPA friendly way */} + Go to Dashboard + {/*...*/} + +---- + +[[routing]] +=== Setting up internal app routing + +It is very common for {kib} apps to use React and React Router. +Common rules to follow in this scenario: + +* Set up `BrowserRouter` and not `HashRouter`. +* *Initialize your router with `history` instance provided by the `core`.* + +This is required to make sure `core` is aware of navigations triggered inside your app, so it could act accordingly when needed. + +* `Core`'s {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] instance. +* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.appmountparameters.history.md[Example usage] +* {kib-repo}tree/{branch}/test/plugin_functional/plugins/core_plugin_a/public/application.tsx#L120[Example plugin] + +Relative links will be resolved relative to your app's route (e.g.: `http://localhost5601/app/{your-app-id}`) +and setting up internal links in your app in SPA friendly way would look something like: + +[source,typescript jsx] +---- +import {Link} from 'react-router-dom'; + +const MyInternalLink = () => +---- + +[[history-and-location]] +=== Using history and browser location + +Try to avoid using `window.location` and `window.history` directly. + +Instead, consider using {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] +instance provided by `core`. + +* This way `core` will know about location changes triggered within your app, and it would act accordingly. +* Some plugins are listening to location changes. Triggering location change manually could lead to unpredictable and hard-to-catch bugs. + +Common use-case for using +`core`'s {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] directly: + +* Reading/writing query params or hash. +* Imperatively triggering internal navigations within your app. +* Listening to browser location changes. + + +[[state-sync]] +=== Syncing state with URL + +Historically {kib} apps store _a lot_ of application state in the URL. +The most common pattern that {kib} apps follow today is storing state in `_a` and `_g` query params in https://github.com/w33ble/rison-node#readme[rison] format. +[[query-params]] +Those query params follow the convention: + +* `_g` (*global*) - global UI state that should be shared and synced across multiple apps. common example from Analyze group apps: time range, refresh interval, *pinned* filters. +* `_a` (*application*) - UI state scoped to current app. + +NOTE: After migrating to KP platform we got navigations without page reloads. Since then there is no real need to follow `_g` and `_a` separation anymore. It's up you to decide if you want to follow this pattern or if you prefer a single query param or something else. The need for this separation earlier is explained in <>. + +There are utils to help you to implement such kind of state syncing. + +**When you should consider using state syncing utils:** + +* You want to sync your application state with URL in similar manner Analyze group applications do. +* You want to follow platform's <> out of the box. +* You want to support `state:storeInSessionStore` escape hatch for URL overflowing out of the box. +* You should also consider using them if you'd like to serialize state to different (not `rison`) format. Utils are composable, and you can implement your own `storage`. +* In case you want to sync part of your state with URL, but other part of it with browser storage. + +**When you shouldn't use state syncing utils:** + +* Adding a query param flag or simple key/value to the URL. + +Follow {kib-repo}tree/{branch}/src/plugins/kibana_utils/docs/state_sync#state-syncing-utilities[these] docs to learn more. + + +[[preserve-state]] +=== Preserving state between navigations + +Consider the scenario: + +1. You are in *Dashboard* app looking at a dashboard with some filters applied; +2. Navigate to *Discover* using in-app navigation; +3. Change the time filter' +4. Navigate to *Dashboard* using in-app navigation. + +You'd notice that you were navigated to *Dashboard* app with the *same state* that you left it with, +except that the time filter has changed to the one you applied on *Discover* app. + +Historically {kib} Analyze groups apps achieve that behavior relying on state in the URL. +If you'd have a closer look on a link in the navigation, +you'd notice that state is stored inside that link, and it also gets updated whenever relevant state changes happen: + +[role="screenshot"] +image:images/state_inside_the_link.png[State is stored inside the navigation link] + +This is where <> into `_a` and `_g` query params comes into play. What is considered a *global* state gets constantly updated in those navigation links. In the example above it was a time filter. +This is backed by {kib-repo}tree/{branch}/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.ts#L57[KbnUrlTracker] util. You can use it to achieve similar behavior. + +NOTE: After migrating to KP navigation works without page reloads and all plugins are loaded simultaneously. +Hence, likely there are simpler ways to preserve state of your application, unless you want to do it through URL. diff --git a/src/plugins/kibana_react/README.md b/src/plugins/kibana_react/README.md index 3389af9f1800b..adbdb628ea9dd 100644 --- a/src/plugins/kibana_react/README.md +++ b/src/plugins/kibana_react/README.md @@ -2,7 +2,6 @@ Tools for building React applications in Kibana. - ## Context You can create React context that holds Core or plugin services that your plugin depends on. @@ -51,7 +50,6 @@ import { KibanaContextProvider } from 'kibana-react'; ``` - ## Accessing context Using `useKibana` hook. @@ -61,11 +59,7 @@ import { useKibana } from 'kibana-react'; const Demo = () => { const kibana = useKibana(); - return ( -
      - {kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'} -
      - ); + return
      {kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'}
      ; }; ``` @@ -75,11 +69,7 @@ Using `withKibana()` higher order component. import { withKibana } from 'kibana-react'; const Demo = ({ kibana }) => { - return ( -
      - {kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'} -
      - ); + return
      {kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'}
      ; }; export default withKibana(Demo); @@ -92,21 +82,17 @@ import { UseKibana } from 'kibana-react'; const Demo = () => { return ( - {kibana => -
      - {kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'} -
      - }
      + + {(kibana) =>
      {kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'}
      } +
      ); }; ``` - ## `uiSettings` service Wrappers around Core's `uiSettings` service. - ### `useUiSetting` hook `useUiSetting` synchronously returns the latest setting from `CoreStart['uiSettings']` service. @@ -116,11 +102,7 @@ import { useUiSetting } from 'kibana-react'; const Demo = () => { const darkMode = useUiSetting('theme:darkMode'); - return ( -
      - {darkMode ? 'dark' : 'light'} -
      - ); + return
      {darkMode ? 'dark' : 'light'}
      ; }; ``` @@ -130,7 +112,6 @@ const Demo = () => { useUiSetting(key: string, defaultValue: T): T; ``` - ### `useUiSetting$` hook `useUiSetting$` synchronously returns the latest setting from `CoreStart['uiSettings']` service and @@ -141,11 +122,7 @@ import { useUiSetting$ } from 'kibana-react'; const Demo = () => { const [darkMode] = useUiSetting$('theme:darkMode'); - return ( -
      - {darkMode ? 'dark' : 'light'} -
      - ); + return
      {darkMode ? 'dark' : 'light'}
      ; }; ``` @@ -155,7 +132,6 @@ const Demo = () => { useUiSetting$(key: string, defaultValue: T): [T, (newValue: T) => void]; ``` - ## `overlays` service Wrapper around Core's `overlays` service, allows you to display React modals and flyouts @@ -166,13 +142,11 @@ import { createKibanaReactContext } from 'kibana-react'; class MyPlugin { start(core) { - const { value: { overlays } } = createKibanaReactContext(core); + const { + value: { overlays }, + } = createKibanaReactContext(core); - overlays.openModal( -
      - Hello world! -
      - ); + overlays.openModal(
      Hello world!
      ); } } ``` @@ -186,16 +160,11 @@ You can access `overlays` service through React context. const Demo = () => { const { overlays } = useKibana(); useEffect(() => { - overlays.openModal( -
      - Oooops! {errorMessage} -
      - ); + overlays.openModal(
      Oooops! {errorMessage}
      ); }, [errorMessage]); }; ``` - ## `notifications` service Wrapper around Core's `notifications` service, allows you to render React elements @@ -206,11 +175,13 @@ import { createKibanaReactContext } from 'kibana-react'; class MyPlugin { start(core) { - const { value: { notifications } } = createKibanaReactContext(core); + const { + value: { notifications }, + } = createKibanaReactContext(core); notifications.toasts.show({ title:
      Hello
      , - body:
      world!
      + body:
      world!
      , }); } } @@ -234,3 +205,15 @@ const Demo = () => { }, [errorMessage]); }; ``` + +## RedirectAppLinks + +Utility component that will intercept click events on children anchor (``) elements to call +`application.navigateToUrl` with the link's href. This will trigger SPA friendly navigation +when the link points to a valid Kibana app. + +```tsx + + Go to another-app + +``` diff --git a/src/plugins/kibana_utils/common/state_containers/README.md b/src/plugins/kibana_utils/common/state_containers/README.md new file mode 100644 index 0000000000000..c623e8b306438 --- /dev/null +++ b/src/plugins/kibana_utils/common/state_containers/README.md @@ -0,0 +1,2 @@ +* [docs](../../docs/state_containers) +* [api reference](https://github.com/elastic/kibana/tree/master/src/plugins/kibana_utils/docs/state_containers) \ No newline at end of file diff --git a/src/plugins/kibana_utils/docs/state_sync/README.md b/src/plugins/kibana_utils/docs/state_sync/README.md index c84bf7f236330..6b4eb0cb1749b 100644 --- a/src/plugins/kibana_utils/docs/state_sync/README.md +++ b/src/plugins/kibana_utils/docs/state_sync/README.md @@ -3,6 +3,18 @@ State syncing utilities are a set of helpers for syncing your application state with URL or browser storage. +**When you should consider using state syncing utils:** + +- You want to sync your application state with URL in similar manner analyze applications do that. +- You want to follow platform's <> out of the box. +- You want to support `state:storeInSessionStore` escape hatch for URL overflowing out of the box. +- You should also consider using them if you'd like to serialize state to different (not `rison`) format. Utils are composable, and you can implement your own `storage`. +- In case you want to sync part of your state with URL, but other part of it with browser storage. + +**When you shouldn't look into using state syncing utils:** + +- Adding a query param flag or simple key/value to URL + They are designed to work together with [state containers](../state_containers). But state containers are not required. State syncing utilities include: @@ -42,9 +54,9 @@ stateContainer.set({ count: 2 }); stop(); ``` -## Demos Plugins +## Demo Plugins -See demos plugins [here](../../../../../examples/state_containers_examples). +See demo plugins [here](../../../../../examples/state_containers_examples). To run them, start kibana with `--run-examples` flag. diff --git a/src/plugins/kibana_utils/public/state_sync/README.md b/src/plugins/kibana_utils/public/state_sync/README.md new file mode 100644 index 0000000000000..eb5f6e60958fc --- /dev/null +++ b/src/plugins/kibana_utils/public/state_sync/README.md @@ -0,0 +1,3 @@ +- [docs](../../docs/state_sync) +- [demo plugins](../../../../../examples/state_containers_examples): run Kibana with `--run-examples` flag. +- [api reference](https://github.com/elastic/kibana/tree/master/src/plugins/kibana_utils/docs/state_sync) From d190a2a2e3df56154eecb37e0fc8d05f62cbfb87 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Tue, 15 Sep 2020 14:42:11 +0200 Subject: [PATCH 20/26] [APM] Use apm_8.0.0 archive where possible (#77450) --- .../tests/observability_overview/has_data.ts | 6 +- .../observability_overview.ts | 73 +- .../basic/tests/service_maps/service_maps.ts | 14 +- .../basic/tests/services/agent_name.ts | 1 + .../basic/tests/services/top_services.ts | 4 +- .../basic/tests/services/transaction_types.ts | 16 +- .../tests/settings/agent_configuration.ts | 56 +- .../basic/tests/settings/custom_link.ts | 6 +- .../traces/__snapshots__/top_traces.snap | 575 +- .../basic/tests/traces/top_traces.ts | 53 +- .../avg_duration_by_browser.snap | 1323 +-- .../__snapshots__/breakdown.snap | 1918 ++++- .../__snapshots__/top_transaction_groups.snap | 149 +- .../__snapshots__/transaction_charts.snap | 7226 ++++------------- .../avg_duration_by_browser.ts | 27 +- .../tests/transaction_groups/breakdown.ts | 64 +- .../tests/transaction_groups/error_rate.ts | 32 +- .../top_transaction_groups.ts | 34 +- .../transaction_groups/transaction_charts.ts | 55 +- .../common/match_snapshot.ts | 17 +- .../__snapshots__/service_maps.snap | 1393 ++++ .../trial/tests/service_maps/service_maps.ts | 347 +- 22 files changed, 5922 insertions(+), 7467 deletions(-) create mode 100644 x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap diff --git a/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts b/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts index 127721e8e2112..6d0d2d3042625 100644 --- a/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts +++ b/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts @@ -10,6 +10,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + describe('Has data', () => { describe('when data is not loaded', () => { it('returns false when there is no data', async () => { @@ -28,8 +30,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns true when there is at least one document on transaction, error or metrics indices', async () => { const response = await supertest.get('/api/apm/observability_overview/has_data'); diff --git a/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts b/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts index 96ac3c3a5e494..6153ddd46a5b4 100644 --- a/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts +++ b/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -11,9 +12,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:00:00.000Z'); - const end = encodeURIComponent('2020-06-29T10:00:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const bucketSize = '60s'; describe('Observability overview', () => { @@ -23,37 +27,58 @@ export default function ApiTest({ getService }: FtrProviderContext) { `/api/apm/observability_overview?start=${start}&end=${end}&bucketSize=${bucketSize}` ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "serviceCount": 0, - "transactionCoordinates": Array [], - } - `); + + expect(response.body.serviceCount).to.be(0); + expect(response.body.transactionCoordinates.length).to.be(0); }); }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns the service count and transaction coordinates', async () => { const response = await supertest.get( `/api/apm/observability_overview?start=${start}&end=${end}&bucketSize=${bucketSize}` ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "serviceCount": 3, - "transactionCoordinates": Array [ - Object { - "x": 1593413220000, - "y": 0.016666666666666666, - }, - Object { - "x": 1593413280000, - "y": 1.0458333333333334, - }, - ], - } + + expect(response.body.serviceCount).to.be.greaterThan(0); + expect(response.body.transactionCoordinates.length).to.be.greaterThan(0); + + expectSnapshot(response.body.serviceCount).toMatchInline(`7`); + + expectSnapshot(response.body.transactionCoordinates.length).toMatchInline(`60`); + + expectSnapshot( + response.body.transactionCoordinates + .slice(0, 5) + .map(({ x, y }: { x: number; y: number }) => ({ + x: new Date(x).toISOString(), + y, + })) + ).toMatchInline(` + Array [ + Object { + "x": "2020-09-10T06:00:00.000Z", + "y": 1.2166666666666666, + }, + Object { + "x": "2020-09-10T06:01:00.000Z", + "y": 0.5, + }, + Object { + "x": "2020-09-10T06:02:00.000Z", + "y": 1.0333333333333334, + }, + Object { + "x": "2020-09-10T06:03:00.000Z", + "y": 0.55, + }, + Object { + "x": "2020-09-10T06:04:00.000Z", + "y": 1.15, + }, + ] `); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts b/x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts index b0e503eb7d1eb..d729680154c1d 100644 --- a/x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts +++ b/x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts @@ -5,22 +5,28 @@ */ import expect from '@kbn/expect'; +import { expectSnapshot } from '../../../common/match_snapshot'; +import archives_metadata from '../../../common/archives_metadata'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; export default function serviceMapsApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); describe('Service Maps', () => { it('is only be available to users with Platinum license (or higher)', async () => { const response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); expect(response.status).to.be(403); - expect(response.body.message).to.be( - "In order to access Service Maps, you must be subscribed to an Elastic Platinum license. With it, you'll have the ability to visualize your entire application stack along with your APM data." + + expectSnapshot(response.body.message).toMatchInline( + `"In order to access Service Maps, you must be subscribed to an Elastic Platinum license. With it, you'll have the ability to visualize your entire application stack along with your APM data."` ); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts b/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts index a87d080e564a2..ee835fde680e0 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts +++ b/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts @@ -39,6 +39,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); + expect(response.body).to.eql({ agentName: 'nodejs' }); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/services/top_services.ts b/x-pack/test/apm_api_integration/basic/tests/services/top_services.ts index 116b2987db32a..c5027565fd6b9 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/top_services.ts +++ b/x-pack/test/apm_api_integration/basic/tests/services/top_services.ts @@ -33,7 +33,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expect(response.body).to.eql({ hasHistoricalData: false, hasLegacyData: false, items: [] }); + expect(response.body.hasHistoricalData).to.be(false); + expect(response.body.hasLegacyData).to.be(false); + expect(response.body.items.length).to.be(0); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts b/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts index a6c6bad21a8b7..1221ce0198d82 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts +++ b/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts @@ -5,6 +5,7 @@ */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -12,9 +13,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); describe('Transaction types', () => { describe('when data is not loaded ', () => { @@ -30,8 +34,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('handles empty state', async () => { const response = await supertest.get( @@ -39,11 +43,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); + expect(response.body.transactionTypes.length).to.be.greaterThan(0); + expectSnapshot(response.body).toMatchInline(` Object { "transactionTypes": Array [ - "request", "Worker", + "request", ], } `); diff --git a/x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts b/x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts index 27023d16f57ca..70ddf276ab35c 100644 --- a/x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts +++ b/x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts @@ -6,6 +6,7 @@ import expect from '@kbn/expect'; import { omit, orderBy } from 'lodash'; +import { expectSnapshot } from '../../../common/match_snapshot'; import { AgentConfigurationIntake } from '../../../../../plugins/apm/common/agent_configuration/configuration_types'; import { AgentConfigSearchParams } from '../../../../../plugins/apm/server/routes/settings/agent_configuration'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -16,6 +17,8 @@ export default function agentConfigurationTests({ getService }: FtrProviderConte const log = getService('log'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + function getServices() { return supertestRead .get(`/api/apm/settings/agent-configuration/services`) @@ -125,31 +128,46 @@ export default function agentConfigurationTests({ getService }: FtrProviderConte }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns all services', async () => { const { body } = await getServices(); - expect(body).to.eql([ - 'ALL_OPTION_VALUE', - 'client', - 'opbeans-dotnet', - 'opbeans-go', - 'opbeans-java', - 'opbeans-node', - 'opbeans-python', - 'opbeans-ruby', - 'opbeans-rum', - ]); + expectSnapshot(body).toMatchInline(` + Array [ + "ALL_OPTION_VALUE", + "opbeans-dotnet", + "opbeans-go", + "opbeans-java", + "opbeans-node", + "opbeans-python", + "opbeans-ruby", + "opbeans-rum", + ] + `); }); - it('returns the environments', async () => { + it('returns the environments, all unconfigured', async () => { const { body } = await getEnvironments('opbeans-node'); - expect(body).to.eql([ - { name: 'ALL_OPTION_VALUE', alreadyConfigured: false }, - { name: 'testing', alreadyConfigured: false }, - { name: 'production', alreadyConfigured: false }, - ]); + + expect(body.map((item: { name: string }) => item.name)).to.contain('ALL_OPTION_VALUE'); + + expect( + body.every((item: { alreadyConfigured: boolean }) => item.alreadyConfigured === false) + ).to.be(true); + + expectSnapshot(body).toMatchInline(` + Array [ + Object { + "alreadyConfigured": false, + "name": "ALL_OPTION_VALUE", + }, + Object { + "alreadyConfigured": false, + "name": "testing", + }, + ] + `); }); it('returns the agent names', async () => { diff --git a/x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts b/x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts index 2acc6522bf479..a1c647a854bf6 100644 --- a/x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts +++ b/x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts @@ -14,6 +14,8 @@ export default function customLinksTests({ getService }: FtrProviderContext) { const log = getService('log'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + function searchCustomLinks(filters?: any) { const path = URL.format({ pathname: `/api/apm/settings/custom_links`, @@ -142,8 +144,8 @@ export default function customLinksTests({ getService }: FtrProviderContext) { }); describe('transaction', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('fetches a transaction sample', async () => { const response = await supertestRead.get( diff --git a/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap b/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap index 5557e0828a338..2d382fa5fa4d3 100644 --- a/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap +++ b/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap @@ -3,301 +3,598 @@ exports[`Top traces when data is loaded returns the correct buckets 1`] = ` Array [ Object { - "averageResponseTime": 2577, + "averageResponseTime": 3853, "impact": 0, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /throw-error", + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#create", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.016666666666666666, }, Object { - "averageResponseTime": 3147, - "impact": 0.06552270160444405, + "averageResponseTime": 5420, + "impact": 0.0013411780236742999, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#orders", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.016666666666666666, }, Object { - "averageResponseTime": 3392.5, - "impact": 0.09374344413758617, + "averageResponseTime": 4135.5, + "impact": 0.0037813174911251156, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#order", + "service.name": "opbeans-node", + "transaction.name": "GET /api/types", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 4713.5, - "impact": 0.24559517890858723, + "averageResponseTime": 11058, + "impact": 0.006166680064182087, "key": Object { "service.name": "opbeans-java", - "transaction.name": "APIRestController#product", + "transaction.name": "APIRestController#products", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.016666666666666666, + }, + Object { + "averageResponseTime": 6014, + "impact": 0.0069968923698388, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "POST /api/orders", + }, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 4757, - "impact": 0.25059559560997896, + "averageResponseTime": 13540, + "impact": 0.00829099649989339, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.product", + }, + "transactionsPerMinute": 0.016666666666666666, + }, + Object { + "averageResponseTime": 8710, + "impact": 0.011611845722520248, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api/products/:id/customers", + "transaction.name": "GET /api/types/:id", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 6787, - "impact": 0.4839483750082622, + "averageResponseTime": 10157, + "impact": 0.014088788415891928, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#products", + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.product_type", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 4749.666666666667, - "impact": 0.5227447114845778, + "averageResponseTime": 6944.333333333333, + "impact": 0.014532994793867014, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/orders/:id", }, - "transactionsPerMinute": 0.75, + "transactionsPerMinute": 0.05, }, Object { - "averageResponseTime": 7624.5, - "impact": 0.5802207655235637, + "averageResponseTime": 8438.333333333334, + "impact": 0.018369089179385976, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/orders", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#customer", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.05, }, Object { - "averageResponseTime": 5098, - "impact": 0.582807187955318, + "averageResponseTime": 13202, + "impact": 0.019301152273056246, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/stats", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#customers", }, - "transactionsPerMinute": 0.75, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 8181, - "impact": 0.6441916136689552, + "averageResponseTime": 9311, + "impact": 0.020609806515684198, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api/types/:id", + "transaction.name": "GET /api/products/:id", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.05, }, Object { - "averageResponseTime": 20011, - "impact": 0.853921734857215, + "averageResponseTime": 14019, + "impact": 0.020699674858049102, "key": Object { "service.name": "opbeans-node", - "transaction.name": "POST /api", + "transaction.name": "GET /api/customers/:id", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 0.03333333333333333, + }, + Object { + "averageResponseTime": 28176, + "impact": 0.020817787536585832, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "POST opbeans.views.post_order", + }, + "transactionsPerMinute": 0.016666666666666666, }, Object { - "averageResponseTime": 6583, - "impact": 1.2172278724376455, + "averageResponseTime": 9298.75, + "impact": 0.02853705020124346, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/products", }, - "transactionsPerMinute": 1, + "transactionsPerMinute": 0.06666666666666667, }, Object { - "averageResponseTime": 33097, - "impact": 1.6060533780113861, + "averageResponseTime": 7441.6, + "impact": 0.028548176757917213, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/products/top", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#order", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 0.08333333333333333, }, Object { - "averageResponseTime": 4825, - "impact": 1.6450221426498186, + "averageResponseTime": 6260.166666666667, + "impact": 0.028850305566058266, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#topProducts", }, - "transactionsPerMinute": 1.75, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 35846, - "impact": 1.7640550505645587, + "averageResponseTime": 7656.2, + "impact": 0.029466545627989022, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /log-error", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#customerWhoBought", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 0.08333333333333333, + }, + Object { + "averageResponseTime": 7016.5, + "impact": 0.032734329734171834, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#show", + }, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 3742.153846153846, - "impact": 2.4998634943716573, + "averageResponseTime": 21102.5, + "impact": 0.03282505396551165, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.customer", + }, + "transactionsPerMinute": 0.03333333333333333, + }, + Object { + "averageResponseTime": 14443.333333333334, + "impact": 0.033787929062278454, "key": Object { "service.name": "opbeans-java", - "transaction.name": "APIRestController#customerWhoBought", + "transaction.name": "APIRestController#stats", }, - "transactionsPerMinute": 3.25, + "transactionsPerMinute": 0.05, }, Object { - "averageResponseTime": 3492.9285714285716, - "impact": 2.5144049360435208, + "averageResponseTime": 2828.0625, + "impact": 0.0354303800051189, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET static file", + "service.name": "opbeans-java", + "transaction.name": "ResourceHttpRequestHandler", + }, + "transactionsPerMinute": 0.26666666666666666, + }, + Object { + "averageResponseTime": 9920.8, + "impact": 0.03915777649082508, + "key": Object { + "service.name": "opbeans-java", + "transaction.name": "APIRestController#product", }, - "transactionsPerMinute": 3.5, + "transactionsPerMinute": 0.08333333333333333, }, Object { - "averageResponseTime": 26992.5, - "impact": 2.8066131947777255, + "averageResponseTime": 16860.333333333332, + "impact": 0.03999398001930612, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.orders", + }, + "transactionsPerMinute": 0.05, + }, + Object { + "averageResponseTime": 10264.8, + "impact": 0.04062990552765966, "key": Object { "service.name": "opbeans-node", + "transaction.name": "GET /api/products/top", + }, + "transactionsPerMinute": 0.08333333333333333, + }, + Object { + "averageResponseTime": 8818.833333333334, + "impact": 0.04198991310878184, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.order", + }, + "transactionsPerMinute": 0.1, + }, + Object { + "averageResponseTime": 4649.307692307692, + "impact": 0.04843304531185787, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/types/:id", + }, + "transactionsPerMinute": 0.21666666666666667, + }, + Object { + "averageResponseTime": 30425, + "impact": 0.048783103902593536, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.products", + }, + "transactionsPerMinute": 0.03333333333333333, + }, + Object { + "averageResponseTime": 4215.2, + "impact": 0.05081840788491484, + "key": Object { + "service.name": "opbeans-go", "transaction.name": "GET /api/types", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.25, }, Object { - "averageResponseTime": 13516.5, - "impact": 2.8112687551548836, + "averageResponseTime": 7333.777777777777, + "impact": 0.053194355679247865, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/products/:id", + "service.name": "opbeans-ruby", + "transaction.name": "Api::StatsController#index", + }, + "transactionsPerMinute": 0.15, + }, + Object { + "averageResponseTime": 7562.111111111111, + "impact": 0.05495320752267524, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::TypesController#index", + }, + "transactionsPerMinute": 0.15, + }, + Object { + "averageResponseTime": 5459.307692307692, + "impact": 0.057445556217595194, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/products", + }, + "transactionsPerMinute": 0.21666666666666667, + }, + Object { + "averageResponseTime": 7248.5, + "impact": 0.058741372125599586, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::TypesController#show", + }, + "transactionsPerMinute": 0.16666666666666666, + }, + Object { + "averageResponseTime": 87771, + "impact": 0.07182449099597951, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.top_products", + }, + "transactionsPerMinute": 0.016666666666666666, + }, + Object { + "averageResponseTime": 6161.2, + "impact": 0.0758018070623576, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/orders/:id", + }, + "transactionsPerMinute": 0.25, + }, + Object { + "averageResponseTime": 19260.8, + "impact": 0.07912779161883388, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.product_types", + }, + "transactionsPerMinute": 0.08333333333333333, + }, + Object { + "averageResponseTime": 10632.4, + "impact": 0.08770379914737025, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::ProductsController#show", + }, + "transactionsPerMinute": 0.16666666666666666, + }, + Object { + "averageResponseTime": 54309.5, + "impact": 0.08966806434477453, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.customers", }, - "transactionsPerMinute": 1, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 20092, - "impact": 3.168195050736987, + "averageResponseTime": 5046.695652173913, + "impact": 0.09604871665268258, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/customers/:id", + }, + "transactionsPerMinute": 0.38333333333333336, + }, + Object { + "averageResponseTime": 20346, + "impact": 0.10118576228005537, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api/customers", + "transaction.name": "GET /api/stats", }, - "transactionsPerMinute": 0.75, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 15535, - "impact": 3.275330415465657, + "averageResponseTime": 18472.85714285714, + "impact": 0.10737726312450965, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#stats", + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.stats", }, - "transactionsPerMinute": 1, + "transactionsPerMinute": 0.11666666666666667, }, Object { - "averageResponseTime": 32667.5, - "impact": 3.458966408120217, + "averageResponseTime": 32662, + "impact": 0.10852244257293098, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /log-message", + "transaction.name": "GET /api/customers", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.06666666666666667, }, Object { - "averageResponseTime": 16690.75, - "impact": 3.541042213287889, + "averageResponseTime": 13975.7, + "impact": 0.11631873524532996, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#customers", + "service.name": "opbeans-ruby", + "transaction.name": "Api::ProductsController#index", }, - "transactionsPerMinute": 1, + "transactionsPerMinute": 0.16666666666666666, }, Object { - "averageResponseTime": 33500, - "impact": 3.5546640380951287, + "averageResponseTime": 13373.615384615385, + "impact": 0.14550454928955053, "key": Object { - "service.name": "client", - "transaction.name": "/customers", + "service.name": "opbeans-go", + "transaction.name": "GET /api/orders", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.21666666666666667, }, Object { - "averageResponseTime": 77000, - "impact": 4.129424578484989, + "averageResponseTime": 19675.333333333332, + "impact": 0.14826136767771575, "key": Object { - "service.name": "client", - "transaction.name": "/products", + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#index", + }, + "transactionsPerMinute": 0.15, + }, + Object { + "averageResponseTime": 12946.266666666666, + "impact": 0.1629107633721697, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::CustomersController#show", }, "transactionsPerMinute": 0.25, }, Object { - "averageResponseTime": 19370.6, - "impact": 5.270496679320978, + "averageResponseTime": 16506.666666666668, + "impact": 0.16623674792864598, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#customer", + "service.name": "opbeans-go", + "transaction.name": "GET /api/products/:id/customers", }, - "transactionsPerMinute": 1.25, + "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 81500, - "impact": 9.072365225837785, + "averageResponseTime": 17101.5, + "impact": 0.1723460834315095, "key": Object { - "service.name": "client", - "transaction.name": "/orders", + "service.name": "opbeans-ruby", + "transaction.name": "Api::ProductsController#top", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 14419.42857142857, - "impact": 11.30657439844125, + "averageResponseTime": 15871.3125, + "impact": 0.21404756195574876, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "ResourceHttpRequestHandler", + "service.name": "opbeans-go", + "transaction.name": "GET /api/stats", }, - "transactionsPerMinute": 3.5, + "transactionsPerMinute": 0.26666666666666666, }, Object { - "averageResponseTime": 270684, - "impact": 15.261616628971955, + "averageResponseTime": 11237.785714285714, + "impact": 0.26601457284498453, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::CustomersController#index", + }, + "transactionsPerMinute": 0.4666666666666667, + }, + Object { + "averageResponseTime": 15403.40909090909, + "impact": 0.28674163615023057, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/products/:id", + }, + "transactionsPerMinute": 0.36666666666666664, + }, + Object { + "averageResponseTime": 101902.16666666667, + "impact": 0.5200039055925703, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.product_customers", + }, + "transactionsPerMinute": 0.1, + }, + Object { + "averageResponseTime": 32236.133333333335, + "impact": 0.82441879318559, "key": Object { "service.name": "opbeans-node", - "transaction.name": "POST /api/orders", + "transaction.name": "GET /api", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 0.5, + }, + Object { + "averageResponseTime": 94012.11111111111, + "impact": 1.445052989113503, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/customers", + }, + "transactionsPerMinute": 0.3, + }, + Object { + "averageResponseTime": 32260.39837398374, + "impact": 3.3928945329783606, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Rack", + }, + "transactionsPerMinute": 2.05, + }, + Object { + "averageResponseTime": 34207.61666666667, + "impact": 3.5100528953080716, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "opbeans.tasks.sync_orders", + }, + "transactionsPerMinute": 2, + }, + Object { + "averageResponseTime": 638040, + "impact": 13.648987298470669, + "key": Object { + "service.name": "opbeans-rum", + "transaction.name": "/customers", + }, + "transactionsPerMinute": 0.4166666666666667, }, Object { - "averageResponseTime": 36010.53846153846, - "impact": 26.61043592713186, + "averageResponseTime": 2061418.6666666667, + "impact": 15.875811844928256, "key": Object { "service.name": "opbeans-java", "transaction.name": "DispatcherServlet#doGet", }, - "transactionsPerMinute": 3.25, + "transactionsPerMinute": 0.15, }, Object { - "averageResponseTime": 208000, - "impact": 35.56882613781033, + "averageResponseTime": 847846.1538461539, + "impact": 18.8639188225597, "key": Object { - "service.name": "client", + "service.name": "opbeans-rum", + "transaction.name": "/orders", + }, + "transactionsPerMinute": 0.43333333333333335, + }, + Object { + "averageResponseTime": 1091031.25, + "impact": 29.87835404059707, + "key": Object { + "service.name": "opbeans-rum", + "transaction.name": "/products", + }, + "transactionsPerMinute": 0.5333333333333333, + }, + Object { + "averageResponseTime": 924980.3921568628, + "impact": 40.37240876189292, + "key": Object { + "service.name": "opbeans-rum", "transaction.name": "/dashboard", }, - "transactionsPerMinute": 0.75, + "transactionsPerMinute": 0.85, }, Object { - "averageResponseTime": 49816.15625, - "impact": 91.32732325394932, + "averageResponseTime": 979844.2117647058, + "impact": 71.28092018746297, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api", + "transaction.name": "Process completed order", }, - "transactionsPerMinute": 8, + "transactionsPerMinute": 1.4166666666666667, }, Object { - "averageResponseTime": 1745009, - "impact": 100, + "averageResponseTime": 996808.380952381, + "impact": 71.66191574108551, "key": Object { "service.name": "opbeans-node", "transaction.name": "Process payment", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 1.4, + }, + Object { + "averageResponseTime": 1083442.5568181819, + "impact": 81.59967772014184, + "key": Object { + "service.name": "opbeans-node", + "transaction.name": "Update shipping status", + }, + "transactionsPerMinute": 1.4666666666666666, + }, + Object { + "averageResponseTime": 134550.32361111112, + "impact": 82.91200201469418, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "opbeans.tasks.update_stats", + }, + "transactionsPerMinute": 12, + }, + Object { + "averageResponseTime": 1600567.6301369863, + "impact": 100, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "opbeans.tasks.sync_customers", + }, + "transactionsPerMinute": 1.2166666666666666, }, ] `; diff --git a/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts b/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts index 2935fb8e2839a..da4bd0aa4f0d9 100644 --- a/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts +++ b/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts @@ -5,6 +5,7 @@ */ import expect from '@kbn/expect'; import { sortBy, omit } from 'lodash'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -12,9 +13,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const uiFilters = encodeURIComponent(JSON.stringify({})); describe('Top traces', () => { @@ -25,32 +29,27 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "bucketSize": 1000, - "isAggregationAccurate": true, - "items": Array [], - } - `); + expect(response.body.items.length).to.be(0); + expect(response.body.isAggregationAccurate).to.be(true); }); }); describe('when data is loaded', () => { let response: any; before(async () => { - await esArchiver.load('8.0.0'); + await esArchiver.load(archiveName); response = await supertest.get( `/api/apm/traces?start=${start}&end=${end}&uiFilters=${uiFilters}` ); }); - after(() => esArchiver.unload('8.0.0')); + after(() => esArchiver.unload(archiveName)); it('returns the correct status code', async () => { expect(response.status).to.be(200); }); it('returns the correct number of buckets', async () => { - expectSnapshot(response.body.items.length).toMatchInline(`33`); + expectSnapshot(response.body.items.length).toMatchInline(`66`); }); it('returns the correct buckets', async () => { @@ -68,49 +67,49 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(firstItem).toMatchInline(` Object { - "averageResponseTime": 2577, + "averageResponseTime": 3853, "impact": 0, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /throw-error", + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#create", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.016666666666666666, } `); expectSnapshot(lastItem).toMatchInline(` Object { - "averageResponseTime": 1745009, + "averageResponseTime": 1600567.6301369863, "impact": 100, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "Process payment", + "service.name": "opbeans-python", + "transaction.name": "opbeans.tasks.sync_customers", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 1.2166666666666666, } `); expectSnapshot(groups).toMatchInline(` Array [ Object { - "service.name": "opbeans-node", - "transaction.name": "GET /throw-error", + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#create", }, Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#orders", }, Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#order", + "service.name": "opbeans-node", + "transaction.name": "GET /api/types", }, Object { "service.name": "opbeans-java", - "transaction.name": "APIRestController#product", + "transaction.name": "APIRestController#products", }, Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/products/:id/customers", + "service.name": "opbeans-go", + "transaction.name": "POST /api/orders", }, ] `); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap index 326797919a095..37473ee008b3d 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap @@ -5,1469 +5,850 @@ Array [ Object { "data": Array [ Object { - "x": 1593413100000, + "x": 1599717600000, + "y": 999000, }, Object { - "x": 1593413101000, + "x": 1599717630000, + "y": 1111000, }, Object { - "x": 1593413102000, + "x": 1599717660000, + "y": 600000, }, Object { - "x": 1593413103000, + "x": 1599717690000, }, Object { - "x": 1593413104000, + "x": 1599717720000, }, Object { - "x": 1593413105000, + "x": 1599717750000, + "y": 1487000, }, Object { - "x": 1593413106000, + "x": 1599717780000, + "y": 312000, }, Object { - "x": 1593413107000, + "x": 1599717810000, }, Object { - "x": 1593413108000, + "x": 1599717840000, }, Object { - "x": 1593413109000, + "x": 1599717870000, + "y": 2073000, }, Object { - "x": 1593413110000, + "x": 1599717900000, + "y": 791333.3333333334, }, Object { - "x": 1593413111000, + "x": 1599717930000, + "y": 604000, }, Object { - "x": 1593413112000, + "x": 1599717960000, }, Object { - "x": 1593413113000, + "x": 1599717990000, + "y": 792000, }, Object { - "x": 1593413114000, + "x": 1599718020000, + "y": 596000, }, Object { - "x": 1593413115000, + "x": 1599718050000, + "y": 661000, }, Object { - "x": 1593413116000, + "x": 1599718080000, }, Object { - "x": 1593413117000, + "x": 1599718110000, + "y": 1016000, }, Object { - "x": 1593413118000, + "x": 1599718140000, + "y": 732000, }, Object { - "x": 1593413119000, + "x": 1599718170000, }, Object { - "x": 1593413120000, + "x": 1599718200000, }, Object { - "x": 1593413121000, + "x": 1599718230000, + "y": 1578000, }, Object { - "x": 1593413122000, + "x": 1599718260000, + "y": 450000, }, Object { - "x": 1593413123000, + "x": 1599718290000, + "y": 911000, }, Object { - "x": 1593413124000, + "x": 1599718320000, }, Object { - "x": 1593413125000, + "x": 1599718350000, + "y": 1599000, }, Object { - "x": 1593413126000, + "x": 1599718380000, + "y": 661000, }, Object { - "x": 1593413127000, + "x": 1599718410000, + "y": 596000, }, Object { - "x": 1593413128000, + "x": 1599718440000, }, Object { - "x": 1593413129000, + "x": 1599718470000, + "y": 823000, }, Object { - "x": 1593413130000, + "x": 1599718500000, + "y": 551666.6666666666, }, Object { - "x": 1593413131000, + "x": 1599718530000, }, Object { - "x": 1593413132000, + "x": 1599718560000, }, Object { - "x": 1593413133000, + "x": 1599718590000, + "y": 1311000, }, Object { - "x": 1593413134000, + "x": 1599718620000, + "y": 574000, }, Object { - "x": 1593413135000, + "x": 1599718650000, }, Object { - "x": 1593413136000, + "x": 1599718680000, }, Object { - "x": 1593413137000, + "x": 1599718710000, + "y": 1806000, }, Object { - "x": 1593413138000, + "x": 1599718740000, + "y": 563000, }, Object { - "x": 1593413139000, + "x": 1599718770000, + "y": 665000, }, Object { - "x": 1593413140000, + "x": 1599718800000, }, Object { - "x": 1593413141000, + "x": 1599718830000, + "y": 1202000, }, Object { - "x": 1593413142000, + "x": 1599718860000, + "y": 542666.6666666666, }, Object { - "x": 1593413143000, + "x": 1599718890000, + "y": 688000, }, Object { - "x": 1593413144000, + "x": 1599718920000, }, Object { - "x": 1593413145000, + "x": 1599718950000, + "y": 995000, }, Object { - "x": 1593413146000, + "x": 1599718980000, + "y": 647000, }, Object { - "x": 1593413147000, + "x": 1599719010000, + "y": 552000, }, Object { - "x": 1593413148000, + "x": 1599719040000, }, Object { - "x": 1593413149000, + "x": 1599719070000, + "y": 1760500, }, Object { - "x": 1593413150000, + "x": 1599719100000, + "y": 556000, }, Object { - "x": 1593413151000, + "x": 1599719130000, + "y": 603000, }, Object { - "x": 1593413152000, + "x": 1599719160000, }, Object { - "x": 1593413153000, + "x": 1599719190000, + "y": 920000, }, Object { - "x": 1593413154000, + "x": 1599719220000, + "y": 523000, }, Object { - "x": 1593413155000, + "x": 1599719250000, }, Object { - "x": 1593413156000, + "x": 1599719280000, }, Object { - "x": 1593413157000, + "x": 1599719310000, + "y": 1074000, }, Object { - "x": 1593413158000, + "x": 1599719340000, + "y": 723500, }, Object { - "x": 1593413159000, + "x": 1599719370000, }, Object { - "x": 1593413160000, + "x": 1599719400000, }, Object { - "x": 1593413161000, + "x": 1599719430000, + "y": 1436000, }, Object { - "x": 1593413162000, + "x": 1599719460000, + "y": 614000, }, Object { - "x": 1593413163000, + "x": 1599719490000, + "y": 789000, }, Object { - "x": 1593413164000, + "x": 1599719520000, }, Object { - "x": 1593413165000, + "x": 1599719550000, + "y": 1919000, }, Object { - "x": 1593413166000, + "x": 1599719580000, + "y": 881000, }, Object { - "x": 1593413167000, + "x": 1599719610000, }, Object { - "x": 1593413168000, + "x": 1599719640000, }, Object { - "x": 1593413169000, + "x": 1599719670000, + "y": 1083000, }, Object { - "x": 1593413170000, + "x": 1599719700000, + "y": 603000, }, Object { - "x": 1593413171000, + "x": 1599719730000, + "y": 906000, }, Object { - "x": 1593413172000, + "x": 1599719760000, }, Object { - "x": 1593413173000, + "x": 1599719790000, + "y": 1222000, }, Object { - "x": 1593413174000, + "x": 1599719820000, + "y": 608000, }, Object { - "x": 1593413175000, + "x": 1599719850000, }, Object { - "x": 1593413176000, + "x": 1599719880000, }, Object { - "x": 1593413177000, + "x": 1599719910000, + "y": 805000, }, Object { - "x": 1593413178000, + "x": 1599719940000, + "y": 477000, }, Object { - "x": 1593413179000, + "x": 1599719970000, + "y": 652000, }, Object { - "x": 1593413180000, + "x": 1599720000000, }, Object { - "x": 1593413181000, + "x": 1599720030000, + "y": 1417000, }, Object { - "x": 1593413182000, + "x": 1599720060000, + "y": 545250, }, Object { - "x": 1593413183000, + "x": 1599720090000, }, Object { - "x": 1593413184000, + "x": 1599720120000, }, Object { - "x": 1593413185000, + "x": 1599720150000, + "y": 1122000, }, Object { - "x": 1593413186000, + "x": 1599720180000, + "y": 686000, }, Object { - "x": 1593413187000, + "x": 1599720210000, + "y": 1978000, }, Object { - "x": 1593413188000, + "x": 1599720240000, + "y": 927000, }, Object { - "x": 1593413189000, + "x": 1599720270000, + "y": 2112500, }, Object { - "x": 1593413190000, + "x": 1599720300000, + "y": 776333.3333333334, }, Object { - "x": 1593413191000, + "x": 1599720330000, }, Object { - "x": 1593413192000, + "x": 1599720360000, }, Object { - "x": 1593413193000, + "x": 1599720390000, + "y": 914000, }, Object { - "x": 1593413194000, + "x": 1599720420000, + "y": 534500, }, Object { - "x": 1593413195000, + "x": 1599720450000, }, Object { - "x": 1593413196000, + "x": 1599720480000, }, Object { - "x": 1593413197000, + "x": 1599720510000, + "y": 930000, }, Object { - "x": 1593413198000, + "x": 1599720540000, + "y": 501000, }, Object { - "x": 1593413199000, + "x": 1599720570000, + "y": 801500, }, Object { - "x": 1593413200000, + "x": 1599720600000, }, Object { - "x": 1593413201000, + "x": 1599720630000, + "y": 698000, }, Object { - "x": 1593413202000, + "x": 1599720660000, + "y": 626000, }, Object { - "x": 1593413203000, + "x": 1599720690000, }, Object { - "x": 1593413204000, + "x": 1599720720000, }, Object { - "x": 1593413205000, + "x": 1599720750000, + "y": 1091000, }, Object { - "x": 1593413206000, + "x": 1599720780000, + "y": 7822000, }, Object { - "x": 1593413207000, + "x": 1599720810000, }, Object { - "x": 1593413208000, + "x": 1599720840000, }, Object { - "x": 1593413209000, + "x": 1599720870000, + "y": 892000, }, Object { - "x": 1593413210000, + "x": 1599720900000, + "y": 591250, }, Object { - "x": 1593413211000, + "x": 1599720930000, }, Object { - "x": 1593413212000, + "x": 1599720960000, }, Object { - "x": 1593413213000, + "x": 1599720990000, + "y": 1096000, }, Object { - "x": 1593413214000, + "x": 1599721020000, + "y": 1087000, }, Object { - "x": 1593413215000, + "x": 1599721050000, }, Object { - "x": 1593413216000, + "x": 1599721080000, }, Object { - "x": 1593413217000, + "x": 1599721110000, + "y": 983000, }, Object { - "x": 1593413218000, + "x": 1599721140000, + "y": 801000, }, Object { - "x": 1593413219000, + "x": 1599721170000, }, Object { - "x": 1593413220000, - }, - Object { - "x": 1593413221000, - }, - Object { - "x": 1593413222000, - }, - Object { - "x": 1593413223000, - }, - Object { - "x": 1593413224000, - }, - Object { - "x": 1593413225000, - }, - Object { - "x": 1593413226000, - }, - Object { - "x": 1593413227000, - }, - Object { - "x": 1593413228000, - }, - Object { - "x": 1593413229000, - }, - Object { - "x": 1593413230000, - }, - Object { - "x": 1593413231000, - }, - Object { - "x": 1593413232000, - }, - Object { - "x": 1593413233000, - }, - Object { - "x": 1593413234000, - }, - Object { - "x": 1593413235000, - }, - Object { - "x": 1593413236000, - }, - Object { - "x": 1593413237000, - }, - Object { - "x": 1593413238000, - }, - Object { - "x": 1593413239000, - }, - Object { - "x": 1593413240000, - }, - Object { - "x": 1593413241000, - }, - Object { - "x": 1593413242000, - }, - Object { - "x": 1593413243000, - }, - Object { - "x": 1593413244000, - }, - Object { - "x": 1593413245000, - }, - Object { - "x": 1593413246000, - }, - Object { - "x": 1593413247000, - }, - Object { - "x": 1593413248000, - }, - Object { - "x": 1593413249000, - }, - Object { - "x": 1593413250000, - }, - Object { - "x": 1593413251000, - }, - Object { - "x": 1593413252000, - }, - Object { - "x": 1593413253000, - }, - Object { - "x": 1593413254000, - }, - Object { - "x": 1593413255000, - }, - Object { - "x": 1593413256000, - }, - Object { - "x": 1593413257000, - }, - Object { - "x": 1593413258000, - }, - Object { - "x": 1593413259000, - }, - Object { - "x": 1593413260000, - }, - Object { - "x": 1593413261000, - }, - Object { - "x": 1593413262000, - }, - Object { - "x": 1593413263000, - }, - Object { - "x": 1593413264000, - }, - Object { - "x": 1593413265000, - }, - Object { - "x": 1593413266000, - }, - Object { - "x": 1593413267000, - }, - Object { - "x": 1593413268000, - }, - Object { - "x": 1593413269000, - }, - Object { - "x": 1593413270000, - }, - Object { - "x": 1593413271000, - }, - Object { - "x": 1593413272000, - }, - Object { - "x": 1593413273000, - }, - Object { - "x": 1593413274000, - }, - Object { - "x": 1593413275000, - }, - Object { - "x": 1593413276000, - }, - Object { - "x": 1593413277000, - }, - Object { - "x": 1593413278000, - }, - Object { - "x": 1593413279000, - }, - Object { - "x": 1593413280000, - }, - Object { - "x": 1593413281000, - }, - Object { - "x": 1593413282000, - }, - Object { - "x": 1593413283000, - }, - Object { - "x": 1593413284000, - }, - Object { - "x": 1593413285000, - }, - Object { - "x": 1593413286000, - }, - Object { - "x": 1593413287000, - "y": 342000, - }, - Object { - "x": 1593413288000, - }, - Object { - "x": 1593413289000, - }, - Object { - "x": 1593413290000, - }, - Object { - "x": 1593413291000, - }, - Object { - "x": 1593413292000, - }, - Object { - "x": 1593413293000, - }, - Object { - "x": 1593413294000, - }, - Object { - "x": 1593413295000, - }, - Object { - "x": 1593413296000, - }, - Object { - "x": 1593413297000, - }, - Object { - "x": 1593413298000, - "y": 173000, - }, - Object { - "x": 1593413299000, - }, - Object { - "x": 1593413300000, - }, - Object { - "x": 1593413301000, - "y": 109000, - }, - Object { - "x": 1593413302000, - }, - Object { - "x": 1593413303000, - }, - Object { - "x": 1593413304000, - }, - Object { - "x": 1593413305000, - }, - Object { - "x": 1593413306000, - }, - Object { - "x": 1593413307000, - }, - Object { - "x": 1593413308000, - }, - Object { - "x": 1593413309000, - }, - Object { - "x": 1593413310000, - }, - Object { - "x": 1593413311000, - }, - Object { - "x": 1593413312000, - }, - Object { - "x": 1593413313000, - }, - Object { - "x": 1593413314000, - }, - Object { - "x": 1593413315000, - }, - Object { - "x": 1593413316000, - }, - Object { - "x": 1593413317000, - }, - Object { - "x": 1593413318000, - "y": 140000, - }, - Object { - "x": 1593413319000, - }, - Object { - "x": 1593413320000, - }, - Object { - "x": 1593413321000, - }, - Object { - "x": 1593413322000, - }, - Object { - "x": 1593413323000, - }, - Object { - "x": 1593413324000, - }, - Object { - "x": 1593413325000, - }, - Object { - "x": 1593413326000, - }, - Object { - "x": 1593413327000, - }, - Object { - "x": 1593413328000, - "y": 77000, - }, - Object { - "x": 1593413329000, - }, - Object { - "x": 1593413330000, - }, - Object { - "x": 1593413331000, - }, - Object { - "x": 1593413332000, - }, - Object { - "x": 1593413333000, - }, - Object { - "x": 1593413334000, - }, - Object { - "x": 1593413335000, - }, - Object { - "x": 1593413336000, - }, - Object { - "x": 1593413337000, - }, - Object { - "x": 1593413338000, - }, - Object { - "x": 1593413339000, - }, - Object { - "x": 1593413340000, + "x": 1599721200000, }, ], - "title": "HeadlessChrome", + "title": "Electron", }, ] `; -exports[`Average duration by browser when data is loaded returns the average duration by browser filtering by transaction name 1`] = ` +exports[`Average duration by browser when data is loaded returns the average duration by browser filtering by transaction name 2`] = ` Array [ Object { "data": Array [ Object { - "x": 1593413100000, - }, - Object { - "x": 1593413101000, - }, - Object { - "x": 1593413102000, - }, - Object { - "x": 1593413103000, - }, - Object { - "x": 1593413104000, - }, - Object { - "x": 1593413105000, - }, - Object { - "x": 1593413106000, - }, - Object { - "x": 1593413107000, - }, - Object { - "x": 1593413108000, - }, - Object { - "x": 1593413109000, - }, - Object { - "x": 1593413110000, - }, - Object { - "x": 1593413111000, - }, - Object { - "x": 1593413112000, - }, - Object { - "x": 1593413113000, - }, - Object { - "x": 1593413114000, - }, - Object { - "x": 1593413115000, - }, - Object { - "x": 1593413116000, - }, - Object { - "x": 1593413117000, - }, - Object { - "x": 1593413118000, - }, - Object { - "x": 1593413119000, - }, - Object { - "x": 1593413120000, - }, - Object { - "x": 1593413121000, - }, - Object { - "x": 1593413122000, - }, - Object { - "x": 1593413123000, - }, - Object { - "x": 1593413124000, - }, - Object { - "x": 1593413125000, - }, - Object { - "x": 1593413126000, - }, - Object { - "x": 1593413127000, - }, - Object { - "x": 1593413128000, - }, - Object { - "x": 1593413129000, - }, - Object { - "x": 1593413130000, - }, - Object { - "x": 1593413131000, - }, - Object { - "x": 1593413132000, - }, - Object { - "x": 1593413133000, - }, - Object { - "x": 1593413134000, - }, - Object { - "x": 1593413135000, - }, - Object { - "x": 1593413136000, - }, - Object { - "x": 1593413137000, - }, - Object { - "x": 1593413138000, - }, - Object { - "x": 1593413139000, - }, - Object { - "x": 1593413140000, - }, - Object { - "x": 1593413141000, - }, - Object { - "x": 1593413142000, - }, - Object { - "x": 1593413143000, - }, - Object { - "x": 1593413144000, - }, - Object { - "x": 1593413145000, - }, - Object { - "x": 1593413146000, - }, - Object { - "x": 1593413147000, - }, - Object { - "x": 1593413148000, - }, - Object { - "x": 1593413149000, - }, - Object { - "x": 1593413150000, - }, - Object { - "x": 1593413151000, - }, - Object { - "x": 1593413152000, - }, - Object { - "x": 1593413153000, - }, - Object { - "x": 1593413154000, - }, - Object { - "x": 1593413155000, - }, - Object { - "x": 1593413156000, - }, - Object { - "x": 1593413157000, - }, - Object { - "x": 1593413158000, - }, - Object { - "x": 1593413159000, - }, - Object { - "x": 1593413160000, - }, - Object { - "x": 1593413161000, - }, - Object { - "x": 1593413162000, - }, - Object { - "x": 1593413163000, - }, - Object { - "x": 1593413164000, - }, - Object { - "x": 1593413165000, - }, - Object { - "x": 1593413166000, - }, - Object { - "x": 1593413167000, - }, - Object { - "x": 1593413168000, - }, - Object { - "x": 1593413169000, - }, - Object { - "x": 1593413170000, - }, - Object { - "x": 1593413171000, - }, - Object { - "x": 1593413172000, - }, - Object { - "x": 1593413173000, - }, - Object { - "x": 1593413174000, - }, - Object { - "x": 1593413175000, - }, - Object { - "x": 1593413176000, - }, - Object { - "x": 1593413177000, - }, - Object { - "x": 1593413178000, - }, - Object { - "x": 1593413179000, - }, - Object { - "x": 1593413180000, - }, - Object { - "x": 1593413181000, - }, - Object { - "x": 1593413182000, - }, - Object { - "x": 1593413183000, - }, - Object { - "x": 1593413184000, - }, - Object { - "x": 1593413185000, - }, - Object { - "x": 1593413186000, - }, - Object { - "x": 1593413187000, - }, - Object { - "x": 1593413188000, - }, - Object { - "x": 1593413189000, - }, - Object { - "x": 1593413190000, - }, - Object { - "x": 1593413191000, - }, - Object { - "x": 1593413192000, - }, - Object { - "x": 1593413193000, - }, - Object { - "x": 1593413194000, - }, - Object { - "x": 1593413195000, - }, - Object { - "x": 1593413196000, - }, - Object { - "x": 1593413197000, - }, - Object { - "x": 1593413198000, - }, - Object { - "x": 1593413199000, - }, - Object { - "x": 1593413200000, - }, - Object { - "x": 1593413201000, - }, - Object { - "x": 1593413202000, - }, - Object { - "x": 1593413203000, - }, - Object { - "x": 1593413204000, - }, - Object { - "x": 1593413205000, - }, - Object { - "x": 1593413206000, - }, - Object { - "x": 1593413207000, - }, - Object { - "x": 1593413208000, - }, - Object { - "x": 1593413209000, - }, - Object { - "x": 1593413210000, - }, - Object { - "x": 1593413211000, - }, - Object { - "x": 1593413212000, - }, - Object { - "x": 1593413213000, - }, - Object { - "x": 1593413214000, - }, - Object { - "x": 1593413215000, - }, - Object { - "x": 1593413216000, - }, - Object { - "x": 1593413217000, - }, - Object { - "x": 1593413218000, - }, - Object { - "x": 1593413219000, - }, - Object { - "x": 1593413220000, + "x": 1599717600000, + "y": 999000, }, Object { - "x": 1593413221000, + "x": 1599717630000, + "y": 1111000, }, Object { - "x": 1593413222000, + "x": 1599717660000, }, Object { - "x": 1593413223000, + "x": 1599717690000, }, Object { - "x": 1593413224000, + "x": 1599717720000, }, Object { - "x": 1593413225000, + "x": 1599717750000, + "y": 1487000, }, Object { - "x": 1593413226000, + "x": 1599717780000, }, Object { - "x": 1593413227000, + "x": 1599717810000, }, Object { - "x": 1593413228000, + "x": 1599717840000, }, Object { - "x": 1593413229000, + "x": 1599717870000, + "y": 1326000, }, Object { - "x": 1593413230000, + "x": 1599717900000, }, Object { - "x": 1593413231000, + "x": 1599717930000, }, Object { - "x": 1593413232000, + "x": 1599717960000, }, Object { - "x": 1593413233000, + "x": 1599717990000, + "y": 792000, }, Object { - "x": 1593413234000, + "x": 1599718020000, }, Object { - "x": 1593413235000, + "x": 1599718050000, }, Object { - "x": 1593413236000, + "x": 1599718080000, }, Object { - "x": 1593413237000, + "x": 1599718110000, + "y": 1016000, }, Object { - "x": 1593413238000, + "x": 1599718140000, }, Object { - "x": 1593413239000, + "x": 1599718170000, }, Object { - "x": 1593413240000, + "x": 1599718200000, }, Object { - "x": 1593413241000, + "x": 1599718230000, + "y": 1578000, }, Object { - "x": 1593413242000, + "x": 1599718260000, }, Object { - "x": 1593413243000, + "x": 1599718290000, }, Object { - "x": 1593413244000, + "x": 1599718320000, }, Object { - "x": 1593413245000, + "x": 1599718350000, + "y": 1020000, }, Object { - "x": 1593413246000, + "x": 1599718380000, }, Object { - "x": 1593413247000, + "x": 1599718410000, }, Object { - "x": 1593413248000, + "x": 1599718440000, }, Object { - "x": 1593413249000, + "x": 1599718470000, + "y": 823000, }, Object { - "x": 1593413250000, + "x": 1599718500000, }, Object { - "x": 1593413251000, + "x": 1599718530000, }, Object { - "x": 1593413252000, + "x": 1599718560000, }, Object { - "x": 1593413253000, + "x": 1599718590000, + "y": 1311000, }, Object { - "x": 1593413254000, + "x": 1599718620000, }, Object { - "x": 1593413255000, + "x": 1599718650000, }, Object { - "x": 1593413256000, + "x": 1599718680000, }, Object { - "x": 1593413257000, + "x": 1599718710000, + "y": 1806000, }, Object { - "x": 1593413258000, + "x": 1599718740000, }, Object { - "x": 1593413259000, + "x": 1599718770000, }, Object { - "x": 1593413260000, + "x": 1599718800000, }, Object { - "x": 1593413261000, + "x": 1599718830000, + "y": 1202000, }, Object { - "x": 1593413262000, + "x": 1599718860000, }, Object { - "x": 1593413263000, + "x": 1599718890000, }, Object { - "x": 1593413264000, + "x": 1599718920000, }, Object { - "x": 1593413265000, + "x": 1599718950000, + "y": 995000, }, Object { - "x": 1593413266000, + "x": 1599718980000, }, Object { - "x": 1593413267000, + "x": 1599719010000, }, Object { - "x": 1593413268000, + "x": 1599719040000, }, Object { - "x": 1593413269000, + "x": 1599719070000, + "y": 1110000, }, Object { - "x": 1593413270000, + "x": 1599719100000, }, Object { - "x": 1593413271000, + "x": 1599719130000, }, Object { - "x": 1593413272000, + "x": 1599719160000, }, Object { - "x": 1593413273000, + "x": 1599719190000, + "y": 920000, }, Object { - "x": 1593413274000, + "x": 1599719220000, }, Object { - "x": 1593413275000, + "x": 1599719250000, }, Object { - "x": 1593413276000, + "x": 1599719280000, }, Object { - "x": 1593413277000, + "x": 1599719310000, + "y": 1074000, }, Object { - "x": 1593413278000, + "x": 1599719340000, }, Object { - "x": 1593413279000, + "x": 1599719370000, }, Object { - "x": 1593413280000, + "x": 1599719400000, }, Object { - "x": 1593413281000, + "x": 1599719430000, + "y": 902000, }, Object { - "x": 1593413282000, + "x": 1599719460000, }, Object { - "x": 1593413283000, + "x": 1599719490000, }, Object { - "x": 1593413284000, + "x": 1599719520000, }, Object { - "x": 1593413285000, + "x": 1599719550000, + "y": 931000, }, Object { - "x": 1593413286000, + "x": 1599719580000, }, Object { - "x": 1593413287000, + "x": 1599719610000, }, Object { - "x": 1593413288000, + "x": 1599719640000, }, Object { - "x": 1593413289000, + "x": 1599719670000, + "y": 1083000, }, Object { - "x": 1593413290000, + "x": 1599719700000, }, Object { - "x": 1593413291000, + "x": 1599719730000, }, Object { - "x": 1593413292000, + "x": 1599719760000, }, Object { - "x": 1593413293000, + "x": 1599719790000, + "y": 1222000, }, Object { - "x": 1593413294000, + "x": 1599719820000, }, Object { - "x": 1593413295000, + "x": 1599719850000, }, Object { - "x": 1593413296000, + "x": 1599719880000, }, Object { - "x": 1593413297000, + "x": 1599719910000, + "y": 805000, }, Object { - "x": 1593413298000, + "x": 1599719940000, }, Object { - "x": 1593413299000, + "x": 1599719970000, }, Object { - "x": 1593413300000, + "x": 1599720000000, }, Object { - "x": 1593413301000, + "x": 1599720030000, + "y": 1417000, }, Object { - "x": 1593413302000, + "x": 1599720060000, }, Object { - "x": 1593413303000, + "x": 1599720090000, }, Object { - "x": 1593413304000, + "x": 1599720120000, }, Object { - "x": 1593413305000, + "x": 1599720150000, + "y": 1122000, }, Object { - "x": 1593413306000, + "x": 1599720180000, }, Object { - "x": 1593413307000, + "x": 1599720210000, }, Object { - "x": 1593413308000, + "x": 1599720240000, + "y": 927000, }, Object { - "x": 1593413309000, + "x": 1599720270000, + "y": 1330000, }, Object { - "x": 1593413310000, + "x": 1599720300000, }, Object { - "x": 1593413311000, + "x": 1599720330000, }, Object { - "x": 1593413312000, + "x": 1599720360000, }, Object { - "x": 1593413313000, + "x": 1599720390000, + "y": 914000, }, Object { - "x": 1593413314000, + "x": 1599720420000, }, Object { - "x": 1593413315000, + "x": 1599720450000, }, Object { - "x": 1593413316000, + "x": 1599720480000, }, Object { - "x": 1593413317000, + "x": 1599720510000, + "y": 930000, }, Object { - "x": 1593413318000, + "x": 1599720540000, }, Object { - "x": 1593413319000, + "x": 1599720570000, }, Object { - "x": 1593413320000, + "x": 1599720600000, }, Object { - "x": 1593413321000, + "x": 1599720630000, + "y": 698000, }, Object { - "x": 1593413322000, + "x": 1599720660000, }, Object { - "x": 1593413323000, + "x": 1599720690000, }, Object { - "x": 1593413324000, + "x": 1599720720000, }, Object { - "x": 1593413325000, + "x": 1599720750000, + "y": 1091000, }, Object { - "x": 1593413326000, + "x": 1599720780000, }, Object { - "x": 1593413327000, + "x": 1599720810000, }, Object { - "x": 1593413328000, - "y": 77000, + "x": 1599720840000, }, Object { - "x": 1593413329000, + "x": 1599720870000, + "y": 892000, }, Object { - "x": 1593413330000, + "x": 1599720900000, }, Object { - "x": 1593413331000, + "x": 1599720930000, }, Object { - "x": 1593413332000, + "x": 1599720960000, }, Object { - "x": 1593413333000, + "x": 1599720990000, + "y": 1096000, }, Object { - "x": 1593413334000, + "x": 1599721020000, }, Object { - "x": 1593413335000, + "x": 1599721050000, }, Object { - "x": 1593413336000, + "x": 1599721080000, }, Object { - "x": 1593413337000, + "x": 1599721110000, + "y": 983000, }, Object { - "x": 1593413338000, + "x": 1599721140000, }, Object { - "x": 1593413339000, + "x": 1599721170000, }, Object { - "x": 1593413340000, + "x": 1599721200000, }, ], - "title": "HeadlessChrome", + "title": "Electron", }, ] `; diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/breakdown.snap b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/breakdown.snap index e204ff41dfa43..516523409a029 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/breakdown.snap +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/breakdown.snap @@ -7,182 +7,1970 @@ Object { "color": "#54b399", "data": Array [ Object { - "x": 1593413100000, + "x": 1599717600000, + "y": 0.058823529411764705, + }, + Object { + "x": 1599717630000, + "y": 0.037037037037037035, + }, + Object { + "x": 1599717660000, + "y": null, + }, + Object { + "x": 1599717690000, + "y": 0.07142857142857142, + }, + Object { + "x": 1599717720000, + "y": null, + }, + Object { + "x": 1599717750000, + "y": 0.023787740164684355, + }, + Object { + "x": 1599717780000, + "y": 0.19444444444444445, + }, + Object { + "x": 1599717810000, + "y": 0.1346153846153846, + }, + Object { + "x": 1599717840000, + "y": null, + }, + Object { + "x": 1599717870000, + "y": 0.6666666666666666, + }, + Object { + "x": 1599717900000, + "y": 0.04411764705882353, + }, + Object { + "x": 1599717930000, + "y": 0.30985915492957744, + }, + Object { + "x": 1599717960000, + "y": null, + }, + Object { + "x": 1599717990000, + "y": 0.1183206106870229, + }, + Object { + "x": 1599718020000, + "y": 1, + }, + Object { + "x": 1599718050000, + "y": 0.03389830508474576, + }, + Object { + "x": 1599718080000, + "y": null, + }, + Object { + "x": 1599718110000, + "y": 0.1657754010695187, + }, + Object { + "x": 1599718140000, + "y": null, + }, + Object { + "x": 1599718170000, + "y": 0.0273972602739726, + }, + Object { + "x": 1599718200000, + "y": 0.7272727272727273, + }, + Object { + "x": 1599718230000, + "y": 0.0954356846473029, + }, + Object { + "x": 1599718260000, + "y": null, + }, + Object { + "x": 1599718290000, + "y": null, + }, + Object { + "x": 1599718320000, + "y": null, + }, + Object { + "x": 1599718350000, + "y": 0.1111111111111111, + }, + Object { + "x": 1599718380000, + "y": 0.05555555555555555, + }, + Object { + "x": 1599718410000, + "y": 0.48484848484848486, + }, + Object { + "x": 1599718440000, + "y": null, + }, + Object { + "x": 1599718470000, + "y": 0.4642857142857143, + }, + Object { + "x": 1599718500000, + "y": 0.045454545454545456, + }, + Object { + "x": 1599718530000, + "y": 1, + }, + Object { + "x": 1599718560000, + "y": null, + }, + Object { + "x": 1599718590000, + "y": 0.3469387755102041, + }, + Object { + "x": 1599718620000, + "y": null, + }, + Object { + "x": 1599718650000, + "y": 0.045454545454545456, + }, + Object { + "x": 1599718680000, + "y": null, + }, + Object { + "x": 1599718710000, + "y": 0.02967032967032967, + }, + Object { + "x": 1599718740000, + "y": 0.7910447761194029, + }, + Object { + "x": 1599718770000, + "y": 0.020833333333333332, + }, + Object { + "x": 1599718800000, + "y": 0.3448275862068966, + }, + Object { + "x": 1599718830000, + "y": null, + }, + Object { + "x": 1599718860000, + "y": 0.4107142857142857, + }, + Object { + "x": 1599718890000, + "y": 0.21428571428571427, + }, + Object { + "x": 1599718920000, + "y": null, + }, + Object { + "x": 1599718950000, + "y": 0.3235294117647059, + }, + Object { + "x": 1599718980000, + "y": null, + }, + Object { + "x": 1599719010000, + "y": null, + }, + Object { + "x": 1599719040000, + "y": 0.4642857142857143, + }, + Object { + "x": 1599719070000, + "y": 0.20192307692307693, + }, + Object { + "x": 1599719100000, + "y": 0.4, + }, + Object { + "x": 1599719130000, + "y": 0.28205128205128205, + }, + Object { + "x": 1599719160000, + "y": null, + }, + Object { + "x": 1599719190000, + "y": 0.020223152022315203, + }, + Object { + "x": 1599719220000, + "y": 0.05263157894736842, + }, + Object { + "x": 1599719250000, + "y": 0.19480519480519481, + }, + Object { + "x": 1599719280000, + "y": null, + }, + Object { + "x": 1599719310000, + "y": 0.136986301369863, + }, + Object { + "x": 1599719340000, + "y": 0.3870967741935484, + }, + Object { + "x": 1599719370000, + "y": null, + }, + Object { + "x": 1599719400000, + "y": null, + }, + Object { + "x": 1599719430000, + "y": 0.11141304347826086, + }, + Object { + "x": 1599719460000, + "y": 0.5769230769230769, + }, + Object { + "x": 1599719490000, + "y": null, + }, + Object { + "x": 1599719520000, + "y": 0.041666666666666664, + }, + Object { + "x": 1599719550000, + "y": 0.02857142857142857, + }, + Object { + "x": 1599719580000, + "y": null, + }, + Object { + "x": 1599719610000, + "y": 0.35714285714285715, + }, + Object { + "x": 1599719640000, + "y": null, + }, + Object { + "x": 1599719670000, + "y": 0.2903225806451613, + }, + Object { + "x": 1599719700000, + "y": null, + }, + Object { + "x": 1599719730000, + "y": null, + }, + Object { + "x": 1599719760000, + "y": 0.6222222222222222, + }, + Object { + "x": 1599719790000, + "y": 0.17857142857142858, + }, + Object { + "x": 1599719820000, + "y": null, + }, + Object { + "x": 1599719850000, + "y": 0.4807692307692308, + }, + Object { + "x": 1599719880000, + "y": null, + }, + Object { + "x": 1599719910000, + "y": 0.5348837209302325, + }, + Object { + "x": 1599719940000, + "y": null, + }, + Object { + "x": 1599719970000, + "y": null, + }, + Object { + "x": 1599720000000, + "y": 0.24444444444444444, + }, + Object { + "x": 1599720030000, + "y": 0.4, + }, + Object { + "x": 1599720060000, + "y": null, + }, + Object { + "x": 1599720090000, + "y": 1, + }, + Object { + "x": 1599720120000, + "y": null, + }, + Object { + "x": 1599720150000, + "y": null, + }, + Object { + "x": 1599720180000, + "y": null, + }, + Object { + "x": 1599720210000, + "y": 0.3793103448275862, + }, + Object { + "x": 1599720240000, + "y": null, + }, + Object { + "x": 1599720270000, + "y": 0.20202020202020202, + }, + Object { + "x": 1599720300000, + "y": null, + }, + Object { + "x": 1599720330000, + "y": 0.023121387283236993, + }, + Object { + "x": 1599720360000, + "y": null, + }, + Object { + "x": 1599720390000, + "y": 1, + }, + Object { + "x": 1599720420000, + "y": 0.3076923076923077, + }, + Object { + "x": 1599720450000, + "y": 0.24675324675324675, + }, + Object { + "x": 1599720480000, + "y": null, + }, + Object { + "x": 1599720510000, + "y": 0.875, + }, + Object { + "x": 1599720540000, + "y": 0.47368421052631576, + }, + Object { + "x": 1599720570000, + "y": null, + }, + Object { + "x": 1599720600000, + "y": null, + }, + Object { + "x": 1599720630000, + "y": 0.22580645161290322, + }, + Object { + "x": 1599720660000, + "y": 0.391304347826087, + }, + Object { + "x": 1599720690000, + "y": 0.75, + }, + Object { + "x": 1599720720000, + "y": null, + }, + Object { + "x": 1599720750000, + "y": 0.7804878048780488, + }, + Object { + "x": 1599720780000, + "y": 0.18518518518518517, + }, + Object { + "x": 1599720810000, + "y": 0.24074074074074073, + }, + Object { + "x": 1599720840000, + "y": null, + }, + Object { + "x": 1599720870000, + "y": 1, + }, + Object { + "x": 1599720900000, + "y": 0.1111111111111111, + }, + Object { + "x": 1599720930000, + "y": 0.5161290322580645, + }, + Object { + "x": 1599720960000, + "y": null, + }, + Object { + "x": 1599720990000, + "y": 0.14285714285714285, + }, + Object { + "x": 1599721020000, + "y": 1, + }, + Object { + "x": 1599721050000, + "y": 0.7272727272727273, + }, + Object { + "x": 1599721080000, + "y": null, + }, + Object { + "x": 1599721110000, + "y": 0.059027777777777776, + }, + Object { + "x": 1599721140000, + "y": 0.022727272727272728, + }, + Object { + "x": 1599721170000, "y": null, }, Object { - "x": 1593413130000, - "y": null, + "x": 1599721200000, + "y": null, + }, + ], + "hideLegend": false, + "legendValue": "14%", + "title": "app", + "type": "areaStacked", + }, + Object { + "color": "#6092c0", + "data": Array [ + Object { + "x": 1599717600000, + "y": 0.9411764705882353, + }, + Object { + "x": 1599717630000, + "y": 0.9629629629629629, + }, + Object { + "x": 1599717660000, + "y": null, + }, + Object { + "x": 1599717690000, + "y": 0.9285714285714286, + }, + Object { + "x": 1599717720000, + "y": null, + }, + Object { + "x": 1599717750000, + "y": 0.9734675205855444, + }, + Object { + "x": 1599717780000, + "y": 0.8055555555555556, + }, + Object { + "x": 1599717810000, + "y": 0.8653846153846154, + }, + Object { + "x": 1599717840000, + "y": null, + }, + Object { + "x": 1599717870000, + "y": 0, + }, + Object { + "x": 1599717900000, + "y": 0.9558823529411765, + }, + Object { + "x": 1599717930000, + "y": 0.6901408450704225, + }, + Object { + "x": 1599717960000, + "y": null, + }, + Object { + "x": 1599717990000, + "y": 0.7404580152671756, + }, + Object { + "x": 1599718020000, + "y": 0, + }, + Object { + "x": 1599718050000, + "y": 0.9661016949152542, + }, + Object { + "x": 1599718080000, + "y": null, + }, + Object { + "x": 1599718110000, + "y": 0.6363636363636364, + }, + Object { + "x": 1599718140000, + "y": null, + }, + Object { + "x": 1599718170000, + "y": 0.9726027397260274, + }, + Object { + "x": 1599718200000, + "y": 0, + }, + Object { + "x": 1599718230000, + "y": 0.8921161825726142, + }, + Object { + "x": 1599718260000, + "y": null, + }, + Object { + "x": 1599718290000, + "y": null, + }, + Object { + "x": 1599718320000, + "y": null, + }, + Object { + "x": 1599718350000, + "y": 0.8888888888888888, + }, + Object { + "x": 1599718380000, + "y": 0.9444444444444444, + }, + Object { + "x": 1599718410000, + "y": 0, + }, + Object { + "x": 1599718440000, + "y": null, + }, + Object { + "x": 1599718470000, + "y": 0.38392857142857145, + }, + Object { + "x": 1599718500000, + "y": 0.9545454545454546, + }, + Object { + "x": 1599718530000, + "y": 0, + }, + Object { + "x": 1599718560000, + "y": null, + }, + Object { + "x": 1599718590000, + "y": 0.3877551020408163, + }, + Object { + "x": 1599718620000, + "y": null, + }, + Object { + "x": 1599718650000, + "y": 0.9545454545454546, + }, + Object { + "x": 1599718680000, + "y": null, + }, + Object { + "x": 1599718710000, + "y": 0.9560439560439561, + }, + Object { + "x": 1599718740000, + "y": 0.208955223880597, + }, + Object { + "x": 1599718770000, + "y": 0.9791666666666666, + }, + Object { + "x": 1599718800000, + "y": 0, + }, + Object { + "x": 1599718830000, + "y": null, + }, + Object { + "x": 1599718860000, + "y": 0, + }, + Object { + "x": 1599718890000, + "y": 0.5833333333333334, + }, + Object { + "x": 1599718920000, + "y": null, + }, + Object { + "x": 1599718950000, + "y": 0.5882352941176471, + }, + Object { + "x": 1599718980000, + "y": null, + }, + Object { + "x": 1599719010000, + "y": null, + }, + Object { + "x": 1599719040000, + "y": 0.5357142857142857, + }, + Object { + "x": 1599719070000, + "y": 0.5, + }, + Object { + "x": 1599719100000, + "y": 0, + }, + Object { + "x": 1599719130000, + "y": 0.6410256410256411, + }, + Object { + "x": 1599719160000, + "y": null, + }, + Object { + "x": 1599719190000, + "y": 0.9672245467224547, + }, + Object { + "x": 1599719220000, + "y": 0.9473684210526315, + }, + Object { + "x": 1599719250000, + "y": 0.7922077922077922, + }, + Object { + "x": 1599719280000, + "y": null, + }, + Object { + "x": 1599719310000, + "y": 0.8356164383561644, + }, + Object { + "x": 1599719340000, + "y": 0.1935483870967742, + }, + Object { + "x": 1599719370000, + "y": null, + }, + Object { + "x": 1599719400000, + "y": null, + }, + Object { + "x": 1599719430000, + "y": 0.8777173913043478, + }, + Object { + "x": 1599719460000, + "y": 0.28205128205128205, + }, + Object { + "x": 1599719490000, + "y": null, + }, + Object { + "x": 1599719520000, + "y": 0.9583333333333334, + }, + Object { + "x": 1599719550000, + "y": 0.9714285714285714, + }, + Object { + "x": 1599719580000, + "y": null, + }, + Object { + "x": 1599719610000, + "y": 0, + }, + Object { + "x": 1599719640000, + "y": null, + }, + Object { + "x": 1599719670000, + "y": 0.5725806451612904, + }, + Object { + "x": 1599719700000, + "y": null, + }, + Object { + "x": 1599719730000, + "y": null, + }, + Object { + "x": 1599719760000, + "y": 0.37777777777777777, + }, + Object { + "x": 1599719790000, + "y": 0.5, + }, + Object { + "x": 1599719820000, + "y": null, + }, + Object { + "x": 1599719850000, + "y": 0.5192307692307693, + }, + Object { + "x": 1599719880000, + "y": null, + }, + Object { + "x": 1599719910000, + "y": 0.46511627906976744, + }, + Object { + "x": 1599719940000, + "y": null, + }, + Object { + "x": 1599719970000, + "y": null, + }, + Object { + "x": 1599720000000, + "y": 0.6666666666666666, + }, + Object { + "x": 1599720030000, + "y": 0.45, + }, + Object { + "x": 1599720060000, + "y": null, + }, + Object { + "x": 1599720090000, + "y": 0, + }, + Object { + "x": 1599720120000, + "y": null, + }, + Object { + "x": 1599720150000, + "y": null, + }, + Object { + "x": 1599720180000, + "y": null, + }, + Object { + "x": 1599720210000, + "y": 0, + }, + Object { + "x": 1599720240000, + "y": null, + }, + Object { + "x": 1599720270000, + "y": 0.797979797979798, + }, + Object { + "x": 1599720300000, + "y": null, + }, + Object { + "x": 1599720330000, + "y": 0.976878612716763, + }, + Object { + "x": 1599720360000, + "y": null, + }, + Object { + "x": 1599720390000, + "y": 0, + }, + Object { + "x": 1599720420000, + "y": 0.6410256410256411, + }, + Object { + "x": 1599720450000, + "y": 0.5064935064935064, + }, + Object { + "x": 1599720480000, + "y": null, + }, + Object { + "x": 1599720510000, + "y": 0, + }, + Object { + "x": 1599720540000, + "y": 0, + }, + Object { + "x": 1599720570000, + "y": null, + }, + Object { + "x": 1599720600000, + "y": null, + }, + Object { + "x": 1599720630000, + "y": 0.7258064516129032, + }, + Object { + "x": 1599720660000, + "y": 0, + }, + Object { + "x": 1599720690000, + "y": 0, }, Object { - "x": 1593413160000, + "x": 1599720720000, "y": null, }, Object { - "x": 1593413190000, - "y": null, + "x": 1599720750000, + "y": 0.21951219512195122, + }, + Object { + "x": 1599720780000, + "y": 0.6111111111111112, + }, + Object { + "x": 1599720810000, + "y": 0.6851851851851852, }, Object { - "x": 1593413220000, + "x": 1599720840000, "y": null, }, Object { - "x": 1593413250000, + "x": 1599720870000, + "y": 0, + }, + Object { + "x": 1599720900000, + "y": 0.7, + }, + Object { + "x": 1599720930000, + "y": 0.41935483870967744, + }, + Object { + "x": 1599720960000, "y": null, }, Object { - "x": 1593413280000, + "x": 1599720990000, + "y": 0.7428571428571429, + }, + Object { + "x": 1599721020000, + "y": 0, + }, + Object { + "x": 1599721050000, + "y": 0, + }, + Object { + "x": 1599721080000, "y": null, }, Object { - "x": 1593413310000, - "y": 0.16700861715223636, + "x": 1599721110000, + "y": 0.8506944444444444, + }, + Object { + "x": 1599721140000, + "y": 0.9772727272727273, + }, + Object { + "x": 1599721170000, + "y": null, }, Object { - "x": 1593413340000, + "x": 1599721200000, "y": null, }, ], "hideLegend": false, - "legendValue": "17%", - "title": "app", + "legendValue": "79%", + "title": "http", "type": "areaStacked", }, Object { - "color": "#6092c0", + "color": "#d36086", "data": Array [ Object { - "x": 1593413100000, + "x": 1599717600000, + "y": 0, + }, + Object { + "x": 1599717630000, + "y": 0, + }, + Object { + "x": 1599717660000, "y": null, }, Object { - "x": 1593413130000, + "x": 1599717690000, + "y": 0, + }, + Object { + "x": 1599717720000, "y": null, }, Object { - "x": 1593413160000, + "x": 1599717750000, + "y": 0.0027447392497712718, + }, + Object { + "x": 1599717780000, + "y": 0, + }, + Object { + "x": 1599717810000, + "y": 0, + }, + Object { + "x": 1599717840000, "y": null, }, Object { - "x": 1593413190000, + "x": 1599717870000, + "y": 0.3333333333333333, + }, + Object { + "x": 1599717900000, + "y": 0, + }, + Object { + "x": 1599717930000, + "y": 0, + }, + Object { + "x": 1599717960000, "y": null, }, Object { - "x": 1593413220000, + "x": 1599717990000, + "y": 0.14122137404580154, + }, + Object { + "x": 1599718020000, + "y": 0, + }, + Object { + "x": 1599718050000, + "y": 0, + }, + Object { + "x": 1599718080000, "y": null, }, Object { - "x": 1593413250000, + "x": 1599718110000, + "y": 0.19786096256684493, + }, + Object { + "x": 1599718140000, "y": null, }, Object { - "x": 1593413280000, + "x": 1599718170000, + "y": 0, + }, + Object { + "x": 1599718200000, + "y": 0.2727272727272727, + }, + Object { + "x": 1599718230000, + "y": 0.012448132780082987, + }, + Object { + "x": 1599718260000, "y": null, }, Object { - "x": 1593413310000, - "y": 0.7702092736971686, + "x": 1599718290000, + "y": null, }, Object { - "x": 1593413340000, + "x": 1599718320000, "y": null, }, - ], - "hideLegend": false, - "legendValue": "77%", - "title": "http", - "type": "areaStacked", - }, - Object { - "color": "#d36086", - "data": Array [ Object { - "x": 1593413100000, + "x": 1599718350000, + "y": 0, + }, + Object { + "x": 1599718380000, + "y": 0, + }, + Object { + "x": 1599718410000, + "y": 0.5151515151515151, + }, + Object { + "x": 1599718440000, + "y": null, + }, + Object { + "x": 1599718470000, + "y": 0.15178571428571427, + }, + Object { + "x": 1599718500000, + "y": 0, + }, + Object { + "x": 1599718530000, + "y": 0, + }, + Object { + "x": 1599718560000, + "y": null, + }, + Object { + "x": 1599718590000, + "y": 0.2653061224489796, + }, + Object { + "x": 1599718620000, "y": null, }, Object { - "x": 1593413130000, + "x": 1599718650000, + "y": 0, + }, + Object { + "x": 1599718680000, "y": null, }, Object { - "x": 1593413160000, + "x": 1599718710000, + "y": 0.014285714285714285, + }, + Object { + "x": 1599718740000, + "y": 0, + }, + Object { + "x": 1599718770000, + "y": 0, + }, + Object { + "x": 1599718800000, + "y": 0.6551724137931034, + }, + Object { + "x": 1599718830000, "y": null, }, Object { - "x": 1593413190000, + "x": 1599718860000, + "y": 0.5892857142857143, + }, + Object { + "x": 1599718890000, + "y": 0.20238095238095238, + }, + Object { + "x": 1599718920000, "y": null, }, Object { - "x": 1593413220000, + "x": 1599718950000, + "y": 0.08823529411764706, + }, + Object { + "x": 1599718980000, "y": null, }, Object { - "x": 1593413250000, + "x": 1599719010000, "y": null, }, Object { - "x": 1593413280000, + "x": 1599719040000, + "y": 0, + }, + Object { + "x": 1599719070000, + "y": 0.2980769230769231, + }, + Object { + "x": 1599719100000, + "y": 0.6, + }, + Object { + "x": 1599719130000, + "y": 0.07692307692307693, + }, + Object { + "x": 1599719160000, "y": null, }, Object { - "x": 1593413310000, - "y": 0.0508822322527698, + "x": 1599719190000, + "y": 0.012552301255230125, + }, + Object { + "x": 1599719220000, + "y": 0, + }, + Object { + "x": 1599719250000, + "y": 0.012987012987012988, }, Object { - "x": 1593413340000, + "x": 1599719280000, "y": null, }, - ], - "hideLegend": false, - "legendValue": "5.1%", - "title": "postgresql", - "type": "areaStacked", - }, - Object { - "color": "#9170b8", - "data": Array [ Object { - "x": 1593413100000, + "x": 1599719310000, + "y": 0.0273972602739726, + }, + Object { + "x": 1599719340000, + "y": 0.41935483870967744, + }, + Object { + "x": 1599719370000, "y": null, }, Object { - "x": 1593413130000, + "x": 1599719400000, "y": null, }, Object { - "x": 1593413160000, + "x": 1599719430000, + "y": 0.010869565217391304, + }, + Object { + "x": 1599719460000, + "y": 0.14102564102564102, + }, + Object { + "x": 1599719490000, + "y": null, + }, + Object { + "x": 1599719520000, + "y": 0, + }, + Object { + "x": 1599719550000, + "y": 0, + }, + Object { + "x": 1599719580000, + "y": null, + }, + Object { + "x": 1599719610000, + "y": 0.6428571428571429, + }, + Object { + "x": 1599719640000, + "y": null, + }, + Object { + "x": 1599719670000, + "y": 0.13709677419354838, + }, + Object { + "x": 1599719700000, + "y": null, + }, + Object { + "x": 1599719730000, + "y": null, + }, + Object { + "x": 1599719760000, + "y": 0, + }, + Object { + "x": 1599719790000, + "y": 0.32142857142857145, + }, + Object { + "x": 1599719820000, + "y": null, + }, + Object { + "x": 1599719850000, + "y": 0, + }, + Object { + "x": 1599719880000, + "y": null, + }, + Object { + "x": 1599719910000, + "y": 0, + }, + Object { + "x": 1599719940000, + "y": null, + }, + Object { + "x": 1599719970000, + "y": null, + }, + Object { + "x": 1599720000000, + "y": 0.08888888888888889, + }, + Object { + "x": 1599720030000, + "y": 0.15, + }, + Object { + "x": 1599720060000, + "y": null, + }, + Object { + "x": 1599720090000, + "y": 0, + }, + Object { + "x": 1599720120000, + "y": null, + }, + Object { + "x": 1599720150000, + "y": null, + }, + Object { + "x": 1599720180000, + "y": null, + }, + Object { + "x": 1599720210000, + "y": 0.6206896551724138, + }, + Object { + "x": 1599720240000, + "y": null, + }, + Object { + "x": 1599720270000, + "y": 0, + }, + Object { + "x": 1599720300000, + "y": null, + }, + Object { + "x": 1599720330000, + "y": 0, + }, + Object { + "x": 1599720360000, + "y": null, + }, + Object { + "x": 1599720390000, + "y": 0, + }, + Object { + "x": 1599720420000, + "y": 0.05128205128205128, + }, + Object { + "x": 1599720450000, + "y": 0.24675324675324675, + }, + Object { + "x": 1599720480000, + "y": null, + }, + Object { + "x": 1599720510000, + "y": 0.125, + }, + Object { + "x": 1599720540000, + "y": 0.5263157894736842, + }, + Object { + "x": 1599720570000, + "y": null, + }, + Object { + "x": 1599720600000, "y": null, }, Object { - "x": 1593413190000, + "x": 1599720630000, + "y": 0.04838709677419355, + }, + Object { + "x": 1599720660000, + "y": 0.6086956521739131, + }, + Object { + "x": 1599720690000, + "y": 0.25, + }, + Object { + "x": 1599720720000, "y": null, }, Object { - "x": 1593413220000, + "x": 1599720750000, + "y": 0, + }, + Object { + "x": 1599720780000, + "y": 0.2037037037037037, + }, + Object { + "x": 1599720810000, + "y": 0.07407407407407407, + }, + Object { + "x": 1599720840000, "y": null, }, Object { - "x": 1593413250000, + "x": 1599720870000, + "y": 0, + }, + Object { + "x": 1599720900000, + "y": 0.18888888888888888, + }, + Object { + "x": 1599720930000, + "y": 0.06451612903225806, + }, + Object { + "x": 1599720960000, "y": null, }, Object { - "x": 1593413280000, + "x": 1599720990000, + "y": 0.11428571428571428, + }, + Object { + "x": 1599721020000, + "y": 0, + }, + Object { + "x": 1599721050000, + "y": 0.2727272727272727, + }, + Object { + "x": 1599721080000, "y": null, }, Object { - "x": 1593413310000, - "y": 0.011899876897825195, + "x": 1599721110000, + "y": 0.09027777777777778, }, Object { - "x": 1593413340000, + "x": 1599721140000, + "y": 0, + }, + Object { + "x": 1599721170000, + "y": null, + }, + Object { + "x": 1599721200000, "y": null, }, ], "hideLegend": false, - "legendValue": "1.2%", - "title": "redis", + "legendValue": "6.4%", + "title": "postgresql", "type": "areaStacked", }, ], } `; + +exports[`Breakdown when data is loaded returns the transaction breakdown for a transaction group 9`] = ` +Array [ + Object { + "x": 1599717600000, + "y": 1, + }, + Object { + "x": 1599717630000, + "y": 1, + }, + Object { + "x": 1599717660000, + "y": null, + }, + Object { + "x": 1599717690000, + "y": 1, + }, + Object { + "x": 1599717720000, + "y": null, + }, + Object { + "x": 1599717750000, + "y": 1, + }, + Object { + "x": 1599717780000, + "y": 1, + }, + Object { + "x": 1599717810000, + "y": 1, + }, + Object { + "x": 1599717840000, + "y": null, + }, + Object { + "x": 1599717870000, + "y": null, + }, + Object { + "x": 1599717900000, + "y": 1, + }, + Object { + "x": 1599717930000, + "y": 1, + }, + Object { + "x": 1599717960000, + "y": null, + }, + Object { + "x": 1599717990000, + "y": 1, + }, + Object { + "x": 1599718020000, + "y": null, + }, + Object { + "x": 1599718050000, + "y": 1, + }, + Object { + "x": 1599718080000, + "y": null, + }, + Object { + "x": 1599718110000, + "y": 1, + }, + Object { + "x": 1599718140000, + "y": null, + }, + Object { + "x": 1599718170000, + "y": 1, + }, + Object { + "x": 1599718200000, + "y": null, + }, + Object { + "x": 1599718230000, + "y": 1, + }, + Object { + "x": 1599718260000, + "y": null, + }, + Object { + "x": 1599718290000, + "y": null, + }, + Object { + "x": 1599718320000, + "y": null, + }, + Object { + "x": 1599718350000, + "y": 1, + }, + Object { + "x": 1599718380000, + "y": 1, + }, + Object { + "x": 1599718410000, + "y": null, + }, + Object { + "x": 1599718440000, + "y": null, + }, + Object { + "x": 1599718470000, + "y": 1, + }, + Object { + "x": 1599718500000, + "y": 1, + }, + Object { + "x": 1599718530000, + "y": null, + }, + Object { + "x": 1599718560000, + "y": null, + }, + Object { + "x": 1599718590000, + "y": 1, + }, + Object { + "x": 1599718620000, + "y": null, + }, + Object { + "x": 1599718650000, + "y": 1, + }, + Object { + "x": 1599718680000, + "y": null, + }, + Object { + "x": 1599718710000, + "y": 1, + }, + Object { + "x": 1599718740000, + "y": 1, + }, + Object { + "x": 1599718770000, + "y": 1, + }, + Object { + "x": 1599718800000, + "y": null, + }, + Object { + "x": 1599718830000, + "y": null, + }, + Object { + "x": 1599718860000, + "y": null, + }, + Object { + "x": 1599718890000, + "y": 1, + }, + Object { + "x": 1599718920000, + "y": null, + }, + Object { + "x": 1599718950000, + "y": 1, + }, + Object { + "x": 1599718980000, + "y": null, + }, + Object { + "x": 1599719010000, + "y": null, + }, + Object { + "x": 1599719040000, + "y": 1, + }, + Object { + "x": 1599719070000, + "y": 1, + }, + Object { + "x": 1599719100000, + "y": null, + }, + Object { + "x": 1599719130000, + "y": 1, + }, + Object { + "x": 1599719160000, + "y": null, + }, + Object { + "x": 1599719190000, + "y": 1, + }, + Object { + "x": 1599719220000, + "y": 1, + }, + Object { + "x": 1599719250000, + "y": 1, + }, + Object { + "x": 1599719280000, + "y": null, + }, + Object { + "x": 1599719310000, + "y": 1, + }, + Object { + "x": 1599719340000, + "y": 1, + }, + Object { + "x": 1599719370000, + "y": null, + }, + Object { + "x": 1599719400000, + "y": null, + }, + Object { + "x": 1599719430000, + "y": 1, + }, + Object { + "x": 1599719460000, + "y": 1, + }, + Object { + "x": 1599719490000, + "y": null, + }, + Object { + "x": 1599719520000, + "y": 1, + }, + Object { + "x": 1599719550000, + "y": 1, + }, + Object { + "x": 1599719580000, + "y": null, + }, + Object { + "x": 1599719610000, + "y": null, + }, + Object { + "x": 1599719640000, + "y": null, + }, + Object { + "x": 1599719670000, + "y": 1, + }, + Object { + "x": 1599719700000, + "y": null, + }, + Object { + "x": 1599719730000, + "y": null, + }, + Object { + "x": 1599719760000, + "y": 1, + }, + Object { + "x": 1599719790000, + "y": 1, + }, + Object { + "x": 1599719820000, + "y": null, + }, + Object { + "x": 1599719850000, + "y": 1, + }, + Object { + "x": 1599719880000, + "y": null, + }, + Object { + "x": 1599719910000, + "y": 1, + }, + Object { + "x": 1599719940000, + "y": null, + }, + Object { + "x": 1599719970000, + "y": null, + }, + Object { + "x": 1599720000000, + "y": 1, + }, + Object { + "x": 1599720030000, + "y": 1, + }, + Object { + "x": 1599720060000, + "y": null, + }, + Object { + "x": 1599720090000, + "y": null, + }, + Object { + "x": 1599720120000, + "y": null, + }, + Object { + "x": 1599720150000, + "y": null, + }, + Object { + "x": 1599720180000, + "y": null, + }, + Object { + "x": 1599720210000, + "y": null, + }, + Object { + "x": 1599720240000, + "y": null, + }, + Object { + "x": 1599720270000, + "y": 1, + }, + Object { + "x": 1599720300000, + "y": null, + }, + Object { + "x": 1599720330000, + "y": 1, + }, + Object { + "x": 1599720360000, + "y": null, + }, + Object { + "x": 1599720390000, + "y": null, + }, + Object { + "x": 1599720420000, + "y": 1, + }, + Object { + "x": 1599720450000, + "y": 1, + }, + Object { + "x": 1599720480000, + "y": null, + }, + Object { + "x": 1599720510000, + "y": null, + }, + Object { + "x": 1599720540000, + "y": null, + }, + Object { + "x": 1599720570000, + "y": null, + }, + Object { + "x": 1599720600000, + "y": null, + }, + Object { + "x": 1599720630000, + "y": 1, + }, + Object { + "x": 1599720660000, + "y": null, + }, + Object { + "x": 1599720690000, + "y": null, + }, + Object { + "x": 1599720720000, + "y": null, + }, + Object { + "x": 1599720750000, + "y": 1, + }, + Object { + "x": 1599720780000, + "y": 1, + }, + Object { + "x": 1599720810000, + "y": 1, + }, + Object { + "x": 1599720840000, + "y": null, + }, + Object { + "x": 1599720870000, + "y": null, + }, + Object { + "x": 1599720900000, + "y": 1, + }, + Object { + "x": 1599720930000, + "y": 1, + }, + Object { + "x": 1599720960000, + "y": null, + }, + Object { + "x": 1599720990000, + "y": 1, + }, + Object { + "x": 1599721020000, + "y": null, + }, + Object { + "x": 1599721050000, + "y": null, + }, + Object { + "x": 1599721080000, + "y": null, + }, + Object { + "x": 1599721110000, + "y": 1, + }, + Object { + "x": 1599721140000, + "y": 1, + }, + Object { + "x": 1599721170000, + "y": null, + }, + Object { + "x": 1599721200000, + "y": null, + }, +] +`; diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/top_transaction_groups.snap b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/top_transaction_groups.snap index 16a5640c5305b..0a656d5c728a2 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/top_transaction_groups.snap +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/top_transaction_groups.snap @@ -3,130 +3,95 @@ exports[`Top transaction groups when data is loaded returns the correct buckets (when ignoring samples) 1`] = ` Array [ Object { - "averageResponseTime": 2577, + "averageResponseTime": 2612, "impact": 0, - "key": "GET /throw-error", - "p95": 3224, - "transactionsPerMinute": 0.5, - }, - Object { - "averageResponseTime": 4757, - "impact": 0.20830834986820673, - "key": "GET /api/products/:id/customers", - "p95": 5616, - "transactionsPerMinute": 0.5, - }, - Object { - "averageResponseTime": 4749.666666666667, - "impact": 0.43453312891085794, - "key": "GET /api/orders/:id", - "p95": 7184, - "transactionsPerMinute": 0.75, + "key": "POST /api/orders", + "p95": 2608, + "transactionsPerMinute": 0.016666666666666666, }, Object { - "averageResponseTime": 8181, - "impact": 0.5354862351657939, + "averageResponseTime": 8710, + "impact": 0.21594473634705155, "key": "GET /api/types/:id", - "p95": 10080, - "transactionsPerMinute": 0.5, - }, - Object { - "averageResponseTime": 20011, - "impact": 0.7098250353192541, - "key": "POST /api", - "p95": 19968, - "transactionsPerMinute": 0.25, - }, - Object { - "averageResponseTime": 35846, - "impact": 1.466376117925459, - "key": "GET /log-error", - "p95": 35840, - "transactionsPerMinute": 0.25, + "p95": 8832, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 7105.333333333333, - "impact": 1.7905918202662048, - "key": "GET /api/stats", - "p95": 15136, - "transactionsPerMinute": 1.5, + "averageResponseTime": 15469, + "impact": 0.41307743123761353, + "key": "GET /api/products/:id/customers", + "p95": 17728, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 22958.5, - "impact": 1.9475397398343375, - "key": "GET /api/products/top", - "p95": 33216, - "transactionsPerMinute": 0.5, + "averageResponseTime": 11161.5, + "impact": 0.6129808919240927, + "key": "GET /api/customers/:id", + "p95": 16096, + "transactionsPerMinute": 0.06666666666666667, }, Object { - "averageResponseTime": 3492.9285714285716, - "impact": 2.0901067389184496, - "key": "GET static file", - "p95": 11900, - "transactionsPerMinute": 3.5, + "averageResponseTime": 8115.166666666667, + "impact": 0.6719690374213795, + "key": "GET /api/types", + "p95": 12336, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 26992.5, - "impact": 2.3330057413794503, - "key": "GET /api/types", - "p95": 45248, - "transactionsPerMinute": 0.5, + "averageResponseTime": 10863.6, + "impact": 0.7540274539141442, + "key": "GET /api/orders/:id", + "p95": 20192, + "transactionsPerMinute": 0.08333333333333333, }, Object { - "averageResponseTime": 13516.5, - "impact": 2.3368756900811305, + "averageResponseTime": 9906, + "impact": 0.8286631346694258, "key": "GET /api/products/:id", - "p95": 37856, - "transactionsPerMinute": 1, + "p95": 13280, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 8585, - "impact": 2.624924094061731, + "averageResponseTime": 8524.454545454546, + "impact": 1.329340513991638, "key": "GET /api/products", - "p95": 22112, - "transactionsPerMinute": 1.75, + "p95": 14256, + "transactionsPerMinute": 0.18333333333333332, }, Object { - "averageResponseTime": 7615.625, - "impact": 2.6645791239678345, + "averageResponseTime": 12947, + "impact": 1.472355777994578, "key": "GET /api/orders", - "p95": 11616, - "transactionsPerMinute": 2, + "p95": 25584, + "transactionsPerMinute": 0.13333333333333333, }, Object { - "averageResponseTime": 3262.95, - "impact": 2.8716452680799467, - "key": "GET /*", - "p95": 4472, - "transactionsPerMinute": 5, - }, - Object { - "averageResponseTime": 32667.5, - "impact": 2.875276331059301, - "key": "GET /log-message", - "p95": 38528, - "transactionsPerMinute": 0.5, + "averageResponseTime": 11307.75, + "impact": 2.6003199505345393, + "key": "GET /api/products/top", + "p95": 16304, + "transactionsPerMinute": 0.26666666666666666, }, Object { - "averageResponseTime": 16896.8, - "impact": 3.790160870423129, + "averageResponseTime": 26755.666666666668, + "impact": 4.644036801602961, "key": "GET /api/customers", - "p95": 26432, - "transactionsPerMinute": 1.25, + "p95": 39104, + "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 270684, - "impact": 12.686265169840583, - "key": "POST /api/orders", - "p95": 270336, - "transactionsPerMinute": 0.25, + "averageResponseTime": 17851.384615384617, + "impact": 6.730394279972759, + "key": "GET /api/stats", + "p95": 24416, + "transactionsPerMinute": 0.43333333333333335, }, Object { - "averageResponseTime": 51175.73170731707, + "averageResponseTime": 61249.30357142857, "impact": 100, "key": "GET /api", - "p95": 259040, - "transactionsPerMinute": 10.25, + "p95": 162784, + "transactionsPerMinute": 1.8666666666666667, }, ] `; diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/transaction_charts.snap b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/transaction_charts.snap index 0ac7741396fd4..c4b9e1ad6c931 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/transaction_charts.snap +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/transaction_charts.snap @@ -1,7755 +1,3425 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Transaction charts when data is loaded returns the transaction charts 1`] = ` +exports[`Transaction charts when data is loaded returns the correct data 4`] = ` Object { "apmTimeseries": Object { - "overallAvgDuration": 38682.52419354839, + "overallAvgDuration": 578297.1431623931, "responseTimes": Object { "avg": Array [ Object { - "x": 1593413100000, - "y": null, + "x": 1599717600000, + "y": 311706, }, Object { - "x": 1593413101000, - "y": null, + "x": 1599717630000, + "y": 885570.5, }, Object { - "x": 1593413102000, - "y": null, + "x": 1599717660000, + "y": 388852.6666666667, }, Object { - "x": 1593413103000, - "y": null, + "x": 1599717690000, + "y": 503725.75, }, Object { - "x": 1593413104000, - "y": null, + "x": 1599717720000, + "y": 647100.2857142857, }, Object { - "x": 1593413105000, - "y": null, + "x": 1599717750000, + "y": 658360.4285714285, }, Object { - "x": 1593413106000, - "y": null, + "x": 1599717780000, + "y": 308246.25, }, Object { - "x": 1593413107000, - "y": null, + "x": 1599717810000, + "y": 1104229.3333333333, }, Object { - "x": 1593413108000, - "y": null, + "x": 1599717840000, + "y": 438727.6666666667, }, Object { - "x": 1593413109000, - "y": null, + "x": 1599717870000, + "y": 475918, }, Object { - "x": 1593413110000, - "y": null, + "x": 1599717900000, + "y": 254092.33333333334, }, Object { - "x": 1593413111000, - "y": null, + "x": 1599717930000, + "y": 1103846.6666666667, }, Object { - "x": 1593413112000, - "y": null, + "x": 1599717960000, + "y": 70868.8, }, Object { - "x": 1593413113000, - "y": null, + "x": 1599717990000, + "y": 384811.5, }, Object { - "x": 1593413114000, - "y": null, + "x": 1599718020000, + "y": 1139810, }, Object { - "x": 1593413115000, - "y": null, + "x": 1599718050000, + "y": 938950, }, Object { - "x": 1593413116000, - "y": null, + "x": 1599718080000, + "y": 286195.4285714286, }, Object { - "x": 1593413117000, - "y": null, + "x": 1599718110000, + "y": 373445.5, }, Object { - "x": 1593413118000, - "y": null, + "x": 1599718140000, + "y": 747249.6, }, Object { - "x": 1593413119000, - "y": null, + "x": 1599718170000, + "y": 1110552.6666666667, }, Object { - "x": 1593413120000, - "y": null, + "x": 1599718200000, + "y": 206614.66666666666, }, Object { - "x": 1593413121000, - "y": null, + "x": 1599718230000, + "y": 412294, }, Object { - "x": 1593413122000, - "y": null, + "x": 1599718260000, + "y": 643594, }, Object { - "x": 1593413123000, - "y": null, + "x": 1599718290000, + "y": 973397.5, }, Object { - "x": 1593413124000, - "y": null, + "x": 1599718320000, + "y": 521419, }, Object { - "x": 1593413125000, - "y": null, + "x": 1599718350000, + "y": 543694.3333333334, }, Object { - "x": 1593413126000, - "y": null, + "x": 1599718380000, + "y": 503212.8, }, Object { - "x": 1593413127000, - "y": null, + "x": 1599718410000, + "y": 1516441.5, }, Object { - "x": 1593413128000, - "y": null, + "x": 1599718440000, + "y": 457890.2, }, Object { - "x": 1593413129000, - "y": null, + "x": 1599718470000, + "y": 160177.55555555556, }, Object { - "x": 1593413130000, - "y": null, + "x": 1599718500000, + "y": 497083.6666666667, }, Object { - "x": 1593413131000, - "y": null, + "x": 1599718530000, + "y": 1276293, }, Object { - "x": 1593413132000, - "y": null, + "x": 1599718560000, + "y": 194131.8, }, Object { - "x": 1593413133000, - "y": null, + "x": 1599718590000, + "y": 1177525, }, Object { - "x": 1593413134000, - "y": null, + "x": 1599718620000, + "y": 504225.2, }, Object { - "x": 1593413135000, - "y": null, + "x": 1599718650000, + "y": 1397496, }, Object { - "x": 1593413136000, - "y": null, + "x": 1599718680000, + "y": 523145, }, Object { - "x": 1593413137000, - "y": null, + "x": 1599718710000, + "y": 355926.6, }, Object { - "x": 1593413138000, - "y": null, + "x": 1599718740000, + "y": 615277, }, Object { - "x": 1593413139000, - "y": null, + "x": 1599718770000, + "y": 725578, }, Object { - "x": 1593413140000, - "y": null, + "x": 1599718800000, + "y": 1721893.5, }, Object { - "x": 1593413141000, - "y": null, + "x": 1599718830000, + "y": 579859.75, }, Object { - "x": 1593413142000, - "y": null, + "x": 1599718860000, + "y": 371836.6, }, Object { - "x": 1593413143000, - "y": null, + "x": 1599718890000, + "y": 1192755.5, }, Object { - "x": 1593413144000, - "y": null, + "x": 1599718920000, + "y": 288524, }, Object { - "x": 1593413145000, - "y": null, + "x": 1599718950000, + "y": 1220730, }, Object { - "x": 1593413146000, - "y": null, + "x": 1599718980000, + "y": 591210.6666666666, }, Object { - "x": 1593413147000, - "y": null, + "x": 1599719010000, + "y": 601443.6666666666, }, Object { - "x": 1593413148000, - "y": null, + "x": 1599719040000, + "y": 225148, }, Object { - "x": 1593413149000, - "y": null, + "x": 1599719070000, + "y": 885271.5, }, Object { - "x": 1593413150000, - "y": null, + "x": 1599719100000, + "y": 578708.25, }, Object { - "x": 1593413151000, - "y": null, + "x": 1599719130000, + "y": 979768.3333333334, }, Object { - "x": 1593413152000, - "y": null, + "x": 1599719160000, + "y": 334608.71428571426, }, Object { - "x": 1593413153000, - "y": null, + "x": 1599719190000, + "y": 555571, }, Object { - "x": 1593413154000, - "y": null, + "x": 1599719220000, + "y": 249780.66666666666, }, Object { - "x": 1593413155000, + "x": 1599719250000, "y": null, }, Object { - "x": 1593413156000, - "y": null, + "x": 1599719280000, + "y": 510084, }, Object { - "x": 1593413157000, - "y": null, + "x": 1599719310000, + "y": 14228.333333333334, }, Object { - "x": 1593413158000, - "y": null, + "x": 1599719340000, + "y": 1056348.5, }, Object { - "x": 1593413159000, - "y": null, + "x": 1599719370000, + "y": 1150066, }, Object { - "x": 1593413160000, - "y": null, + "x": 1599719400000, + "y": 456110.5833333333, }, Object { - "x": 1593413161000, - "y": null, + "x": 1599719430000, + "y": 333431, }, Object { - "x": 1593413162000, - "y": null, + "x": 1599719460000, + "y": 1157360.6666666667, }, Object { - "x": 1593413163000, - "y": null, + "x": 1599719490000, + "y": 687888.75, }, Object { - "x": 1593413164000, - "y": null, + "x": 1599719520000, + "y": 574561, }, Object { - "x": 1593413165000, - "y": null, + "x": 1599719550000, + "y": 893728, }, Object { - "x": 1593413166000, - "y": null, + "x": 1599719580000, + "y": 773178.4, }, Object { - "x": 1593413167000, - "y": null, + "x": 1599719610000, + "y": 928312, }, Object { - "x": 1593413168000, - "y": null, + "x": 1599719640000, + "y": 371156.14285714284, }, Object { - "x": 1593413169000, - "y": null, + "x": 1599719670000, + "y": 464665.6666666667, }, Object { - "x": 1593413170000, + "x": 1599719700000, "y": null, }, Object { - "x": 1593413171000, - "y": null, + "x": 1599719730000, + "y": 426927.5, }, Object { - "x": 1593413172000, - "y": null, + "x": 1599719760000, + "y": 552956.7142857143, }, Object { - "x": 1593413173000, - "y": null, + "x": 1599719790000, + "y": 1099390, }, Object { - "x": 1593413174000, - "y": null, + "x": 1599719820000, + "y": 675592.75, }, Object { - "x": 1593413175000, - "y": null, + "x": 1599719850000, + "y": 1212971, }, Object { - "x": 1593413176000, - "y": null, + "x": 1599719880000, + "y": 169532.16666666666, }, Object { - "x": 1593413177000, - "y": null, + "x": 1599719910000, + "y": 1116040.6666666667, }, Object { - "x": 1593413178000, - "y": null, + "x": 1599719940000, + "y": 832511.3333333334, }, Object { - "x": 1593413179000, - "y": null, + "x": 1599719970000, + "y": 838424.75, }, Object { - "x": 1593413180000, - "y": null, + "x": 1599720000000, + "y": 705166, }, Object { - "x": 1593413181000, - "y": null, + "x": 1599720030000, + "y": 881526.3333333334, }, Object { - "x": 1593413182000, - "y": null, + "x": 1599720060000, + "y": 493560.5, }, Object { - "x": 1593413183000, - "y": null, + "x": 1599720090000, + "y": 1272019, }, Object { - "x": 1593413184000, - "y": null, + "x": 1599720120000, + "y": 1571697, }, Object { - "x": 1593413185000, - "y": null, + "x": 1599720150000, + "y": 947327.6666666666, }, Object { - "x": 1593413186000, - "y": null, + "x": 1599720180000, + "y": 770506, }, Object { - "x": 1593413187000, - "y": null, + "x": 1599720210000, + "y": 1476976, }, Object { - "x": 1593413188000, - "y": null, + "x": 1599720240000, + "y": 394579.5714285714, }, Object { - "x": 1593413189000, - "y": null, + "x": 1599720270000, + "y": 793661, }, Object { - "x": 1593413190000, - "y": null, + "x": 1599720300000, + "y": 698110.25, }, Object { - "x": 1593413191000, - "y": null, + "x": 1599720330000, + "y": 1623979, }, Object { - "x": 1593413192000, - "y": null, + "x": 1599720360000, + "y": 766940, }, Object { - "x": 1593413193000, - "y": null, + "x": 1599720390000, + "y": 516763.3, }, Object { - "x": 1593413194000, - "y": null, + "x": 1599720420000, + "y": 227079.66666666666, }, Object { - "x": 1593413195000, - "y": null, + "x": 1599720450000, + "y": 1235171, }, Object { - "x": 1593413196000, - "y": null, + "x": 1599720480000, + "y": 1110705.3333333333, }, Object { - "x": 1593413197000, - "y": null, + "x": 1599720510000, + "y": 457118, }, Object { - "x": 1593413198000, - "y": null, + "x": 1599720540000, + "y": 1113258, }, Object { - "x": 1593413199000, - "y": null, + "x": 1599720570000, + "y": 780817, }, Object { - "x": 1593413200000, - "y": null, + "x": 1599720600000, + "y": 396914.6666666667, }, Object { - "x": 1593413201000, - "y": null, + "x": 1599720630000, + "y": 323583.1666666667, }, Object { - "x": 1593413202000, - "y": null, + "x": 1599720660000, + "y": 788903.3333333334, }, Object { - "x": 1593413203000, - "y": null, + "x": 1599720690000, + "y": 339649, }, Object { - "x": 1593413204000, - "y": null, + "x": 1599720720000, + "y": 501015, }, Object { - "x": 1593413205000, - "y": null, + "x": 1599720750000, + "y": 501758.5, }, Object { - "x": 1593413206000, - "y": null, + "x": 1599720780000, + "y": 776868, }, Object { - "x": 1593413207000, - "y": null, + "x": 1599720810000, + "y": 1198145, }, Object { - "x": 1593413208000, - "y": null, + "x": 1599720840000, + "y": 561771.6666666666, }, Object { - "x": 1593413209000, - "y": null, + "x": 1599720870000, + "y": 594213.3333333334, }, Object { - "x": 1593413210000, - "y": null, + "x": 1599720900000, + "y": 188626.5, }, Object { - "x": 1593413211000, - "y": null, + "x": 1599720930000, + "y": 970632, }, Object { - "x": 1593413212000, - "y": null, + "x": 1599720960000, + "y": 750907.2, }, Object { - "x": 1593413213000, - "y": null, + "x": 1599720990000, + "y": 851925.25, }, Object { - "x": 1593413214000, - "y": null, + "x": 1599721020000, + "y": 774642.5, }, Object { - "x": 1593413215000, - "y": null, + "x": 1599721050000, + "y": 322259.5, }, Object { - "x": 1593413216000, - "y": null, + "x": 1599721080000, + "y": 369298.28571428574, }, Object { - "x": 1593413217000, - "y": null, + "x": 1599721110000, + "y": 657293.6666666666, }, Object { - "x": 1593413218000, - "y": null, + "x": 1599721140000, + "y": 479701.3333333333, }, Object { - "x": 1593413219000, - "y": null, + "x": 1599721170000, + "y": 1037489, }, Object { - "x": 1593413220000, + "x": 1599721200000, "y": null, }, + ], + "p95": Array [ Object { - "x": 1593413221000, - "y": null, + "x": 1599717600000, + "y": 483072, }, Object { - "x": 1593413222000, - "y": null, + "x": 1599717630000, + "y": 1310592, }, Object { - "x": 1593413223000, - "y": null, + "x": 1599717660000, + "y": 970688, }, Object { - "x": 1593413224000, - "y": null, + "x": 1599717690000, + "y": 814080, }, Object { - "x": 1593413225000, - "y": null, + "x": 1599717720000, + "y": 1449920, }, Object { - "x": 1593413226000, - "y": null, + "x": 1599717750000, + "y": 1302496, }, Object { - "x": 1593413227000, - "y": null, + "x": 1599717780000, + "y": 622464, }, Object { - "x": 1593413228000, - "y": null, + "x": 1599717810000, + "y": 1323008, }, Object { - "x": 1593413229000, - "y": null, + "x": 1599717840000, + "y": 1003456, }, Object { - "x": 1593413230000, - "y": null, + "x": 1599717870000, + "y": 1195904, }, Object { - "x": 1593413231000, - "y": null, + "x": 1599717900000, + "y": 692096, }, Object { - "x": 1593413232000, - "y": null, + "x": 1599717930000, + "y": 1904640, }, Object { - "x": 1593413233000, - "y": null, + "x": 1599717960000, + "y": 268224, }, Object { - "x": 1593413234000, - "y": null, + "x": 1599717990000, + "y": 1171424, }, Object { - "x": 1593413235000, - "y": null, + "x": 1599718020000, + "y": 1908480, }, Object { - "x": 1593413236000, - "y": null, + "x": 1599718050000, + "y": 937984, }, Object { - "x": 1593413237000, - "y": null, + "x": 1599718080000, + "y": 982912, }, Object { - "x": 1593413238000, - "y": null, + "x": 1599718110000, + "y": 733120, }, Object { - "x": 1593413239000, - "y": null, + "x": 1599718140000, + "y": 1736576, }, Object { - "x": 1593413240000, - "y": null, + "x": 1599718170000, + "y": 1748992, }, Object { - "x": 1593413241000, - "y": null, + "x": 1599718200000, + "y": 970720, }, Object { - "x": 1593413242000, - "y": null, + "x": 1599718230000, + "y": 1540032, }, Object { - "x": 1593413243000, - "y": null, + "x": 1599718260000, + "y": 796672, }, Object { - "x": 1593413244000, - "y": null, + "x": 1599718290000, + "y": 1134592, }, Object { - "x": 1593413245000, - "y": null, + "x": 1599718320000, + "y": 1875904, }, Object { - "x": 1593413246000, - "y": null, + "x": 1599718350000, + "y": 1253312, }, Object { - "x": 1593413247000, - "y": null, + "x": 1599718380000, + "y": 1048512, }, Object { - "x": 1593413248000, - "y": null, + "x": 1599718410000, + "y": 1654784, }, Object { - "x": 1593413249000, - "y": null, + "x": 1599718440000, + "y": 1368048, }, Object { - "x": 1593413250000, - "y": null, + "x": 1599718470000, + "y": 745456, }, Object { - "x": 1593413251000, - "y": null, + "x": 1599718500000, + "y": 1277696, }, Object { - "x": 1593413252000, - "y": null, + "x": 1599718530000, + "y": 1699840, }, Object { - "x": 1593413253000, - "y": null, + "x": 1599718560000, + "y": 1851376, }, Object { - "x": 1593413254000, - "y": null, + "x": 1599718590000, + "y": 1277952, }, Object { - "x": 1593413255000, - "y": null, + "x": 1599718620000, + "y": 1384320, }, Object { - "x": 1593413256000, - "y": null, + "x": 1599718650000, + "y": 1392640, }, Object { - "x": 1593413257000, - "y": null, + "x": 1599718680000, + "y": 1785792, }, Object { - "x": 1593413258000, - "y": null, + "x": 1599718710000, + "y": 1236928, }, Object { - "x": 1593413259000, - "y": null, + "x": 1599718740000, + "y": 1138176, }, Object { - "x": 1593413260000, - "y": null, + "x": 1599718770000, + "y": 1474432, }, Object { - "x": 1593413261000, - "y": null, + "x": 1599718800000, + "y": 1875968, }, Object { - "x": 1593413262000, - "y": null, + "x": 1599718830000, + "y": 1703920, }, Object { - "x": 1593413263000, - "y": null, + "x": 1599718860000, + "y": 1466240, }, Object { - "x": 1593413264000, - "y": null, + "x": 1599718890000, + "y": 1286144, }, Object { - "x": 1593413265000, - "y": null, + "x": 1599718920000, + "y": 831424, }, Object { - "x": 1593413266000, - "y": null, + "x": 1599718950000, + "y": 1253376, }, Object { - "x": 1593413267000, - "y": null, + "x": 1599718980000, + "y": 822272, }, Object { - "x": 1593413268000, - "y": null, + "x": 1599719010000, + "y": 1540032, }, Object { - "x": 1593413269000, - "y": null, + "x": 1599719040000, + "y": 1269728, }, Object { - "x": 1593413270000, - "y": null, + "x": 1599719070000, + "y": 1531872, }, Object { - "x": 1593413271000, - "y": null, + "x": 1599719100000, + "y": 1507264, }, Object { - "x": 1593413272000, - "y": 45093, + "x": 1599719130000, + "y": 1216512, }, Object { - "x": 1593413273000, - "y": 7498, + "x": 1599719160000, + "y": 909248, }, Object { - "x": 1593413274000, - "y": null, + "x": 1599719190000, + "y": 1097600, }, Object { - "x": 1593413275000, - "y": null, + "x": 1599719220000, + "y": 786416, }, Object { - "x": 1593413276000, + "x": 1599719250000, "y": null, }, Object { - "x": 1593413277000, - "y": 37709, + "x": 1599719280000, + "y": 1212352, }, Object { - "x": 1593413278000, - "y": null, + "x": 1599719310000, + "y": 19040, }, Object { - "x": 1593413279000, - "y": null, + "x": 1599719340000, + "y": 1077248, }, Object { - "x": 1593413280000, - "y": null, + "x": 1599719370000, + "y": 1146880, }, Object { - "x": 1593413281000, - "y": 33097, + "x": 1599719400000, + "y": 1777600, }, Object { - "x": 1593413282000, - "y": null, + "x": 1599719430000, + "y": 1261504, }, Object { - "x": 1593413283000, - "y": null, + "x": 1599719460000, + "y": 1617920, }, Object { - "x": 1593413284000, - "y": 388507, + "x": 1599719490000, + "y": 1105664, }, Object { - "x": 1593413285000, - "y": 42331.5, + "x": 1599719520000, + "y": 1163008, }, Object { - "x": 1593413286000, - "y": 99104.25, + "x": 1599719550000, + "y": 892928, }, Object { - "x": 1593413287000, - "y": 18939.5, + "x": 1599719580000, + "y": 1343360, }, Object { - "x": 1593413288000, - "y": 23229.5, + "x": 1599719610000, + "y": 925696, }, Object { - "x": 1593413289000, - "y": 11318, + "x": 1599719640000, + "y": 1277936, }, Object { - "x": 1593413290000, - "y": 15651.25, + "x": 1599719670000, + "y": 1499072, }, Object { - "x": 1593413291000, - "y": 2376, + "x": 1599719700000, + "y": null, }, Object { - "x": 1593413292000, - "y": 7796, + "x": 1599719730000, + "y": 1204096, }, Object { - "x": 1593413293000, - "y": 7571, + "x": 1599719760000, + "y": 1572800, }, Object { - "x": 1593413294000, - "y": 4219.333333333333, + "x": 1599719790000, + "y": 1097728, }, Object { - "x": 1593413295000, - "y": 6827.5, + "x": 1599719820000, + "y": 1376128, }, Object { - "x": 1593413296000, - "y": 10415.5, + "x": 1599719850000, + "y": 1277952, }, Object { - "x": 1593413297000, - "y": 10082, + "x": 1599719880000, + "y": 815072, }, Object { - "x": 1593413298000, - "y": 6459.375, + "x": 1599719910000, + "y": 1765376, }, Object { - "x": 1593413299000, - "y": 3131.5, + "x": 1599719940000, + "y": 937984, }, Object { - "x": 1593413300000, - "y": 6713.333333333333, + "x": 1599719970000, + "y": 1687488, }, Object { - "x": 1593413301000, - "y": 8800, + "x": 1599720000000, + "y": 1212352, }, Object { - "x": 1593413302000, - "y": 3743.5, + "x": 1599720030000, + "y": 1441728, }, Object { - "x": 1593413303000, - "y": 9239.5, + "x": 1599720060000, + "y": 970624, }, Object { - "x": 1593413304000, - "y": 8402, + "x": 1599720090000, + "y": 1409024, }, Object { - "x": 1593413305000, - "y": 20520.666666666668, + "x": 1599720120000, + "y": 1564672, }, Object { - "x": 1593413306000, - "y": 9319.5, + "x": 1599720150000, + "y": 1447936, }, Object { - "x": 1593413307000, - "y": 7694.333333333333, + "x": 1599720180000, + "y": 1195904, }, Object { - "x": 1593413308000, - "y": 20131, + "x": 1599720210000, + "y": 1474560, }, Object { - "x": 1593413309000, - "y": 439937.75, + "x": 1599720240000, + "y": 1220544, }, Object { - "x": 1593413310000, - "y": 11933, + "x": 1599720270000, + "y": 1261504, }, Object { - "x": 1593413311000, - "y": 18670.5, + "x": 1599720300000, + "y": 1712064, }, Object { - "x": 1593413312000, - "y": 9232, + "x": 1599720330000, + "y": 1622016, }, Object { - "x": 1593413313000, - "y": 7602, + "x": 1599720360000, + "y": 1245120, }, Object { - "x": 1593413314000, - "y": 10428.8, + "x": 1599720390000, + "y": 1646560, }, Object { - "x": 1593413315000, - "y": 8405.25, + "x": 1599720420000, + "y": 970688, }, Object { - "x": 1593413316000, - "y": 10654.5, + "x": 1599720450000, + "y": 1228800, }, Object { - "x": 1593413317000, - "y": 10250, + "x": 1599720480000, + "y": 1191936, }, Object { - "x": 1593413318000, - "y": 5775, + "x": 1599720510000, + "y": 1572832, }, Object { - "x": 1593413319000, - "y": 137867, + "x": 1599720540000, + "y": 1200128, }, Object { - "x": 1593413320000, - "y": 5694.333333333333, + "x": 1599720570000, + "y": 1071104, }, Object { - "x": 1593413321000, - "y": 6115, + "x": 1599720600000, + "y": 1130368, }, Object { - "x": 1593413322000, - "y": 1832.5, + "x": 1599720630000, + "y": 933824, }, Object { - "x": 1593413323000, - "y": null, + "x": 1599720660000, + "y": 1220544, }, Object { - "x": 1593413324000, - "y": null, + "x": 1599720690000, + "y": 337920, }, Object { - "x": 1593413325000, - "y": null, + "x": 1599720720000, + "y": 1032128, }, Object { - "x": 1593413326000, - "y": null, + "x": 1599720750000, + "y": 1736672, }, Object { - "x": 1593413327000, - "y": null, + "x": 1599720780000, + "y": 1843136, }, Object { - "x": 1593413328000, - "y": null, + "x": 1599720810000, + "y": 1404928, }, Object { - "x": 1593413329000, - "y": null, + "x": 1599720840000, + "y": 1036160, }, Object { - "x": 1593413330000, - "y": null, + "x": 1599720870000, + "y": 1351552, }, Object { - "x": 1593413331000, - "y": null, + "x": 1599720900000, + "y": 720864, }, Object { - "x": 1593413332000, - "y": null, + "x": 1599720930000, + "y": 966656, }, Object { - "x": 1593413333000, - "y": null, + "x": 1599720960000, + "y": 1892224, }, Object { - "x": 1593413334000, - "y": null, + "x": 1599720990000, + "y": 1384320, }, Object { - "x": 1593413335000, - "y": null, + "x": 1599721020000, + "y": 1540032, }, Object { - "x": 1593413336000, - "y": null, + "x": 1599721050000, + "y": 451584, }, Object { - "x": 1593413337000, - "y": null, + "x": 1599721080000, + "y": 1228768, }, Object { - "x": 1593413338000, - "y": null, + "x": 1599721110000, + "y": 927744, }, Object { - "x": 1593413339000, - "y": null, + "x": 1599721140000, + "y": 1048320, }, Object { - "x": 1593413340000, + "x": 1599721170000, + "y": 1363968, + }, + Object { + "x": 1599721200000, "y": null, }, ], - "p95": Array [ + "p99": Array [ Object { - "x": 1593413100000, - "y": null, + "x": 1599717600000, + "y": 483072, }, Object { - "x": 1593413101000, - "y": null, + "x": 1599717630000, + "y": 1310592, }, Object { - "x": 1593413102000, - "y": null, + "x": 1599717660000, + "y": 970688, }, Object { - "x": 1593413103000, - "y": null, + "x": 1599717690000, + "y": 814080, }, Object { - "x": 1593413104000, - "y": null, + "x": 1599717720000, + "y": 1449920, }, Object { - "x": 1593413105000, - "y": null, + "x": 1599717750000, + "y": 1302496, }, Object { - "x": 1593413106000, - "y": null, + "x": 1599717780000, + "y": 622464, }, Object { - "x": 1593413107000, - "y": null, + "x": 1599717810000, + "y": 1323008, }, Object { - "x": 1593413108000, - "y": null, + "x": 1599717840000, + "y": 1003456, }, Object { - "x": 1593413109000, - "y": null, + "x": 1599717870000, + "y": 1195904, }, Object { - "x": 1593413110000, - "y": null, + "x": 1599717900000, + "y": 692096, }, Object { - "x": 1593413111000, - "y": null, + "x": 1599717930000, + "y": 1904640, }, Object { - "x": 1593413112000, - "y": null, + "x": 1599717960000, + "y": 268224, }, Object { - "x": 1593413113000, - "y": null, + "x": 1599717990000, + "y": 1171424, }, Object { - "x": 1593413114000, - "y": null, + "x": 1599718020000, + "y": 1908480, }, Object { - "x": 1593413115000, - "y": null, + "x": 1599718050000, + "y": 937984, }, Object { - "x": 1593413116000, - "y": null, + "x": 1599718080000, + "y": 982912, }, Object { - "x": 1593413117000, - "y": null, + "x": 1599718110000, + "y": 733120, }, Object { - "x": 1593413118000, - "y": null, + "x": 1599718140000, + "y": 1736576, }, Object { - "x": 1593413119000, - "y": null, + "x": 1599718170000, + "y": 1748992, }, Object { - "x": 1593413120000, - "y": null, + "x": 1599718200000, + "y": 970720, }, Object { - "x": 1593413121000, - "y": null, + "x": 1599718230000, + "y": 1540032, }, Object { - "x": 1593413122000, - "y": null, + "x": 1599718260000, + "y": 796672, }, Object { - "x": 1593413123000, - "y": null, + "x": 1599718290000, + "y": 1134592, }, Object { - "x": 1593413124000, - "y": null, + "x": 1599718320000, + "y": 1875904, }, Object { - "x": 1593413125000, - "y": null, + "x": 1599718350000, + "y": 1253312, }, Object { - "x": 1593413126000, - "y": null, + "x": 1599718380000, + "y": 1048512, }, Object { - "x": 1593413127000, - "y": null, + "x": 1599718410000, + "y": 1654784, }, Object { - "x": 1593413128000, - "y": null, + "x": 1599718440000, + "y": 1368048, }, Object { - "x": 1593413129000, - "y": null, + "x": 1599718470000, + "y": 745456, }, Object { - "x": 1593413130000, - "y": null, + "x": 1599718500000, + "y": 1277696, }, Object { - "x": 1593413131000, - "y": null, + "x": 1599718530000, + "y": 1699840, }, Object { - "x": 1593413132000, - "y": null, + "x": 1599718560000, + "y": 1851376, }, Object { - "x": 1593413133000, - "y": null, + "x": 1599718590000, + "y": 1277952, }, Object { - "x": 1593413134000, - "y": null, + "x": 1599718620000, + "y": 1384320, }, Object { - "x": 1593413135000, - "y": null, + "x": 1599718650000, + "y": 1392640, }, Object { - "x": 1593413136000, - "y": null, + "x": 1599718680000, + "y": 1785792, }, Object { - "x": 1593413137000, - "y": null, + "x": 1599718710000, + "y": 1236928, }, Object { - "x": 1593413138000, - "y": null, + "x": 1599718740000, + "y": 1138176, }, Object { - "x": 1593413139000, - "y": null, + "x": 1599718770000, + "y": 1474432, }, Object { - "x": 1593413140000, - "y": null, + "x": 1599718800000, + "y": 1875968, }, Object { - "x": 1593413141000, - "y": null, + "x": 1599718830000, + "y": 1703920, }, Object { - "x": 1593413142000, - "y": null, + "x": 1599718860000, + "y": 1466240, }, Object { - "x": 1593413143000, - "y": null, + "x": 1599718890000, + "y": 1286144, }, Object { - "x": 1593413144000, - "y": null, + "x": 1599718920000, + "y": 831424, }, Object { - "x": 1593413145000, - "y": null, + "x": 1599718950000, + "y": 1253376, }, Object { - "x": 1593413146000, - "y": null, + "x": 1599718980000, + "y": 822272, }, Object { - "x": 1593413147000, - "y": null, + "x": 1599719010000, + "y": 1540032, }, Object { - "x": 1593413148000, - "y": null, + "x": 1599719040000, + "y": 1269728, }, Object { - "x": 1593413149000, - "y": null, + "x": 1599719070000, + "y": 1531872, }, Object { - "x": 1593413150000, - "y": null, + "x": 1599719100000, + "y": 1507264, }, Object { - "x": 1593413151000, - "y": null, + "x": 1599719130000, + "y": 1216512, }, Object { - "x": 1593413152000, - "y": null, + "x": 1599719160000, + "y": 909248, }, Object { - "x": 1593413153000, - "y": null, + "x": 1599719190000, + "y": 1097600, }, Object { - "x": 1593413154000, - "y": null, + "x": 1599719220000, + "y": 786416, }, Object { - "x": 1593413155000, + "x": 1599719250000, "y": null, }, Object { - "x": 1593413156000, - "y": null, + "x": 1599719280000, + "y": 1212352, }, Object { - "x": 1593413157000, - "y": null, - }, - Object { - "x": 1593413158000, - "y": null, - }, - Object { - "x": 1593413159000, - "y": null, - }, - Object { - "x": 1593413160000, - "y": null, - }, - Object { - "x": 1593413161000, - "y": null, - }, - Object { - "x": 1593413162000, - "y": null, - }, - Object { - "x": 1593413163000, - "y": null, - }, - Object { - "x": 1593413164000, - "y": null, - }, - Object { - "x": 1593413165000, - "y": null, - }, - Object { - "x": 1593413166000, - "y": null, - }, - Object { - "x": 1593413167000, - "y": null, - }, - Object { - "x": 1593413168000, - "y": null, - }, - Object { - "x": 1593413169000, - "y": null, - }, - Object { - "x": 1593413170000, - "y": null, - }, - Object { - "x": 1593413171000, - "y": null, - }, - Object { - "x": 1593413172000, - "y": null, - }, - Object { - "x": 1593413173000, - "y": null, - }, - Object { - "x": 1593413174000, - "y": null, - }, - Object { - "x": 1593413175000, - "y": null, - }, - Object { - "x": 1593413176000, - "y": null, - }, - Object { - "x": 1593413177000, - "y": null, - }, - Object { - "x": 1593413178000, - "y": null, - }, - Object { - "x": 1593413179000, - "y": null, - }, - Object { - "x": 1593413180000, - "y": null, - }, - Object { - "x": 1593413181000, - "y": null, - }, - Object { - "x": 1593413182000, - "y": null, - }, - Object { - "x": 1593413183000, - "y": null, - }, - Object { - "x": 1593413184000, - "y": null, - }, - Object { - "x": 1593413185000, - "y": null, - }, - Object { - "x": 1593413186000, - "y": null, - }, - Object { - "x": 1593413187000, - "y": null, - }, - Object { - "x": 1593413188000, - "y": null, - }, - Object { - "x": 1593413189000, - "y": null, - }, - Object { - "x": 1593413190000, - "y": null, - }, - Object { - "x": 1593413191000, - "y": null, - }, - Object { - "x": 1593413192000, - "y": null, - }, - Object { - "x": 1593413193000, - "y": null, - }, - Object { - "x": 1593413194000, - "y": null, - }, - Object { - "x": 1593413195000, - "y": null, - }, - Object { - "x": 1593413196000, - "y": null, - }, - Object { - "x": 1593413197000, - "y": null, - }, - Object { - "x": 1593413198000, - "y": null, - }, - Object { - "x": 1593413199000, - "y": null, - }, - Object { - "x": 1593413200000, - "y": null, - }, - Object { - "x": 1593413201000, - "y": null, - }, - Object { - "x": 1593413202000, - "y": null, - }, - Object { - "x": 1593413203000, - "y": null, - }, - Object { - "x": 1593413204000, - "y": null, - }, - Object { - "x": 1593413205000, - "y": null, - }, - Object { - "x": 1593413206000, - "y": null, - }, - Object { - "x": 1593413207000, - "y": null, - }, - Object { - "x": 1593413208000, - "y": null, - }, - Object { - "x": 1593413209000, - "y": null, - }, - Object { - "x": 1593413210000, - "y": null, - }, - Object { - "x": 1593413211000, - "y": null, - }, - Object { - "x": 1593413212000, - "y": null, - }, - Object { - "x": 1593413213000, - "y": null, - }, - Object { - "x": 1593413214000, - "y": null, - }, - Object { - "x": 1593413215000, - "y": null, - }, - Object { - "x": 1593413216000, - "y": null, - }, - Object { - "x": 1593413217000, - "y": null, - }, - Object { - "x": 1593413218000, - "y": null, - }, - Object { - "x": 1593413219000, - "y": null, - }, - Object { - "x": 1593413220000, - "y": null, - }, - Object { - "x": 1593413221000, - "y": null, - }, - Object { - "x": 1593413222000, - "y": null, - }, - Object { - "x": 1593413223000, - "y": null, - }, - Object { - "x": 1593413224000, - "y": null, + "x": 1599719310000, + "y": 19040, }, Object { - "x": 1593413225000, - "y": null, + "x": 1599719340000, + "y": 1077248, }, Object { - "x": 1593413226000, - "y": null, + "x": 1599719370000, + "y": 1146880, }, Object { - "x": 1593413227000, - "y": null, + "x": 1599719400000, + "y": 1908672, }, Object { - "x": 1593413228000, - "y": null, + "x": 1599719430000, + "y": 1261504, }, Object { - "x": 1593413229000, - "y": null, + "x": 1599719460000, + "y": 1617920, }, Object { - "x": 1593413230000, - "y": null, + "x": 1599719490000, + "y": 1105664, }, Object { - "x": 1593413231000, - "y": null, + "x": 1599719520000, + "y": 1163008, }, Object { - "x": 1593413232000, - "y": null, + "x": 1599719550000, + "y": 892928, }, Object { - "x": 1593413233000, - "y": null, + "x": 1599719580000, + "y": 1343360, }, Object { - "x": 1593413234000, - "y": null, + "x": 1599719610000, + "y": 925696, }, Object { - "x": 1593413235000, - "y": null, + "x": 1599719640000, + "y": 1277936, }, Object { - "x": 1593413236000, - "y": null, + "x": 1599719670000, + "y": 1499072, }, Object { - "x": 1593413237000, + "x": 1599719700000, "y": null, }, Object { - "x": 1593413238000, - "y": null, + "x": 1599719730000, + "y": 1204096, }, Object { - "x": 1593413239000, - "y": null, + "x": 1599719760000, + "y": 1572800, }, Object { - "x": 1593413240000, - "y": null, + "x": 1599719790000, + "y": 1097728, }, Object { - "x": 1593413241000, - "y": null, + "x": 1599719820000, + "y": 1376128, }, Object { - "x": 1593413242000, - "y": null, + "x": 1599719850000, + "y": 1277952, }, Object { - "x": 1593413243000, - "y": null, + "x": 1599719880000, + "y": 815072, }, Object { - "x": 1593413244000, - "y": null, + "x": 1599719910000, + "y": 1765376, }, Object { - "x": 1593413245000, - "y": null, + "x": 1599719940000, + "y": 937984, }, Object { - "x": 1593413246000, - "y": null, + "x": 1599719970000, + "y": 1687488, }, Object { - "x": 1593413247000, - "y": null, + "x": 1599720000000, + "y": 1212352, }, Object { - "x": 1593413248000, - "y": null, + "x": 1599720030000, + "y": 1441728, }, Object { - "x": 1593413249000, - "y": null, + "x": 1599720060000, + "y": 970624, }, Object { - "x": 1593413250000, - "y": null, + "x": 1599720090000, + "y": 1409024, }, Object { - "x": 1593413251000, - "y": null, + "x": 1599720120000, + "y": 1564672, }, Object { - "x": 1593413252000, - "y": null, + "x": 1599720150000, + "y": 1447936, }, Object { - "x": 1593413253000, - "y": null, + "x": 1599720180000, + "y": 1195904, }, Object { - "x": 1593413254000, - "y": null, + "x": 1599720210000, + "y": 1474560, }, Object { - "x": 1593413255000, - "y": null, + "x": 1599720240000, + "y": 1220544, }, Object { - "x": 1593413256000, - "y": null, + "x": 1599720270000, + "y": 1261504, }, Object { - "x": 1593413257000, - "y": null, + "x": 1599720300000, + "y": 1712064, }, Object { - "x": 1593413258000, - "y": null, + "x": 1599720330000, + "y": 1622016, }, Object { - "x": 1593413259000, - "y": null, + "x": 1599720360000, + "y": 1245120, }, Object { - "x": 1593413260000, - "y": null, + "x": 1599720390000, + "y": 1646560, }, Object { - "x": 1593413261000, - "y": null, + "x": 1599720420000, + "y": 970688, }, Object { - "x": 1593413262000, - "y": null, + "x": 1599720450000, + "y": 1228800, }, Object { - "x": 1593413263000, - "y": null, + "x": 1599720480000, + "y": 1191936, }, Object { - "x": 1593413264000, - "y": null, + "x": 1599720510000, + "y": 1572832, }, Object { - "x": 1593413265000, - "y": null, + "x": 1599720540000, + "y": 1200128, }, Object { - "x": 1593413266000, - "y": null, + "x": 1599720570000, + "y": 1071104, }, Object { - "x": 1593413267000, - "y": null, + "x": 1599720600000, + "y": 1130368, }, Object { - "x": 1593413268000, - "y": null, + "x": 1599720630000, + "y": 933824, }, Object { - "x": 1593413269000, - "y": null, + "x": 1599720660000, + "y": 1220544, }, Object { - "x": 1593413270000, - "y": null, + "x": 1599720690000, + "y": 337920, }, Object { - "x": 1593413271000, - "y": null, + "x": 1599720720000, + "y": 1032128, }, Object { - "x": 1593413272000, - "y": 45056, + "x": 1599720750000, + "y": 1736672, }, Object { - "x": 1593413273000, - "y": 10080, + "x": 1599720780000, + "y": 1843136, }, Object { - "x": 1593413274000, - "y": null, + "x": 1599720810000, + "y": 1404928, }, Object { - "x": 1593413275000, - "y": null, + "x": 1599720840000, + "y": 1036160, }, Object { - "x": 1593413276000, - "y": null, + "x": 1599720870000, + "y": 1351552, }, Object { - "x": 1593413277000, - "y": 37632, + "x": 1599720900000, + "y": 720864, }, Object { - "x": 1593413278000, - "y": null, + "x": 1599720930000, + "y": 966656, }, Object { - "x": 1593413279000, - "y": null, + "x": 1599720960000, + "y": 1892224, }, Object { - "x": 1593413280000, - "y": null, + "x": 1599720990000, + "y": 1384320, }, Object { - "x": 1593413281000, - "y": 33024, + "x": 1599721020000, + "y": 1540032, }, Object { - "x": 1593413282000, - "y": null, + "x": 1599721050000, + "y": 451584, }, Object { - "x": 1593413283000, - "y": null, + "x": 1599721080000, + "y": 1228768, }, Object { - "x": 1593413284000, - "y": 761728, - }, - Object { - "x": 1593413285000, - "y": 81904, - }, - Object { - "x": 1593413286000, - "y": 358384, - }, - Object { - "x": 1593413287000, - "y": 36088, - }, - Object { - "x": 1593413288000, - "y": 44536, - }, - Object { - "x": 1593413289000, - "y": 11648, - }, - Object { - "x": 1593413290000, - "y": 31984, - }, - Object { - "x": 1593413291000, - "y": 2920, - }, - Object { - "x": 1593413292000, - "y": 9312, - }, - Object { - "x": 1593413293000, - "y": 10912, - }, - Object { - "x": 1593413294000, - "y": 6392, - }, - Object { - "x": 1593413295000, - "y": 11704, - }, - Object { - "x": 1593413296000, - "y": 10816, - }, - Object { - "x": 1593413297000, - "y": 12000, - }, - Object { - "x": 1593413298000, - "y": 15164, - }, - Object { - "x": 1593413299000, - "y": 3216, - }, - Object { - "x": 1593413300000, - "y": 9584, - }, - Object { - "x": 1593413301000, - "y": 21240, - }, - Object { - "x": 1593413302000, - "y": 5624, - }, - Object { - "x": 1593413303000, - "y": 11360, - }, - Object { - "x": 1593413304000, - "y": 12320, - }, - Object { - "x": 1593413305000, - "y": 38640, - }, - Object { - "x": 1593413306000, - "y": 9728, - }, - Object { - "x": 1593413307000, - "y": 17016, - }, - Object { - "x": 1593413308000, - "y": 26848, - }, - Object { - "x": 1593413309000, - "y": 1753072, - }, - Object { - "x": 1593413310000, - "y": 16992, - }, - Object { - "x": 1593413311000, - "y": 26560, - }, - Object { - "x": 1593413312000, - "y": 11232, - }, - Object { - "x": 1593413313000, - "y": 11424, - }, - Object { - "x": 1593413314000, - "y": 16096, - }, - Object { - "x": 1593413315000, - "y": 18800, - }, - Object { - "x": 1593413316000, - "y": 12672, - }, - Object { - "x": 1593413317000, - "y": 24316, - }, - Object { - "x": 1593413318000, - "y": 8944, - }, - Object { - "x": 1593413319000, - "y": 272352, - }, - Object { - "x": 1593413320000, - "y": 7992, - }, - Object { - "x": 1593413321000, - "y": 8368, - }, - Object { - "x": 1593413322000, - "y": 1928, - }, - Object { - "x": 1593413323000, - "y": null, - }, - Object { - "x": 1593413324000, - "y": null, - }, - Object { - "x": 1593413325000, - "y": null, - }, - Object { - "x": 1593413326000, - "y": null, - }, - Object { - "x": 1593413327000, - "y": null, - }, - Object { - "x": 1593413328000, - "y": null, - }, - Object { - "x": 1593413329000, - "y": null, - }, - Object { - "x": 1593413330000, - "y": null, - }, - Object { - "x": 1593413331000, - "y": null, - }, - Object { - "x": 1593413332000, - "y": null, - }, - Object { - "x": 1593413333000, - "y": null, - }, - Object { - "x": 1593413334000, - "y": null, - }, - Object { - "x": 1593413335000, - "y": null, - }, - Object { - "x": 1593413336000, - "y": null, - }, - Object { - "x": 1593413337000, - "y": null, - }, - Object { - "x": 1593413338000, - "y": null, - }, - Object { - "x": 1593413339000, - "y": null, - }, - Object { - "x": 1593413340000, - "y": null, - }, - ], - "p99": Array [ - Object { - "x": 1593413100000, - "y": null, - }, - Object { - "x": 1593413101000, - "y": null, - }, - Object { - "x": 1593413102000, - "y": null, - }, - Object { - "x": 1593413103000, - "y": null, - }, - Object { - "x": 1593413104000, - "y": null, - }, - Object { - "x": 1593413105000, - "y": null, - }, - Object { - "x": 1593413106000, - "y": null, - }, - Object { - "x": 1593413107000, - "y": null, - }, - Object { - "x": 1593413108000, - "y": null, - }, - Object { - "x": 1593413109000, - "y": null, - }, - Object { - "x": 1593413110000, - "y": null, - }, - Object { - "x": 1593413111000, - "y": null, - }, - Object { - "x": 1593413112000, - "y": null, - }, - Object { - "x": 1593413113000, - "y": null, - }, - Object { - "x": 1593413114000, - "y": null, - }, - Object { - "x": 1593413115000, - "y": null, - }, - Object { - "x": 1593413116000, - "y": null, - }, - Object { - "x": 1593413117000, - "y": null, - }, - Object { - "x": 1593413118000, - "y": null, - }, - Object { - "x": 1593413119000, - "y": null, - }, - Object { - "x": 1593413120000, - "y": null, - }, - Object { - "x": 1593413121000, - "y": null, - }, - Object { - "x": 1593413122000, - "y": null, - }, - Object { - "x": 1593413123000, - "y": null, - }, - Object { - "x": 1593413124000, - "y": null, - }, - Object { - "x": 1593413125000, - "y": null, - }, - Object { - "x": 1593413126000, - "y": null, - }, - Object { - "x": 1593413127000, - "y": null, - }, - Object { - "x": 1593413128000, - "y": null, - }, - Object { - "x": 1593413129000, - "y": null, - }, - Object { - "x": 1593413130000, - "y": null, - }, - Object { - "x": 1593413131000, - "y": null, - }, - Object { - "x": 1593413132000, - "y": null, - }, - Object { - "x": 1593413133000, - "y": null, - }, - Object { - "x": 1593413134000, - "y": null, - }, - Object { - "x": 1593413135000, - "y": null, - }, - Object { - "x": 1593413136000, - "y": null, - }, - Object { - "x": 1593413137000, - "y": null, - }, - Object { - "x": 1593413138000, - "y": null, - }, - Object { - "x": 1593413139000, - "y": null, - }, - Object { - "x": 1593413140000, - "y": null, - }, - Object { - "x": 1593413141000, - "y": null, - }, - Object { - "x": 1593413142000, - "y": null, - }, - Object { - "x": 1593413143000, - "y": null, - }, - Object { - "x": 1593413144000, - "y": null, - }, - Object { - "x": 1593413145000, - "y": null, - }, - Object { - "x": 1593413146000, - "y": null, - }, - Object { - "x": 1593413147000, - "y": null, - }, - Object { - "x": 1593413148000, - "y": null, - }, - Object { - "x": 1593413149000, - "y": null, - }, - Object { - "x": 1593413150000, - "y": null, - }, - Object { - "x": 1593413151000, - "y": null, - }, - Object { - "x": 1593413152000, - "y": null, - }, - Object { - "x": 1593413153000, - "y": null, - }, - Object { - "x": 1593413154000, - "y": null, - }, - Object { - "x": 1593413155000, - "y": null, - }, - Object { - "x": 1593413156000, - "y": null, - }, - Object { - "x": 1593413157000, - "y": null, - }, - Object { - "x": 1593413158000, - "y": null, - }, - Object { - "x": 1593413159000, - "y": null, - }, - Object { - "x": 1593413160000, - "y": null, - }, - Object { - "x": 1593413161000, - "y": null, - }, - Object { - "x": 1593413162000, - "y": null, - }, - Object { - "x": 1593413163000, - "y": null, - }, - Object { - "x": 1593413164000, - "y": null, - }, - Object { - "x": 1593413165000, - "y": null, - }, - Object { - "x": 1593413166000, - "y": null, - }, - Object { - "x": 1593413167000, - "y": null, - }, - Object { - "x": 1593413168000, - "y": null, - }, - Object { - "x": 1593413169000, - "y": null, - }, - Object { - "x": 1593413170000, - "y": null, - }, - Object { - "x": 1593413171000, - "y": null, - }, - Object { - "x": 1593413172000, - "y": null, - }, - Object { - "x": 1593413173000, - "y": null, - }, - Object { - "x": 1593413174000, - "y": null, - }, - Object { - "x": 1593413175000, - "y": null, - }, - Object { - "x": 1593413176000, - "y": null, - }, - Object { - "x": 1593413177000, - "y": null, - }, - Object { - "x": 1593413178000, - "y": null, - }, - Object { - "x": 1593413179000, - "y": null, - }, - Object { - "x": 1593413180000, - "y": null, - }, - Object { - "x": 1593413181000, - "y": null, - }, - Object { - "x": 1593413182000, - "y": null, - }, - Object { - "x": 1593413183000, - "y": null, - }, - Object { - "x": 1593413184000, - "y": null, - }, - Object { - "x": 1593413185000, - "y": null, - }, - Object { - "x": 1593413186000, - "y": null, - }, - Object { - "x": 1593413187000, - "y": null, - }, - Object { - "x": 1593413188000, - "y": null, - }, - Object { - "x": 1593413189000, - "y": null, - }, - Object { - "x": 1593413190000, - "y": null, - }, - Object { - "x": 1593413191000, - "y": null, - }, - Object { - "x": 1593413192000, - "y": null, - }, - Object { - "x": 1593413193000, - "y": null, - }, - Object { - "x": 1593413194000, - "y": null, - }, - Object { - "x": 1593413195000, - "y": null, - }, - Object { - "x": 1593413196000, - "y": null, - }, - Object { - "x": 1593413197000, - "y": null, - }, - Object { - "x": 1593413198000, - "y": null, - }, - Object { - "x": 1593413199000, - "y": null, - }, - Object { - "x": 1593413200000, - "y": null, - }, - Object { - "x": 1593413201000, - "y": null, - }, - Object { - "x": 1593413202000, - "y": null, - }, - Object { - "x": 1593413203000, - "y": null, - }, - Object { - "x": 1593413204000, - "y": null, - }, - Object { - "x": 1593413205000, - "y": null, - }, - Object { - "x": 1593413206000, - "y": null, - }, - Object { - "x": 1593413207000, - "y": null, - }, - Object { - "x": 1593413208000, - "y": null, - }, - Object { - "x": 1593413209000, - "y": null, - }, - Object { - "x": 1593413210000, - "y": null, - }, - Object { - "x": 1593413211000, - "y": null, - }, - Object { - "x": 1593413212000, - "y": null, - }, - Object { - "x": 1593413213000, - "y": null, - }, - Object { - "x": 1593413214000, - "y": null, - }, - Object { - "x": 1593413215000, - "y": null, - }, - Object { - "x": 1593413216000, - "y": null, - }, - Object { - "x": 1593413217000, - "y": null, - }, - Object { - "x": 1593413218000, - "y": null, - }, - Object { - "x": 1593413219000, - "y": null, - }, - Object { - "x": 1593413220000, - "y": null, - }, - Object { - "x": 1593413221000, - "y": null, - }, - Object { - "x": 1593413222000, - "y": null, - }, - Object { - "x": 1593413223000, - "y": null, - }, - Object { - "x": 1593413224000, - "y": null, - }, - Object { - "x": 1593413225000, - "y": null, - }, - Object { - "x": 1593413226000, - "y": null, - }, - Object { - "x": 1593413227000, - "y": null, - }, - Object { - "x": 1593413228000, - "y": null, - }, - Object { - "x": 1593413229000, - "y": null, - }, - Object { - "x": 1593413230000, - "y": null, - }, - Object { - "x": 1593413231000, - "y": null, - }, - Object { - "x": 1593413232000, - "y": null, - }, - Object { - "x": 1593413233000, - "y": null, - }, - Object { - "x": 1593413234000, - "y": null, - }, - Object { - "x": 1593413235000, - "y": null, - }, - Object { - "x": 1593413236000, - "y": null, - }, - Object { - "x": 1593413237000, - "y": null, - }, - Object { - "x": 1593413238000, - "y": null, - }, - Object { - "x": 1593413239000, - "y": null, - }, - Object { - "x": 1593413240000, - "y": null, - }, - Object { - "x": 1593413241000, - "y": null, - }, - Object { - "x": 1593413242000, - "y": null, - }, - Object { - "x": 1593413243000, - "y": null, - }, - Object { - "x": 1593413244000, - "y": null, - }, - Object { - "x": 1593413245000, - "y": null, - }, - Object { - "x": 1593413246000, - "y": null, - }, - Object { - "x": 1593413247000, - "y": null, - }, - Object { - "x": 1593413248000, - "y": null, - }, - Object { - "x": 1593413249000, - "y": null, - }, - Object { - "x": 1593413250000, - "y": null, - }, - Object { - "x": 1593413251000, - "y": null, - }, - Object { - "x": 1593413252000, - "y": null, - }, - Object { - "x": 1593413253000, - "y": null, - }, - Object { - "x": 1593413254000, - "y": null, - }, - Object { - "x": 1593413255000, - "y": null, - }, - Object { - "x": 1593413256000, - "y": null, - }, - Object { - "x": 1593413257000, - "y": null, - }, - Object { - "x": 1593413258000, - "y": null, - }, - Object { - "x": 1593413259000, - "y": null, - }, - Object { - "x": 1593413260000, - "y": null, - }, - Object { - "x": 1593413261000, - "y": null, - }, - Object { - "x": 1593413262000, - "y": null, - }, - Object { - "x": 1593413263000, - "y": null, - }, - Object { - "x": 1593413264000, - "y": null, - }, - Object { - "x": 1593413265000, - "y": null, - }, - Object { - "x": 1593413266000, - "y": null, - }, - Object { - "x": 1593413267000, - "y": null, - }, - Object { - "x": 1593413268000, - "y": null, - }, - Object { - "x": 1593413269000, - "y": null, - }, - Object { - "x": 1593413270000, - "y": null, - }, - Object { - "x": 1593413271000, - "y": null, - }, - Object { - "x": 1593413272000, - "y": 45056, - }, - Object { - "x": 1593413273000, - "y": 10080, - }, - Object { - "x": 1593413274000, - "y": null, - }, - Object { - "x": 1593413275000, - "y": null, - }, - Object { - "x": 1593413276000, - "y": null, - }, - Object { - "x": 1593413277000, - "y": 37632, - }, - Object { - "x": 1593413278000, - "y": null, - }, - Object { - "x": 1593413279000, - "y": null, - }, - Object { - "x": 1593413280000, - "y": null, - }, - Object { - "x": 1593413281000, - "y": 33024, - }, - Object { - "x": 1593413282000, - "y": null, - }, - Object { - "x": 1593413283000, - "y": null, - }, - Object { - "x": 1593413284000, - "y": 761728, - }, - Object { - "x": 1593413285000, - "y": 81904, - }, - Object { - "x": 1593413286000, - "y": 358384, - }, - Object { - "x": 1593413287000, - "y": 36088, - }, - Object { - "x": 1593413288000, - "y": 44536, - }, - Object { - "x": 1593413289000, - "y": 11648, - }, - Object { - "x": 1593413290000, - "y": 31984, - }, - Object { - "x": 1593413291000, - "y": 2920, - }, - Object { - "x": 1593413292000, - "y": 9312, - }, - Object { - "x": 1593413293000, - "y": 10912, - }, - Object { - "x": 1593413294000, - "y": 6392, - }, - Object { - "x": 1593413295000, - "y": 11704, - }, - Object { - "x": 1593413296000, - "y": 10816, - }, - Object { - "x": 1593413297000, - "y": 12000, - }, - Object { - "x": 1593413298000, - "y": 15164, - }, - Object { - "x": 1593413299000, - "y": 3216, - }, - Object { - "x": 1593413300000, - "y": 9584, - }, - Object { - "x": 1593413301000, - "y": 21240, - }, - Object { - "x": 1593413302000, - "y": 5624, - }, - Object { - "x": 1593413303000, - "y": 11360, - }, - Object { - "x": 1593413304000, - "y": 12320, - }, - Object { - "x": 1593413305000, - "y": 38640, - }, - Object { - "x": 1593413306000, - "y": 9728, - }, - Object { - "x": 1593413307000, - "y": 17016, - }, - Object { - "x": 1593413308000, - "y": 26848, - }, - Object { - "x": 1593413309000, - "y": 1753072, - }, - Object { - "x": 1593413310000, - "y": 16992, - }, - Object { - "x": 1593413311000, - "y": 26560, - }, - Object { - "x": 1593413312000, - "y": 11232, - }, - Object { - "x": 1593413313000, - "y": 11424, - }, - Object { - "x": 1593413314000, - "y": 16096, - }, - Object { - "x": 1593413315000, - "y": 18800, - }, - Object { - "x": 1593413316000, - "y": 12672, - }, - Object { - "x": 1593413317000, - "y": 24316, - }, - Object { - "x": 1593413318000, - "y": 8944, - }, - Object { - "x": 1593413319000, - "y": 272352, - }, - Object { - "x": 1593413320000, - "y": 7992, - }, - Object { - "x": 1593413321000, - "y": 8368, - }, - Object { - "x": 1593413322000, - "y": 1928, - }, - Object { - "x": 1593413323000, - "y": null, - }, - Object { - "x": 1593413324000, - "y": null, - }, - Object { - "x": 1593413325000, - "y": null, - }, - Object { - "x": 1593413326000, - "y": null, - }, - Object { - "x": 1593413327000, - "y": null, - }, - Object { - "x": 1593413328000, - "y": null, - }, - Object { - "x": 1593413329000, - "y": null, - }, - Object { - "x": 1593413330000, - "y": null, - }, - Object { - "x": 1593413331000, - "y": null, - }, - Object { - "x": 1593413332000, - "y": null, - }, - Object { - "x": 1593413333000, - "y": null, - }, - Object { - "x": 1593413334000, - "y": null, - }, - Object { - "x": 1593413335000, - "y": null, - }, - Object { - "x": 1593413336000, - "y": null, - }, - Object { - "x": 1593413337000, - "y": null, - }, - Object { - "x": 1593413338000, - "y": null, - }, - Object { - "x": 1593413339000, - "y": null, - }, - Object { - "x": 1593413340000, - "y": null, - }, - ], - }, - "tpmBuckets": Array [ - Object { - "avg": 24.75, - "dataPoints": Array [ - Object { - "x": 1593413100000, - "y": 0, - }, - Object { - "x": 1593413101000, - "y": 0, - }, - Object { - "x": 1593413102000, - "y": 0, - }, - Object { - "x": 1593413103000, - "y": 0, - }, - Object { - "x": 1593413104000, - "y": 0, - }, - Object { - "x": 1593413105000, - "y": 0, - }, - Object { - "x": 1593413106000, - "y": 0, - }, - Object { - "x": 1593413107000, - "y": 0, - }, - Object { - "x": 1593413108000, - "y": 0, - }, - Object { - "x": 1593413109000, - "y": 0, - }, - Object { - "x": 1593413110000, - "y": 0, - }, - Object { - "x": 1593413111000, - "y": 0, - }, - Object { - "x": 1593413112000, - "y": 0, - }, - Object { - "x": 1593413113000, - "y": 0, - }, - Object { - "x": 1593413114000, - "y": 0, - }, - Object { - "x": 1593413115000, - "y": 0, - }, - Object { - "x": 1593413116000, - "y": 0, - }, - Object { - "x": 1593413117000, - "y": 0, - }, - Object { - "x": 1593413118000, - "y": 0, - }, - Object { - "x": 1593413119000, - "y": 0, - }, - Object { - "x": 1593413120000, - "y": 0, - }, - Object { - "x": 1593413121000, - "y": 0, - }, - Object { - "x": 1593413122000, - "y": 0, - }, - Object { - "x": 1593413123000, - "y": 0, - }, - Object { - "x": 1593413124000, - "y": 0, - }, - Object { - "x": 1593413125000, - "y": 0, - }, - Object { - "x": 1593413126000, - "y": 0, - }, - Object { - "x": 1593413127000, - "y": 0, - }, - Object { - "x": 1593413128000, - "y": 0, - }, - Object { - "x": 1593413129000, - "y": 0, - }, - Object { - "x": 1593413130000, - "y": 0, - }, - Object { - "x": 1593413131000, - "y": 0, - }, - Object { - "x": 1593413132000, - "y": 0, - }, - Object { - "x": 1593413133000, - "y": 0, - }, - Object { - "x": 1593413134000, - "y": 0, - }, - Object { - "x": 1593413135000, - "y": 0, - }, - Object { - "x": 1593413136000, - "y": 0, - }, - Object { - "x": 1593413137000, - "y": 0, - }, - Object { - "x": 1593413138000, - "y": 0, - }, - Object { - "x": 1593413139000, - "y": 0, - }, - Object { - "x": 1593413140000, - "y": 0, - }, - Object { - "x": 1593413141000, - "y": 0, - }, - Object { - "x": 1593413142000, - "y": 0, - }, - Object { - "x": 1593413143000, - "y": 0, - }, - Object { - "x": 1593413144000, - "y": 0, - }, - Object { - "x": 1593413145000, - "y": 0, - }, - Object { - "x": 1593413146000, - "y": 0, - }, - Object { - "x": 1593413147000, - "y": 0, - }, - Object { - "x": 1593413148000, - "y": 0, - }, - Object { - "x": 1593413149000, - "y": 0, - }, - Object { - "x": 1593413150000, - "y": 0, - }, - Object { - "x": 1593413151000, - "y": 0, - }, - Object { - "x": 1593413152000, - "y": 0, - }, - Object { - "x": 1593413153000, - "y": 0, - }, - Object { - "x": 1593413154000, - "y": 0, - }, - Object { - "x": 1593413155000, - "y": 0, - }, - Object { - "x": 1593413156000, - "y": 0, - }, - Object { - "x": 1593413157000, - "y": 0, - }, - Object { - "x": 1593413158000, - "y": 0, - }, - Object { - "x": 1593413159000, - "y": 0, - }, - Object { - "x": 1593413160000, - "y": 0, - }, - Object { - "x": 1593413161000, - "y": 0, - }, - Object { - "x": 1593413162000, - "y": 0, - }, - Object { - "x": 1593413163000, - "y": 0, - }, - Object { - "x": 1593413164000, - "y": 0, - }, - Object { - "x": 1593413165000, - "y": 0, - }, - Object { - "x": 1593413166000, - "y": 0, - }, - Object { - "x": 1593413167000, - "y": 0, - }, - Object { - "x": 1593413168000, - "y": 0, - }, - Object { - "x": 1593413169000, - "y": 0, - }, - Object { - "x": 1593413170000, - "y": 0, - }, - Object { - "x": 1593413171000, - "y": 0, - }, - Object { - "x": 1593413172000, - "y": 0, - }, - Object { - "x": 1593413173000, - "y": 0, - }, - Object { - "x": 1593413174000, - "y": 0, - }, - Object { - "x": 1593413175000, - "y": 0, - }, - Object { - "x": 1593413176000, - "y": 0, - }, - Object { - "x": 1593413177000, - "y": 0, - }, - Object { - "x": 1593413178000, - "y": 0, - }, - Object { - "x": 1593413179000, - "y": 0, - }, - Object { - "x": 1593413180000, - "y": 0, - }, - Object { - "x": 1593413181000, - "y": 0, - }, - Object { - "x": 1593413182000, - "y": 0, - }, - Object { - "x": 1593413183000, - "y": 0, - }, - Object { - "x": 1593413184000, - "y": 0, - }, - Object { - "x": 1593413185000, - "y": 0, - }, - Object { - "x": 1593413186000, - "y": 0, - }, - Object { - "x": 1593413187000, - "y": 0, - }, - Object { - "x": 1593413188000, - "y": 0, - }, - Object { - "x": 1593413189000, - "y": 0, - }, - Object { - "x": 1593413190000, - "y": 0, - }, - Object { - "x": 1593413191000, - "y": 0, - }, - Object { - "x": 1593413192000, - "y": 0, - }, - Object { - "x": 1593413193000, - "y": 0, - }, - Object { - "x": 1593413194000, - "y": 0, - }, - Object { - "x": 1593413195000, - "y": 0, - }, - Object { - "x": 1593413196000, - "y": 0, - }, - Object { - "x": 1593413197000, - "y": 0, - }, - Object { - "x": 1593413198000, - "y": 0, - }, - Object { - "x": 1593413199000, - "y": 0, - }, - Object { - "x": 1593413200000, - "y": 0, - }, - Object { - "x": 1593413201000, - "y": 0, - }, - Object { - "x": 1593413202000, - "y": 0, - }, - Object { - "x": 1593413203000, - "y": 0, - }, - Object { - "x": 1593413204000, - "y": 0, - }, - Object { - "x": 1593413205000, - "y": 0, - }, - Object { - "x": 1593413206000, - "y": 0, - }, - Object { - "x": 1593413207000, - "y": 0, - }, - Object { - "x": 1593413208000, - "y": 0, - }, - Object { - "x": 1593413209000, - "y": 0, - }, - Object { - "x": 1593413210000, - "y": 0, - }, - Object { - "x": 1593413211000, - "y": 0, - }, - Object { - "x": 1593413212000, - "y": 0, - }, - Object { - "x": 1593413213000, - "y": 0, - }, - Object { - "x": 1593413214000, - "y": 0, - }, - Object { - "x": 1593413215000, - "y": 0, - }, - Object { - "x": 1593413216000, - "y": 0, - }, - Object { - "x": 1593413217000, - "y": 0, - }, - Object { - "x": 1593413218000, - "y": 0, - }, - Object { - "x": 1593413219000, - "y": 0, - }, - Object { - "x": 1593413220000, - "y": 0, - }, - Object { - "x": 1593413221000, - "y": 0, - }, - Object { - "x": 1593413222000, - "y": 0, - }, - Object { - "x": 1593413223000, - "y": 0, - }, - Object { - "x": 1593413224000, - "y": 0, - }, - Object { - "x": 1593413225000, - "y": 0, - }, - Object { - "x": 1593413226000, - "y": 0, - }, - Object { - "x": 1593413227000, - "y": 0, - }, - Object { - "x": 1593413228000, - "y": 0, - }, - Object { - "x": 1593413229000, - "y": 0, - }, - Object { - "x": 1593413230000, - "y": 0, - }, - Object { - "x": 1593413231000, - "y": 0, - }, - Object { - "x": 1593413232000, - "y": 0, - }, - Object { - "x": 1593413233000, - "y": 0, - }, - Object { - "x": 1593413234000, - "y": 0, - }, - Object { - "x": 1593413235000, - "y": 0, - }, - Object { - "x": 1593413236000, - "y": 0, - }, - Object { - "x": 1593413237000, - "y": 0, - }, - Object { - "x": 1593413238000, - "y": 0, - }, - Object { - "x": 1593413239000, - "y": 0, - }, - Object { - "x": 1593413240000, - "y": 0, - }, - Object { - "x": 1593413241000, - "y": 0, - }, - Object { - "x": 1593413242000, - "y": 0, - }, - Object { - "x": 1593413243000, - "y": 0, - }, - Object { - "x": 1593413244000, - "y": 0, - }, - Object { - "x": 1593413245000, - "y": 0, - }, - Object { - "x": 1593413246000, - "y": 0, - }, - Object { - "x": 1593413247000, - "y": 0, - }, - Object { - "x": 1593413248000, - "y": 0, - }, - Object { - "x": 1593413249000, - "y": 0, - }, - Object { - "x": 1593413250000, - "y": 0, - }, - Object { - "x": 1593413251000, - "y": 0, - }, - Object { - "x": 1593413252000, - "y": 0, - }, - Object { - "x": 1593413253000, - "y": 0, - }, - Object { - "x": 1593413254000, - "y": 0, - }, - Object { - "x": 1593413255000, - "y": 0, - }, - Object { - "x": 1593413256000, - "y": 0, - }, - Object { - "x": 1593413257000, - "y": 0, - }, - Object { - "x": 1593413258000, - "y": 0, - }, - Object { - "x": 1593413259000, - "y": 0, - }, - Object { - "x": 1593413260000, - "y": 0, - }, - Object { - "x": 1593413261000, - "y": 0, - }, - Object { - "x": 1593413262000, - "y": 0, - }, - Object { - "x": 1593413263000, - "y": 0, - }, - Object { - "x": 1593413264000, - "y": 0, - }, - Object { - "x": 1593413265000, - "y": 0, - }, - Object { - "x": 1593413266000, - "y": 0, - }, - Object { - "x": 1593413267000, - "y": 0, - }, - Object { - "x": 1593413268000, - "y": 0, - }, - Object { - "x": 1593413269000, - "y": 0, - }, - Object { - "x": 1593413270000, - "y": 0, - }, - Object { - "x": 1593413271000, - "y": 0, - }, - Object { - "x": 1593413272000, - "y": 1, - }, - Object { - "x": 1593413273000, - "y": 2, - }, - Object { - "x": 1593413274000, - "y": 0, - }, - Object { - "x": 1593413275000, - "y": 0, - }, - Object { - "x": 1593413276000, - "y": 0, - }, - Object { - "x": 1593413277000, - "y": 1, - }, - Object { - "x": 1593413278000, - "y": 0, - }, - Object { - "x": 1593413279000, - "y": 0, - }, - Object { - "x": 1593413280000, - "y": 0, - }, - Object { - "x": 1593413281000, - "y": 1, - }, - Object { - "x": 1593413282000, - "y": 0, - }, - Object { - "x": 1593413283000, - "y": 0, - }, - Object { - "x": 1593413284000, - "y": 2, - }, - Object { - "x": 1593413285000, - "y": 2, - }, - Object { - "x": 1593413286000, - "y": 7, - }, - Object { - "x": 1593413287000, - "y": 1, - }, - Object { - "x": 1593413288000, - "y": 2, - }, - Object { - "x": 1593413289000, - "y": 1, - }, - Object { - "x": 1593413290000, - "y": 4, - }, - Object { - "x": 1593413291000, - "y": 2, - }, - Object { - "x": 1593413292000, - "y": 1, - }, - Object { - "x": 1593413293000, - "y": 2, - }, - Object { - "x": 1593413294000, - "y": 3, - }, - Object { - "x": 1593413295000, - "y": 2, - }, - Object { - "x": 1593413296000, - "y": 2, - }, - Object { - "x": 1593413297000, - "y": 2, - }, - Object { - "x": 1593413298000, - "y": 6, - }, - Object { - "x": 1593413299000, - "y": 1, - }, - Object { - "x": 1593413300000, - "y": 2, - }, - Object { - "x": 1593413301000, - "y": 3, - }, - Object { - "x": 1593413302000, - "y": 2, - }, - Object { - "x": 1593413303000, - "y": 2, - }, - Object { - "x": 1593413304000, - "y": 2, - }, - Object { - "x": 1593413305000, - "y": 1, - }, - Object { - "x": 1593413306000, - "y": 2, - }, - Object { - "x": 1593413307000, - "y": 3, - }, - Object { - "x": 1593413308000, - "y": 2, - }, - Object { - "x": 1593413309000, - "y": 2, - }, - Object { - "x": 1593413310000, - "y": 2, - }, - Object { - "x": 1593413311000, - "y": 1, - }, - Object { - "x": 1593413312000, - "y": 3, - }, - Object { - "x": 1593413313000, - "y": 3, - }, - Object { - "x": 1593413314000, - "y": 5, - }, - Object { - "x": 1593413315000, - "y": 2, - }, - Object { - "x": 1593413316000, - "y": 2, - }, - Object { - "x": 1593413317000, - "y": 6, - }, - Object { - "x": 1593413318000, - "y": 2, - }, - Object { - "x": 1593413319000, - "y": 2, - }, - Object { - "x": 1593413320000, - "y": 2, - }, - Object { - "x": 1593413321000, - "y": 2, - }, - Object { - "x": 1593413322000, - "y": 1, - }, - Object { - "x": 1593413323000, - "y": 0, - }, - Object { - "x": 1593413324000, - "y": 0, - }, - Object { - "x": 1593413325000, - "y": 0, - }, - Object { - "x": 1593413326000, - "y": 0, - }, - Object { - "x": 1593413327000, - "y": 0, - }, - Object { - "x": 1593413328000, - "y": 0, - }, - Object { - "x": 1593413329000, - "y": 0, - }, - Object { - "x": 1593413330000, - "y": 0, - }, - Object { - "x": 1593413331000, - "y": 0, - }, - Object { - "x": 1593413332000, - "y": 0, - }, - Object { - "x": 1593413333000, - "y": 0, - }, - Object { - "x": 1593413334000, - "y": 0, - }, - Object { - "x": 1593413335000, - "y": 0, - }, - Object { - "x": 1593413336000, - "y": 0, - }, - Object { - "x": 1593413337000, - "y": 0, - }, - Object { - "x": 1593413338000, - "y": 0, - }, - Object { - "x": 1593413339000, - "y": 0, - }, - Object { - "x": 1593413340000, - "y": 0, - }, - ], - "key": "HTTP 2xx", - }, - Object { - "avg": 1.75, - "dataPoints": Array [ - Object { - "x": 1593413100000, - "y": 0, - }, - Object { - "x": 1593413101000, - "y": 0, - }, - Object { - "x": 1593413102000, - "y": 0, - }, - Object { - "x": 1593413103000, - "y": 0, - }, - Object { - "x": 1593413104000, - "y": 0, - }, - Object { - "x": 1593413105000, - "y": 0, - }, - Object { - "x": 1593413106000, - "y": 0, - }, - Object { - "x": 1593413107000, - "y": 0, - }, - Object { - "x": 1593413108000, - "y": 0, - }, - Object { - "x": 1593413109000, - "y": 0, - }, - Object { - "x": 1593413110000, - "y": 0, - }, - Object { - "x": 1593413111000, - "y": 0, - }, - Object { - "x": 1593413112000, - "y": 0, - }, - Object { - "x": 1593413113000, - "y": 0, - }, - Object { - "x": 1593413114000, - "y": 0, - }, - Object { - "x": 1593413115000, - "y": 0, - }, - Object { - "x": 1593413116000, - "y": 0, - }, - Object { - "x": 1593413117000, - "y": 0, - }, - Object { - "x": 1593413118000, - "y": 0, - }, - Object { - "x": 1593413119000, - "y": 0, - }, - Object { - "x": 1593413120000, - "y": 0, - }, - Object { - "x": 1593413121000, - "y": 0, - }, - Object { - "x": 1593413122000, - "y": 0, - }, - Object { - "x": 1593413123000, - "y": 0, - }, - Object { - "x": 1593413124000, - "y": 0, - }, - Object { - "x": 1593413125000, - "y": 0, - }, - Object { - "x": 1593413126000, - "y": 0, - }, - Object { - "x": 1593413127000, - "y": 0, - }, - Object { - "x": 1593413128000, - "y": 0, - }, - Object { - "x": 1593413129000, - "y": 0, - }, - Object { - "x": 1593413130000, - "y": 0, - }, - Object { - "x": 1593413131000, - "y": 0, - }, - Object { - "x": 1593413132000, - "y": 0, - }, - Object { - "x": 1593413133000, - "y": 0, - }, - Object { - "x": 1593413134000, - "y": 0, - }, - Object { - "x": 1593413135000, - "y": 0, - }, - Object { - "x": 1593413136000, - "y": 0, - }, - Object { - "x": 1593413137000, - "y": 0, - }, - Object { - "x": 1593413138000, - "y": 0, - }, - Object { - "x": 1593413139000, - "y": 0, - }, - Object { - "x": 1593413140000, - "y": 0, - }, - Object { - "x": 1593413141000, - "y": 0, - }, - Object { - "x": 1593413142000, - "y": 0, - }, - Object { - "x": 1593413143000, - "y": 0, - }, - Object { - "x": 1593413144000, - "y": 0, - }, - Object { - "x": 1593413145000, - "y": 0, - }, - Object { - "x": 1593413146000, - "y": 0, - }, - Object { - "x": 1593413147000, - "y": 0, - }, - Object { - "x": 1593413148000, - "y": 0, - }, - Object { - "x": 1593413149000, - "y": 0, - }, - Object { - "x": 1593413150000, - "y": 0, - }, - Object { - "x": 1593413151000, - "y": 0, - }, - Object { - "x": 1593413152000, - "y": 0, - }, - Object { - "x": 1593413153000, - "y": 0, - }, - Object { - "x": 1593413154000, - "y": 0, - }, - Object { - "x": 1593413155000, - "y": 0, - }, - Object { - "x": 1593413156000, - "y": 0, - }, - Object { - "x": 1593413157000, - "y": 0, - }, - Object { - "x": 1593413158000, - "y": 0, - }, - Object { - "x": 1593413159000, - "y": 0, - }, - Object { - "x": 1593413160000, - "y": 0, - }, - Object { - "x": 1593413161000, - "y": 0, - }, - Object { - "x": 1593413162000, - "y": 0, - }, - Object { - "x": 1593413163000, - "y": 0, - }, - Object { - "x": 1593413164000, - "y": 0, - }, - Object { - "x": 1593413165000, - "y": 0, - }, - Object { - "x": 1593413166000, - "y": 0, - }, - Object { - "x": 1593413167000, - "y": 0, - }, - Object { - "x": 1593413168000, - "y": 0, - }, - Object { - "x": 1593413169000, - "y": 0, - }, - Object { - "x": 1593413170000, - "y": 0, - }, - Object { - "x": 1593413171000, - "y": 0, - }, - Object { - "x": 1593413172000, - "y": 0, - }, - Object { - "x": 1593413173000, - "y": 0, - }, - Object { - "x": 1593413174000, - "y": 0, - }, - Object { - "x": 1593413175000, - "y": 0, - }, - Object { - "x": 1593413176000, - "y": 0, - }, - Object { - "x": 1593413177000, - "y": 0, - }, - Object { - "x": 1593413178000, - "y": 0, - }, - Object { - "x": 1593413179000, - "y": 0, - }, - Object { - "x": 1593413180000, - "y": 0, - }, - Object { - "x": 1593413181000, - "y": 0, - }, - Object { - "x": 1593413182000, - "y": 0, - }, - Object { - "x": 1593413183000, - "y": 0, - }, - Object { - "x": 1593413184000, - "y": 0, - }, - Object { - "x": 1593413185000, - "y": 0, - }, - Object { - "x": 1593413186000, - "y": 0, - }, - Object { - "x": 1593413187000, - "y": 0, - }, - Object { - "x": 1593413188000, - "y": 0, - }, - Object { - "x": 1593413189000, - "y": 0, - }, - Object { - "x": 1593413190000, - "y": 0, - }, - Object { - "x": 1593413191000, - "y": 0, - }, - Object { - "x": 1593413192000, - "y": 0, - }, - Object { - "x": 1593413193000, - "y": 0, - }, - Object { - "x": 1593413194000, - "y": 0, - }, - Object { - "x": 1593413195000, - "y": 0, - }, - Object { - "x": 1593413196000, - "y": 0, - }, - Object { - "x": 1593413197000, - "y": 0, - }, - Object { - "x": 1593413198000, - "y": 0, - }, - Object { - "x": 1593413199000, - "y": 0, - }, - Object { - "x": 1593413200000, - "y": 0, - }, - Object { - "x": 1593413201000, - "y": 0, - }, - Object { - "x": 1593413202000, - "y": 0, - }, - Object { - "x": 1593413203000, - "y": 0, - }, - Object { - "x": 1593413204000, - "y": 0, - }, - Object { - "x": 1593413205000, - "y": 0, - }, - Object { - "x": 1593413206000, - "y": 0, - }, - Object { - "x": 1593413207000, - "y": 0, - }, - Object { - "x": 1593413208000, - "y": 0, - }, - Object { - "x": 1593413209000, - "y": 0, - }, - Object { - "x": 1593413210000, - "y": 0, - }, - Object { - "x": 1593413211000, - "y": 0, - }, - Object { - "x": 1593413212000, - "y": 0, - }, - Object { - "x": 1593413213000, - "y": 0, - }, - Object { - "x": 1593413214000, - "y": 0, - }, - Object { - "x": 1593413215000, - "y": 0, - }, - Object { - "x": 1593413216000, - "y": 0, - }, - Object { - "x": 1593413217000, - "y": 0, - }, - Object { - "x": 1593413218000, - "y": 0, - }, - Object { - "x": 1593413219000, - "y": 0, - }, - Object { - "x": 1593413220000, - "y": 0, - }, - Object { - "x": 1593413221000, - "y": 0, - }, - Object { - "x": 1593413222000, - "y": 0, - }, - Object { - "x": 1593413223000, - "y": 0, - }, - Object { - "x": 1593413224000, - "y": 0, - }, - Object { - "x": 1593413225000, - "y": 0, - }, - Object { - "x": 1593413226000, - "y": 0, - }, - Object { - "x": 1593413227000, - "y": 0, - }, - Object { - "x": 1593413228000, - "y": 0, - }, - Object { - "x": 1593413229000, - "y": 0, - }, - Object { - "x": 1593413230000, - "y": 0, - }, - Object { - "x": 1593413231000, - "y": 0, - }, - Object { - "x": 1593413232000, - "y": 0, - }, - Object { - "x": 1593413233000, - "y": 0, - }, - Object { - "x": 1593413234000, - "y": 0, - }, - Object { - "x": 1593413235000, - "y": 0, - }, - Object { - "x": 1593413236000, - "y": 0, - }, - Object { - "x": 1593413237000, - "y": 0, - }, - Object { - "x": 1593413238000, - "y": 0, - }, - Object { - "x": 1593413239000, - "y": 0, - }, - Object { - "x": 1593413240000, - "y": 0, - }, - Object { - "x": 1593413241000, - "y": 0, - }, - Object { - "x": 1593413242000, - "y": 0, - }, - Object { - "x": 1593413243000, - "y": 0, - }, - Object { - "x": 1593413244000, - "y": 0, - }, - Object { - "x": 1593413245000, - "y": 0, - }, - Object { - "x": 1593413246000, - "y": 0, - }, - Object { - "x": 1593413247000, - "y": 0, - }, - Object { - "x": 1593413248000, - "y": 0, - }, - Object { - "x": 1593413249000, - "y": 0, - }, - Object { - "x": 1593413250000, - "y": 0, - }, - Object { - "x": 1593413251000, - "y": 0, - }, - Object { - "x": 1593413252000, - "y": 0, - }, - Object { - "x": 1593413253000, - "y": 0, - }, - Object { - "x": 1593413254000, - "y": 0, - }, - Object { - "x": 1593413255000, - "y": 0, - }, - Object { - "x": 1593413256000, - "y": 0, - }, - Object { - "x": 1593413257000, - "y": 0, - }, - Object { - "x": 1593413258000, - "y": 0, - }, - Object { - "x": 1593413259000, - "y": 0, - }, - Object { - "x": 1593413260000, - "y": 0, - }, - Object { - "x": 1593413261000, - "y": 0, - }, - Object { - "x": 1593413262000, - "y": 0, - }, - Object { - "x": 1593413263000, - "y": 0, - }, - Object { - "x": 1593413264000, - "y": 0, - }, - Object { - "x": 1593413265000, - "y": 0, - }, - Object { - "x": 1593413266000, - "y": 0, - }, - Object { - "x": 1593413267000, - "y": 0, - }, - Object { - "x": 1593413268000, - "y": 0, - }, - Object { - "x": 1593413269000, - "y": 0, - }, - Object { - "x": 1593413270000, - "y": 0, - }, - Object { - "x": 1593413271000, - "y": 0, - }, - Object { - "x": 1593413272000, - "y": 0, - }, - Object { - "x": 1593413273000, - "y": 0, - }, - Object { - "x": 1593413274000, - "y": 0, - }, - Object { - "x": 1593413275000, - "y": 0, - }, - Object { - "x": 1593413276000, - "y": 0, - }, - Object { - "x": 1593413277000, - "y": 0, - }, - Object { - "x": 1593413278000, - "y": 0, - }, - Object { - "x": 1593413279000, - "y": 0, - }, - Object { - "x": 1593413280000, - "y": 0, - }, - Object { - "x": 1593413281000, - "y": 0, - }, - Object { - "x": 1593413282000, - "y": 0, - }, - Object { - "x": 1593413283000, - "y": 0, - }, - Object { - "x": 1593413284000, - "y": 0, - }, - Object { - "x": 1593413285000, - "y": 0, - }, - Object { - "x": 1593413286000, - "y": 0, - }, - Object { - "x": 1593413287000, - "y": 0, - }, - Object { - "x": 1593413288000, - "y": 0, - }, - Object { - "x": 1593413289000, - "y": 0, - }, - Object { - "x": 1593413290000, - "y": 0, - }, - Object { - "x": 1593413291000, - "y": 0, - }, - Object { - "x": 1593413292000, - "y": 0, - }, - Object { - "x": 1593413293000, - "y": 0, - }, - Object { - "x": 1593413294000, - "y": 0, - }, - Object { - "x": 1593413295000, - "y": 0, - }, - Object { - "x": 1593413296000, - "y": 0, - }, - Object { - "x": 1593413297000, - "y": 0, - }, - Object { - "x": 1593413298000, - "y": 2, - }, - Object { - "x": 1593413299000, - "y": 0, - }, - Object { - "x": 1593413300000, - "y": 0, - }, - Object { - "x": 1593413301000, - "y": 3, - }, - Object { - "x": 1593413302000, - "y": 0, - }, - Object { - "x": 1593413303000, - "y": 0, - }, - Object { - "x": 1593413304000, - "y": 0, - }, - Object { - "x": 1593413305000, - "y": 0, - }, - Object { - "x": 1593413306000, - "y": 0, - }, - Object { - "x": 1593413307000, - "y": 0, - }, - Object { - "x": 1593413308000, - "y": 0, - }, - Object { - "x": 1593413309000, - "y": 0, - }, - Object { - "x": 1593413310000, - "y": 0, - }, - Object { - "x": 1593413311000, - "y": 0, - }, - Object { - "x": 1593413312000, - "y": 0, - }, - Object { - "x": 1593413313000, - "y": 0, - }, - Object { - "x": 1593413314000, - "y": 0, - }, - Object { - "x": 1593413315000, - "y": 0, - }, - Object { - "x": 1593413316000, - "y": 0, - }, - Object { - "x": 1593413317000, - "y": 2, - }, - Object { - "x": 1593413318000, - "y": 0, - }, - Object { - "x": 1593413319000, - "y": 0, - }, - Object { - "x": 1593413320000, - "y": 0, - }, - Object { - "x": 1593413321000, - "y": 0, - }, - Object { - "x": 1593413322000, - "y": 0, - }, - Object { - "x": 1593413323000, - "y": 0, - }, - Object { - "x": 1593413324000, - "y": 0, - }, - Object { - "x": 1593413325000, - "y": 0, - }, - Object { - "x": 1593413326000, - "y": 0, - }, - Object { - "x": 1593413327000, - "y": 0, - }, - Object { - "x": 1593413328000, - "y": 0, - }, - Object { - "x": 1593413329000, - "y": 0, - }, - Object { - "x": 1593413330000, - "y": 0, - }, - Object { - "x": 1593413331000, - "y": 0, - }, - Object { - "x": 1593413332000, - "y": 0, - }, - Object { - "x": 1593413333000, - "y": 0, - }, - Object { - "x": 1593413334000, - "y": 0, - }, - Object { - "x": 1593413335000, - "y": 0, - }, - Object { - "x": 1593413336000, - "y": 0, - }, - Object { - "x": 1593413337000, - "y": 0, - }, - Object { - "x": 1593413338000, - "y": 0, - }, - Object { - "x": 1593413339000, - "y": 0, - }, - Object { - "x": 1593413340000, - "y": 0, - }, - ], - "key": "HTTP 3xx", - }, - Object { - "avg": 2, - "dataPoints": Array [ - Object { - "x": 1593413100000, - "y": 0, - }, - Object { - "x": 1593413101000, - "y": 0, - }, - Object { - "x": 1593413102000, - "y": 0, - }, - Object { - "x": 1593413103000, - "y": 0, - }, - Object { - "x": 1593413104000, - "y": 0, - }, - Object { - "x": 1593413105000, - "y": 0, - }, - Object { - "x": 1593413106000, - "y": 0, - }, - Object { - "x": 1593413107000, - "y": 0, - }, - Object { - "x": 1593413108000, - "y": 0, - }, - Object { - "x": 1593413109000, - "y": 0, - }, - Object { - "x": 1593413110000, - "y": 0, - }, - Object { - "x": 1593413111000, - "y": 0, - }, - Object { - "x": 1593413112000, - "y": 0, - }, - Object { - "x": 1593413113000, - "y": 0, - }, - Object { - "x": 1593413114000, - "y": 0, - }, - Object { - "x": 1593413115000, - "y": 0, - }, - Object { - "x": 1593413116000, - "y": 0, - }, - Object { - "x": 1593413117000, - "y": 0, - }, - Object { - "x": 1593413118000, - "y": 0, - }, - Object { - "x": 1593413119000, - "y": 0, - }, - Object { - "x": 1593413120000, - "y": 0, - }, - Object { - "x": 1593413121000, - "y": 0, - }, - Object { - "x": 1593413122000, - "y": 0, - }, - Object { - "x": 1593413123000, - "y": 0, - }, - Object { - "x": 1593413124000, - "y": 0, - }, - Object { - "x": 1593413125000, - "y": 0, - }, - Object { - "x": 1593413126000, - "y": 0, - }, - Object { - "x": 1593413127000, - "y": 0, - }, - Object { - "x": 1593413128000, - "y": 0, - }, - Object { - "x": 1593413129000, - "y": 0, - }, - Object { - "x": 1593413130000, - "y": 0, - }, - Object { - "x": 1593413131000, - "y": 0, - }, - Object { - "x": 1593413132000, - "y": 0, - }, - Object { - "x": 1593413133000, - "y": 0, - }, - Object { - "x": 1593413134000, - "y": 0, - }, - Object { - "x": 1593413135000, - "y": 0, - }, - Object { - "x": 1593413136000, - "y": 0, - }, - Object { - "x": 1593413137000, - "y": 0, - }, - Object { - "x": 1593413138000, - "y": 0, - }, - Object { - "x": 1593413139000, - "y": 0, - }, - Object { - "x": 1593413140000, - "y": 0, - }, - Object { - "x": 1593413141000, - "y": 0, - }, - Object { - "x": 1593413142000, - "y": 0, - }, - Object { - "x": 1593413143000, - "y": 0, - }, - Object { - "x": 1593413144000, - "y": 0, - }, - Object { - "x": 1593413145000, - "y": 0, - }, - Object { - "x": 1593413146000, - "y": 0, - }, - Object { - "x": 1593413147000, - "y": 0, - }, - Object { - "x": 1593413148000, - "y": 0, - }, - Object { - "x": 1593413149000, - "y": 0, - }, - Object { - "x": 1593413150000, - "y": 0, - }, - Object { - "x": 1593413151000, - "y": 0, - }, - Object { - "x": 1593413152000, - "y": 0, - }, - Object { - "x": 1593413153000, - "y": 0, - }, - Object { - "x": 1593413154000, - "y": 0, - }, - Object { - "x": 1593413155000, - "y": 0, - }, - Object { - "x": 1593413156000, - "y": 0, - }, - Object { - "x": 1593413157000, - "y": 0, - }, - Object { - "x": 1593413158000, - "y": 0, - }, - Object { - "x": 1593413159000, - "y": 0, - }, - Object { - "x": 1593413160000, - "y": 0, - }, - Object { - "x": 1593413161000, - "y": 0, - }, - Object { - "x": 1593413162000, - "y": 0, - }, - Object { - "x": 1593413163000, - "y": 0, - }, - Object { - "x": 1593413164000, - "y": 0, - }, - Object { - "x": 1593413165000, - "y": 0, - }, - Object { - "x": 1593413166000, - "y": 0, - }, - Object { - "x": 1593413167000, - "y": 0, - }, - Object { - "x": 1593413168000, - "y": 0, - }, - Object { - "x": 1593413169000, - "y": 0, - }, - Object { - "x": 1593413170000, - "y": 0, - }, - Object { - "x": 1593413171000, - "y": 0, - }, - Object { - "x": 1593413172000, - "y": 0, - }, - Object { - "x": 1593413173000, - "y": 0, - }, - Object { - "x": 1593413174000, - "y": 0, - }, - Object { - "x": 1593413175000, - "y": 0, - }, - Object { - "x": 1593413176000, - "y": 0, - }, - Object { - "x": 1593413177000, - "y": 0, - }, - Object { - "x": 1593413178000, - "y": 0, - }, - Object { - "x": 1593413179000, - "y": 0, - }, - Object { - "x": 1593413180000, - "y": 0, - }, - Object { - "x": 1593413181000, - "y": 0, - }, - Object { - "x": 1593413182000, - "y": 0, - }, - Object { - "x": 1593413183000, - "y": 0, - }, - Object { - "x": 1593413184000, - "y": 0, - }, - Object { - "x": 1593413185000, - "y": 0, - }, - Object { - "x": 1593413186000, - "y": 0, - }, - Object { - "x": 1593413187000, - "y": 0, - }, - Object { - "x": 1593413188000, - "y": 0, - }, - Object { - "x": 1593413189000, - "y": 0, - }, - Object { - "x": 1593413190000, - "y": 0, - }, - Object { - "x": 1593413191000, - "y": 0, - }, - Object { - "x": 1593413192000, - "y": 0, - }, - Object { - "x": 1593413193000, - "y": 0, - }, - Object { - "x": 1593413194000, - "y": 0, - }, - Object { - "x": 1593413195000, - "y": 0, - }, - Object { - "x": 1593413196000, - "y": 0, - }, - Object { - "x": 1593413197000, - "y": 0, - }, - Object { - "x": 1593413198000, - "y": 0, - }, - Object { - "x": 1593413199000, - "y": 0, - }, - Object { - "x": 1593413200000, - "y": 0, - }, - Object { - "x": 1593413201000, - "y": 0, - }, - Object { - "x": 1593413202000, - "y": 0, - }, - Object { - "x": 1593413203000, - "y": 0, - }, - Object { - "x": 1593413204000, - "y": 0, - }, - Object { - "x": 1593413205000, - "y": 0, - }, - Object { - "x": 1593413206000, - "y": 0, - }, - Object { - "x": 1593413207000, - "y": 0, - }, - Object { - "x": 1593413208000, - "y": 0, - }, - Object { - "x": 1593413209000, - "y": 0, - }, - Object { - "x": 1593413210000, - "y": 0, - }, - Object { - "x": 1593413211000, - "y": 0, - }, - Object { - "x": 1593413212000, - "y": 0, - }, - Object { - "x": 1593413213000, - "y": 0, - }, - Object { - "x": 1593413214000, - "y": 0, - }, - Object { - "x": 1593413215000, - "y": 0, - }, - Object { - "x": 1593413216000, - "y": 0, - }, - Object { - "x": 1593413217000, - "y": 0, - }, - Object { - "x": 1593413218000, - "y": 0, - }, - Object { - "x": 1593413219000, - "y": 0, - }, - Object { - "x": 1593413220000, - "y": 0, - }, - Object { - "x": 1593413221000, - "y": 0, - }, - Object { - "x": 1593413222000, - "y": 0, - }, - Object { - "x": 1593413223000, - "y": 0, - }, - Object { - "x": 1593413224000, - "y": 0, - }, - Object { - "x": 1593413225000, - "y": 0, - }, - Object { - "x": 1593413226000, - "y": 0, - }, - Object { - "x": 1593413227000, - "y": 0, - }, - Object { - "x": 1593413228000, - "y": 0, - }, - Object { - "x": 1593413229000, - "y": 0, - }, - Object { - "x": 1593413230000, - "y": 0, - }, - Object { - "x": 1593413231000, - "y": 0, - }, - Object { - "x": 1593413232000, - "y": 0, - }, - Object { - "x": 1593413233000, - "y": 0, - }, - Object { - "x": 1593413234000, - "y": 0, - }, - Object { - "x": 1593413235000, - "y": 0, - }, - Object { - "x": 1593413236000, - "y": 0, - }, - Object { - "x": 1593413237000, - "y": 0, - }, - Object { - "x": 1593413238000, - "y": 0, - }, - Object { - "x": 1593413239000, - "y": 0, - }, - Object { - "x": 1593413240000, - "y": 0, - }, - Object { - "x": 1593413241000, - "y": 0, - }, - Object { - "x": 1593413242000, - "y": 0, - }, - Object { - "x": 1593413243000, - "y": 0, - }, - Object { - "x": 1593413244000, - "y": 0, - }, - Object { - "x": 1593413245000, - "y": 0, - }, - Object { - "x": 1593413246000, - "y": 0, - }, - Object { - "x": 1593413247000, - "y": 0, - }, - Object { - "x": 1593413248000, - "y": 0, - }, - Object { - "x": 1593413249000, - "y": 0, - }, - Object { - "x": 1593413250000, - "y": 0, - }, - Object { - "x": 1593413251000, - "y": 0, - }, - Object { - "x": 1593413252000, - "y": 0, - }, - Object { - "x": 1593413253000, - "y": 0, - }, - Object { - "x": 1593413254000, - "y": 0, - }, - Object { - "x": 1593413255000, - "y": 0, - }, - Object { - "x": 1593413256000, - "y": 0, - }, - Object { - "x": 1593413257000, - "y": 0, - }, - Object { - "x": 1593413258000, - "y": 0, - }, - Object { - "x": 1593413259000, - "y": 0, - }, - Object { - "x": 1593413260000, - "y": 0, - }, - Object { - "x": 1593413261000, - "y": 0, - }, - Object { - "x": 1593413262000, - "y": 0, - }, - Object { - "x": 1593413263000, - "y": 0, - }, - Object { - "x": 1593413264000, - "y": 0, - }, - Object { - "x": 1593413265000, - "y": 0, - }, - Object { - "x": 1593413266000, - "y": 0, - }, - Object { - "x": 1593413267000, - "y": 0, - }, - Object { - "x": 1593413268000, - "y": 0, - }, - Object { - "x": 1593413269000, - "y": 0, - }, - Object { - "x": 1593413270000, - "y": 0, - }, - Object { - "x": 1593413271000, - "y": 0, - }, - Object { - "x": 1593413272000, - "y": 0, - }, - Object { - "x": 1593413273000, - "y": 0, - }, - Object { - "x": 1593413274000, - "y": 0, - }, - Object { - "x": 1593413275000, - "y": 0, - }, - Object { - "x": 1593413276000, - "y": 0, - }, - Object { - "x": 1593413277000, - "y": 0, - }, - Object { - "x": 1593413278000, - "y": 0, - }, - Object { - "x": 1593413279000, - "y": 0, - }, - Object { - "x": 1593413280000, - "y": 0, - }, - Object { - "x": 1593413281000, - "y": 0, - }, - Object { - "x": 1593413282000, - "y": 0, - }, - Object { - "x": 1593413283000, - "y": 0, - }, - Object { - "x": 1593413284000, - "y": 0, - }, - Object { - "x": 1593413285000, - "y": 0, - }, - Object { - "x": 1593413286000, - "y": 0, - }, - Object { - "x": 1593413287000, - "y": 0, - }, - Object { - "x": 1593413288000, - "y": 0, - }, - Object { - "x": 1593413289000, - "y": 1, - }, - Object { - "x": 1593413290000, - "y": 0, - }, - Object { - "x": 1593413291000, - "y": 0, - }, - Object { - "x": 1593413292000, - "y": 1, - }, - Object { - "x": 1593413293000, - "y": 0, - }, - Object { - "x": 1593413294000, - "y": 0, - }, - Object { - "x": 1593413295000, - "y": 0, - }, - Object { - "x": 1593413296000, - "y": 0, - }, - Object { - "x": 1593413297000, - "y": 0, - }, - Object { - "x": 1593413298000, - "y": 0, - }, - Object { - "x": 1593413299000, - "y": 0, - }, - Object { - "x": 1593413300000, - "y": 1, - }, - Object { - "x": 1593413301000, - "y": 0, - }, - Object { - "x": 1593413302000, - "y": 0, - }, - Object { - "x": 1593413303000, - "y": 0, - }, - Object { - "x": 1593413304000, - "y": 0, - }, - Object { - "x": 1593413305000, - "y": 1, - }, - Object { - "x": 1593413306000, - "y": 0, - }, - Object { - "x": 1593413307000, - "y": 0, - }, - Object { - "x": 1593413308000, - "y": 0, - }, - Object { - "x": 1593413309000, - "y": 1, - }, - Object { - "x": 1593413310000, - "y": 1, - }, - Object { - "x": 1593413311000, - "y": 0, - }, - Object { - "x": 1593413312000, - "y": 0, - }, - Object { - "x": 1593413313000, - "y": 0, - }, - Object { - "x": 1593413314000, - "y": 0, - }, - Object { - "x": 1593413315000, - "y": 1, - }, - Object { - "x": 1593413316000, - "y": 0, - }, - Object { - "x": 1593413317000, - "y": 0, - }, - Object { - "x": 1593413318000, - "y": 0, - }, + "x": 1599721110000, + "y": 927744, + }, + Object { + "x": 1599721140000, + "y": 1048320, + }, + Object { + "x": 1599721170000, + "y": 1363968, + }, + Object { + "x": 1599721200000, + "y": null, + }, + ], + }, + "tpmBuckets": Array [ + Object { + "avg": 3.183333333333333, + "dataPoints": Array [ Object { - "x": 1593413319000, + "x": 1599717600000, "y": 0, }, Object { - "x": 1593413320000, + "x": 1599717630000, "y": 1, }, Object { - "x": 1593413321000, - "y": 0, - }, - Object { - "x": 1593413322000, - "y": 0, - }, - Object { - "x": 1593413323000, - "y": 0, - }, - Object { - "x": 1593413324000, - "y": 0, - }, - Object { - "x": 1593413325000, - "y": 0, - }, - Object { - "x": 1593413326000, - "y": 0, - }, - Object { - "x": 1593413327000, - "y": 0, - }, - Object { - "x": 1593413328000, - "y": 0, - }, - Object { - "x": 1593413329000, - "y": 0, - }, - Object { - "x": 1593413330000, - "y": 0, - }, - Object { - "x": 1593413331000, - "y": 0, - }, - Object { - "x": 1593413332000, - "y": 0, - }, - Object { - "x": 1593413333000, - "y": 0, + "x": 1599717660000, + "y": 2, }, Object { - "x": 1593413334000, + "x": 1599717690000, "y": 0, }, Object { - "x": 1593413335000, - "y": 0, + "x": 1599717720000, + "y": 3, }, Object { - "x": 1593413336000, - "y": 0, + "x": 1599717750000, + "y": 3, }, Object { - "x": 1593413337000, - "y": 0, + "x": 1599717780000, + "y": 2, }, Object { - "x": 1593413338000, + "x": 1599717810000, "y": 0, }, Object { - "x": 1593413339000, - "y": 0, + "x": 1599717840000, + "y": 1, }, Object { - "x": 1593413340000, - "y": 0, + "x": 1599717870000, + "y": 2, }, - ], - "key": "HTTP 4xx", - }, - Object { - "avg": 2.25, - "dataPoints": Array [ Object { - "x": 1593413100000, - "y": 0, + "x": 1599717900000, + "y": 2, }, Object { - "x": 1593413101000, + "x": 1599717930000, "y": 0, }, Object { - "x": 1593413102000, - "y": 0, + "x": 1599717960000, + "y": 4, }, Object { - "x": 1593413103000, - "y": 0, + "x": 1599717990000, + "y": 4, }, Object { - "x": 1593413104000, - "y": 0, + "x": 1599718020000, + "y": 1, }, Object { - "x": 1593413105000, + "x": 1599718050000, "y": 0, }, Object { - "x": 1593413106000, - "y": 0, + "x": 1599718080000, + "y": 5, }, Object { - "x": 1593413107000, - "y": 0, + "x": 1599718110000, + "y": 1, }, Object { - "x": 1593413108000, - "y": 0, + "x": 1599718140000, + "y": 2, }, Object { - "x": 1593413109000, + "x": 1599718170000, "y": 0, }, Object { - "x": 1593413110000, - "y": 0, + "x": 1599718200000, + "y": 6, }, Object { - "x": 1593413111000, - "y": 0, + "x": 1599718230000, + "y": 2, }, Object { - "x": 1593413112000, + "x": 1599718260000, "y": 0, }, Object { - "x": 1593413113000, + "x": 1599718290000, "y": 0, }, Object { - "x": 1593413114000, - "y": 0, + "x": 1599718320000, + "y": 2, }, Object { - "x": 1593413115000, - "y": 0, + "x": 1599718350000, + "y": 3, }, Object { - "x": 1593413116000, - "y": 0, + "x": 1599718380000, + "y": 2, }, Object { - "x": 1593413117000, + "x": 1599718410000, "y": 0, }, Object { - "x": 1593413118000, - "y": 0, + "x": 1599718440000, + "y": 3, }, Object { - "x": 1593413119000, - "y": 0, + "x": 1599718470000, + "y": 6, }, Object { - "x": 1593413120000, - "y": 0, + "x": 1599718500000, + "y": 1, }, Object { - "x": 1593413121000, + "x": 1599718530000, "y": 0, }, Object { - "x": 1593413122000, - "y": 0, + "x": 1599718560000, + "y": 7, }, Object { - "x": 1593413123000, + "x": 1599718590000, "y": 0, }, Object { - "x": 1593413124000, - "y": 0, + "x": 1599718620000, + "y": 2, }, Object { - "x": 1593413125000, + "x": 1599718650000, "y": 0, }, Object { - "x": 1593413126000, - "y": 0, + "x": 1599718680000, + "y": 3, }, Object { - "x": 1593413127000, - "y": 0, + "x": 1599718710000, + "y": 2, }, Object { - "x": 1593413128000, - "y": 0, + "x": 1599718740000, + "y": 1, }, Object { - "x": 1593413129000, - "y": 0, + "x": 1599718770000, + "y": 1, }, Object { - "x": 1593413130000, + "x": 1599718800000, "y": 0, }, Object { - "x": 1593413131000, - "y": 0, + "x": 1599718830000, + "y": 4, }, Object { - "x": 1593413132000, - "y": 0, + "x": 1599718860000, + "y": 1, }, Object { - "x": 1593413133000, + "x": 1599718890000, "y": 0, }, Object { - "x": 1593413134000, - "y": 0, + "x": 1599718920000, + "y": 2, }, Object { - "x": 1593413135000, + "x": 1599718950000, "y": 0, }, Object { - "x": 1593413136000, + "x": 1599718980000, "y": 0, }, Object { - "x": 1593413137000, - "y": 0, + "x": 1599719010000, + "y": 3, }, Object { - "x": 1593413138000, - "y": 0, + "x": 1599719040000, + "y": 4, }, Object { - "x": 1593413139000, - "y": 0, + "x": 1599719070000, + "y": 1, }, Object { - "x": 1593413140000, - "y": 0, + "x": 1599719100000, + "y": 2, }, Object { - "x": 1593413141000, + "x": 1599719130000, "y": 0, }, Object { - "x": 1593413142000, - "y": 0, + "x": 1599719160000, + "y": 6, }, Object { - "x": 1593413143000, - "y": 0, + "x": 1599719190000, + "y": 1, }, Object { - "x": 1593413144000, - "y": 0, + "x": 1599719220000, + "y": 5, }, Object { - "x": 1593413145000, + "x": 1599719250000, "y": 0, }, Object { - "x": 1593413146000, - "y": 0, + "x": 1599719280000, + "y": 2, }, Object { - "x": 1593413147000, - "y": 0, + "x": 1599719310000, + "y": 3, }, Object { - "x": 1593413148000, + "x": 1599719340000, "y": 0, }, Object { - "x": 1593413149000, + "x": 1599719370000, "y": 0, }, Object { - "x": 1593413150000, - "y": 0, + "x": 1599719400000, + "y": 6, }, Object { - "x": 1593413151000, - "y": 0, + "x": 1599719430000, + "y": 3, }, Object { - "x": 1593413152000, + "x": 1599719460000, "y": 0, }, Object { - "x": 1593413153000, - "y": 0, + "x": 1599719490000, + "y": 1, }, Object { - "x": 1593413154000, - "y": 0, + "x": 1599719520000, + "y": 1, }, Object { - "x": 1593413155000, + "x": 1599719550000, "y": 0, }, Object { - "x": 1593413156000, - "y": 0, + "x": 1599719580000, + "y": 1, }, Object { - "x": 1593413157000, + "x": 1599719610000, "y": 0, }, Object { - "x": 1593413158000, - "y": 0, + "x": 1599719640000, + "y": 4, }, Object { - "x": 1593413159000, - "y": 0, + "x": 1599719670000, + "y": 2, }, Object { - "x": 1593413160000, + "x": 1599719700000, "y": 0, }, Object { - "x": 1593413161000, - "y": 0, + "x": 1599719730000, + "y": 2, }, Object { - "x": 1593413162000, - "y": 0, + "x": 1599719760000, + "y": 3, }, Object { - "x": 1593413163000, + "x": 1599719790000, "y": 0, }, Object { - "x": 1593413164000, - "y": 0, + "x": 1599719820000, + "y": 2, }, Object { - "x": 1593413165000, + "x": 1599719850000, "y": 0, }, Object { - "x": 1593413166000, - "y": 0, + "x": 1599719880000, + "y": 4, }, Object { - "x": 1593413167000, + "x": 1599719910000, "y": 0, }, Object { - "x": 1593413168000, + "x": 1599719940000, "y": 0, }, Object { - "x": 1593413169000, - "y": 0, + "x": 1599719970000, + "y": 1, }, Object { - "x": 1593413170000, - "y": 0, + "x": 1599720000000, + "y": 1, }, Object { - "x": 1593413171000, - "y": 0, + "x": 1599720030000, + "y": 1, }, Object { - "x": 1593413172000, - "y": 0, + "x": 1599720060000, + "y": 1, }, Object { - "x": 1593413173000, + "x": 1599720090000, "y": 0, }, Object { - "x": 1593413174000, + "x": 1599720120000, "y": 0, }, Object { - "x": 1593413175000, + "x": 1599720150000, "y": 0, }, Object { - "x": 1593413176000, - "y": 0, + "x": 1599720180000, + "y": 1, }, Object { - "x": 1593413177000, + "x": 1599720210000, "y": 0, }, Object { - "x": 1593413178000, - "y": 0, + "x": 1599720240000, + "y": 4, }, Object { - "x": 1593413179000, - "y": 0, + "x": 1599720270000, + "y": 1, }, Object { - "x": 1593413180000, - "y": 0, + "x": 1599720300000, + "y": 2, }, Object { - "x": 1593413181000, + "x": 1599720330000, "y": 0, }, Object { - "x": 1593413182000, - "y": 0, + "x": 1599720360000, + "y": 1, }, Object { - "x": 1593413183000, - "y": 0, + "x": 1599720390000, + "y": 5, }, Object { - "x": 1593413184000, - "y": 0, + "x": 1599720420000, + "y": 4, }, Object { - "x": 1593413185000, + "x": 1599720450000, "y": 0, }, Object { - "x": 1593413186000, + "x": 1599720480000, "y": 0, }, Object { - "x": 1593413187000, - "y": 0, + "x": 1599720510000, + "y": 3, }, Object { - "x": 1593413188000, + "x": 1599720540000, "y": 0, }, Object { - "x": 1593413189000, + "x": 1599720570000, "y": 0, }, Object { - "x": 1593413190000, - "y": 0, + "x": 1599720600000, + "y": 2, }, Object { - "x": 1593413191000, - "y": 0, + "x": 1599720630000, + "y": 3, }, Object { - "x": 1593413192000, - "y": 0, + "x": 1599720660000, + "y": 1, }, Object { - "x": 1593413193000, + "x": 1599720690000, "y": 0, }, Object { - "x": 1593413194000, - "y": 0, + "x": 1599720720000, + "y": 2, }, Object { - "x": 1593413195000, - "y": 0, + "x": 1599720750000, + "y": 4, }, Object { - "x": 1593413196000, - "y": 0, + "x": 1599720780000, + "y": 2, }, Object { - "x": 1593413197000, + "x": 1599720810000, "y": 0, }, Object { - "x": 1593413198000, - "y": 0, + "x": 1599720840000, + "y": 1, }, Object { - "x": 1593413199000, - "y": 0, + "x": 1599720870000, + "y": 3, }, Object { - "x": 1593413200000, - "y": 0, + "x": 1599720900000, + "y": 3, }, Object { - "x": 1593413201000, + "x": 1599720930000, "y": 0, }, Object { - "x": 1593413202000, - "y": 0, + "x": 1599720960000, + "y": 1, }, Object { - "x": 1593413203000, - "y": 0, + "x": 1599720990000, + "y": 1, }, Object { - "x": 1593413204000, - "y": 0, + "x": 1599721020000, + "y": 1, }, Object { - "x": 1593413205000, + "x": 1599721050000, "y": 0, }, Object { - "x": 1593413206000, - "y": 0, + "x": 1599721080000, + "y": 4, }, Object { - "x": 1593413207000, + "x": 1599721110000, "y": 0, }, Object { - "x": 1593413208000, - "y": 0, + "x": 1599721140000, + "y": 1, }, Object { - "x": 1593413209000, + "x": 1599721170000, "y": 0, }, Object { - "x": 1593413210000, + "x": 1599721200000, "y": 0, }, + ], + "key": "HTTP 2xx", + }, + Object { + "avg": 0.21666666666666667, + "dataPoints": Array [ Object { - "x": 1593413211000, + "x": 1599717600000, "y": 0, }, Object { - "x": 1593413212000, + "x": 1599717630000, "y": 0, }, Object { - "x": 1593413213000, + "x": 1599717660000, "y": 0, }, Object { - "x": 1593413214000, + "x": 1599717690000, "y": 0, }, Object { - "x": 1593413215000, - "y": 0, + "x": 1599717720000, + "y": 1, }, Object { - "x": 1593413216000, + "x": 1599717750000, "y": 0, }, Object { - "x": 1593413217000, + "x": 1599717780000, "y": 0, }, Object { - "x": 1593413218000, + "x": 1599717810000, "y": 0, }, Object { - "x": 1593413219000, + "x": 1599717840000, "y": 0, }, Object { - "x": 1593413220000, + "x": 1599717870000, "y": 0, }, Object { - "x": 1593413221000, + "x": 1599717900000, "y": 0, }, Object { - "x": 1593413222000, + "x": 1599717930000, "y": 0, }, Object { - "x": 1593413223000, + "x": 1599717960000, "y": 0, }, Object { - "x": 1593413224000, + "x": 1599717990000, "y": 0, }, Object { - "x": 1593413225000, + "x": 1599718020000, "y": 0, }, Object { - "x": 1593413226000, + "x": 1599718050000, "y": 0, }, Object { - "x": 1593413227000, + "x": 1599718080000, "y": 0, }, Object { - "x": 1593413228000, + "x": 1599718110000, "y": 0, }, Object { - "x": 1593413229000, + "x": 1599718140000, "y": 0, }, Object { - "x": 1593413230000, + "x": 1599718170000, "y": 0, }, Object { - "x": 1593413231000, - "y": 0, + "x": 1599718200000, + "y": 1, }, Object { - "x": 1593413232000, + "x": 1599718230000, "y": 0, }, Object { - "x": 1593413233000, + "x": 1599718260000, "y": 0, }, Object { - "x": 1593413234000, + "x": 1599718290000, "y": 0, }, Object { - "x": 1593413235000, + "x": 1599718320000, "y": 0, }, Object { - "x": 1593413236000, + "x": 1599718350000, "y": 0, }, Object { - "x": 1593413237000, + "x": 1599718380000, "y": 0, }, Object { - "x": 1593413238000, + "x": 1599718410000, "y": 0, }, Object { - "x": 1593413239000, + "x": 1599718440000, "y": 0, }, Object { - "x": 1593413240000, - "y": 0, + "x": 1599718470000, + "y": 1, }, Object { - "x": 1593413241000, + "x": 1599718500000, "y": 0, }, Object { - "x": 1593413242000, + "x": 1599718530000, "y": 0, }, Object { - "x": 1593413243000, - "y": 0, + "x": 1599718560000, + "y": 2, }, Object { - "x": 1593413244000, + "x": 1599718590000, "y": 0, }, Object { - "x": 1593413245000, + "x": 1599718620000, "y": 0, }, Object { - "x": 1593413246000, + "x": 1599718650000, "y": 0, }, Object { - "x": 1593413247000, - "y": 0, + "x": 1599718680000, + "y": 2, }, Object { - "x": 1593413248000, + "x": 1599718710000, "y": 0, }, Object { - "x": 1593413249000, + "x": 1599718740000, "y": 0, }, Object { - "x": 1593413250000, + "x": 1599718770000, "y": 0, }, Object { - "x": 1593413251000, + "x": 1599718800000, "y": 0, }, Object { - "x": 1593413252000, + "x": 1599718830000, "y": 0, }, Object { - "x": 1593413253000, + "x": 1599718860000, "y": 0, }, Object { - "x": 1593413254000, + "x": 1599718890000, "y": 0, }, Object { - "x": 1593413255000, + "x": 1599718920000, "y": 0, }, Object { - "x": 1593413256000, + "x": 1599718950000, "y": 0, }, Object { - "x": 1593413257000, + "x": 1599718980000, "y": 0, }, Object { - "x": 1593413258000, + "x": 1599719010000, "y": 0, }, Object { - "x": 1593413259000, - "y": 0, + "x": 1599719040000, + "y": 1, }, Object { - "x": 1593413260000, + "x": 1599719070000, "y": 0, }, Object { - "x": 1593413261000, + "x": 1599719100000, "y": 0, }, Object { - "x": 1593413262000, + "x": 1599719130000, "y": 0, }, Object { - "x": 1593413263000, + "x": 1599719160000, "y": 0, }, Object { - "x": 1593413264000, + "x": 1599719190000, "y": 0, }, Object { - "x": 1593413265000, + "x": 1599719220000, "y": 0, }, Object { - "x": 1593413266000, + "x": 1599719250000, "y": 0, }, Object { - "x": 1593413267000, + "x": 1599719280000, "y": 0, }, Object { - "x": 1593413268000, + "x": 1599719310000, "y": 0, }, Object { - "x": 1593413269000, + "x": 1599719340000, "y": 0, }, Object { - "x": 1593413270000, + "x": 1599719370000, "y": 0, }, Object { - "x": 1593413271000, - "y": 0, + "x": 1599719400000, + "y": 2, }, Object { - "x": 1593413272000, + "x": 1599719430000, "y": 0, }, Object { - "x": 1593413273000, + "x": 1599719460000, "y": 0, }, Object { - "x": 1593413274000, + "x": 1599719490000, "y": 0, }, Object { - "x": 1593413275000, + "x": 1599719520000, "y": 0, }, Object { - "x": 1593413276000, + "x": 1599719550000, "y": 0, }, Object { - "x": 1593413277000, + "x": 1599719580000, "y": 0, }, Object { - "x": 1593413278000, + "x": 1599719610000, "y": 0, }, Object { - "x": 1593413279000, - "y": 0, + "x": 1599719640000, + "y": 1, }, Object { - "x": 1593413280000, - "y": 0, + "x": 1599719670000, + "y": 1, }, Object { - "x": 1593413281000, + "x": 1599719700000, "y": 0, }, Object { - "x": 1593413282000, + "x": 1599719730000, "y": 0, }, Object { - "x": 1593413283000, + "x": 1599719760000, "y": 0, }, Object { - "x": 1593413284000, + "x": 1599719790000, "y": 0, }, Object { - "x": 1593413285000, + "x": 1599719820000, "y": 0, }, Object { - "x": 1593413286000, - "y": 1, - }, - Object { - "x": 1593413287000, - "y": 1, - }, - Object { - "x": 1593413288000, + "x": 1599719850000, "y": 0, }, Object { - "x": 1593413289000, + "x": 1599719880000, "y": 0, }, Object { - "x": 1593413290000, + "x": 1599719910000, "y": 0, }, Object { - "x": 1593413291000, + "x": 1599719940000, "y": 0, }, Object { - "x": 1593413292000, + "x": 1599719970000, "y": 0, }, Object { - "x": 1593413293000, + "x": 1599720000000, "y": 0, }, Object { - "x": 1593413294000, + "x": 1599720030000, "y": 0, }, Object { - "x": 1593413295000, + "x": 1599720060000, "y": 0, }, Object { - "x": 1593413296000, + "x": 1599720090000, "y": 0, }, Object { - "x": 1593413297000, + "x": 1599720120000, "y": 0, }, Object { - "x": 1593413298000, + "x": 1599720150000, "y": 0, }, Object { - "x": 1593413299000, - "y": 1, - }, - Object { - "x": 1593413300000, + "x": 1599720180000, "y": 0, }, Object { - "x": 1593413301000, - "y": 1, - }, - Object { - "x": 1593413302000, + "x": 1599720210000, "y": 0, }, Object { - "x": 1593413303000, + "x": 1599720240000, "y": 0, }, Object { - "x": 1593413304000, + "x": 1599720270000, "y": 0, }, Object { - "x": 1593413305000, - "y": 1, - }, - Object { - "x": 1593413306000, + "x": 1599720300000, "y": 0, }, Object { - "x": 1593413307000, + "x": 1599720330000, "y": 0, }, Object { - "x": 1593413308000, - "y": 1, - }, - Object { - "x": 1593413309000, + "x": 1599720360000, "y": 0, }, Object { - "x": 1593413310000, + "x": 1599720390000, "y": 0, }, Object { - "x": 1593413311000, - "y": 1, - }, - Object { - "x": 1593413312000, + "x": 1599720420000, "y": 0, }, Object { - "x": 1593413313000, + "x": 1599720450000, "y": 0, }, Object { - "x": 1593413314000, + "x": 1599720480000, "y": 0, }, Object { - "x": 1593413315000, - "y": 1, - }, - Object { - "x": 1593413316000, + "x": 1599720510000, "y": 0, }, Object { - "x": 1593413317000, + "x": 1599720540000, "y": 0, }, Object { - "x": 1593413318000, + "x": 1599720570000, "y": 0, }, Object { - "x": 1593413319000, + "x": 1599720600000, "y": 0, }, Object { - "x": 1593413320000, + "x": 1599720630000, "y": 0, }, Object { - "x": 1593413321000, + "x": 1599720660000, "y": 0, }, Object { - "x": 1593413322000, - "y": 1, - }, - Object { - "x": 1593413323000, + "x": 1599720690000, "y": 0, }, Object { - "x": 1593413324000, + "x": 1599720720000, "y": 0, }, Object { - "x": 1593413325000, + "x": 1599720750000, "y": 0, }, Object { - "x": 1593413326000, + "x": 1599720780000, "y": 0, }, Object { - "x": 1593413327000, + "x": 1599720810000, "y": 0, }, Object { - "x": 1593413328000, + "x": 1599720840000, "y": 0, }, Object { - "x": 1593413329000, + "x": 1599720870000, "y": 0, }, Object { - "x": 1593413330000, + "x": 1599720900000, "y": 0, }, Object { - "x": 1593413331000, + "x": 1599720930000, "y": 0, }, Object { - "x": 1593413332000, - "y": 0, + "x": 1599720960000, + "y": 1, }, Object { - "x": 1593413333000, + "x": 1599720990000, "y": 0, }, Object { - "x": 1593413334000, + "x": 1599721020000, "y": 0, }, Object { - "x": 1593413335000, + "x": 1599721050000, "y": 0, }, Object { - "x": 1593413336000, + "x": 1599721080000, "y": 0, }, Object { - "x": 1593413337000, + "x": 1599721110000, "y": 0, }, Object { - "x": 1593413338000, + "x": 1599721140000, "y": 0, }, Object { - "x": 1593413339000, + "x": 1599721170000, "y": 0, }, Object { - "x": 1593413340000, + "x": 1599721200000, "y": 0, }, ], - "key": "HTTP 5xx", + "key": "HTTP 4xx", }, Object { - "avg": 0.25, + "avg": 0.11666666666666667, "dataPoints": Array [ Object { - "x": 1593413100000, - "y": 0, + "x": 1599717600000, + "y": 1, }, Object { - "x": 1593413101000, + "x": 1599717630000, "y": 0, }, Object { - "x": 1593413102000, + "x": 1599717660000, "y": 0, }, Object { - "x": 1593413103000, + "x": 1599717690000, "y": 0, }, Object { - "x": 1593413104000, + "x": 1599717720000, "y": 0, }, Object { - "x": 1593413105000, + "x": 1599717750000, "y": 0, }, Object { - "x": 1593413106000, + "x": 1599717780000, "y": 0, }, Object { - "x": 1593413107000, + "x": 1599717810000, "y": 0, }, Object { - "x": 1593413108000, + "x": 1599717840000, "y": 0, }, Object { - "x": 1593413109000, + "x": 1599717870000, "y": 0, }, Object { - "x": 1593413110000, + "x": 1599717900000, "y": 0, }, Object { - "x": 1593413111000, + "x": 1599717930000, "y": 0, }, Object { - "x": 1593413112000, + "x": 1599717960000, "y": 0, }, Object { - "x": 1593413113000, + "x": 1599717990000, "y": 0, }, Object { - "x": 1593413114000, + "x": 1599718020000, "y": 0, }, Object { - "x": 1593413115000, + "x": 1599718050000, "y": 0, }, Object { - "x": 1593413116000, + "x": 1599718080000, "y": 0, }, Object { - "x": 1593413117000, + "x": 1599718110000, "y": 0, }, Object { - "x": 1593413118000, + "x": 1599718140000, "y": 0, }, Object { - "x": 1593413119000, + "x": 1599718170000, "y": 0, }, Object { - "x": 1593413120000, + "x": 1599718200000, "y": 0, }, Object { - "x": 1593413121000, - "y": 0, + "x": 1599718230000, + "y": 1, }, Object { - "x": 1593413122000, + "x": 1599718260000, "y": 0, }, Object { - "x": 1593413123000, + "x": 1599718290000, "y": 0, }, Object { - "x": 1593413124000, + "x": 1599718320000, "y": 0, }, Object { - "x": 1593413125000, + "x": 1599718350000, "y": 0, }, Object { - "x": 1593413126000, + "x": 1599718380000, "y": 0, }, Object { - "x": 1593413127000, + "x": 1599718410000, "y": 0, }, Object { - "x": 1593413128000, + "x": 1599718440000, "y": 0, }, Object { - "x": 1593413129000, + "x": 1599718470000, "y": 0, }, Object { - "x": 1593413130000, + "x": 1599718500000, "y": 0, }, Object { - "x": 1593413131000, + "x": 1599718530000, "y": 0, }, Object { - "x": 1593413132000, + "x": 1599718560000, "y": 0, }, Object { - "x": 1593413133000, + "x": 1599718590000, "y": 0, }, Object { - "x": 1593413134000, + "x": 1599718620000, "y": 0, }, Object { - "x": 1593413135000, + "x": 1599718650000, "y": 0, }, Object { - "x": 1593413136000, + "x": 1599718680000, "y": 0, }, Object { - "x": 1593413137000, - "y": 0, + "x": 1599718710000, + "y": 1, }, Object { - "x": 1593413138000, + "x": 1599718740000, "y": 0, }, Object { - "x": 1593413139000, + "x": 1599718770000, "y": 0, }, Object { - "x": 1593413140000, + "x": 1599718800000, "y": 0, }, Object { - "x": 1593413141000, + "x": 1599718830000, "y": 0, }, Object { - "x": 1593413142000, - "y": 0, + "x": 1599718860000, + "y": 2, }, Object { - "x": 1593413143000, + "x": 1599718890000, "y": 0, }, Object { - "x": 1593413144000, + "x": 1599718920000, "y": 0, }, Object { - "x": 1593413145000, + "x": 1599718950000, "y": 0, }, Object { - "x": 1593413146000, + "x": 1599718980000, "y": 0, }, Object { - "x": 1593413147000, + "x": 1599719010000, "y": 0, }, Object { - "x": 1593413148000, + "x": 1599719040000, "y": 0, }, Object { - "x": 1593413149000, + "x": 1599719070000, "y": 0, }, Object { - "x": 1593413150000, + "x": 1599719100000, "y": 0, }, Object { - "x": 1593413151000, + "x": 1599719130000, "y": 0, }, Object { - "x": 1593413152000, + "x": 1599719160000, "y": 0, }, Object { - "x": 1593413153000, + "x": 1599719190000, "y": 0, }, Object { - "x": 1593413154000, + "x": 1599719220000, "y": 0, }, Object { - "x": 1593413155000, + "x": 1599719250000, "y": 0, }, Object { - "x": 1593413156000, + "x": 1599719280000, "y": 0, }, Object { - "x": 1593413157000, + "x": 1599719310000, "y": 0, }, Object { - "x": 1593413158000, + "x": 1599719340000, "y": 0, }, Object { - "x": 1593413159000, + "x": 1599719370000, "y": 0, }, Object { - "x": 1593413160000, + "x": 1599719400000, "y": 0, }, Object { - "x": 1593413161000, + "x": 1599719430000, "y": 0, }, Object { - "x": 1593413162000, + "x": 1599719460000, "y": 0, }, Object { - "x": 1593413163000, + "x": 1599719490000, "y": 0, }, Object { - "x": 1593413164000, + "x": 1599719520000, "y": 0, }, Object { - "x": 1593413165000, + "x": 1599719550000, "y": 0, }, Object { - "x": 1593413166000, + "x": 1599719580000, "y": 0, }, Object { - "x": 1593413167000, + "x": 1599719610000, "y": 0, }, Object { - "x": 1593413168000, + "x": 1599719640000, "y": 0, }, Object { - "x": 1593413169000, + "x": 1599719670000, "y": 0, }, Object { - "x": 1593413170000, + "x": 1599719700000, "y": 0, }, Object { - "x": 1593413171000, + "x": 1599719730000, "y": 0, }, Object { - "x": 1593413172000, + "x": 1599719760000, "y": 0, }, Object { - "x": 1593413173000, + "x": 1599719790000, "y": 0, }, Object { - "x": 1593413174000, + "x": 1599719820000, "y": 0, }, Object { - "x": 1593413175000, + "x": 1599719850000, "y": 0, }, Object { - "x": 1593413176000, + "x": 1599719880000, "y": 0, }, Object { - "x": 1593413177000, + "x": 1599719910000, "y": 0, }, Object { - "x": 1593413178000, + "x": 1599719940000, "y": 0, }, Object { - "x": 1593413179000, - "y": 0, + "x": 1599719970000, + "y": 1, }, Object { - "x": 1593413180000, + "x": 1599720000000, "y": 0, }, Object { - "x": 1593413181000, + "x": 1599720030000, "y": 0, }, Object { - "x": 1593413182000, + "x": 1599720060000, "y": 0, }, Object { - "x": 1593413183000, + "x": 1599720090000, "y": 0, }, Object { - "x": 1593413184000, + "x": 1599720120000, "y": 0, }, Object { - "x": 1593413185000, + "x": 1599720150000, "y": 0, }, Object { - "x": 1593413186000, + "x": 1599720180000, "y": 0, }, Object { - "x": 1593413187000, + "x": 1599720210000, "y": 0, }, Object { - "x": 1593413188000, + "x": 1599720240000, "y": 0, }, Object { - "x": 1593413189000, + "x": 1599720270000, "y": 0, }, Object { - "x": 1593413190000, + "x": 1599720300000, "y": 0, }, Object { - "x": 1593413191000, + "x": 1599720330000, "y": 0, }, Object { - "x": 1593413192000, + "x": 1599720360000, "y": 0, }, Object { - "x": 1593413193000, + "x": 1599720390000, "y": 0, }, Object { - "x": 1593413194000, + "x": 1599720420000, "y": 0, }, Object { - "x": 1593413195000, + "x": 1599720450000, "y": 0, }, Object { - "x": 1593413196000, + "x": 1599720480000, "y": 0, }, Object { - "x": 1593413197000, + "x": 1599720510000, "y": 0, }, Object { - "x": 1593413198000, + "x": 1599720540000, "y": 0, }, Object { - "x": 1593413199000, + "x": 1599720570000, "y": 0, }, Object { - "x": 1593413200000, + "x": 1599720600000, "y": 0, }, Object { - "x": 1593413201000, + "x": 1599720630000, "y": 0, }, Object { - "x": 1593413202000, + "x": 1599720660000, "y": 0, }, Object { - "x": 1593413203000, + "x": 1599720690000, "y": 0, }, Object { - "x": 1593413204000, + "x": 1599720720000, "y": 0, }, Object { - "x": 1593413205000, + "x": 1599720750000, "y": 0, }, Object { - "x": 1593413206000, + "x": 1599720780000, "y": 0, }, Object { - "x": 1593413207000, + "x": 1599720810000, "y": 0, }, Object { - "x": 1593413208000, + "x": 1599720840000, "y": 0, }, Object { - "x": 1593413209000, + "x": 1599720870000, "y": 0, }, Object { - "x": 1593413210000, + "x": 1599720900000, "y": 0, }, Object { - "x": 1593413211000, + "x": 1599720930000, "y": 0, }, Object { - "x": 1593413212000, + "x": 1599720960000, "y": 0, }, Object { - "x": 1593413213000, + "x": 1599720990000, "y": 0, }, Object { - "x": 1593413214000, + "x": 1599721020000, "y": 0, }, Object { - "x": 1593413215000, + "x": 1599721050000, "y": 0, }, Object { - "x": 1593413216000, - "y": 0, + "x": 1599721080000, + "y": 1, }, Object { - "x": 1593413217000, + "x": 1599721110000, "y": 0, }, Object { - "x": 1593413218000, + "x": 1599721140000, "y": 0, }, Object { - "x": 1593413219000, + "x": 1599721170000, "y": 0, }, Object { - "x": 1593413220000, + "x": 1599721200000, "y": 0, }, + ], + "key": "HTTP 5xx", + }, + Object { + "avg": 4.283333333333333, + "dataPoints": Array [ Object { - "x": 1593413221000, - "y": 0, + "x": 1599717600000, + "y": 2, }, Object { - "x": 1593413222000, - "y": 0, + "x": 1599717630000, + "y": 3, }, Object { - "x": 1593413223000, - "y": 0, + "x": 1599717660000, + "y": 1, }, Object { - "x": 1593413224000, - "y": 0, + "x": 1599717690000, + "y": 4, }, Object { - "x": 1593413225000, - "y": 0, + "x": 1599717720000, + "y": 3, }, Object { - "x": 1593413226000, - "y": 0, + "x": 1599717750000, + "y": 4, }, Object { - "x": 1593413227000, - "y": 0, + "x": 1599717780000, + "y": 2, }, Object { - "x": 1593413228000, - "y": 0, + "x": 1599717810000, + "y": 3, }, Object { - "x": 1593413229000, - "y": 0, + "x": 1599717840000, + "y": 2, }, Object { - "x": 1593413230000, - "y": 0, + "x": 1599717870000, + "y": 2, }, Object { - "x": 1593413231000, - "y": 0, + "x": 1599717900000, + "y": 1, }, Object { - "x": 1593413232000, - "y": 0, + "x": 1599717930000, + "y": 3, }, Object { - "x": 1593413233000, - "y": 0, + "x": 1599717960000, + "y": 1, }, Object { - "x": 1593413234000, - "y": 0, + "x": 1599717990000, + "y": 2, }, Object { - "x": 1593413235000, - "y": 0, + "x": 1599718020000, + "y": 3, }, Object { - "x": 1593413236000, - "y": 0, + "x": 1599718050000, + "y": 1, }, Object { - "x": 1593413237000, - "y": 0, + "x": 1599718080000, + "y": 2, }, Object { - "x": 1593413238000, - "y": 0, + "x": 1599718110000, + "y": 1, }, Object { - "x": 1593413239000, - "y": 0, + "x": 1599718140000, + "y": 3, }, Object { - "x": 1593413240000, - "y": 0, + "x": 1599718170000, + "y": 3, }, Object { - "x": 1593413241000, - "y": 0, + "x": 1599718200000, + "y": 2, }, Object { - "x": 1593413242000, - "y": 0, + "x": 1599718230000, + "y": 2, }, Object { - "x": 1593413243000, - "y": 0, + "x": 1599718260000, + "y": 2, }, Object { - "x": 1593413244000, - "y": 0, + "x": 1599718290000, + "y": 2, }, Object { - "x": 1593413245000, - "y": 0, + "x": 1599718320000, + "y": 2, }, Object { - "x": 1593413246000, - "y": 0, + "x": 1599718350000, + "y": 3, }, Object { - "x": 1593413247000, - "y": 0, + "x": 1599718380000, + "y": 3, }, Object { - "x": 1593413248000, - "y": 0, + "x": 1599718410000, + "y": 2, }, Object { - "x": 1593413249000, - "y": 0, + "x": 1599718440000, + "y": 2, }, Object { - "x": 1593413250000, - "y": 0, + "x": 1599718470000, + "y": 2, }, Object { - "x": 1593413251000, - "y": 0, + "x": 1599718500000, + "y": 2, }, Object { - "x": 1593413252000, - "y": 0, + "x": 1599718530000, + "y": 3, }, Object { - "x": 1593413253000, - "y": 0, + "x": 1599718560000, + "y": 1, }, Object { - "x": 1593413254000, - "y": 0, + "x": 1599718590000, + "y": 3, }, Object { - "x": 1593413255000, - "y": 0, + "x": 1599718620000, + "y": 3, }, Object { - "x": 1593413256000, - "y": 0, + "x": 1599718650000, + "y": 1, }, Object { - "x": 1593413257000, - "y": 0, + "x": 1599718680000, + "y": 3, }, Object { - "x": 1593413258000, - "y": 0, + "x": 1599718710000, + "y": 2, }, Object { - "x": 1593413259000, - "y": 0, + "x": 1599718740000, + "y": 1, }, Object { - "x": 1593413260000, - "y": 0, + "x": 1599718770000, + "y": 2, }, Object { - "x": 1593413261000, - "y": 0, + "x": 1599718800000, + "y": 2, }, Object { - "x": 1593413262000, - "y": 0, + "x": 1599718830000, + "y": 4, }, Object { - "x": 1593413263000, - "y": 0, + "x": 1599718860000, + "y": 2, }, Object { - "x": 1593413264000, - "y": 0, + "x": 1599718890000, + "y": 2, }, Object { - "x": 1593413265000, - "y": 0, + "x": 1599718920000, + "y": 1, }, Object { - "x": 1593413266000, - "y": 0, + "x": 1599718950000, + "y": 2, }, Object { - "x": 1593413267000, - "y": 0, + "x": 1599718980000, + "y": 3, }, Object { - "x": 1593413268000, - "y": 0, + "x": 1599719010000, + "y": 3, }, Object { - "x": 1593413269000, - "y": 0, + "x": 1599719040000, + "y": 1, }, Object { - "x": 1593413270000, - "y": 0, + "x": 1599719070000, + "y": 3, }, Object { - "x": 1593413271000, - "y": 0, + "x": 1599719100000, + "y": 2, }, Object { - "x": 1593413272000, - "y": 0, + "x": 1599719130000, + "y": 3, }, Object { - "x": 1593413273000, - "y": 0, + "x": 1599719160000, + "y": 1, }, Object { - "x": 1593413274000, - "y": 0, + "x": 1599719190000, + "y": 1, }, Object { - "x": 1593413275000, - "y": 0, + "x": 1599719220000, + "y": 4, }, Object { - "x": 1593413276000, + "x": 1599719250000, "y": 0, }, Object { - "x": 1593413277000, - "y": 0, + "x": 1599719280000, + "y": 4, }, Object { - "x": 1593413278000, + "x": 1599719310000, "y": 0, }, Object { - "x": 1593413279000, - "y": 0, + "x": 1599719340000, + "y": 2, }, Object { - "x": 1593413280000, - "y": 0, + "x": 1599719370000, + "y": 1, }, Object { - "x": 1593413281000, - "y": 0, + "x": 1599719400000, + "y": 4, }, Object { - "x": 1593413282000, - "y": 0, + "x": 1599719430000, + "y": 1, }, Object { - "x": 1593413283000, - "y": 0, + "x": 1599719460000, + "y": 3, }, Object { - "x": 1593413284000, - "y": 0, + "x": 1599719490000, + "y": 3, }, Object { - "x": 1593413285000, - "y": 0, + "x": 1599719520000, + "y": 2, }, Object { - "x": 1593413286000, - "y": 0, + "x": 1599719550000, + "y": 1, }, Object { - "x": 1593413287000, - "y": 0, + "x": 1599719580000, + "y": 4, }, Object { - "x": 1593413288000, - "y": 0, + "x": 1599719610000, + "y": 1, }, Object { - "x": 1593413289000, - "y": 0, + "x": 1599719640000, + "y": 2, }, Object { - "x": 1593413290000, - "y": 0, + "x": 1599719670000, + "y": 3, }, Object { - "x": 1593413291000, + "x": 1599719700000, "y": 0, }, Object { - "x": 1593413292000, - "y": 0, + "x": 1599719730000, + "y": 2, }, Object { - "x": 1593413293000, - "y": 0, + "x": 1599719760000, + "y": 4, }, Object { - "x": 1593413294000, - "y": 0, + "x": 1599719790000, + "y": 1, }, Object { - "x": 1593413295000, - "y": 0, + "x": 1599719820000, + "y": 2, }, Object { - "x": 1593413296000, - "y": 0, + "x": 1599719850000, + "y": 2, }, Object { - "x": 1593413297000, - "y": 0, + "x": 1599719880000, + "y": 2, }, Object { - "x": 1593413298000, - "y": 0, + "x": 1599719910000, + "y": 3, }, Object { - "x": 1593413299000, - "y": 0, + "x": 1599719940000, + "y": 3, }, Object { - "x": 1593413300000, - "y": 0, + "x": 1599719970000, + "y": 2, }, Object { - "x": 1593413301000, - "y": 0, + "x": 1599720000000, + "y": 2, }, Object { - "x": 1593413302000, - "y": 0, + "x": 1599720030000, + "y": 2, }, Object { - "x": 1593413303000, - "y": 0, + "x": 1599720060000, + "y": 1, }, Object { - "x": 1593413304000, - "y": 0, + "x": 1599720090000, + "y": 2, }, Object { - "x": 1593413305000, - "y": 0, + "x": 1599720120000, + "y": 1, }, Object { - "x": 1593413306000, - "y": 0, + "x": 1599720150000, + "y": 3, }, Object { - "x": 1593413307000, - "y": 0, + "x": 1599720180000, + "y": 2, }, Object { - "x": 1593413308000, - "y": 0, + "x": 1599720210000, + "y": 1, }, Object { - "x": 1593413309000, - "y": 1, + "x": 1599720240000, + "y": 3, }, Object { - "x": 1593413310000, - "y": 0, + "x": 1599720270000, + "y": 3, }, Object { - "x": 1593413311000, - "y": 0, + "x": 1599720300000, + "y": 2, }, Object { - "x": 1593413312000, - "y": 0, + "x": 1599720330000, + "y": 1, }, Object { - "x": 1593413313000, - "y": 0, + "x": 1599720360000, + "y": 2, }, Object { - "x": 1593413314000, - "y": 0, + "x": 1599720390000, + "y": 5, }, Object { - "x": 1593413315000, - "y": 0, + "x": 1599720420000, + "y": 2, }, Object { - "x": 1593413316000, - "y": 0, + "x": 1599720450000, + "y": 1, }, Object { - "x": 1593413317000, - "y": 0, + "x": 1599720480000, + "y": 3, }, Object { - "x": 1593413318000, - "y": 0, + "x": 1599720510000, + "y": 2, }, Object { - "x": 1593413319000, - "y": 0, + "x": 1599720540000, + "y": 2, }, Object { - "x": 1593413320000, - "y": 0, + "x": 1599720570000, + "y": 2, }, Object { - "x": 1593413321000, - "y": 0, + "x": 1599720600000, + "y": 1, }, Object { - "x": 1593413322000, - "y": 0, + "x": 1599720630000, + "y": 3, }, Object { - "x": 1593413323000, - "y": 0, + "x": 1599720660000, + "y": 2, }, Object { - "x": 1593413324000, - "y": 0, + "x": 1599720690000, + "y": 1, }, Object { - "x": 1593413325000, - "y": 0, + "x": 1599720720000, + "y": 2, }, Object { - "x": 1593413326000, - "y": 0, + "x": 1599720750000, + "y": 2, }, Object { - "x": 1593413327000, - "y": 0, + "x": 1599720780000, + "y": 2, }, Object { - "x": 1593413328000, - "y": 0, + "x": 1599720810000, + "y": 2, }, Object { - "x": 1593413329000, - "y": 0, + "x": 1599720840000, + "y": 2, }, Object { - "x": 1593413330000, - "y": 0, + "x": 1599720870000, + "y": 3, }, Object { - "x": 1593413331000, - "y": 0, + "x": 1599720900000, + "y": 1, }, Object { - "x": 1593413332000, - "y": 0, + "x": 1599720930000, + "y": 1, }, Object { - "x": 1593413333000, - "y": 0, + "x": 1599720960000, + "y": 3, }, Object { - "x": 1593413334000, - "y": 0, + "x": 1599720990000, + "y": 3, }, Object { - "x": 1593413335000, - "y": 0, + "x": 1599721020000, + "y": 1, }, Object { - "x": 1593413336000, - "y": 0, + "x": 1599721050000, + "y": 2, }, Object { - "x": 1593413337000, - "y": 0, + "x": 1599721080000, + "y": 2, }, Object { - "x": 1593413338000, - "y": 0, + "x": 1599721110000, + "y": 3, }, Object { - "x": 1593413339000, - "y": 0, + "x": 1599721140000, + "y": 2, + }, + Object { + "x": 1599721170000, + "y": 2, }, Object { - "x": 1593413340000, + "x": 1599721200000, "y": 0, }, ], diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts index 21f3aaa04a7b3..087bf1f0655e6 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -11,8 +12,11 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const transactionName = '/products'; const uiFilters = encodeURIComponent(JSON.stringify({})); @@ -28,23 +32,34 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns the average duration by browser', async () => { const response = await supertest.get( - `/api/apm/services/client/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}` + `/api/apm/services/opbeans-rum/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}` ); expect(response.status).to.be(200); + + expect(response.body.length).to.be.greaterThan(0); + expectSnapshot(response.body).toMatch(); + + expectSnapshot(response.body.length).toMatchInline(`1`); }); + it('returns the average duration by browser filtering by transaction name', async () => { const response = await supertest.get( - `/api/apm/services/client/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionName=${transactionName}` + `/api/apm/services/opbeans-rum/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionName=${transactionName}` ); expect(response.status).to.be(200); + + expect(response.body.length).to.be.greaterThan(0); + + expectSnapshot(response.body.length).toMatchInline(`1`); + expectSnapshot(response.body).toMatch(); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts index 4e1b1e57fba0f..27e26bebd825b 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -11,8 +12,11 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const transactionType = 'request'; const transactionName = 'GET /api'; const uiFilters = encodeURIComponent(JSON.stringify({})); @@ -29,8 +33,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns the transaction breakdown for a service', async () => { const response = await supertest.get( @@ -46,45 +50,46 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); + const { timeseries } = response.body; + + const numberOfSeries = timeseries.length; + + expectSnapshot(numberOfSeries).toMatchInline(`1`); + const { title, color, type, data, hideLegend, legendValue } = timeseries[0]; - expectSnapshot(data).toMatchInline(` + const nonNullDataPoints = data.filter((y: number | null) => y !== null); + + expectSnapshot(nonNullDataPoints.length).toMatchInline(`121`); + + expectSnapshot( + data.slice(0, 5).map(({ x, y }: { x: number; y: number | null }) => { + return { + x: new Date(x ?? NaN).toISOString(), + y, + }; + }) + ).toMatchInline(` Array [ Object { - "x": 1593413100000, - "y": null, - }, - Object { - "x": 1593413130000, - "y": null, - }, - Object { - "x": 1593413160000, - "y": null, - }, - Object { - "x": 1593413190000, - "y": null, - }, - Object { - "x": 1593413220000, - "y": null, + "x": "2020-09-10T06:00:00.000Z", + "y": 1, }, Object { - "x": 1593413250000, - "y": null, + "x": "2020-09-10T06:00:30.000Z", + "y": 1, }, Object { - "x": 1593413280000, + "x": "2020-09-10T06:01:00.000Z", "y": null, }, Object { - "x": 1593413310000, + "x": "2020-09-10T06:01:30.000Z", "y": 1, }, Object { - "x": 1593413340000, + "x": "2020-09-10T06:02:00.000Z", "y": null, }, ] @@ -95,6 +100,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(type).toMatchInline(`"areaStacked"`); expectSnapshot(hideLegend).toMatchInline(`false`); expectSnapshot(legendValue).toMatchInline(`"100%"`); + + expectSnapshot(data).toMatch(); }); it('returns the transaction breakdown sorted by name', async () => { const response = await supertest.get( @@ -108,7 +115,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { "app", "http", "postgresql", - "redis", ] `); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/error_rate.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/error_rate.ts index cf23883612b7c..c7e84bd5270ee 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/error_rate.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/error_rate.ts @@ -5,6 +5,7 @@ */ import expect from '@kbn/expect'; import { first, last } from 'lodash'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -12,9 +13,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-08-26T11:00:00.000Z'); - const end = encodeURIComponent('2020-08-26T11:30:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const uiFilters = encodeURIComponent(JSON.stringify({})); describe('Error rate', () => { @@ -24,16 +28,16 @@ export default function ApiTest({ getService }: FtrProviderContext) { `/api/apm/services/opbeans-java/transaction_groups/error_rate?start=${start}&end=${end}&uiFilters=${uiFilters}` ); expect(response.status).to.be(200); - expect(response.body).to.eql({ - noHits: true, - erroneousTransactionsRate: [], - average: null, - }); + + expect(response.body.noHits).to.be(true); + + expect(response.body.erroneousTransactionsRate.length).to.be(0); + expect(response.body.average).to.be(null); }); }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); describe('returns the transaction error rate', () => { let errorRateResponse: { @@ -50,26 +54,26 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('has the correct start date', () => { expectSnapshot( new Date(first(errorRateResponse.erroneousTransactionsRate)?.x ?? NaN).toISOString() - ).toMatchInline(`"2020-08-26T11:00:00.000Z"`); + ).toMatchInline(`"2020-09-10T06:00:00.000Z"`); }); it('has the correct end date', () => { expectSnapshot( new Date(last(errorRateResponse.erroneousTransactionsRate)?.x ?? NaN).toISOString() - ).toMatchInline(`"2020-08-26T11:30:00.000Z"`); + ).toMatchInline(`"2020-09-10T07:00:00.000Z"`); }); it('has the correct number of buckets', () => { - expectSnapshot(errorRateResponse.erroneousTransactionsRate.length).toMatchInline(`61`); + expectSnapshot(errorRateResponse.erroneousTransactionsRate.length).toMatchInline(`121`); }); it('has the correct calculation for average', () => { - expectSnapshot(errorRateResponse.average).toMatchInline(`0.18894993894993897`); + expectSnapshot(errorRateResponse.average).toMatchInline(`0.16097046413502106`); }); it('has the correct error rate', () => { expectSnapshot(first(errorRateResponse.erroneousTransactionsRate)?.y).toMatchInline( - `0.5` + `0.6666666666666666` ); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/top_transaction_groups.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/top_transaction_groups.ts index cebf27ecdff2b..e944235ac41a8 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/top_transaction_groups.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/top_transaction_groups.ts @@ -5,6 +5,7 @@ */ import expect from '@kbn/expect'; import { sortBy } from 'lodash'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -20,9 +21,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const uiFilters = encodeURIComponent(JSON.stringify({})); const transactionType = 'request'; @@ -34,39 +38,37 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "bucketSize": 1000, - "isAggregationAccurate": true, - "items": Array [], - } - `); + + expect(response.body.isAggregationAccurate).to.be(true); + expect(response.body.items.length).to.be(0); }); }); describe('when data is loaded', () => { let response: any; before(async () => { - await esArchiver.load('8.0.0'); + await esArchiver.load(archiveName); response = await supertest.get( `/api/apm/services/opbeans-node/transaction_groups?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` ); }); - after(() => esArchiver.unload('8.0.0')); + after(() => esArchiver.unload(archiveName)); - it('returns the correct status code', async () => { + it('returns the correct metadata', () => { expect(response.status).to.be(200); + expect(response.body.isAggregationAccurate).to.be(true); + expect(response.body.items.length).to.be.greaterThan(0); }); - it('returns the correct number of buckets', async () => { - expectSnapshot(response.body.items.length).toMatchInline(`18`); + it('returns the correct number of buckets', () => { + expectSnapshot(response.body.items.length).toMatchInline(`13`); }); - it('returns the correct buckets (when ignoring samples)', async () => { + it('returns the correct buckets (when ignoring samples)', () => { expectSnapshot(omitSampleFromTransactionGroups(response.body.items)).toMatch(); }); - it('returns the correct buckets and samples', async () => { + it('returns the correct buckets and samples', () => { // sample should provide enough information to deeplink to a transaction detail page response.body.items.forEach((item: any) => { expect(item.sample.trace.id).to.be.an('string'); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts index a8418fe2860a3..43504a4ec401e 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; +import { PromiseReturnType } from '../../../../../plugins/apm/typings/common'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -11,9 +13,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const uiFilters = encodeURIComponent(JSON.stringify({})); describe('Transaction charts', () => { @@ -24,32 +29,44 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "apmTimeseries": Object { - "overallAvgDuration": null, - "responseTimes": Object { - "avg": Array [], - "p95": Array [], - "p99": Array [], - }, - "tpmBuckets": Array [], - }, - } - `); + + expect(response.body.apmTimeseries.overallAvgDuration).to.be(null); + expect(response.body.apmTimeseries.responseTimes.avg.length).to.be(0); + expect(response.body.apmTimeseries.responseTimes.p95.length).to.be(0); + expect(response.body.apmTimeseries.responseTimes.p99.length).to.be(0); + expect(response.body.apmTimeseries.tpmBuckets.length).to.be(0); }); }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); - it('returns the transaction charts', async () => { - const response = await supertest.get( + let response: PromiseReturnType; + + before(async () => { + response = await supertest.get( `/api/apm/services/opbeans-node/transaction_groups/charts?start=${start}&end=${end}&uiFilters=${uiFilters}` ); + }); + it('returns some data', async () => { expect(response.status).to.be(200); + + expect(response.body.apmTimeseries.overallAvgDuration).not.to.be(null); + expect(response.body.apmTimeseries.responseTimes.avg.length).to.be.greaterThan(0); + expect(response.body.apmTimeseries.responseTimes.p95.length).to.be.greaterThan(0); + expect(response.body.apmTimeseries.responseTimes.p99.length).to.be.greaterThan(0); + expect(response.body.apmTimeseries.tpmBuckets.length).to.be.greaterThan(0); + }); + + it('returns the correct data', () => { + expectSnapshot(response.body.apmTimeseries.overallAvgDuration).toMatchInline( + `578297.1431623931` + ); + expectSnapshot(response.body.apmTimeseries.responseTimes.avg.length).toMatchInline(`121`); + expectSnapshot(response.body.apmTimeseries.tpmBuckets.length).toMatchInline(`4`); + expectSnapshot(response.body).toMatch(); }); }); diff --git a/x-pack/test/apm_api_integration/common/match_snapshot.ts b/x-pack/test/apm_api_integration/common/match_snapshot.ts index a8cb0418583af..4ac812a0ee168 100644 --- a/x-pack/test/apm_api_integration/common/match_snapshot.ts +++ b/x-pack/test/apm_api_integration/common/match_snapshot.ts @@ -12,6 +12,7 @@ import prettier from 'prettier'; // @ts-expect-error import babelTraverse from '@babel/traverse'; import { Suite, Test } from 'mocha'; +import { flatten } from 'lodash'; type ISnapshotState = InstanceType; @@ -143,18 +144,24 @@ Error.prepareStackTrace = (error, structuredStackTrace) => { } }; +function recursivelyGetTestsFromSuite(suite: Suite): Test[] { + return suite.tests.concat(flatten(suite.suites.map((s) => recursivelyGetTestsFromSuite(s)))); +} + function getSnapshotState(file: string, test: Test) { const dirname = path.dirname(file); const filename = path.basename(file); - let parent = test.parent; - const testsInFile: Test[] = []; + let parent: Suite | undefined = test.parent; - while (parent) { - testsInFile.push(...parent.tests); + while (parent && parent.parent?.file === file) { parent = parent.parent; } + if (!parent) { + throw new Error('Top-level suite not found'); + } + const snapshotState = new SnapshotState( path.join(dirname + `/__snapshots__/` + filename.replace(path.extname(filename), '.snap')), { @@ -164,7 +171,7 @@ function getSnapshotState(file: string, test: Test) { } ); - return { snapshotState, testsInFile }; + return { snapshotState, testsInFile: recursivelyGetTestsFromSuite(parent) }; } export function expectSnapshot(received: any) { diff --git a/x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap b/x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap new file mode 100644 index 0000000000000..859f928c211a4 --- /dev/null +++ b/x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap @@ -0,0 +1,1393 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Service Maps with a trial license /api/apm/service-map when there is data returns the correct data 3`] = ` +Array [ + Object { + "data": Object { + "id": "opbeans-go~>postgresql", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-go~opbeans-node", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-go~opbeans-python", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-go~opbeans-ruby", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-java~>postgresql", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-node", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-python", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-ruby", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~>postgresql", + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~opbeans-go", + "isInverseEdge": true, + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-node~opbeans-python", + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>elasticsearch", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">elasticsearch", + "targetData": Object { + "id": ">elasticsearch", + "label": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.subtype": "elasticsearch", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>postgresql", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>redis", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">redis", + "targetData": Object { + "id": ">redis", + "label": "redis", + "span.destination.service.resource": "redis", + "span.subtype": "redis", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-go", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-node", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-python~opbeans-ruby", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~>postgresql", + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-node", + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-python", + "isInverseEdge": true, + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-go", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-java", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-node", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-python", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-ruby", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + }, + Object { + "data": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + Object { + "data": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + Object { + "data": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + Object { + "data": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + Object { + "data": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + Object { + "data": Object { + "id": ">elasticsearch", + "label": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.subtype": "elasticsearch", + "span.type": "db", + }, + }, + Object { + "data": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + Object { + "data": Object { + "id": ">redis", + "label": "redis", + "span.destination.service.resource": "redis", + "span.subtype": "redis", + "span.type": "db", + }, + }, + Object { + "data": Object { + "agent.name": "dotnet", + "id": "opbeans-dotnet", + "service.environment": null, + "service.name": "opbeans-dotnet", + }, + }, +] +`; + +exports[`Service Maps with a trial license when there is data with anomalies returns the correct anomaly stats 3`] = ` +Object { + "elements": Array [ + Object { + "data": Object { + "id": "opbeans-go~>postgresql", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-go~opbeans-node", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-go~opbeans-python", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-go~opbeans-ruby", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-java~>postgresql", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-node", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-python", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-ruby", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~>postgresql", + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~opbeans-go", + "isInverseEdge": true, + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-node~opbeans-python", + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>elasticsearch", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">elasticsearch", + "targetData": Object { + "id": ">elasticsearch", + "label": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.subtype": "elasticsearch", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>postgresql", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>redis", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">redis", + "targetData": Object { + "id": ">redis", + "label": "redis", + "span.destination.service.resource": "redis", + "span.subtype": "redis", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-go", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-node", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-python~opbeans-ruby", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~>postgresql", + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-node", + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-python", + "isInverseEdge": true, + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-go", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-java", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-node", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-python", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-ruby", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + }, + Object { + "data": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + Object { + "data": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + Object { + "data": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + Object { + "data": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + Object { + "data": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + Object { + "data": Object { + "id": ">elasticsearch", + "label": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.subtype": "elasticsearch", + "span.type": "db", + }, + }, + Object { + "data": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + Object { + "data": Object { + "id": ">redis", + "label": "redis", + "span.destination.service.resource": "redis", + "span.subtype": "redis", + "span.type": "db", + }, + }, + Object { + "data": Object { + "agent.name": "dotnet", + "id": "opbeans-dotnet", + "service.environment": null, + "service.name": "opbeans-dotnet", + }, + }, + ], +} +`; diff --git a/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts b/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts index f799d80f6ef13..9dc13f58268df 100644 --- a/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts +++ b/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts @@ -6,7 +6,9 @@ import querystring from 'querystring'; import expect from '@kbn/expect'; -import { isEmpty } from 'lodash'; +import { isEmpty, uniq } from 'lodash'; +import archives_metadata from '../../../common/archives_metadata'; +import { PromiseReturnType } from '../../../../../plugins/apm/typings/common'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -14,13 +16,16 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); + describe('Service Maps with a trial license', () => { describe('/api/apm/service-map', () => { describe('when there is no data', () => { it('returns empty list', async () => { - const response = await supertest.get( - '/api/apm/service-map?start=2020-06-28T10%3A24%3A46.055Z&end=2020-06-29T10%3A24%3A46.055Z' - ); + const response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); expect(response.status).to.be(200); expect(response.body.elements.length).to.be(0); @@ -28,239 +33,56 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) }); describe('when there is data', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); - it('returns service map elements', async () => { - const response = await supertest.get( - '/api/apm/service-map?start=2020-06-28T10%3A24%3A46.055Z&end=2020-06-29T10%3A24%3A46.055Z' - ); + let response: PromiseReturnType; + before(async () => { + response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); + }); + + it('returns service map elements', () => { expect(response.status).to.be(200); + expect(response.body.elements.length).to.be.greaterThan(0); + }); - expectSnapshot(response.body).toMatchInline(` - Object { - "elements": Array [ - Object { - "data": Object { - "id": "client~opbeans-node", - "source": "client", - "sourceData": Object { - "agent.name": "rum-js", - "id": "client", - "service.name": "client", - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~>opbeans-java:3000", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - "target": ">opbeans-java:3000", - "targetData": Object { - "id": ">opbeans-java:3000", - "label": "opbeans-java:3000", - "span.destination.service.resource": "opbeans-java:3000", - "span.subtype": "http", - "span.type": "external", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~>postgresql", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-java~opbeans-node", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>93.184.216.34:80", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "target": ">93.184.216.34:80", - "targetData": Object { - "id": ">93.184.216.34:80", - "label": "93.184.216.34:80", - "span.destination.service.resource": "93.184.216.34:80", - "span.subtype": "http", - "span.type": "external", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>postgresql", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>redis", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "target": ">redis", - "targetData": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~opbeans-java", - "isInverseEdge": true, - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - }, - }, - Object { - "data": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - }, - Object { - "data": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - Object { - "data": Object { - "id": ">opbeans-java:3000", - "label": "opbeans-java:3000", - "span.destination.service.resource": "opbeans-java:3000", - "span.subtype": "http", - "span.type": "external", - }, - }, - Object { - "data": Object { - "agent.name": "rum-js", - "id": "client", - "service.name": "client", - }, - }, - Object { - "data": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - Object { - "data": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - Object { - "data": Object { - "id": ">93.184.216.34:80", - "label": "93.184.216.34:80", - "span.destination.service.resource": "93.184.216.34:80", - "span.subtype": "http", - "span.type": "external", - }, - }, - ], - } + it('returns the correct data', () => { + const elements: Array<{ data: Record }> = response.body.elements; + + const serviceNames = uniq( + elements + .filter((element) => element.data['service.name'] !== undefined) + .map((element) => element.data['service.name']) + ); + + expectSnapshot(serviceNames).toMatchInline(` + Array [ + "opbeans-rum", + "opbeans-go", + "opbeans-node", + "opbeans-python", + "opbeans-ruby", + "opbeans-java", + "opbeans-dotnet", + ] + `); + + const externalDestinations = uniq( + elements + .filter((element) => element.data.target?.startsWith('>')) + .map((element) => element.data.target) + ); + + expectSnapshot(externalDestinations).toMatchInline(` + Array [ + ">postgresql", + ">elasticsearch", + ">redis", + ] `); + + expectSnapshot(elements).toMatch(); }); }); }); @@ -269,48 +91,75 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) describe('when there is no data', () => { it('returns an object with nulls', async () => { const q = querystring.stringify({ - start: '2020-06-28T10:24:46.055Z', - end: '2020-06-29T10:24:46.055Z', + start: metadata.start, + end: metadata.end, uiFilters: {}, }); const response = await supertest.get(`/api/apm/service-map/service/opbeans-node?${q}`); expect(response.status).to.be(200); - expect(response.body).to.eql({ - avgCpuUsage: null, - avgErrorRate: null, - avgMemoryUsage: null, - transactionStats: { - avgRequestsPerMinute: null, - avgTransactionDuration: null, - }, - }); + expect(response.body.avgCpuUsage).to.be(null); + expect(response.body.avgErrorRate).to.be(null); + expect(response.body.avgMemoryUsage).to.be(null); + expect(response.body.transactionStats.avgRequestsPerMinute).to.be(null); + expect(response.body.transactionStats.avgTransactionDuration).to.be(null); }); }); }); describe('when there is data with anomalies', () => { - before(() => esArchiver.load('apm_8.0.0')); - after(() => esArchiver.unload('apm_8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); - it('returns service map elements', async () => { - const start = encodeURIComponent('2020-09-10T06:00:00.000Z'); - const end = encodeURIComponent('2020-09-10T07:00:00.000Z'); + let response: PromiseReturnType; - const response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); + before(async () => { + response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); + }); + it('returns service map elements with anomaly stats', () => { expect(response.status).to.be(200); const dataWithAnomalies = response.body.elements.filter( (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats) ); + expect(dataWithAnomalies).to.not.empty(); + dataWithAnomalies.forEach(({ data }: any) => { expect( Object.values(data.serviceAnomalyStats).filter((value) => isEmpty(value)) ).to.not.empty(); }); }); + + it('returns the correct anomaly stats', () => { + const dataWithAnomalies = response.body.elements.filter( + (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats) + ); + + expectSnapshot(dataWithAnomalies.length).toMatchInline(`1`); + expectSnapshot(dataWithAnomalies.slice(0, 3)).toMatchInline(` + Array [ + Object { + "data": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + ] + `); + + expectSnapshot(response.body).toMatch(); + }); }); }); } From cdea019dfc6b95498e3f2f72ac457ec5e3c1c45f Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 15 Sep 2020 15:16:23 +0200 Subject: [PATCH 21/26] migrate pid file to core (#77037) * migrate pid file to core * use correct log level + add comment * move `unhandledRejection` to service's setup * update comment --- .../environment/environment_service.test.ts | 26 +++- .../server/environment/environment_service.ts | 13 +- src/core/server/environment/fs.ts | 1 + src/core/server/environment/index.ts | 1 + src/core/server/environment/pid_config.ts | 30 ++++ .../server/environment/write_pid_file.test.ts | 144 ++++++++++++++++++ src/core/server/environment/write_pid_file.ts | 64 ++++++++ src/core/server/server.ts | 3 +- src/legacy/server/config/schema.js | 5 +- src/legacy/server/kbn_server.js | 4 - src/legacy/server/pid/index.js | 73 --------- 11 files changed, 278 insertions(+), 86 deletions(-) create mode 100644 src/core/server/environment/pid_config.ts create mode 100644 src/core/server/environment/write_pid_file.test.ts create mode 100644 src/core/server/environment/write_pid_file.ts delete mode 100644 src/legacy/server/pid/index.js diff --git a/src/core/server/environment/environment_service.test.ts b/src/core/server/environment/environment_service.test.ts index 06fd250ebe4f9..f6cffb5e26a9e 100644 --- a/src/core/server/environment/environment_service.test.ts +++ b/src/core/server/environment/environment_service.test.ts @@ -21,6 +21,7 @@ import { BehaviorSubject } from 'rxjs'; import { EnvironmentService } from './environment_service'; import { resolveInstanceUuid } from './resolve_uuid'; import { createDataFolder } from './create_data_folder'; +import { writePidFile } from './write_pid_file'; import { CoreContext } from '../core_context'; import { configServiceMock } from '../config/config_service.mock'; @@ -35,12 +36,20 @@ jest.mock('./create_data_folder', () => ({ createDataFolder: jest.fn(), })); +jest.mock('./write_pid_file', () => ({ + writePidFile: jest.fn(), +})); + const pathConfig = { data: 'data-folder', }; const serverConfig = { uuid: 'SOME_UUID', }; +const pidConfig = { + file: '/pid/file', + exclusive: 'false', +}; const getConfigService = () => { const configService = configServiceMock.create(); @@ -51,6 +60,9 @@ const getConfigService = () => { if (path === 'server') { return new BehaviorSubject(serverConfig); } + if (path === 'pid') { + return new BehaviorSubject(pidConfig); + } return new BehaviorSubject({}); }); return configService; @@ -76,7 +88,7 @@ describe('UuidService', () => { expect(resolveInstanceUuid).toHaveBeenCalledWith({ pathConfig, serverConfig, - logger: logger.get('uuid'), + logger: logger.get('environment'), }); }); @@ -86,7 +98,17 @@ describe('UuidService', () => { expect(createDataFolder).toHaveBeenCalledTimes(1); expect(createDataFolder).toHaveBeenCalledWith({ pathConfig, - logger: logger.get('uuid'), + logger: logger.get('environment'), + }); + }); + + it('calls writePidFile with correct parameters', async () => { + const service = new EnvironmentService(coreContext); + await service.setup(); + expect(writePidFile).toHaveBeenCalledTimes(1); + expect(writePidFile).toHaveBeenCalledWith({ + pidConfig, + logger: logger.get('environment'), }); }); diff --git a/src/core/server/environment/environment_service.ts b/src/core/server/environment/environment_service.ts index 6a0b1122c7053..caa4f34bcfaa7 100644 --- a/src/core/server/environment/environment_service.ts +++ b/src/core/server/environment/environment_service.ts @@ -23,8 +23,10 @@ import { Logger } from '../logging'; import { IConfigService } from '../config'; import { PathConfigType, config as pathConfigDef } from '../path'; import { HttpConfigType, config as httpConfigDef } from '../http'; +import { PidConfigType, config as pidConfigDef } from './pid_config'; import { resolveInstanceUuid } from './resolve_uuid'; import { createDataFolder } from './create_data_folder'; +import { writePidFile } from './write_pid_file'; /** * @internal @@ -43,17 +45,24 @@ export class EnvironmentService { private uuid: string = ''; constructor(core: CoreContext) { - this.log = core.logger.get('uuid'); + this.log = core.logger.get('environment'); this.configService = core.configService; } public async setup() { - const [pathConfig, serverConfig] = await Promise.all([ + const [pathConfig, serverConfig, pidConfig] = await Promise.all([ this.configService.atPath(pathConfigDef.path).pipe(take(1)).toPromise(), this.configService.atPath(httpConfigDef.path).pipe(take(1)).toPromise(), + this.configService.atPath(pidConfigDef.path).pipe(take(1)).toPromise(), ]); + // was present in the legacy `pid` file. + process.on('unhandledRejection', (reason) => { + this.log.warn(`Detected an unhandled Promise rejection.\n${reason}`); + }); + await createDataFolder({ pathConfig, logger: this.log }); + await writePidFile({ pidConfig, logger: this.log }); this.uuid = await resolveInstanceUuid({ pathConfig, diff --git a/src/core/server/environment/fs.ts b/src/core/server/environment/fs.ts index dc040ccb73615..b79c70dbee280 100644 --- a/src/core/server/environment/fs.ts +++ b/src/core/server/environment/fs.ts @@ -23,3 +23,4 @@ import { promisify } from 'util'; export const readFile = promisify(Fs.readFile); export const writeFile = promisify(Fs.writeFile); export const mkdir = promisify(Fs.mkdir); +export const exists = promisify(Fs.exists); diff --git a/src/core/server/environment/index.ts b/src/core/server/environment/index.ts index 57a26d5ea3c79..92b57c6af2fff 100644 --- a/src/core/server/environment/index.ts +++ b/src/core/server/environment/index.ts @@ -18,3 +18,4 @@ */ export { EnvironmentService, InternalEnvironmentServiceSetup } from './environment_service'; +export { config, PidConfigType } from './pid_config'; diff --git a/src/core/server/environment/pid_config.ts b/src/core/server/environment/pid_config.ts new file mode 100644 index 0000000000000..ee9963016717e --- /dev/null +++ b/src/core/server/environment/pid_config.ts @@ -0,0 +1,30 @@ +/* + * 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 { TypeOf, schema } from '@kbn/config-schema'; + +export const config = { + path: 'pid', + schema: schema.object({ + file: schema.maybe(schema.string()), + exclusive: schema.boolean({ defaultValue: false }), + }), +}; + +export type PidConfigType = TypeOf; diff --git a/src/core/server/environment/write_pid_file.test.ts b/src/core/server/environment/write_pid_file.test.ts new file mode 100644 index 0000000000000..f9eb78a486970 --- /dev/null +++ b/src/core/server/environment/write_pid_file.test.ts @@ -0,0 +1,144 @@ +/* + * 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 { writeFile, exists } from './fs'; +import { writePidFile } from './write_pid_file'; +import { loggingSystemMock } from '../logging/logging_system.mock'; + +jest.mock('./fs', () => ({ + writeFile: jest.fn(), + exists: jest.fn(), +})); + +const writeFileMock = writeFile as jest.MockedFunction; +const existsMock = exists as jest.MockedFunction; + +const pid = String(process.pid); + +describe('writePidFile', () => { + let logger: ReturnType; + + beforeEach(() => { + logger = loggingSystemMock.createLogger(); + jest.spyOn(process, 'once'); + + writeFileMock.mockImplementation(() => Promise.resolve()); + existsMock.mockImplementation(() => Promise.resolve(false)); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + const allLogs = () => + Object.entries(loggingSystemMock.collect(logger)).reduce((messages, [key, value]) => { + return [...messages, ...(key === 'log' ? [] : (value as any[]).map(([msg]) => [key, msg]))]; + }, [] as any[]); + + it('does nothing if `pid.file` is not set', async () => { + await writePidFile({ + pidConfig: { + file: undefined, + exclusive: false, + }, + logger, + }); + expect(writeFile).not.toHaveBeenCalled(); + expect(process.once).not.toHaveBeenCalled(); + expect(allLogs()).toMatchInlineSnapshot(`Array []`); + }); + + it('writes the pid file to `pid.file`', async () => { + existsMock.mockResolvedValue(false); + + await writePidFile({ + pidConfig: { + file: '/pid-file', + exclusive: false, + }, + logger, + }); + + expect(writeFile).toHaveBeenCalledTimes(1); + expect(writeFile).toHaveBeenCalledWith('/pid-file', pid); + + expect(process.once).toHaveBeenCalledTimes(2); + expect(process.once).toHaveBeenCalledWith('exit', expect.any(Function)); + expect(process.once).toHaveBeenCalledWith('SIGINT', expect.any(Function)); + + expect(allLogs()).toMatchInlineSnapshot(` + Array [ + Array [ + "debug", + "wrote pid file to /pid-file", + ], + ] + `); + }); + + it('throws an error if the file exists and `pid.exclusive is true`', async () => { + existsMock.mockResolvedValue(true); + + await expect( + writePidFile({ + pidConfig: { + file: '/pid-file', + exclusive: true, + }, + logger, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"pid file already exists at /pid-file"`); + + expect(writeFile).not.toHaveBeenCalled(); + expect(process.once).not.toHaveBeenCalled(); + expect(allLogs()).toMatchInlineSnapshot(`Array []`); + }); + + it('logs a warning if the file exists and `pid.exclusive` is false', async () => { + existsMock.mockResolvedValue(true); + + await writePidFile({ + pidConfig: { + file: '/pid-file', + exclusive: false, + }, + logger, + }); + + expect(writeFile).toHaveBeenCalledTimes(1); + expect(writeFile).toHaveBeenCalledWith('/pid-file', pid); + + expect(process.once).toHaveBeenCalledTimes(2); + expect(process.once).toHaveBeenCalledWith('exit', expect.any(Function)); + expect(process.once).toHaveBeenCalledWith('SIGINT', expect.any(Function)); + + expect(allLogs()).toMatchInlineSnapshot(` + Array [ + Array [ + "debug", + "wrote pid file to /pid-file", + ], + Array [ + "warn", + "pid file already exists at /pid-file", + ], + ] + `); + }); +}); diff --git a/src/core/server/environment/write_pid_file.ts b/src/core/server/environment/write_pid_file.ts new file mode 100644 index 0000000000000..6ee20af02d7b0 --- /dev/null +++ b/src/core/server/environment/write_pid_file.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 { unlinkSync as unlink } from 'fs'; +import once from 'lodash/once'; +import { Logger } from '../logging'; +import { writeFile, exists } from './fs'; +import { PidConfigType } from './pid_config'; + +export const writePidFile = async ({ + pidConfig, + logger, +}: { + pidConfig: PidConfigType; + logger: Logger; +}) => { + const path = pidConfig.file; + if (!path) { + return; + } + + const pid = String(process.pid); + + if (await exists(path)) { + const message = `pid file already exists at ${path}`; + if (pidConfig.exclusive) { + throw new Error(message); + } else { + logger.warn(message, { path, pid }); + } + } + + await writeFile(path, pid); + + logger.debug(`wrote pid file to ${path}`, { path, pid }); + + const clean = once(() => { + unlink(path); + }); + + process.once('exit', clean); // for "natural" exits + process.once('SIGINT', () => { + // for Ctrl-C exits + clean(); + // resend SIGINT + process.kill(process.pid, 'SIGINT'); + }); +}; diff --git a/src/core/server/server.ts b/src/core/server/server.ts index a02b0f51b559f..609a7fc83baf9 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -31,7 +31,7 @@ import { PluginsService, config as pluginsConfig } from './plugins'; import { SavedObjectsService } from '../server/saved_objects'; import { MetricsService, opsConfig } from './metrics'; import { CapabilitiesService } from './capabilities'; -import { EnvironmentService } from './environment'; +import { EnvironmentService, config as pidConfig } from './environment'; import { StatusService } from './status/status_service'; import { config as cspConfig } from './csp'; @@ -310,6 +310,7 @@ export class Server { uiSettingsConfig, opsConfig, statusConfig, + pidConfig, ]; this.configService.addDeprecationProvider(rootConfigPath, coreDeprecationProvider); diff --git a/src/legacy/server/config/schema.js b/src/legacy/server/config/schema.js index ce7a500a00dc8..f8736fb30f90e 100644 --- a/src/legacy/server/config/schema.js +++ b/src/legacy/server/config/schema.js @@ -42,10 +42,7 @@ export default () => basePathProxyTarget: Joi.number().default(5603), }).default(), - pid: Joi.object({ - file: Joi.string(), - exclusive: Joi.boolean().default(false), - }).default(), + pid: HANDLED_IN_NEW_PLATFORM, csp: HANDLED_IN_NEW_PLATFORM, diff --git a/src/legacy/server/kbn_server.js b/src/legacy/server/kbn_server.js index a5eefd140c8fa..24d00abb99a05 100644 --- a/src/legacy/server/kbn_server.js +++ b/src/legacy/server/kbn_server.js @@ -29,7 +29,6 @@ import { coreMixin } from './core'; import { loggingMixin } from './logging'; import warningsMixin from './warnings'; import { statusMixin } from './status'; -import pidMixin from './pid'; import configCompleteMixin from './config/complete'; import { optimizeMixin } from '../../optimize'; import * as Plugins from './plugins'; @@ -93,9 +92,6 @@ export default class KbnServer { warningsMixin, statusMixin, - // writes pid file - pidMixin, - // scan translations dirs, register locale files and initialize i18n engine. i18nMixin, diff --git a/src/legacy/server/pid/index.js b/src/legacy/server/pid/index.js deleted file mode 100644 index d7b9da1292252..0000000000000 --- a/src/legacy/server/pid/index.js +++ /dev/null @@ -1,73 +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 _ from 'lodash'; -import Boom from 'boom'; -import Bluebird from 'bluebird'; -import { unlinkSync as unlink } from 'fs'; -const writeFile = Bluebird.promisify(require('fs').writeFile); - -export default Bluebird.method(function (kbnServer, server, config) { - const path = config.get('pid.file'); - if (!path) return; - - const pid = String(process.pid); - - return writeFile(path, pid, { flag: 'wx' }) - .catch(function (err) { - if (err.code !== 'EEXIST') throw err; - - const message = `pid file already exists at ${path}`; - const metadata = { - path: path, - pid: pid, - }; - - if (config.get('pid.exclusive')) { - throw Boom.internal(message, { message, ...metadata }); - } else { - server.log(['pid', 'warning'], message, metadata); - } - - return writeFile(path, pid); - }) - .then(function () { - server.logWithMetadata(['pid', 'debug'], `wrote pid file to ${path}`, { - path: path, - pid: pid, - }); - - const clean = _.once(function () { - unlink(path); - }); - - process.once('exit', clean); // for "natural" exits - process.once('SIGINT', function () { - // for Ctrl-C exits - clean(); - - // resend SIGINT - process.kill(process.pid, 'SIGINT'); - }); - - process.on('unhandledRejection', function (reason) { - server.log(['warning'], `Detected an unhandled Promise rejection.\n${reason}`); - }); - }); -}); From 043ef5e1d7f1492609c975264e89fe4bb59fb02b Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 15 Sep 2020 15:21:05 +0200 Subject: [PATCH 22/26] Create the `@kbn/std` package (#77329) * move `src/core/utils` to the @kbn/std package * update README * update codeowners and add yarn lock file * remove export from src/core/public and src/core/server and use package import instead * update generated doc * adapt forgotten import * update `data` plugin doc --- .github/CODEOWNERS | 1 + .../kibana-plugin-core-public.assertnever.md | 24 ----------- .../kibana-plugin-core-public.deepfreeze.md | 24 ----------- .../kibana-plugin-core-public.freezable.md | 14 ------ ...a-plugin-core-public.getflattenedobject.md | 30 ------------- ...kibana-plugin-core-public.isrelativeurl.md | 24 ----------- .../core/public/kibana-plugin-core-public.md | 12 ------ .../kibana-plugin-core-public.modifyurl.md | 31 ------------- ...gin-core-public.urlmeaningfulparts.auth.md | 11 ----- ...gin-core-public.urlmeaningfulparts.hash.md | 11 ----- ...core-public.urlmeaningfulparts.hostname.md | 11 ----- ...a-plugin-core-public.urlmeaningfulparts.md | 27 ------------ ...core-public.urlmeaningfulparts.pathname.md | 11 ----- ...gin-core-public.urlmeaningfulparts.port.md | 11 ----- ...core-public.urlmeaningfulparts.protocol.md | 11 ----- ...in-core-public.urlmeaningfulparts.query.md | 11 ----- ...-core-public.urlmeaningfulparts.slashes.md | 11 ----- .../kibana-plugin-core-server.assertnever.md | 24 ----------- .../kibana-plugin-core-server.deepfreeze.md | 24 ----------- .../kibana-plugin-core-server.freezable.md | 14 ------ ...a-plugin-core-server.getflattenedobject.md | 30 ------------- ...kibana-plugin-core-server.isrelativeurl.md | 24 ----------- .../core/server/kibana-plugin-core-server.md | 7 --- .../kibana-plugin-core-server.modifyurl.md | 31 ------------- ...gin-core-server.urlmeaningfulparts.auth.md | 11 ----- ...gin-core-server.urlmeaningfulparts.hash.md | 11 ----- ...core-server.urlmeaningfulparts.hostname.md | 11 ----- ...a-plugin-core-server.urlmeaningfulparts.md | 27 ------------ ...core-server.urlmeaningfulparts.pathname.md | 11 ----- ...gin-core-server.urlmeaningfulparts.port.md | 11 ----- ...core-server.urlmeaningfulparts.protocol.md | 11 ----- ...in-core-server.urlmeaningfulparts.query.md | 11 ----- ...-core-server.urlmeaningfulparts.slashes.md | 11 ----- ...in-plugins-data-public.querystringinput.md | 2 +- package.json | 1 + packages/kbn-std/README.md | 3 ++ packages/kbn-std/package.json | 21 +++++++++ .../src}/__snapshots__/get.test.ts.snap | 0 .../kbn-std/src}/assert_never.ts | 0 .../kbn-std/src}/deep_freeze.test.ts | 0 .../kbn-std/src}/deep_freeze.ts | 0 .../kbn-std/src}/get.test.ts | 0 .../utils => packages/kbn-std/src}/get.ts | 0 .../kbn-std/src}/get_flattened_object.test.ts | 0 .../kbn-std/src}/get_flattened_object.ts | 0 packages/kbn-std/src/index.ts | 29 +++++++++++++ .../kbn-std/src}/map_to_object.ts | 0 .../kbn-std/src}/map_utils.test.ts | 0 .../kbn-std/src}/map_utils.ts | 0 .../kbn-std/src}/merge.test.ts | 0 .../utils => packages/kbn-std/src}/merge.ts | 2 +- .../utils => packages/kbn-std/src}/pick.ts | 0 .../kbn-std/src}/promise.test.ts | 0 .../utils => packages/kbn-std/src}/promise.ts | 0 .../kbn-std/src}/unset.test.ts | 0 .../utils => packages/kbn-std/src}/unset.ts | 0 .../kbn-std/src}/url.test.ts | 0 .../utils => packages/kbn-std/src}/url.ts | 0 packages/kbn-std/tsconfig.json | 16 +++++++ packages/kbn-std/yarn.lock | 1 + .../capabilities/capabilities_service.mock.ts | 3 +- .../capabilities/capabilities_service.tsx | 2 +- src/core/public/chrome/nav_links/nav_link.ts | 2 +- src/core/public/core_system.ts | 2 +- .../public/doc_links/doc_links_service.ts | 2 +- src/core/public/http/base_path.ts | 2 +- src/core/public/index.ts | 13 +----- .../injected_metadata_service.ts | 2 +- src/core/public/plugins/plugins_service.ts | 2 +- src/core/public/public.api.md | 43 ------------------- .../config/deprecation/deprecation_factory.ts | 4 +- .../server/config/object_to_config_adapter.ts | 4 +- .../elasticsearch/elasticsearch_service.ts | 2 +- .../legacy/elasticsearch_client_config.ts | 2 +- src/core/server/http/base_path_service.ts | 4 +- src/core/server/http/http_service.ts | 2 +- src/core/server/http/router/headers.ts | 3 +- src/core/server/http/router/request.ts | 2 +- src/core/server/index.ts | 11 +---- .../legacy/config/get_unused_config_keys.ts | 2 +- .../server/logging/appenders/appenders.ts | 2 +- src/core/server/logging/layouts/layouts.ts | 2 +- src/core/server/logging/log_level.ts | 2 +- src/core/server/plugins/plugin_context.ts | 3 +- src/core/server/plugins/plugins_service.ts | 4 +- src/core/server/plugins/plugins_system.ts | 2 +- .../saved_objects_type_registry.ts | 2 +- src/core/server/server.api.md | 43 ------------------- src/core/server/server.ts | 2 +- src/core/server/status/types.ts | 2 +- .../server/ui_settings/settings/navigation.ts | 2 +- .../server/ui_settings/ui_settings_service.ts | 4 +- src/core/utils/context.ts | 4 +- src/core/utils/index.ts | 21 ++++----- src/plugins/data/public/public.api.md | 2 +- .../shard_failure_description.tsx | 2 +- src/plugins/share/server/routes/goto.ts | 2 +- .../vis_type_timelion/server/plugin.ts | 2 +- test/functional/services/common/browser.ts | 2 +- .../actions/server/lib/license_state.ts | 2 +- .../alerts/server/lib/license_state.ts | 2 +- x-pack/plugins/features/server/plugin.ts | 2 +- .../public/state_management/url_templates.ts | 2 +- .../ingest_manager/services/index.ts | 2 +- .../server/authentication/providers/base.ts | 2 +- x-pack/plugins/security/server/plugin.ts | 2 +- .../spaces/server/saved_objects/mappings.ts | 2 +- .../url_drilldown/url_drilldown_scope.ts | 2 +- .../api_consumer_plugin/server/index.ts | 2 +- 109 files changed, 138 insertions(+), 715 deletions(-) delete mode 100644 docs/development/core/public/kibana-plugin-core-public.assertnever.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.deepfreeze.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.freezable.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.modifyurl.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.assertnever.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.deepfreeze.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.freezable.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.modifyurl.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md create mode 100644 packages/kbn-std/README.md create mode 100644 packages/kbn-std/package.json rename {src/core/utils => packages/kbn-std/src}/__snapshots__/get.test.ts.snap (100%) rename {src/core/utils => packages/kbn-std/src}/assert_never.ts (100%) rename {src/core/utils => packages/kbn-std/src}/deep_freeze.test.ts (100%) rename {src/core/utils => packages/kbn-std/src}/deep_freeze.ts (100%) rename {src/core/utils => packages/kbn-std/src}/get.test.ts (100%) rename {src/core/utils => packages/kbn-std/src}/get.ts (100%) rename {src/core/utils => packages/kbn-std/src}/get_flattened_object.test.ts (100%) rename {src/core/utils => packages/kbn-std/src}/get_flattened_object.ts (100%) create mode 100644 packages/kbn-std/src/index.ts rename {src/core/utils => packages/kbn-std/src}/map_to_object.ts (100%) rename {src/core/utils => packages/kbn-std/src}/map_utils.test.ts (100%) rename {src/core/utils => packages/kbn-std/src}/map_utils.ts (100%) rename {src/core/utils => packages/kbn-std/src}/merge.test.ts (100%) rename {src/core/utils => packages/kbn-std/src}/merge.ts (98%) rename {src/core/utils => packages/kbn-std/src}/pick.ts (100%) rename {src/core/utils => packages/kbn-std/src}/promise.test.ts (100%) rename {src/core/utils => packages/kbn-std/src}/promise.ts (100%) rename {src/core/utils => packages/kbn-std/src}/unset.test.ts (100%) rename {src/core/utils => packages/kbn-std/src}/unset.ts (100%) rename {src/core/utils => packages/kbn-std/src}/url.test.ts (100%) rename {src/core/utils => packages/kbn-std/src}/url.ts (100%) create mode 100644 packages/kbn-std/tsconfig.json create mode 120000 packages/kbn-std/yarn.lock diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 03a4f9520c2ba..089e708e91f43 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -153,6 +153,7 @@ /x-pack/plugins/cloud/ @elastic/kibana-platform /x-pack/test/saved_objects_field_count/ @elastic/kibana-platform /packages/kbn-config-schema/ @elastic/kibana-platform +/packages/kbn-std/ @elastic/kibana-platform /src/legacy/server/config/ @elastic/kibana-platform /src/legacy/server/http/ @elastic/kibana-platform /src/legacy/server/logging/ @elastic/kibana-platform diff --git a/docs/development/core/public/kibana-plugin-core-public.assertnever.md b/docs/development/core/public/kibana-plugin-core-public.assertnever.md deleted file mode 100644 index 8fefd4450d49b..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.assertnever.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [assertNever](./kibana-plugin-core-public.assertnever.md) - -## assertNever() function - -Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking - -Signature: - -```typescript -export declare function assertNever(x: never): never; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| x | never | | - -Returns: - -`never` - diff --git a/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md b/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md deleted file mode 100644 index 7c879b659a852..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [deepFreeze](./kibana-plugin-core-public.deepfreeze.md) - -## deepFreeze() function - -Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively - -Signature: - -```typescript -export declare function deepFreeze(object: T): RecursiveReadonly; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| object | T | | - -Returns: - -`RecursiveReadonly` - diff --git a/docs/development/core/public/kibana-plugin-core-public.freezable.md b/docs/development/core/public/kibana-plugin-core-public.freezable.md deleted file mode 100644 index fee87dde25c28..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.freezable.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [Freezable](./kibana-plugin-core-public.freezable.md) - -## Freezable type - - -Signature: - -```typescript -export declare type Freezable = { - [k: string]: any; -} | any[]; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md b/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md deleted file mode 100644 index 3ef9b6bf703eb..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md +++ /dev/null @@ -1,30 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [getFlattenedObject](./kibana-plugin-core-public.getflattenedobject.md) - -## getFlattenedObject() function - -Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from `rootValue`. - -example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } - -Signature: - -```typescript -export declare function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| rootValue | Record<string, any> | | - -Returns: - -`{ - [key: string]: any; -}` - diff --git a/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md b/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md deleted file mode 100644 index 3c2ffa6340a97..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [isRelativeUrl](./kibana-plugin-core-public.isrelativeurl.md) - -## isRelativeUrl() function - -Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* - -Signature: - -```typescript -export declare function isRelativeUrl(candidatePath: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| candidatePath | string | | - -Returns: - -`boolean` - diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index 08b12190ef638..f2bf72a597656 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -27,16 +27,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AppNavLinkStatus](./kibana-plugin-core-public.appnavlinkstatus.md) | Status of the application's navLink. | | [AppStatus](./kibana-plugin-core-public.appstatus.md) | Accessibility status of an application. | -## Functions - -| Function | Description | -| --- | --- | -| [assertNever(x)](./kibana-plugin-core-public.assertnever.md) | Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking | -| [deepFreeze(object)](./kibana-plugin-core-public.deepfreeze.md) | Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively | -| [getFlattenedObject(rootValue)](./kibana-plugin-core-public.getflattenedobject.md) | Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from rootValue.example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } | -| [isRelativeUrl(candidatePath)](./kibana-plugin-core-public.isrelativeurl.md) | Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* | -| [modifyUrl(url, urlModifier)](./kibana-plugin-core-public.modifyurl.md) | Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url.Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hashWhy? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints | - ## Interfaces | Interface | Description | @@ -128,7 +118,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ToastOptions](./kibana-plugin-core-public.toastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) APIs. | | [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) | UiSettings parameters defined by the plugins. | | [UiSettingsState](./kibana-plugin-core-public.uisettingsstate.md) | | -| [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) | We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". | | [UserProvidedValues](./kibana-plugin-core-public.userprovidedvalues.md) | Describes the values explicitly set by user. | ## Variables @@ -156,7 +145,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) | | | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | -| [Freezable](./kibana-plugin-core-public.freezable.md) | | | [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) to represent the type of the context. | | [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-core-public.icontextcontainer.md) | | [HandlerParameters](./kibana-plugin-core-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md). | diff --git a/docs/development/core/public/kibana-plugin-core-public.modifyurl.md b/docs/development/core/public/kibana-plugin-core-public.modifyurl.md deleted file mode 100644 index b174f733a5c64..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.modifyurl.md +++ /dev/null @@ -1,31 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [modifyUrl](./kibana-plugin-core-public.modifyurl.md) - -## modifyUrl() function - -Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url. - -Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hash - -Why? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints - -Signature: - -```typescript -export declare function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | string | | -| urlModifier | (urlParts: URLMeaningfulParts) => Partial<URLMeaningfulParts> | void | | - -Returns: - -`string` - -The modified and reformatted url - diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md deleted file mode 100644 index 238dd66885896..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [auth](./kibana-plugin-core-public.urlmeaningfulparts.auth.md) - -## URLMeaningfulParts.auth property - -Signature: - -```typescript -auth?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md deleted file mode 100644 index 161e7dc7ebfae..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [hash](./kibana-plugin-core-public.urlmeaningfulparts.hash.md) - -## URLMeaningfulParts.hash property - -Signature: - -```typescript -hash?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md deleted file mode 100644 index f1884718337b5..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [hostname](./kibana-plugin-core-public.urlmeaningfulparts.hostname.md) - -## URLMeaningfulParts.hostname property - -Signature: - -```typescript -hostname?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md deleted file mode 100644 index 2816d4c7df541..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md +++ /dev/null @@ -1,27 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) - -## URLMeaningfulParts interface - -We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". - -Signature: - -```typescript -export interface URLMeaningfulParts -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [auth](./kibana-plugin-core-public.urlmeaningfulparts.auth.md) | string | null | | -| [hash](./kibana-plugin-core-public.urlmeaningfulparts.hash.md) | string | null | | -| [hostname](./kibana-plugin-core-public.urlmeaningfulparts.hostname.md) | string | null | | -| [pathname](./kibana-plugin-core-public.urlmeaningfulparts.pathname.md) | string | null | | -| [port](./kibana-plugin-core-public.urlmeaningfulparts.port.md) | string | null | | -| [protocol](./kibana-plugin-core-public.urlmeaningfulparts.protocol.md) | string | null | | -| [query](./kibana-plugin-core-public.urlmeaningfulparts.query.md) | ParsedQuery | | -| [slashes](./kibana-plugin-core-public.urlmeaningfulparts.slashes.md) | boolean | null | | - diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md deleted file mode 100644 index 5ad21f004481c..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [pathname](./kibana-plugin-core-public.urlmeaningfulparts.pathname.md) - -## URLMeaningfulParts.pathname property - -Signature: - -```typescript -pathname?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md deleted file mode 100644 index 2e70da2f17421..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [port](./kibana-plugin-core-public.urlmeaningfulparts.port.md) - -## URLMeaningfulParts.port property - -Signature: - -```typescript -port?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md deleted file mode 100644 index cedc7f0b878e3..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [protocol](./kibana-plugin-core-public.urlmeaningfulparts.protocol.md) - -## URLMeaningfulParts.protocol property - -Signature: - -```typescript -protocol?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md deleted file mode 100644 index a9541efe0882a..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [query](./kibana-plugin-core-public.urlmeaningfulparts.query.md) - -## URLMeaningfulParts.query property - -Signature: - -```typescript -query: ParsedQuery; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md deleted file mode 100644 index cb28a25f9e162..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [slashes](./kibana-plugin-core-public.urlmeaningfulparts.slashes.md) - -## URLMeaningfulParts.slashes property - -Signature: - -```typescript -slashes?: boolean | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.assertnever.md b/docs/development/core/server/kibana-plugin-core-server.assertnever.md deleted file mode 100644 index c13c88df9b9bf..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.assertnever.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [assertNever](./kibana-plugin-core-server.assertnever.md) - -## assertNever() function - -Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking - -Signature: - -```typescript -export declare function assertNever(x: never): never; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| x | never | | - -Returns: - -`never` - diff --git a/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md b/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md deleted file mode 100644 index 946050bff0585..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [deepFreeze](./kibana-plugin-core-server.deepfreeze.md) - -## deepFreeze() function - -Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively - -Signature: - -```typescript -export declare function deepFreeze(object: T): RecursiveReadonly; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| object | T | | - -Returns: - -`RecursiveReadonly` - diff --git a/docs/development/core/server/kibana-plugin-core-server.freezable.md b/docs/development/core/server/kibana-plugin-core-server.freezable.md deleted file mode 100644 index 32ba89e8370c1..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.freezable.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Freezable](./kibana-plugin-core-server.freezable.md) - -## Freezable type - - -Signature: - -```typescript -export declare type Freezable = { - [k: string]: any; -} | any[]; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md b/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md deleted file mode 100644 index 2e7850ca579f6..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md +++ /dev/null @@ -1,30 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [getFlattenedObject](./kibana-plugin-core-server.getflattenedobject.md) - -## getFlattenedObject() function - -Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from `rootValue`. - -example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } - -Signature: - -```typescript -export declare function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| rootValue | Record<string, any> | | - -Returns: - -`{ - [key: string]: any; -}` - diff --git a/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md b/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md deleted file mode 100644 index bff9eb05419be..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [isRelativeUrl](./kibana-plugin-core-server.isrelativeurl.md) - -## isRelativeUrl() function - -Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* - -Signature: - -```typescript -export declare function isRelativeUrl(candidatePath: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| candidatePath | string | | - -Returns: - -`boolean` - diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index c16600d1d0492..30b98b9f0553e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -42,13 +42,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | Function | Description | | --- | --- | -| [assertNever(x)](./kibana-plugin-core-server.assertnever.md) | Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking | -| [deepFreeze(object)](./kibana-plugin-core-server.deepfreeze.md) | Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively | | [exportSavedObjectsToStream({ types, objects, search, savedObjectsClient, exportSizeLimit, includeReferencesDeep, excludeExportDetails, namespace, })](./kibana-plugin-core-server.exportsavedobjectstostream.md) | Generates sorted saved object stream to be used for export. See the [options](./kibana-plugin-core-server.savedobjectsexportoptions.md) for more detailed information. | -| [getFlattenedObject(rootValue)](./kibana-plugin-core-server.getflattenedobject.md) | Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from rootValue.example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } | | [importSavedObjectsFromStream({ readStream, objectLimit, overwrite, createNewCopies, savedObjectsClient, typeRegistry, namespace, })](./kibana-plugin-core-server.importsavedobjectsfromstream.md) | Import saved objects from given stream. See the [options](./kibana-plugin-core-server.savedobjectsimportoptions.md) for more detailed information. | -| [isRelativeUrl(candidatePath)](./kibana-plugin-core-server.isrelativeurl.md) | Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* | -| [modifyUrl(url, urlModifier)](./kibana-plugin-core-server.modifyurl.md) | Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url.Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hashWhy? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints | | [resolveSavedObjectsImportErrors({ readStream, objectLimit, retries, savedObjectsClient, typeRegistry, namespace, createNewCopies, })](./kibana-plugin-core-server.resolvesavedobjectsimporterrors.md) | Resolve and return saved object import errors. See the [options](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) for more detailed informations. | ## Interfaces @@ -217,7 +212,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) | UiSettings parameters defined by the plugins. | | [UiSettingsServiceSetup](./kibana-plugin-core-server.uisettingsservicesetup.md) | | | [UiSettingsServiceStart](./kibana-plugin-core-server.uisettingsservicestart.md) | | -| [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) | We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". | | [UserProvidedValues](./kibana-plugin-core-server.userprovidedvalues.md) | Describes the values explicitly set by user. | ## Variables @@ -246,7 +240,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DestructiveRouteMethod](./kibana-plugin-core-server.destructiveroutemethod.md) | Set of HTTP methods changing the state of the server. | | [ElasticsearchClient](./kibana-plugin-core-server.elasticsearchclient.md) | Client used to query the elasticsearch cluster. | | [ElasticsearchClientConfig](./kibana-plugin-core-server.elasticsearchclientconfig.md) | Configuration options to be used to create a [cluster client](./kibana-plugin-core-server.iclusterclient.md) using the [createClient API](./kibana-plugin-core-server.elasticsearchservicestart.createclient.md) | -| [Freezable](./kibana-plugin-core-server.freezable.md) | | | [GetAuthHeaders](./kibana-plugin-core-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. | | [GetAuthState](./kibana-plugin-core-server.getauthstate.md) | Gets authentication state for a request. Returned by auth interceptor. | | [HandlerContextType](./kibana-plugin-core-server.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-server.handlerfunction.md) to represent the type of the context. | diff --git a/docs/development/core/server/kibana-plugin-core-server.modifyurl.md b/docs/development/core/server/kibana-plugin-core-server.modifyurl.md deleted file mode 100644 index fc0bc354a3ca3..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.modifyurl.md +++ /dev/null @@ -1,31 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [modifyUrl](./kibana-plugin-core-server.modifyurl.md) - -## modifyUrl() function - -Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url. - -Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hash - -Why? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints - -Signature: - -```typescript -export declare function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | string | | -| urlModifier | (urlParts: URLMeaningfulParts) => Partial<URLMeaningfulParts> | void | | - -Returns: - -`string` - -The modified and reformatted url - diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md deleted file mode 100644 index 0422738669a70..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [auth](./kibana-plugin-core-server.urlmeaningfulparts.auth.md) - -## URLMeaningfulParts.auth property - -Signature: - -```typescript -auth?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md deleted file mode 100644 index 13a3f4a9c95c8..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [hash](./kibana-plugin-core-server.urlmeaningfulparts.hash.md) - -## URLMeaningfulParts.hash property - -Signature: - -```typescript -hash?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md deleted file mode 100644 index 6631f6f6744c5..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [hostname](./kibana-plugin-core-server.urlmeaningfulparts.hostname.md) - -## URLMeaningfulParts.hostname property - -Signature: - -```typescript -hostname?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md deleted file mode 100644 index 257f7b4b634ab..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md +++ /dev/null @@ -1,27 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) - -## URLMeaningfulParts interface - -We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". - -Signature: - -```typescript -export interface URLMeaningfulParts -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [auth](./kibana-plugin-core-server.urlmeaningfulparts.auth.md) | string | null | | -| [hash](./kibana-plugin-core-server.urlmeaningfulparts.hash.md) | string | null | | -| [hostname](./kibana-plugin-core-server.urlmeaningfulparts.hostname.md) | string | null | | -| [pathname](./kibana-plugin-core-server.urlmeaningfulparts.pathname.md) | string | null | | -| [port](./kibana-plugin-core-server.urlmeaningfulparts.port.md) | string | null | | -| [protocol](./kibana-plugin-core-server.urlmeaningfulparts.protocol.md) | string | null | | -| [query](./kibana-plugin-core-server.urlmeaningfulparts.query.md) | ParsedQuery | | -| [slashes](./kibana-plugin-core-server.urlmeaningfulparts.slashes.md) | boolean | null | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md deleted file mode 100644 index 8fee8c8e146ca..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [pathname](./kibana-plugin-core-server.urlmeaningfulparts.pathname.md) - -## URLMeaningfulParts.pathname property - -Signature: - -```typescript -pathname?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md deleted file mode 100644 index dcf3517d92ba2..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [port](./kibana-plugin-core-server.urlmeaningfulparts.port.md) - -## URLMeaningfulParts.port property - -Signature: - -```typescript -port?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md deleted file mode 100644 index 914dcd4e8a8a5..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [protocol](./kibana-plugin-core-server.urlmeaningfulparts.protocol.md) - -## URLMeaningfulParts.protocol property - -Signature: - -```typescript -protocol?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md deleted file mode 100644 index 358adcfd3d180..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [query](./kibana-plugin-core-server.urlmeaningfulparts.query.md) - -## URLMeaningfulParts.query property - -Signature: - -```typescript -query: ParsedQuery; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md deleted file mode 100644 index d5b598167f2f2..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [slashes](./kibana-plugin-core-server.urlmeaningfulparts.slashes.md) - -## URLMeaningfulParts.slashes property - -Signature: - -```typescript -slashes?: boolean | null; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md index cf171d9ee9f37..e85747b8cc3d7 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md @@ -7,5 +7,5 @@ Signature: ```typescript -QueryStringInput: React.FC> +QueryStringInput: React.FC> ``` diff --git a/package.json b/package.json index 7468a49d56959..d4ebfefc87270 100644 --- a/package.json +++ b/package.json @@ -141,6 +141,7 @@ "@kbn/i18n": "1.0.0", "@kbn/interpreter": "1.0.0", "@kbn/pm": "1.0.0", + "@kbn/std": "1.0.0", "@kbn/telemetry-tools": "1.0.0", "@kbn/test-subj-selector": "0.2.1", "@kbn/ui-framework": "1.0.0", diff --git a/packages/kbn-std/README.md b/packages/kbn-std/README.md new file mode 100644 index 0000000000000..dfd98287ada4b --- /dev/null +++ b/packages/kbn-std/README.md @@ -0,0 +1,3 @@ +# `@kbn/std` — Kibana standard library + +This package is a set of utilities that can be used both on server-side and client-side. \ No newline at end of file diff --git a/packages/kbn-std/package.json b/packages/kbn-std/package.json new file mode 100644 index 0000000000000..4c67706b45d27 --- /dev/null +++ b/packages/kbn-std/package.json @@ -0,0 +1,21 @@ +{ + "name": "@kbn/std", + "main": "./target/index.js", + "types": "./target/index.d.ts", + "version": "1.0.0", + "license": "Apache-2.0", + "private": true, + "scripts": { + "build": "tsc", + "kbn:bootstrap": "yarn build" + }, + "devDependencies": { + "typescript": "4.0.2", + "tsd": "^0.13.1" + }, + "dependencies": { + "@kbn/utility-types": "1.0.0", + "lodash": "^4.17.15", + "query-string": "5.1.1" + } +} diff --git a/src/core/utils/__snapshots__/get.test.ts.snap b/packages/kbn-std/src/__snapshots__/get.test.ts.snap similarity index 100% rename from src/core/utils/__snapshots__/get.test.ts.snap rename to packages/kbn-std/src/__snapshots__/get.test.ts.snap diff --git a/src/core/utils/assert_never.ts b/packages/kbn-std/src/assert_never.ts similarity index 100% rename from src/core/utils/assert_never.ts rename to packages/kbn-std/src/assert_never.ts diff --git a/src/core/utils/deep_freeze.test.ts b/packages/kbn-std/src/deep_freeze.test.ts similarity index 100% rename from src/core/utils/deep_freeze.test.ts rename to packages/kbn-std/src/deep_freeze.test.ts diff --git a/src/core/utils/deep_freeze.ts b/packages/kbn-std/src/deep_freeze.ts similarity index 100% rename from src/core/utils/deep_freeze.ts rename to packages/kbn-std/src/deep_freeze.ts diff --git a/src/core/utils/get.test.ts b/packages/kbn-std/src/get.test.ts similarity index 100% rename from src/core/utils/get.test.ts rename to packages/kbn-std/src/get.test.ts diff --git a/src/core/utils/get.ts b/packages/kbn-std/src/get.ts similarity index 100% rename from src/core/utils/get.ts rename to packages/kbn-std/src/get.ts diff --git a/src/core/utils/get_flattened_object.test.ts b/packages/kbn-std/src/get_flattened_object.test.ts similarity index 100% rename from src/core/utils/get_flattened_object.test.ts rename to packages/kbn-std/src/get_flattened_object.test.ts diff --git a/src/core/utils/get_flattened_object.ts b/packages/kbn-std/src/get_flattened_object.ts similarity index 100% rename from src/core/utils/get_flattened_object.ts rename to packages/kbn-std/src/get_flattened_object.ts diff --git a/packages/kbn-std/src/index.ts b/packages/kbn-std/src/index.ts new file mode 100644 index 0000000000000..7cf70a0e28e2c --- /dev/null +++ b/packages/kbn-std/src/index.ts @@ -0,0 +1,29 @@ +/* + * 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 { assertNever } from './assert_never'; +export { deepFreeze, Freezable } from './deep_freeze'; +export { get } from './get'; +export { mapToObject } from './map_to_object'; +export { merge } from './merge'; +export { pick } from './pick'; +export { withTimeout } from './promise'; +export { isRelativeUrl, modifyUrl, URLMeaningfulParts } from './url'; +export { unset } from './unset'; +export { getFlattenedObject } from './get_flattened_object'; diff --git a/src/core/utils/map_to_object.ts b/packages/kbn-std/src/map_to_object.ts similarity index 100% rename from src/core/utils/map_to_object.ts rename to packages/kbn-std/src/map_to_object.ts diff --git a/src/core/utils/map_utils.test.ts b/packages/kbn-std/src/map_utils.test.ts similarity index 100% rename from src/core/utils/map_utils.test.ts rename to packages/kbn-std/src/map_utils.test.ts diff --git a/src/core/utils/map_utils.ts b/packages/kbn-std/src/map_utils.ts similarity index 100% rename from src/core/utils/map_utils.ts rename to packages/kbn-std/src/map_utils.ts diff --git a/src/core/utils/merge.test.ts b/packages/kbn-std/src/merge.test.ts similarity index 100% rename from src/core/utils/merge.test.ts rename to packages/kbn-std/src/merge.test.ts diff --git a/src/core/utils/merge.ts b/packages/kbn-std/src/merge.ts similarity index 98% rename from src/core/utils/merge.ts rename to packages/kbn-std/src/merge.ts index 43878c27b1e19..c0de50544a34e 100644 --- a/src/core/utils/merge.ts +++ b/packages/kbn-std/src/merge.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { isPlainObject } from 'lodash'; +import isPlainObject from 'lodash/isPlainObject'; /** * Deeply merges two objects, omitting undefined values, and not deeply merging Arrays. * diff --git a/src/core/utils/pick.ts b/packages/kbn-std/src/pick.ts similarity index 100% rename from src/core/utils/pick.ts rename to packages/kbn-std/src/pick.ts diff --git a/src/core/utils/promise.test.ts b/packages/kbn-std/src/promise.test.ts similarity index 100% rename from src/core/utils/promise.test.ts rename to packages/kbn-std/src/promise.test.ts diff --git a/src/core/utils/promise.ts b/packages/kbn-std/src/promise.ts similarity index 100% rename from src/core/utils/promise.ts rename to packages/kbn-std/src/promise.ts diff --git a/src/core/utils/unset.test.ts b/packages/kbn-std/src/unset.test.ts similarity index 100% rename from src/core/utils/unset.test.ts rename to packages/kbn-std/src/unset.test.ts diff --git a/src/core/utils/unset.ts b/packages/kbn-std/src/unset.ts similarity index 100% rename from src/core/utils/unset.ts rename to packages/kbn-std/src/unset.ts diff --git a/src/core/utils/url.test.ts b/packages/kbn-std/src/url.test.ts similarity index 100% rename from src/core/utils/url.test.ts rename to packages/kbn-std/src/url.test.ts diff --git a/src/core/utils/url.ts b/packages/kbn-std/src/url.ts similarity index 100% rename from src/core/utils/url.ts rename to packages/kbn-std/src/url.ts diff --git a/packages/kbn-std/tsconfig.json b/packages/kbn-std/tsconfig.json new file mode 100644 index 0000000000000..5c86ad17a90e9 --- /dev/null +++ b/packages/kbn-std/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "declaration": true, + "declarationDir": "./target", + "outDir": "./target", + "stripInternal": true, + "declarationMap": true, + "types": ["jest", "node"] + }, + "include": [ + "./src/**/*.ts", + "../../typings/query_string.d.ts" + ], + "exclude": ["target"] +} diff --git a/packages/kbn-std/yarn.lock b/packages/kbn-std/yarn.lock new file mode 120000 index 0000000000000..3f82ebc9cdbae --- /dev/null +++ b/packages/kbn-std/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/src/core/public/application/capabilities/capabilities_service.mock.ts b/src/core/public/application/capabilities/capabilities_service.mock.ts index d7b0c27879aad..ee37854762666 100644 --- a/src/core/public/application/capabilities/capabilities_service.mock.ts +++ b/src/core/public/application/capabilities/capabilities_service.mock.ts @@ -16,9 +16,10 @@ * specific language governing permissions and limitations * under the License. */ + +import { deepFreeze } from '@kbn/std'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { CapabilitiesService, CapabilitiesStart } from './capabilities_service'; -import { deepFreeze } from '../../../utils'; const createStartContractMock = (): jest.Mocked => ({ capabilities: deepFreeze({ diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx index 7304a8e5a66bc..1164164aec4c5 100644 --- a/src/core/public/application/capabilities/capabilities_service.tsx +++ b/src/core/public/application/capabilities/capabilities_service.tsx @@ -17,9 +17,9 @@ * under the License. */ import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; import { Capabilities } from '../../../types/capabilities'; -import { deepFreeze } from '../../../utils'; import { HttpStart } from '../../http'; interface StartDeps { diff --git a/src/core/public/chrome/nav_links/nav_link.ts b/src/core/public/chrome/nav_links/nav_link.ts index 4b82e0ced4505..80f0265819c40 100644 --- a/src/core/public/chrome/nav_links/nav_link.ts +++ b/src/core/public/chrome/nav_links/nav_link.ts @@ -17,7 +17,7 @@ * under the License. */ -import { pick } from '../../../utils'; +import { pick } from '@kbn/std'; import { AppCategory } from '../../'; /** diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 006d0036f7a12..a1d6f9c988b27 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -17,6 +17,7 @@ * under the License. */ +import { pick } from '@kbn/std'; import { CoreId } from '../server'; import { PackageInfo, EnvironmentMode } from '../server/types'; import { CoreSetup, CoreStart } from '.'; @@ -35,7 +36,6 @@ import { OverlayService } from './overlays'; import { PluginsService } from './plugins'; import { UiSettingsService } from './ui_settings'; import { ApplicationService } from './application'; -import { pick } from '../utils/'; import { DocLinksService } from './doc_links'; import { RenderingService } from './rendering'; import { SavedObjectsService } from './saved_objects'; diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index fae7a272c9635..47f58a3a9fcbf 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -17,8 +17,8 @@ * under the License. */ +import { deepFreeze } from '@kbn/std'; import { InjectedMetadataSetup } from '../injected_metadata'; -import { deepFreeze } from '../../utils'; interface StartDeps { injectedMetadata: InjectedMetadataSetup; diff --git a/src/core/public/http/base_path.ts b/src/core/public/http/base_path.ts index ac85d71c793fe..5d9eb51023b78 100644 --- a/src/core/public/http/base_path.ts +++ b/src/core/public/http/base_path.ts @@ -35,7 +35,7 @@ * under the License. */ -import { modifyUrl } from '../../utils'; +import { modifyUrl } from '@kbn/std'; export class BasePath { constructor( diff --git a/src/core/public/index.ts b/src/core/public/index.ts index a9774dafd2340..24d19e2d32074 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -68,7 +68,6 @@ import { UiSettingsState, IUiSettingsClient } from './ui_settings'; import { ApplicationSetup, Capabilities, ApplicationStart } from './application'; import { DocLinksStart } from './doc_links'; import { SavedObjectsStart } from './saved_objects'; -export { PackageInfo, EnvironmentMode } from '../server/types'; import { IContextContainer, IContextProvider, @@ -78,17 +77,9 @@ import { HandlerParameters, } from './context'; +export { PackageInfo, EnvironmentMode } from '../server/types'; export { CoreContext, CoreSystem } from './core_system'; -export { - DEFAULT_APP_CATEGORIES, - getFlattenedObject, - URLMeaningfulParts, - modifyUrl, - isRelativeUrl, - Freezable, - deepFreeze, - assertNever, -} from '../utils'; +export { DEFAULT_APP_CATEGORIES } from '../utils'; export { AppCategory, UiSettingsParams, diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts index 23630a5bcf228..5b51bc823d166 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.ts @@ -18,6 +18,7 @@ */ import { get } from 'lodash'; +import { deepFreeze } from '@kbn/std'; import { DiscoveredPlugin, PluginName } from '../../server'; import { EnvironmentMode, @@ -25,7 +26,6 @@ import { UiSettingsParams, UserProvidedValues, } from '../../server/types'; -import { deepFreeze } from '../../utils/'; import { AppCategory } from '../'; export interface InjectedPluginMetadata { diff --git a/src/core/public/plugins/plugins_service.ts b/src/core/public/plugins/plugins_service.ts index f9bc40ca52601..87219f4c0bdd3 100644 --- a/src/core/public/plugins/plugins_service.ts +++ b/src/core/public/plugins/plugins_service.ts @@ -17,6 +17,7 @@ * under the License. */ +import { withTimeout } from '@kbn/std'; import { PluginName, PluginOpaqueId } from '../../server'; import { CoreService } from '../../types'; import { CoreContext } from '../core_system'; @@ -28,7 +29,6 @@ import { } from './plugin_context'; import { InternalCoreSetup, InternalCoreStart } from '../core_system'; import { InjectedPluginMetadata } from '../injected_metadata'; -import { withTimeout } from '../../utils'; const Sec = 1000; /** @internal */ diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index a4f9234b539d6..d0b9e115bd524 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -21,7 +21,6 @@ import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; import { MaybePromise } from '@kbn/utility-types'; import { Observable } from 'rxjs'; -import { ParsedQuery } from 'query-string'; import { Path } from 'history'; import { PublicMethodsOf } from '@kbn/utility-types'; import { PublicUiSettingsParams as PublicUiSettingsParams_2 } from 'src/core/server/types'; @@ -185,9 +184,6 @@ export type AppUpdatableFields = Pick Partial | undefined; -// @public -export function assertNever(x: never): never; - // @public export interface Capabilities { [key: string]: Record>; @@ -444,9 +440,6 @@ export class CoreSystem { stop(): void; } -// @public -export function deepFreeze(object: T): RecursiveReadonly; - // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Readonly<{ kibana: { @@ -616,16 +609,6 @@ export interface FatalErrorsSetup { // @public export type FatalErrorsStart = FatalErrorsSetup; -// @public (undocumented) -export type Freezable = { - [k: string]: any; -} | any[]; - -// @public -export function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; - // @public export type HandlerContextType> = T extends HandlerFunction ? U : never; @@ -837,9 +820,6 @@ export interface ImageValidation { }; } -// @public -export function isRelativeUrl(candidatePath: string): boolean; - // @public export type IToasts = Pick; @@ -868,9 +848,6 @@ export interface IUiSettingsClient { set: (key: string, value: any) => Promise; } -// @public -export function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; - // @public export type MountPoint = (element: T) => UnmountCallback; @@ -1447,26 +1424,6 @@ export type UnmountCallback = () => void; // @public export const URL_MAX_LENGTH: number; -// @public -export interface URLMeaningfulParts { - // (undocumented) - auth?: string | null; - // (undocumented) - hash?: string | null; - // (undocumented) - hostname?: string | null; - // (undocumented) - pathname?: string | null; - // (undocumented) - port?: string | null; - // (undocumented) - protocol?: string | null; - // (undocumented) - query: ParsedQuery; - // (undocumented) - slashes?: boolean | null; -} - // @public export interface UserProvidedValues { // (undocumented) diff --git a/src/core/server/config/deprecation/deprecation_factory.ts b/src/core/server/config/deprecation/deprecation_factory.ts index cbc9984924c5d..0598347d2cffc 100644 --- a/src/core/server/config/deprecation/deprecation_factory.ts +++ b/src/core/server/config/deprecation/deprecation_factory.ts @@ -17,10 +17,10 @@ * under the License. */ -import { set } from '@elastic/safer-lodash-set'; import { get } from 'lodash'; +import { set } from '@elastic/safer-lodash-set'; +import { unset } from '@kbn/std'; import { ConfigDeprecation, ConfigDeprecationLogger, ConfigDeprecationFactory } from './types'; -import { unset } from '../../../utils'; const _rename = ( config: Record, diff --git a/src/core/server/config/object_to_config_adapter.ts b/src/core/server/config/object_to_config_adapter.ts index 50b31722dceeb..c4d6ac02ccf05 100644 --- a/src/core/server/config/object_to_config_adapter.ts +++ b/src/core/server/config/object_to_config_adapter.ts @@ -17,10 +17,10 @@ * under the License. */ -import { set } from '@elastic/safer-lodash-set'; import { cloneDeep, get, has } from 'lodash'; +import { set } from '@elastic/safer-lodash-set'; +import { getFlattenedObject } from '@kbn/std'; -import { getFlattenedObject } from '../../utils'; import { Config, ConfigPath } from './'; /** diff --git a/src/core/server/elasticsearch/elasticsearch_service.ts b/src/core/server/elasticsearch/elasticsearch_service.ts index 2cc065aaaaeb1..5d07840e8bda7 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.ts @@ -19,9 +19,9 @@ import { Observable, Subject } from 'rxjs'; import { first, map, shareReplay, takeUntil } from 'rxjs/operators'; +import { merge } from '@kbn/std'; import { CoreService } from '../../types'; -import { merge } from '../../utils'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { diff --git a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts index 3dbc1c2c647a9..6896c0a2e301f 100644 --- a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts +++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts @@ -22,7 +22,7 @@ import { cloneDeep } from 'lodash'; import { Duration } from 'moment'; import { checkServerIdentity } from 'tls'; import url from 'url'; -import { pick } from '../../../utils'; +import { pick } from '@kbn/std'; import { Logger } from '../../logging'; import { ElasticsearchConfig } from '../elasticsearch_config'; diff --git a/src/core/server/http/base_path_service.ts b/src/core/server/http/base_path_service.ts index 093d73b2da3bf..059eb36f42dd5 100644 --- a/src/core/server/http/base_path_service.ts +++ b/src/core/server/http/base_path_service.ts @@ -16,9 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -import { ensureRawRequest, KibanaRequest, LegacyRequest } from './router'; +import { modifyUrl } from '@kbn/std'; -import { modifyUrl } from '../../utils'; +import { ensureRawRequest, KibanaRequest, LegacyRequest } from './router'; /** * Access or manipulate the Kibana base path diff --git a/src/core/server/http/http_service.ts b/src/core/server/http/http_service.ts index c2fd653918171..82b141c8e50dd 100644 --- a/src/core/server/http/http_service.ts +++ b/src/core/server/http/http_service.ts @@ -20,9 +20,9 @@ import { Observable, Subscription, combineLatest } from 'rxjs'; import { first, map } from 'rxjs/operators'; import { Server } from 'hapi'; +import { pick } from '@kbn/std'; import { CoreService } from '../../types'; -import { pick } from '../../utils'; import { Logger, LoggerFactory } from '../logging'; import { ContextSetup } from '../context'; import { Env } from '../config'; diff --git a/src/core/server/http/router/headers.ts b/src/core/server/http/router/headers.ts index f27f5e937b2c0..498dd153a43dd 100644 --- a/src/core/server/http/router/headers.ts +++ b/src/core/server/http/router/headers.ts @@ -17,8 +17,7 @@ * under the License. */ import { IncomingHttpHeaders } from 'http'; - -import { pick } from '../../../utils'; +import { pick } from '@kbn/std'; /** * Creates a Union type of all known keys of a given interface. diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index 76f8761a7e998..e04f8585981b5 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -23,8 +23,8 @@ import { Request, RouteOptionsApp, ApplicationState } from 'hapi'; import { Observable, fromEvent, merge } from 'rxjs'; import { shareReplay, first, takeUntil } from 'rxjs/operators'; import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; -import { deepFreeze } from '../../../utils'; import { Headers } from './headers'; import { RouteMethod, RouteConfigOptions, validBodyOutput, isSafeMethod } from './route'; import { KibanaSocket, IKibanaSocket } from './socket'; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index d127471348d9f..01797d073ae2e 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -322,16 +322,7 @@ export { MetricsServiceSetup, } from './metrics'; -export { - DEFAULT_APP_CATEGORIES, - getFlattenedObject, - URLMeaningfulParts, - modifyUrl, - isRelativeUrl, - Freezable, - deepFreeze, - assertNever, -} from '../utils'; +export { DEFAULT_APP_CATEGORIES } from '../utils'; export { SavedObject, diff --git a/src/core/server/legacy/config/get_unused_config_keys.ts b/src/core/server/legacy/config/get_unused_config_keys.ts index d10c574f04974..c15c3b270df05 100644 --- a/src/core/server/legacy/config/get_unused_config_keys.ts +++ b/src/core/server/legacy/config/get_unused_config_keys.ts @@ -18,8 +18,8 @@ */ import { difference } from 'lodash'; +import { getFlattenedObject } from '@kbn/std'; import { unset } from '../../../../legacy/utils'; -import { getFlattenedObject } from '../../../utils'; import { hasConfigPathIntersection } from '../../config'; import { LegacyPluginSpec, LegacyConfig, LegacyVars } from '../types'; diff --git a/src/core/server/logging/appenders/appenders.ts b/src/core/server/logging/appenders/appenders.ts index edfce4988275a..9c19ee2bd8be5 100644 --- a/src/core/server/logging/appenders/appenders.ts +++ b/src/core/server/logging/appenders/appenders.ts @@ -18,8 +18,8 @@ */ import { schema } from '@kbn/config-schema'; +import { assertNever } from '@kbn/std'; -import { assertNever } from '../../../utils'; import { LegacyAppender, LegacyAppenderConfig, diff --git a/src/core/server/logging/layouts/layouts.ts b/src/core/server/logging/layouts/layouts.ts index 124c007bae104..03e8adbee6311 100644 --- a/src/core/server/logging/layouts/layouts.ts +++ b/src/core/server/logging/layouts/layouts.ts @@ -18,8 +18,8 @@ */ import { schema } from '@kbn/config-schema'; +import { assertNever } from '@kbn/std'; -import { assertNever } from '../../../utils'; import { LogRecord } from '../log_record'; import { JsonLayout, JsonLayoutConfigType } from './json_layout'; import { PatternLayout, PatternLayoutConfigType } from './pattern_layout'; diff --git a/src/core/server/logging/log_level.ts b/src/core/server/logging/log_level.ts index 577239ddae8e5..165e56e632d6d 100644 --- a/src/core/server/logging/log_level.ts +++ b/src/core/server/logging/log_level.ts @@ -17,7 +17,7 @@ * under the License. */ -import { assertNever } from '../../utils'; +import { assertNever } from '@kbn/std'; /** * Possible log level string values. diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index af0b0e19b3227..55e63941523ee 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -19,6 +19,8 @@ import { map, shareReplay } from 'rxjs/operators'; import { combineLatest } from 'rxjs'; +import { pick, deepFreeze } from '@kbn/std'; + import { CoreContext } from '../core_context'; import { PluginWrapper } from './plugin'; import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service'; @@ -34,7 +36,6 @@ import { ElasticsearchConfigType, config as elasticsearchConfig, } from '../elasticsearch/elasticsearch_config'; -import { pick, deepFreeze } from '../../utils'; import { CoreSetup, CoreStart } from '..'; export interface InstanceInfo { diff --git a/src/core/server/plugins/plugins_service.ts b/src/core/server/plugins/plugins_service.ts index 30cd47c9d44e1..e8fe42ee491ca 100644 --- a/src/core/server/plugins/plugins_service.ts +++ b/src/core/server/plugins/plugins_service.ts @@ -20,9 +20,10 @@ import Path from 'path'; import { Observable } from 'rxjs'; import { filter, first, map, mergeMap, tap, toArray } from 'rxjs/operators'; +import { pick } from '@kbn/std'; + import { CoreService } from '../../types'; import { CoreContext } from '../core_context'; - import { Logger } from '../logging'; import { discover, PluginDiscoveryError, PluginDiscoveryErrorType } from './discovery'; import { PluginWrapper } from './plugin'; @@ -31,7 +32,6 @@ import { PluginsConfig, PluginsConfigType } from './plugins_config'; import { PluginsSystem } from './plugins_system'; import { InternalCoreSetup, InternalCoreStart } from '../internal_types'; import { IConfigService } from '../config'; -import { pick } from '../../utils'; import { InternalEnvironmentServiceSetup } from '../environment'; /** @internal */ diff --git a/src/core/server/plugins/plugins_system.ts b/src/core/server/plugins/plugins_system.ts index b2acd9a6fd04b..72d2cfe158b37 100644 --- a/src/core/server/plugins/plugins_system.ts +++ b/src/core/server/plugins/plugins_system.ts @@ -17,13 +17,13 @@ * under the License. */ +import { withTimeout } from '@kbn/std'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { PluginWrapper } from './plugin'; import { DiscoveredPlugin, PluginName } from './types'; import { createPluginSetupContext, createPluginStartContext } from './plugin_context'; import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service'; -import { withTimeout } from '../../utils'; import { PluginDependencies } from '.'; const Sec = 1000; diff --git a/src/core/server/saved_objects/saved_objects_type_registry.ts b/src/core/server/saved_objects/saved_objects_type_registry.ts index d0035294226ea..bb840e459bf22 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.ts @@ -17,7 +17,7 @@ * under the License. */ -import { deepFreeze } from '../../utils'; +import { deepFreeze } from '@kbn/std'; import { SavedObjectsType } from './types'; /** diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index d6572ee8e7d3e..97276a1425d53 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -105,7 +105,6 @@ import { NodesInfoParams } from 'elasticsearch'; import { NodesStatsParams } from 'elasticsearch'; import { ObjectType } from '@kbn/config-schema'; import { Observable } from 'rxjs'; -import { ParsedQuery } from 'query-string'; import { PeerCertificate } from 'tls'; import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; @@ -157,9 +156,6 @@ import { Url } from 'url'; // @public (undocumented) export type AppenderConfigType = ConsoleAppenderConfig | FileAppenderConfig | LegacyAppenderConfig; -// @public -export function assertNever(x: never): never; - // @public @deprecated (undocumented) export interface AssistanceAPIResponse { // (undocumented) @@ -501,9 +497,6 @@ export interface CustomHttpResponseOptions(object: T): RecursiveReadonly; - // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Readonly<{ kibana: { @@ -713,11 +706,6 @@ export interface FakeRequest { headers: Headers; } -// @public (undocumented) -export type Freezable = { - [k: string]: any; -} | any[]; - // @public export type GetAuthHeaders = (request: KibanaRequest | LegacyRequest) => AuthHeaders | undefined; @@ -727,11 +715,6 @@ export type GetAuthState = (request: KibanaRequest | LegacyRequest) state: T; }; -// @public -export function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; - // @public (undocumented) export interface GetResponse { // (undocumented) @@ -963,9 +946,6 @@ export interface IScopedClusterClient { readonly asInternalUser: ElasticsearchClient; } -// @public -export function isRelativeUrl(candidatePath: string): boolean; - // @public export interface IUiSettingsClient { get: (key: string) => Promise; @@ -1540,9 +1520,6 @@ export type MIGRATION_ASSISTANCE_INDEX_ACTION = 'upgrade' | 'reindex'; // @public @deprecated (undocumented) export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; -// @public -export function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; - // @public export type MutatingOperationRefreshSetting = boolean | 'wait_for'; @@ -2845,26 +2822,6 @@ export interface UiSettingsServiceStart { // @public export type UiSettingsType = 'undefined' | 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string' | 'array' | 'image'; -// @public -export interface URLMeaningfulParts { - // (undocumented) - auth?: string | null; - // (undocumented) - hash?: string | null; - // (undocumented) - hostname?: string | null; - // (undocumented) - pathname?: string | null; - // (undocumented) - port?: string | null; - // (undocumented) - protocol?: string | null; - // (undocumented) - query: ParsedQuery; - // (undocumented) - slashes?: boolean | null; -} - // @public export interface UserProvidedValues { // (undocumented) diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 609a7fc83baf9..8015b184f6130 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -17,6 +17,7 @@ * under the License. */ +import { mapToObject } from '@kbn/std'; import { ConfigService, Env, RawConfigurationProvider, coreDeprecationProvider } from './config'; import { CoreApp } from './core_app'; import { AuditTrailService } from './audit_trail'; @@ -44,7 +45,6 @@ import { config as kibanaConfig } from './kibana_config'; import { savedObjectsConfig, savedObjectsMigrationConfig } from './saved_objects'; import { config as uiSettingsConfig } from './ui_settings'; import { config as statusConfig } from './status'; -import { mapToObject } from '../utils'; import { ContextService } from './context'; import { RequestHandlerContext } from '.'; import { InternalCoreSetup, InternalCoreStart, ServiceConfigDescriptor } from './internal_types'; diff --git a/src/core/server/status/types.ts b/src/core/server/status/types.ts index f884b80316fa8..9fa33a8c6d40c 100644 --- a/src/core/server/status/types.ts +++ b/src/core/server/status/types.ts @@ -18,7 +18,7 @@ */ import { Observable } from 'rxjs'; -import { deepFreeze } from '../../utils'; +import { deepFreeze } from '@kbn/std'; import { PluginName } from '../plugins'; /** diff --git a/src/core/server/ui_settings/settings/navigation.ts b/src/core/server/ui_settings/settings/navigation.ts index 6483e86a1395a..ec825a2779f38 100644 --- a/src/core/server/ui_settings/settings/navigation.ts +++ b/src/core/server/ui_settings/settings/navigation.ts @@ -19,8 +19,8 @@ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; +import { isRelativeUrl } from '@kbn/std'; import { UiSettingsParams } from '../../../types'; -import { isRelativeUrl } from '../../../utils'; export const getNavigationSettings = (): Record => { return { diff --git a/src/core/server/ui_settings/ui_settings_service.ts b/src/core/server/ui_settings/ui_settings_service.ts index 8598cf7a62287..25062490f5b6b 100644 --- a/src/core/server/ui_settings/ui_settings_service.ts +++ b/src/core/server/ui_settings/ui_settings_service.ts @@ -19,10 +19,11 @@ import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; +import { mapToObject } from '@kbn/std'; + import { CoreService } from '../../types'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; - import { SavedObjectsClientContract } from '../saved_objects/types'; import { InternalSavedObjectsServiceSetup } from '../saved_objects'; import { InternalHttpServiceSetup } from '../http'; @@ -33,7 +34,6 @@ import { InternalUiSettingsServiceStart, UiSettingsParams, } from './types'; -import { mapToObject } from '../../utils/'; import { uiSettingsType } from './saved_objects'; import { registerRoutes } from './routes'; import { getCoreSettings } from './settings'; diff --git a/src/core/utils/context.ts b/src/core/utils/context.ts index 941bbceb0cd92..f28d3330b8e36 100644 --- a/src/core/utils/context.ts +++ b/src/core/utils/context.ts @@ -19,8 +19,8 @@ import { flatten } from 'lodash'; import { ShallowPromise } from '@kbn/utility-types'; -import { pick } from '.'; -import { CoreId, PluginOpaqueId } from '../server'; +import { pick } from '@kbn/std'; +import type { CoreId, PluginOpaqueId } from '../server'; /** * Make all properties in T optional, except for the properties whose keys are in the union K diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts index a6df0992f6cc6..c620e4e5ee155 100644 --- a/src/core/utils/index.ts +++ b/src/core/utils/index.ts @@ -17,15 +17,12 @@ * under the License. */ -export * from './assert_never'; -export * from './context'; -export * from './deep_freeze'; -export * from './get'; -export * from './map_to_object'; -export * from './merge'; -export * from './pick'; -export * from './promise'; -export * from './url'; -export * from './unset'; -export * from './get_flattened_object'; -export * from './default_app_categories'; +export { + ContextContainer, + HandlerContextType, + HandlerFunction, + HandlerParameters, + IContextContainer, + IContextProvider, +} from './context'; +export { DEFAULT_APP_CATEGORIES } from './default_app_categories'; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 09da0f462a3cc..9afaaeab921f7 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1686,7 +1686,7 @@ export interface QueryStateChange extends QueryStateChangePartial { // Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const QueryStringInput: React.FC>; +export const QueryStringInput: React.FC>; // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; diff --git a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx index 3606bfbaeb1f9..1f124291669ec 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx @@ -17,9 +17,9 @@ * under the License. */ import React from 'react'; +import { getFlattenedObject } from '@kbn/std'; import { EuiCodeBlock, EuiDescriptionList, EuiSpacer } from '@elastic/eui'; import { ShardFailure } from './shard_failure_types'; -import { getFlattenedObject } from '../../../../../core/public'; import { ShardFailureDescriptionHeader } from './shard_failure_description_header'; /** diff --git a/src/plugins/share/server/routes/goto.ts b/src/plugins/share/server/routes/goto.ts index 193f2acb87c95..0cd6d26adac26 100644 --- a/src/plugins/share/server/routes/goto.ts +++ b/src/plugins/share/server/routes/goto.ts @@ -19,11 +19,11 @@ import { CoreSetup, IRouter } from 'kibana/server'; import { schema } from '@kbn/config-schema'; +import { modifyUrl } from '@kbn/std'; import { shortUrlAssertValid } from './lib/short_url_assert_valid'; import { ShortUrlLookupService } from './lib/short_url_lookup'; import { getGotoPath } from '../../common/short_url_routes'; -import { modifyUrl } from '../../../../core/server'; export const createGotoRoute = ({ router, diff --git a/src/plugins/vis_type_timelion/server/plugin.ts b/src/plugins/vis_type_timelion/server/plugin.ts index 52c50b0646299..c518b73bb3cde 100644 --- a/src/plugins/vis_type_timelion/server/plugin.ts +++ b/src/plugins/vis_type_timelion/server/plugin.ts @@ -21,10 +21,10 @@ import { i18n } from '@kbn/i18n'; import { first } from 'rxjs/operators'; import { TypeOf, schema } from '@kbn/config-schema'; import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; import { PluginStart } from '../../../../src/plugins/data/server'; import { CoreSetup, PluginInitializerContext } from '../../../../src/core/server'; -import { deepFreeze } from '../../../../src/core/server'; import { configSchema } from '../config'; import loadFunctions from './lib/load_functions'; import { functionsRoute } from './routes/functions'; diff --git a/test/functional/services/common/browser.ts b/test/functional/services/common/browser.ts index e81845023a8fa..2f8e87c1d58d6 100644 --- a/test/functional/services/common/browser.ts +++ b/test/functional/services/common/browser.ts @@ -22,9 +22,9 @@ import { Key, Origin } from 'selenium-webdriver'; // @ts-ignore internal modules are not typed import { LegacyActionSequence } from 'selenium-webdriver/lib/actions'; import { ProvidedType } from '@kbn/test/types/ftr'; +import { modifyUrl } from '@kbn/std'; import Jimp from 'jimp'; -import { modifyUrl } from '../../../../src/core/utils'; import { WebElementWrapper } from '../lib/web_element_wrapper'; import { FtrProviderContext } from '../../ftr_provider_context'; import { Browsers } from '../remote/browsers'; diff --git a/x-pack/plugins/actions/server/lib/license_state.ts b/x-pack/plugins/actions/server/lib/license_state.ts index 914aada08bb2c..1686d0201e96c 100644 --- a/x-pack/plugins/actions/server/lib/license_state.ts +++ b/x-pack/plugins/actions/server/lib/license_state.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import { Observable, Subscription } from 'rxjs'; -import { assertNever } from '../../../../../src/core/server'; +import { assertNever } from '@kbn/std'; import { ILicense } from '../../../licensing/common/types'; import { PLUGIN } from '../constants/plugin'; import { ActionType } from '../types'; diff --git a/x-pack/plugins/alerts/server/lib/license_state.ts b/x-pack/plugins/alerts/server/lib/license_state.ts index ea0106f717b02..b3204d886960f 100644 --- a/x-pack/plugins/alerts/server/lib/license_state.ts +++ b/x-pack/plugins/alerts/server/lib/license_state.ts @@ -6,9 +6,9 @@ import Boom from 'boom'; import { i18n } from '@kbn/i18n'; +import { assertNever } from '@kbn/std'; import { Observable, Subscription } from 'rxjs'; import { ILicense } from '../../../licensing/common/types'; -import { assertNever } from '../../../../../src/core/server'; import { PLUGIN } from '../constants/plugin'; export interface AlertingLicenseInformation { diff --git a/x-pack/plugins/features/server/plugin.ts b/x-pack/plugins/features/server/plugin.ts index 8a799887bba09..857bba4c606d4 100644 --- a/x-pack/plugins/features/server/plugin.ts +++ b/x-pack/plugins/features/server/plugin.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; import { CoreSetup, CoreStart, @@ -12,7 +13,6 @@ import { PluginInitializerContext, } from '../../../../src/core/server'; import { Capabilities as UICapabilities } from '../../../../src/core/server'; -import { deepFreeze } from '../../../../src/core/server'; import { PluginSetupContract as TimelionSetupContract } from '../../../../src/plugins/vis_type_timelion/server'; import { FeatureRegistry } from './feature_registry'; import { uiCapabilitiesForFeatures } from './ui_capabilities_for_features'; diff --git a/x-pack/plugins/graph/public/state_management/url_templates.ts b/x-pack/plugins/graph/public/state_management/url_templates.ts index 19de52d444209..9149a27a4f986 100644 --- a/x-pack/plugins/graph/public/state_management/url_templates.ts +++ b/x-pack/plugins/graph/public/state_management/url_templates.ts @@ -7,6 +7,7 @@ import actionCreatorFactory from 'typescript-fsa'; import { reducerWithInitialState } from 'typescript-fsa-reducers/dist'; import { i18n } from '@kbn/i18n'; +import { modifyUrl } from '@kbn/std'; import rison from 'rison-node'; import { takeEvery, select } from 'redux-saga/effects'; import { format, parse } from 'url'; @@ -17,7 +18,6 @@ import { setDatasource, IndexpatternDatasource, requestDatasource } from './data import { outlinkEncoders } from '../helpers/outlink_encoders'; import { urlTemplatePlaceholder } from '../helpers/url_template'; import { matchesOne } from './helpers'; -import { modifyUrl } from '../../../../../src/core/public'; const actionCreator = actionCreatorFactory('x-pack/graph/urlTemplates'); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts index 56179b02c5ba2..2c9e8b84d4069 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export { getFlattenedObject } from '../../../../../../../src/core/public'; +export { getFlattenedObject } from '@kbn/std'; export { AgentStatusKueryHelper, diff --git a/x-pack/plugins/security/server/authentication/providers/base.ts b/x-pack/plugins/security/server/authentication/providers/base.ts index 631721b032752..7b2ad510db968 100644 --- a/x-pack/plugins/security/server/authentication/providers/base.ts +++ b/x-pack/plugins/security/server/authentication/providers/base.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { deepFreeze } from '@kbn/std'; import { KibanaRequest, Logger, @@ -11,7 +12,6 @@ import { ILegacyClusterClient, Headers, } from '../../../../../../src/core/server'; -import { deepFreeze } from '../../../../../../src/core/server'; import { AuthenticatedUser } from '../../../common/model'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts index dc9139473004b..69b55fcb3d0a4 100644 --- a/x-pack/plugins/security/server/plugin.ts +++ b/x-pack/plugins/security/server/plugin.ts @@ -7,9 +7,9 @@ import { combineLatest } from 'rxjs'; import { first, map } from 'rxjs/operators'; import { TypeOf } from '@kbn/config-schema'; +import { deepFreeze } from '@kbn/std'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { - deepFreeze, CoreSetup, CoreStart, Logger, diff --git a/x-pack/plugins/spaces/server/saved_objects/mappings.ts b/x-pack/plugins/spaces/server/saved_objects/mappings.ts index 3afa7c389927c..875a164e25217 100644 --- a/x-pack/plugins/spaces/server/saved_objects/mappings.ts +++ b/x-pack/plugins/spaces/server/saved_objects/mappings.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { deepFreeze } from '../../../../../src/core/server'; +import { deepFreeze } from '@kbn/std'; export const SpacesSavedObjectMappings = deepFreeze({ properties: { diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/url_drilldown_scope.ts b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/url_drilldown_scope.ts index d499812a9d5ae..2c9237fac593f 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/url_drilldown_scope.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/url_drilldown_scope.ts @@ -5,8 +5,8 @@ */ import partition from 'lodash/partition'; +import { getFlattenedObject } from '@kbn/std'; import { UrlDrilldownGlobalScope, UrlDrilldownScope } from './types'; -import { getFlattenedObject } from '../../../../../../src/core/public'; export function buildScope< ContextScope extends object = object, diff --git a/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts b/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts index 87bed7f416019..33ceee68a6013 100644 --- a/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts +++ b/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { deepFreeze } from '@kbn/std'; import { - deepFreeze, CoreSetup, PluginInitializer, SavedObjectsNamespaceType, From 0574efaa8d75d31bb29b4241c55e17128367702f Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 15 Sep 2020 06:25:27 -0700 Subject: [PATCH 23/26] Increase memory for type check to 5GB (#77432) We're quickly approaching the current 4GB limit, this gives us another gigabyte. Signed-off-by: Tyler Smalley --- src/dev/typescript/run_type_check_cli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dev/typescript/run_type_check_cli.ts b/src/dev/typescript/run_type_check_cli.ts index e1fca23274a5a..00968b7259a30 100644 --- a/src/dev/typescript/run_type_check_cli.ts +++ b/src/dev/typescript/run_type_check_cli.ts @@ -98,7 +98,7 @@ export async function runTypeCheckCli() { } execInProjects(log, projects, process.execPath, (project) => [ - '--max-old-space-size=4096', + '--max-old-space-size=5120', require.resolve('typescript/bin/tsc'), ...['--project', project.tsConfigPath], ...tscArgs, From 1ab229aea8a9fc56cd9725ef2993eb7b2a2e8b9e Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Tue, 15 Sep 2020 15:43:56 +0200 Subject: [PATCH 24/26] [x-pack/test] convert PO to typescript, improve find/testSubject usage (#77389) --- .../page_objects/vega_chart_page.ts | 9 +- ...tting_page.js => account_settings_page.ts} | 8 +- .../page_objects/{gis_page.js => gis_page.ts} | 85 ++++++++++--------- .../functional/page_objects/graph_page.ts | 2 +- ...debugger_page.js => grok_debugger_page.ts} | 4 +- x-pack/test/functional/page_objects/index.ts | 16 +--- .../test/functional/page_objects/lens_page.ts | 9 +- ...{monitoring_page.js => monitoring_page.ts} | 18 ++-- .../functional/page_objects/reporting_page.ts | 5 +- .../{rollup_page.js => rollup_page.ts} | 41 ++++----- .../functional/page_objects/security_page.ts | 2 +- .../page_objects/space_selector_page.ts | 2 +- .../{status_page.js => status_page.ts} | 9 +- ...assistant.js => upgrade_assistant_page.ts} | 21 +++-- .../functional/page_objects/uptime_page.ts | 2 +- .../{watcher_page.js => watcher_page.ts} | 11 +-- ...gest_manager_create_package_policy_page.ts | 6 +- .../page_objects/policy_page.ts | 5 +- 18 files changed, 121 insertions(+), 134 deletions(-) rename x-pack/test/functional/page_objects/{accountsetting_page.js => account_settings_page.ts} (80%) rename x-pack/test/functional/page_objects/{gis_page.js => gis_page.ts} (90%) rename x-pack/test/functional/page_objects/{grok_debugger_page.js => grok_debugger_page.ts} (86%) rename x-pack/test/functional/page_objects/{monitoring_page.js => monitoring_page.ts} (84%) rename x-pack/test/functional/page_objects/{rollup_page.js => rollup_page.ts} (85%) rename x-pack/test/functional/page_objects/{status_page.js => status_page.ts} (81%) rename x-pack/test/functional/page_objects/{upgrade_assistant.js => upgrade_assistant_page.ts} (76%) rename x-pack/test/functional/page_objects/{watcher_page.js => watcher_page.ts} (89%) diff --git a/test/functional/page_objects/vega_chart_page.ts b/test/functional/page_objects/vega_chart_page.ts index 557c6bfada01e..044b6b61790ac 100644 --- a/test/functional/page_objects/vega_chart_page.ts +++ b/test/functional/page_objects/vega_chart_page.ts @@ -17,7 +17,6 @@ * under the License. */ -import { Key } from 'selenium-webdriver'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; @@ -94,9 +93,9 @@ export function VegaChartPageProvider({ const aceGutter = await this.getAceGutterContainer(); await aceGutter.doubleClick(); - await browser.pressKeys(Key.RIGHT); - await browser.pressKeys(Key.LEFT); - await browser.pressKeys(Key.LEFT); + await browser.pressKeys(browser.keys.RIGHT); + await browser.pressKeys(browser.keys.LEFT); + await browser.pressKeys(browser.keys.LEFT); await browser.pressKeys(text); } @@ -105,7 +104,7 @@ export function VegaChartPageProvider({ await retry.try(async () => { await aceGutter.doubleClick(); - await browser.pressKeys(Key.BACK_SPACE); + await browser.pressKeys(browser.keys.BACK_SPACE); expect(await this.getSpec()).to.be(''); }); diff --git a/x-pack/test/functional/page_objects/accountsetting_page.js b/x-pack/test/functional/page_objects/account_settings_page.ts similarity index 80% rename from x-pack/test/functional/page_objects/accountsetting_page.js rename to x-pack/test/functional/page_objects/account_settings_page.ts index 283199a76a033..b7351b1e1cf22 100644 --- a/x-pack/test/functional/page_objects/accountsetting_page.js +++ b/x-pack/test/functional/page_objects/account_settings_page.ts @@ -4,15 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -//import { map as mapAsync } from 'bluebird'; import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function AccountSettingProvider({ getService }) { +export function AccountSettingProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const userMenu = getService('userMenu'); class AccountSettingsPage { - async verifyAccountSettings(expectedEmail, expectedUserName) { + async verifyAccountSettings(expectedEmail: string, expectedUserName: string) { await userMenu.clickProvileLink(); const usernameField = await testSubjects.find('username'); @@ -25,7 +25,7 @@ export function AccountSettingProvider({ getService }) { await userMenu.closeMenu(); } - async changePassword(currentPassword, newPassword) { + async changePassword(currentPassword: string, newPassword: string) { await testSubjects.setValue('currentPassword', currentPassword); await testSubjects.setValue('newPassword', newPassword); await testSubjects.setValue('confirmNewPassword', newPassword); diff --git a/x-pack/test/functional/page_objects/gis_page.js b/x-pack/test/functional/page_objects/gis_page.ts similarity index 90% rename from x-pack/test/functional/page_objects/gis_page.js rename to x-pack/test/functional/page_objects/gis_page.ts index 4998635096c39..7be0aa425509e 100644 --- a/x-pack/test/functional/page_objects/gis_page.js +++ b/x-pack/test/functional/page_objects/gis_page.ts @@ -6,8 +6,9 @@ import _ from 'lodash'; import { APP_ID } from '../../../plugins/maps/common/constants'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function GisPageProvider({ getService, getPageObjects }) { +export function GisPageProvider({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'header', 'timePicker']); const log = getService('log'); @@ -19,25 +20,27 @@ export function GisPageProvider({ getService, getPageObjects }) { const comboBox = getService('comboBox'); const renderable = getService('renderable'); - function escapeLayerName(layerName) { + function escapeLayerName(layerName: string) { return layerName.split(' ').join('_'); } class GisPage { + basePath; + constructor() { this.basePath = ''; } - setBasePath(basePath) { + setBasePath(basePath: string) { this.basePath = basePath; } - async setAbsoluteRange(start, end) { + async setAbsoluteRange(start: string, end: string) { await PageObjects.timePicker.setAbsoluteRange(start, end); await this.waitForLayersToLoad(); } - async setAndSubmitQuery(query) { + async setAndSubmitQuery(query: string) { await queryBar.setQuery(query); await queryBar.submitQuery(); await this.waitForLayersToLoad(); @@ -70,7 +73,7 @@ export function GisPageProvider({ getService, getPageObjects }) { // this method waits until the map view has stabilized, signaling that the panning/zooming is complete. // Pass origView parameter when the new map view determinition is async // so method knows when panning/zooming has started. - async waitForMapPanAndZoom(origView) { + async waitForMapPanAndZoom(origView?: { lon: number; lat: number; zoom: number }) { await retry.try(async () => { log.debug('Waiting for map pan and zoom to complete'); const prevView = await this.getView(); @@ -94,7 +97,7 @@ export function GisPageProvider({ getService, getPageObjects }) { }); } - async waitForLayerDeleted(layerName) { + async waitForLayerDeleted(layerName: string) { log.debug('Wait for layer deleted'); await retry.waitFor('Layer to be deleted', async () => { const doesLayerExist = await this.doesLayerExist(layerName); @@ -104,7 +107,7 @@ export function GisPageProvider({ getService, getPageObjects }) { // use the search filter box to narrow the results down to a single // entry, or at least to a single page of results - async loadSavedMap(name) { + async loadSavedMap(name: string) { log.debug(`Load Saved Map ${name}`); await retry.try(async () => { @@ -121,7 +124,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async deleteSavedMaps(search) { + async deleteSavedMaps(search: string) { await this.searchForMapWithName(search); await testSubjects.click('checkboxSelectAll'); await testSubjects.click('deleteSelectedItems'); @@ -139,7 +142,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await renderable.waitForRender(); } - async saveMap(name, uncheckReturnToOriginModeSwitch = false) { + async saveMap(name: string, uncheckReturnToOriginModeSwitch = false) { await testSubjects.click('mapSaveButton'); await testSubjects.setValue('savedObjectTitle', name); if (uncheckReturnToOriginModeSwitch) { @@ -180,7 +183,7 @@ export function GisPageProvider({ getService, getPageObjects }) { return exists; } - async searchForMapWithName(name) { + async searchForMapWithName(name: string) { log.debug(`searchForMapWithName: ${name}`); await this.gotoMapListingPage(); @@ -196,7 +199,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); } - async selectMap(name) { + async selectMap(name: string) { await testSubjects.click(`mapListingTitleLink-${name.split(' ').join('-')}`); } @@ -221,7 +224,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async getMapCountWithName(name) { + async getMapCountWithName(name: string) { await this.gotoMapListingPage(); log.debug(`getMapCountWithName: ${name}`); @@ -260,7 +263,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async setView(lat, lon, zoom) { + async setView(lat: number, lon: number, zoom: number) { log.debug( `Set view lat: ${lat.toString()}, lon: ${lon.toString()}, zoom: ${zoom.toString()}` ); @@ -286,7 +289,7 @@ export function GisPageProvider({ getService, getPageObjects }) { }; } - async toggleLayerVisibility(layerName) { + async toggleLayerVisibility(layerName: string) { log.debug(`Toggle layer visibility, layer: ${layerName}`); await this.openLayerTocActionsPanel(layerName); await testSubjects.click('layerVisibilityToggleButton'); @@ -300,7 +303,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async clickFitToBounds(layerName) { + async clickFitToBounds(layerName: string) { log.debug(`Fit to bounds, layer: ${layerName}`); const origView = await this.getView(); await this.openLayerTocActionsPanel(layerName); @@ -308,7 +311,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForMapPanAndZoom(origView); } - async openLayerTocActionsPanel(layerName) { + async openLayerTocActionsPanel(layerName: string) { const escapedDisplayName = escapeLayerName(layerName); const isOpen = await testSubjects.exists(`layerTocActionsPanel${escapedDisplayName}`); if (!isOpen) { @@ -316,7 +319,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async openLayerPanel(layerName) { + async openLayerPanel(layerName: string) { log.debug(`Open layer panel, layer: ${layerName}`); await this.openLayerTocActionsPanel(layerName); await testSubjects.click('editLayerButton'); @@ -327,7 +330,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async getLayerTOCDetails(layerName) { + async getLayerTOCDetails(layerName: string) { return await testSubjects.getVisibleText(`mapLayerTOCDetails${escapeLayerName(layerName)}`); } @@ -352,13 +355,13 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async doesLayerExist(layerName) { + async doesLayerExist(layerName: string) { return await testSubjects.exists( `layerTocActionsPanelToggleButton${escapeLayerName(layerName)}` ); } - async hasFilePickerLoadedFile(fileName) { + async hasFilePickerLoadedFile(fileName: string) { log.debug(`Has file picker loaded file ${fileName}`); const filePickerText = await find.byCssSelector('.euiFilePicker__promptText'); const filePickerTextContent = await filePickerText.getVisibleText(); @@ -393,7 +396,7 @@ export function GisPageProvider({ getService, getPageObjects }) { }); } - async cancelLayerAdd(layerName) { + async cancelLayerAdd(layerName: string) { log.debug(`Cancel layer add`); const cancelExists = await testSubjects.exists('layerAddCancelButton'); if (cancelExists) { @@ -405,7 +408,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async closeOrCancelLayer(layerName) { + async closeOrCancelLayer(layerName: string) { log.debug(`Close or cancel layer add`); const cancelExists = await testSubjects.exists('layerAddCancelButton'); const closeExists = await testSubjects.exists('layerPanelCancelButton'); @@ -449,24 +452,24 @@ export function GisPageProvider({ getService, getPageObjects }) { await testSubjects.click('importFileButton'); } - async setIndexName(indexName) { + async setIndexName(indexName: string) { log.debug(`Set index name to: ${indexName}`); await testSubjects.setValue('fileUploadIndexNameInput', indexName); } - async setIndexType(indexType) { + async setIndexType(indexType: string) { log.debug(`Set index type to: ${indexType}`); await testSubjects.selectValue('fileImportIndexSelect', indexType); } - async indexTypeOptionExists(indexType) { + async indexTypeOptionExists(indexType: string) { log.debug(`Check index type "${indexType}" available`); return await find.existsByCssSelector( `select[data-test-subj="fileImportIndexSelect"] > option[value="${indexType}"]` ); } - async getCodeBlockParsedJson(dataTestSubjName) { + async getCodeBlockParsedJson(dataTestSubjName: string) { log.debug(`Get parsed code block for ${dataTestSubjName}`); const indexRespCodeBlock = await testSubjects.find(`${dataTestSubjName}`); const indexRespJson = await indexRespCodeBlock.getAttribute('innerText'); @@ -483,7 +486,7 @@ export function GisPageProvider({ getService, getPageObjects }) { return await this.getCodeBlockParsedJson('indexPatternRespCodeBlock'); } - async setLayerQuery(layerName, query) { + async setLayerQuery(layerName: string, query: string) { await this.openLayerPanel(layerName); await testSubjects.click('mapLayerPanelOpenFilterEditorButton'); const filterEditorContainer = await testSubjects.find('mapFilterEditor'); @@ -505,7 +508,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async setJoinWhereQuery(layerName, query) { + async setJoinWhereQuery(layerName: string, query: string) { await this.openLayerPanel(layerName); await testSubjects.click('mapJoinWhereExpressionButton'); const filterEditorContainer = await testSubjects.find('mapJoinWhereFilterEditor'); @@ -531,7 +534,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await testSubjects.click('uploadGeoJson'); } - async uploadJsonFileForIndexing(path) { + async uploadJsonFileForIndexing(path: string) { await PageObjects.common.setFileInputPath(path); log.debug(`File selected`); @@ -540,7 +543,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } // Returns first layer by default - async selectVectorLayer(vectorLayerName) { + async selectVectorLayer(vectorLayerName: string) { log.debug(`Select EMS vector layer ${vectorLayerName}`); if (!vectorLayerName) { throw new Error(`You did not provide the EMS layer to select`); @@ -549,14 +552,14 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async removeLayer(layerName) { + async removeLayer(layerName: string) { log.debug(`Remove layer ${layerName}`); await this.openLayerPanel(layerName); await testSubjects.click(`mapRemoveLayerButton`); await this.waitForLayerDeleted(layerName); } - async getLayerErrorText(layerName) { + async getLayerErrorText(layerName: string) { log.debug(`Remove layer ${layerName}`); await this.openLayerPanel(layerName); return await testSubjects.getVisibleText(`layerErrorMessage`); @@ -589,7 +592,7 @@ export function GisPageProvider({ getService, getPageObjects }) { // Method should only be used when multiple requests are expected // RequestSelector will only display inspectorRequestChooser when there is more than one request - async openInspectorRequest(requestName) { + async openInspectorRequest(requestName: string) { await inspector.open(); await inspector.openInspectorRequestsView(); log.debug(`Open Inspector request ${requestName}`); @@ -620,12 +623,12 @@ export function GisPageProvider({ getService, getPageObjects }) { return mapboxStyle; } - getInspectorStatRowHit(stats, rowName) { + getInspectorStatRowHit(stats: string[][], rowName: string) { const STATS_ROW_NAME_INDEX = 0; const STATS_ROW_VALUE_INDEX = 1; - const statsRow = stats.find((statsRow) => { - return statsRow[STATS_ROW_NAME_INDEX] === rowName; + const statsRow = stats.find((row) => { + return row[STATS_ROW_NAME_INDEX] === rowName; }); if (!statsRow) { throw new Error(`Unable to find value for row ${rowName} in ${stats}`); @@ -634,7 +637,7 @@ export function GisPageProvider({ getService, getPageObjects }) { return statsRow[STATS_ROW_VALUE_INDEX]; } - async triggerSingleRefresh(refreshInterval) { + async triggerSingleRefresh(refreshInterval: number) { log.debug(`triggerSingleRefresh, refreshInterval: ${refreshInterval}`); await PageObjects.timePicker.resumeAutoRefresh(); log.debug('waiting to give time for refresh timer to fire'); @@ -643,7 +646,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async lockTooltipAtPosition(xOffset, yOffset) { + async lockTooltipAtPosition(xOffset: number, yOffset: number) { await retry.try(async () => { const mapContainerElement = await testSubjects.find('mapContainer'); await mapContainerElement.moveMouseTo({ xOffset, yOffset }); @@ -656,12 +659,12 @@ export function GisPageProvider({ getService, getPageObjects }) { }); } - async setStyleByValue(styleName, fieldName) { + async setStyleByValue(styleName: string, fieldName: string) { await testSubjects.selectValue(`staticDynamicSelect_${styleName}`, 'DYNAMIC'); await comboBox.set(`styleFieldSelect_${styleName}`, fieldName); } - async selectCustomColorRamp(styleName) { + async selectCustomColorRamp(styleName: string) { // open super select menu await testSubjects.click(`colorMapSelect_${styleName}`); // Click option diff --git a/x-pack/test/functional/page_objects/graph_page.ts b/x-pack/test/functional/page_objects/graph_page.ts index 639add8b0e904..9ce1f87b5bf3d 100644 --- a/x-pack/test/functional/page_objects/graph_page.ts +++ b/x-pack/test/functional/page_objects/graph_page.ts @@ -23,7 +23,7 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon const find = getService('find'); const log = getService('log'); const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'header', 'settings']); + const PageObjects = getPageObjects(['common', 'header']); const retry = getService('retry'); class GraphPage { diff --git a/x-pack/test/functional/page_objects/grok_debugger_page.js b/x-pack/test/functional/page_objects/grok_debugger_page.ts similarity index 86% rename from x-pack/test/functional/page_objects/grok_debugger_page.js rename to x-pack/test/functional/page_objects/grok_debugger_page.ts index fec3e9de3c74b..d3edbe6c27e77 100644 --- a/x-pack/test/functional/page_objects/grok_debugger_page.js +++ b/x-pack/test/functional/page_objects/grok_debugger_page.ts @@ -4,7 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -export function GrokDebuggerPageProvider({ getPageObjects, getService }) { +import { FtrProviderContext } from '../ftr_provider_context'; + +export function GrokDebuggerPageProvider({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects(['common']); const grokDebugger = getService('grokDebugger'); diff --git a/x-pack/test/functional/page_objects/index.ts b/x-pack/test/functional/page_objects/index.ts index 833cc452a5d31..7569904fe90fd 100644 --- a/x-pack/test/functional/page_objects/index.ts +++ b/x-pack/test/functional/page_objects/index.ts @@ -7,30 +7,20 @@ import { pageObjects as kibanaFunctionalPageObjects } from '../../../../test/functional/page_objects'; import { CanvasPageProvider } from './canvas_page'; -// @ts-ignore not ts yet import { SecurityPageProvider } from './security_page'; -// @ts-ignore not ts yet import { MonitoringPageProvider } from './monitoring_page'; // @ts-ignore not ts yet import { LogstashPageProvider } from './logstash_page'; -// @ts-ignore not ts yet import { GraphPageProvider } from './graph_page'; -// @ts-ignore not ts yet import { GrokDebuggerPageProvider } from './grok_debugger_page'; -// @ts-ignore not ts yet import { WatcherPageProvider } from './watcher_page'; import { ReportingPageProvider } from './reporting_page'; -// @ts-ignore not ts yet -import { AccountSettingProvider } from './accountsetting_page'; +import { AccountSettingProvider } from './account_settings_page'; import { InfraHomePageProvider } from './infra_home_page'; import { InfraLogsPageProvider } from './infra_logs_page'; -// @ts-ignore not ts yet import { GisPageProvider } from './gis_page'; -// @ts-ignore not ts yet import { StatusPagePageProvider } from './status_page'; -// @ts-ignore not ts yet -import { UpgradeAssistantProvider } from './upgrade_assistant'; -// @ts-ignore not ts yet +import { UpgradeAssistantPageProvider } from './upgrade_assistant_page'; import { RollupPageProvider } from './rollup_page'; import { UptimePageProvider } from './uptime_page'; import { ApiKeysPageProvider } from './api_keys_page'; @@ -66,7 +56,7 @@ export const pageObjects = { infraLogs: InfraLogsPageProvider, maps: GisPageProvider, statusPage: StatusPagePageProvider, - upgradeAssistant: UpgradeAssistantProvider, + upgradeAssistant: UpgradeAssistantPageProvider, uptime: UptimePageProvider, rollup: RollupPageProvider, apiKeys: ApiKeysPageProvider, diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index edd7c2a43b343..e3c21085b92d3 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -13,14 +13,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont const retry = getService('retry'); const find = getService('find'); const comboBox = getService('comboBox'); - const PageObjects = getPageObjects([ - 'header', - 'common', - 'visualize', - 'dashboard', - 'header', - 'timePicker', - ]); + const PageObjects = getPageObjects(['header', 'header', 'timePicker']); return logWrapper('lensPage', log, { /** diff --git a/x-pack/test/functional/page_objects/monitoring_page.js b/x-pack/test/functional/page_objects/monitoring_page.ts similarity index 84% rename from x-pack/test/functional/page_objects/monitoring_page.js rename to x-pack/test/functional/page_objects/monitoring_page.ts index c3b9d20b3ac4a..bbfa884e71cda 100644 --- a/x-pack/test/functional/page_objects/monitoring_page.js +++ b/x-pack/test/functional/page_objects/monitoring_page.ts @@ -4,8 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -export function MonitoringPageProvider({ getPageObjects, getService }) { - const PageObjects = getPageObjects(['common', 'header', 'security', 'login', 'spaceSelector']); +import { FtrProviderContext } from '../ftr_provider_context'; + +export function MonitoringPageProvider({ getPageObjects, getService }: FtrProviderContext) { + const PageObjects = getPageObjects(['common', 'header', 'security', 'login']); const testSubjects = getService('testSubjects'); const security = getService('security'); const find = getService('find'); @@ -35,34 +37,34 @@ export function MonitoringPageProvider({ getPageObjects, getService }) { return testSubjects.getVisibleText('accessDeniedTitle'); } - async clickBreadcrumb(subj) { + async clickBreadcrumb(subj: string) { return testSubjects.click(subj); } - async assertTableNoData(subj) { + async assertTableNoData(subj: string) { if (!(await testSubjects.exists(subj))) { throw new Error('Expected to find the no data message'); } } - async tableGetRows(subj) { + async tableGetRows(subj: string) { const table = await testSubjects.find(subj); return table.findAllByTagName('tr'); } - async tableGetRowsFromContainer(subj) { + async tableGetRowsFromContainer(subj: string) { const table = await testSubjects.find(subj); const tbody = await table.findByTagName('tbody'); return tbody.findAllByTagName('tr'); } - async tableSetFilter(subj, text) { + async tableSetFilter(subj: string, text: string) { await testSubjects.setValue(subj, text); await PageObjects.common.pressEnterKey(); await PageObjects.header.waitUntilLoadingHasFinished(); } - async tableClearFilter(subj) { + async tableClearFilter(subj: string) { return await testSubjects.setValue(subj, ' \uE003'); // space and backspace to trigger onChange event } })(); diff --git a/x-pack/test/functional/page_objects/reporting_page.ts b/x-pack/test/functional/page_objects/reporting_page.ts index 7631d0cbce59a..5828871d7c685 100644 --- a/x-pack/test/functional/page_objects/reporting_page.ts +++ b/x-pack/test/functional/page_objects/reporting_page.ts @@ -5,16 +5,15 @@ */ import http, { IncomingMessage } from 'http'; -import { FtrProviderContext } from 'test/functional/ftr_provider_context'; import { parse } from 'url'; +import { FtrProviderContext } from '../ftr_provider_context'; export function ReportingPageProvider({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); const log = getService('log'); const retry = getService('retry'); const testSubjects = getService('testSubjects'); - - const PageObjects = getPageObjects(['common', 'security' as any, 'share', 'timePicker']); // FIXME: Security PageObject is not Typescript + const PageObjects = getPageObjects(['security', 'share', 'timePicker']); class ReportingPage { async forceSharedItemsContainerSize({ width }: { width: number }) { diff --git a/x-pack/test/functional/page_objects/rollup_page.js b/x-pack/test/functional/page_objects/rollup_page.ts similarity index 85% rename from x-pack/test/functional/page_objects/rollup_page.js rename to x-pack/test/functional/page_objects/rollup_page.ts index f974f60271746..fbeb6acd3ebf2 100644 --- a/x-pack/test/functional/page_objects/rollup_page.js +++ b/x-pack/test/functional/page_objects/rollup_page.ts @@ -6,8 +6,9 @@ import expect from '@kbn/expect'; import { map as mapAsync } from 'bluebird'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function RollupPageProvider({ getService, getPageObjects }) { +export function RollupPageProvider({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const log = getService('log'); const find = getService('find'); @@ -15,16 +16,16 @@ export function RollupPageProvider({ getService, getPageObjects }) { class RollupJobPage { async createNewRollUpJob( - jobName, - indexPattern, - indexName, - interval, + jobName: string, + indexPattern: string, + indexName: string, + interval: string, delay = '1d', startImmediately = false, scheduledTime = { time: 'minute', cron: true } ) { let stepNum = 1; - //Step 1 + // Step 1 await testSubjects.click('createRollupJobButton'); await this.verifyStepIsActive(stepNum); await this.addRollupNameandIndexPattern(jobName, indexPattern); @@ -34,47 +35,47 @@ export function RollupPageProvider({ getService, getPageObjects }) { await this.setRollupDelay(delay); stepNum = await this.moveToNextStep(stepNum); - //Step 2: Histogram + // Step 2: Histogram await this.verifyStepIsActive(stepNum); await this.setJobInterval(interval); stepNum = await this.moveToNextStep(stepNum); - //Step 3: Terms (optional) + // Step 3: Terms (optional) await this.verifyStepIsActive(stepNum); stepNum = await this.moveToNextStep(); - //Step 4: Histogram(optional) + // Step 4: Histogram(optional) await this.verifyStepIsActive(stepNum); stepNum = await this.moveToNextStep(); - //Step 5: Metrics(optional) + // Step 5: Metrics(optional) await this.verifyStepIsActive(stepNum); stepNum = await this.moveToNextStep(); - //Step 6: saveJob and verify the name in the list + // Step 6: saveJob and verify the name in the list await this.verifyStepIsActive(stepNum); await this.saveJob(startImmediately); } - async verifyStepIsActive(stepNumber) { + async verifyStepIsActive(stepNumber = 0) { await testSubjects.exists(`createRollupStep${stepNumber}--active`); } - async setScheduleTime(time, cron) { - if (cron) { + async setScheduleTime(time: string, isCron: boolean) { + if (isCron) { await testSubjects.click('rollupShowAdvancedCronLink'); await testSubjects.setValue('rollupAdvancedCron', time); } // TODO: Add handling for if Cron is false to go through clicking options. } - async addRollupNameandIndexPattern(name, indexPattern) { + async addRollupNameandIndexPattern(name: string, indexPattern: string) { log.debug(`Adding name ${name} to form`); await testSubjects.setValue('rollupJobName', name); await testSubjects.setValue('rollupIndexPattern', indexPattern); } - async setRollupDelay(time) { + async setRollupDelay(time: string) { log.debug(`Setting rollup delay to "${time}"`); await testSubjects.setValue('rollupDelay', time); } @@ -86,20 +87,20 @@ export function RollupPageProvider({ getService, getPageObjects }) { expect(text).to.be.equal('Success! Index pattern has matching indices.'); } - async setIndexName(name) { + async setIndexName(name: string) { await testSubjects.setValue('rollupIndexName', name); } - async moveToNextStep(stepNum) { + async moveToNextStep(stepNum = 0) { await testSubjects.click('rollupJobNextButton'); return stepNum + 1; } - async setJobInterval(time) { + async setJobInterval(time: string) { await testSubjects.setValue('rollupJobInterval', time); } - async saveJob(startImmediately) { + async saveJob(startImmediately: boolean) { if (startImmediately) { const checkbox = await find.byCssSelector('.euiCheckbox'); await checkbox.click(); diff --git a/x-pack/test/functional/page_objects/security_page.ts b/x-pack/test/functional/page_objects/security_page.ts index e3efc8731e6b3..3ce8a0e681d69 100644 --- a/x-pack/test/functional/page_objects/security_page.ts +++ b/x-pack/test/functional/page_objects/security_page.ts @@ -17,7 +17,7 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider const esArchiver = getService('esArchiver'); const userMenu = getService('userMenu'); const comboBox = getService('comboBox'); - const PageObjects = getPageObjects(['common', 'header', 'settings', 'home', 'error']); + const PageObjects = getPageObjects(['common', 'header', 'error']); interface LoginOptions { expectSpaceSelector?: boolean; diff --git a/x-pack/test/functional/page_objects/space_selector_page.ts b/x-pack/test/functional/page_objects/space_selector_page.ts index b272175ff2b21..acf8a65362f01 100644 --- a/x-pack/test/functional/page_objects/space_selector_page.ts +++ b/x-pack/test/functional/page_objects/space_selector_page.ts @@ -13,7 +13,7 @@ export function SpaceSelectorPageProvider({ getService, getPageObjects }: FtrPro const testSubjects = getService('testSubjects'); const browser = getService('browser'); const find = getService('find'); - const PageObjects = getPageObjects(['common', 'header', 'security']); + const PageObjects = getPageObjects(['common']); class SpaceSelectorPage { async initTests() { diff --git a/x-pack/test/functional/page_objects/status_page.js b/x-pack/test/functional/page_objects/status_page.ts similarity index 81% rename from x-pack/test/functional/page_objects/status_page.js rename to x-pack/test/functional/page_objects/status_page.ts index eba5e7dd18496..08726e1320f29 100644 --- a/x-pack/test/functional/page_objects/status_page.js +++ b/x-pack/test/functional/page_objects/status_page.ts @@ -5,13 +5,14 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function StatusPagePageProvider({ getService, getPageObjects }) { +export function StatusPagePageProvider({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const log = getService('log'); const browser = getService('browser'); const find = getService('find'); - const PageObjects = getPageObjects(['common', 'home', 'security']); + const { common } = getPageObjects(['common']); class StatusPage { async initTests() { @@ -20,13 +21,13 @@ export function StatusPagePageProvider({ getService, getPageObjects }) { async navigateToPage() { return await retry.try(async () => { - const url = PageObjects.common.getHostPort() + '/status'; + const url = common.getHostPort() + '/status'; log.info(`StatusPage:navigateToPage(): ${url}`); await browser.get(url); }); } - async expectStatusPage() { + async expectStatusPage(): Promise { return await retry.try(async () => { log.debug(`expectStatusPage()`); await find.byCssSelector('[data-test-subj="statusPageRoot"]', 20000); diff --git a/x-pack/test/functional/page_objects/upgrade_assistant.js b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts similarity index 76% rename from x-pack/test/functional/page_objects/upgrade_assistant.js rename to x-pack/test/functional/page_objects/upgrade_assistant_page.ts index 72dbb2175abc9..3fe60747505a7 100644 --- a/x-pack/test/functional/page_objects/upgrade_assistant.js +++ b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts @@ -5,14 +5,15 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function UpgradeAssistantProvider({ getService, getPageObjects }) { +export function UpgradeAssistantPageProvider({ getPageObjects, getService }: FtrProviderContext) { const retry = getService('retry'); const log = getService('log'); const browser = getService('browser'); const find = getService('find'); const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'settings', 'security']); + const { common } = getPageObjects(['common']); class UpgradeAssistant { async initTests() { @@ -21,7 +22,7 @@ export function UpgradeAssistantProvider({ getService, getPageObjects }) { async navigateToPage() { return await retry.try(async () => { - await PageObjects.common.navigateToApp('settings'); + await common.navigateToApp('settings'); await testSubjects.click('upgrade_assistant'); }); } @@ -29,7 +30,7 @@ export function UpgradeAssistantProvider({ getService, getPageObjects }) { async expectUpgradeAssistant() { return await retry.try(async () => { log.debug(`expectUpgradeAssistant()`); - expect(testSubjects.exists('upgradeAssistantRoot')).to.be.true; + expect(await testSubjects.exists('upgradeAssistantRoot')).to.equal(true); const url = await browser.getCurrentUrl(); expect(url).to.contain(`/upgrade_assistant`); }); @@ -42,7 +43,7 @@ export function UpgradeAssistantProvider({ getService, getPageObjects }) { }); } - async expectDeprecationLoggingLabel(labelText) { + async expectDeprecationLoggingLabel(labelText: string) { return await retry.try(async () => { log.debug('expectDeprecationLoggingLabel()'); const label = await find.byCssSelector( @@ -53,19 +54,17 @@ export function UpgradeAssistantProvider({ getService, getPageObjects }) { }); } - async clickTab(tabId) { + async clickTab(tabId: string) { return await retry.try(async () => { log.debug('clickTab()'); - const tab = await find.byCssSelector(`.euiTabs .euiTab#${tabId}`); - await tab.click(); + await find.clickByCssSelector(`.euiTabs .euiTab#${tabId}`); }); } - async expectIssueSummary(summary) { + async expectIssueSummary(summary: string) { return await retry.try(async () => { log.debug('expectIssueSummary()'); - const summaryEl = await testSubjects.find('upgradeAssistantIssueSummary'); - const summaryElText = await summaryEl.getVisibleText(); + const summaryElText = await testSubjects.getVisibleText('upgradeAssistantIssueSummary'); expect(summaryElText).to.eql(summary); }); } diff --git a/x-pack/test/functional/page_objects/uptime_page.ts b/x-pack/test/functional/page_objects/uptime_page.ts index d0b610ec861b8..fd47478909585 100644 --- a/x-pack/test/functional/page_objects/uptime_page.ts +++ b/x-pack/test/functional/page_objects/uptime_page.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; export function UptimePageProvider({ getPageObjects, getService }: FtrProviderContext) { - const pageObjects = getPageObjects(['common', 'timePicker', 'header']); + const pageObjects = getPageObjects(['timePicker', 'header']); const { common: commonService, monitor, navigation } = getService('uptime'); const retry = getService('retry'); diff --git a/x-pack/test/functional/page_objects/watcher_page.js b/x-pack/test/functional/page_objects/watcher_page.ts similarity index 89% rename from x-pack/test/functional/page_objects/watcher_page.js rename to x-pack/test/functional/page_objects/watcher_page.ts index dfc31a6ad5ed2..ce6d9edcb6cdb 100644 --- a/x-pack/test/functional/page_objects/watcher_page.js +++ b/x-pack/test/functional/page_objects/watcher_page.ts @@ -5,9 +5,10 @@ */ import { map as mapAsync } from 'bluebird'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function WatcherPageProvider({ getPageObjects, getService }) { - const PageObjects = getPageObjects(['common', 'header', 'settings']); +export function WatcherPageProvider({ getPageObjects, getService }: FtrProviderContext) { + const PageObjects = getPageObjects(['header']); const find = getService('find'); const testSubjects = getService('testSubjects'); @@ -22,7 +23,7 @@ export function WatcherPageProvider({ getPageObjects, getService }) { } } - async createWatch(watchName, name) { + async createWatch(watchName: string, name: string) { await testSubjects.click('createWatchButton'); await testSubjects.click('jsonWatchCreateLink'); await find.setValue('#id', watchName); @@ -31,7 +32,7 @@ export function WatcherPageProvider({ getPageObjects, getService }) { await PageObjects.header.waitUntilLoadingHasFinished(); } - async getWatch(watchID) { + async getWatch(watchID: string) { const watchIdColumn = await testSubjects.find(`watchIdColumn-${watchID}`); const watchNameColumn = await testSubjects.find(`watchNameColumn-${watchID}`); const id = await watchIdColumn.getVisibleText(); @@ -47,7 +48,7 @@ export function WatcherPageProvider({ getPageObjects, getService }) { await testSubjects.click('btnDeleteWatches'); } - //get all the watches in the list + // get all the watches in the list async getWatches() { const watches = await find.allByCssSelector('.euiTableRow'); return mapAsync(watches, async (watch) => { diff --git a/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts b/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts index 13b1f8c9d9842..523b327b8de1c 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts @@ -52,13 +52,11 @@ export function IngestManagerCreatePackagePolicy({ async selectAgentPolicy(name?: string) { // if we have a name, then find the button with that `title` set. if (name) { - await ( - await find.byCssSelector(`[data-test-subj="agentPolicyItem"][title="${name}"]`) - ).click(); + await find.clickByCssSelector(`[data-test-subj="agentPolicyItem"][title="${name}"]`); } // Else, just select the first agent policy that is present else { - await (await testSubjects.find('agentPolicyItem')).click(); + await testSubjects.click('agentPolicyItem'); } }, diff --git a/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts b/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts index 9c1fa0c6e86b2..d661b3097bd35 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts @@ -27,7 +27,7 @@ export function EndpointPolicyPageProvider({ getService, getPageObjects }: FtrPr */ async findFirstActionsButton() { await this.ensureIsOnPolicyPage(); - return (await testSubjects.findAll('policyActionsButton'))[0]; + return await testSubjects.find('policyActionsButton'); }, /** @@ -36,8 +36,7 @@ export function EndpointPolicyPageProvider({ getService, getPageObjects }: FtrPr async launchAndFindDeleteModal() { const actionsButton = await this.findFirstActionsButton(); await actionsButton.click(); - const deleteAction = await testSubjects.find('policyDeleteButton'); - await deleteAction.click(); + await testSubjects.click('policyDeleteButton'); return await testSubjects.find('policyListDeleteModal'); }, From 98113eeb1baa653029bb5525ca858ad448f35837 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Tue, 15 Sep 2020 17:02:03 +0300 Subject: [PATCH 25/26] [Functional] Fixes cloud failures on TSVB markdown (#77158) * [TSVB] Remove the char by char typing on markodown * revert * Add the markdown to be computed immediately and give some time to compute it * Add retry to locate TSVB tabs --- test/functional/page_objects/visual_builder_page.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index a95d535281fa3..6e49fd3b03494 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -58,7 +58,10 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro } public async checkTabIsLoaded(testSubj: string, name: string) { - const isPresent = await testSubjects.exists(testSubj, { timeout: 10000 }); + let isPresent = false; + await retry.try(async () => { + isPresent = await testSubjects.exists(testSubj, { timeout: 20000 }); + }); if (!isPresent) { throw new Error(`TSVB ${name} tab is not loaded`); } @@ -130,8 +133,8 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro public async enterMarkdown(markdown: string) { const input = await find.byCssSelector('.tvbMarkdownEditor__editor textarea'); await this.clearMarkdown(); - await input.type(markdown, { charByChar: true }); - await PageObjects.visChart.waitForVisualizationRenderingStabilized(); + await input.type(markdown); + await PageObjects.common.sleep(3000); } public async clearMarkdown() { From e6d675185267edfdb15407a6342ebff79ce0c5c4 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Tue, 15 Sep 2020 08:05:19 -0600 Subject: [PATCH 26/26] [data.search.SearchSource] Unify FetchHandler types & add onResponse/callMsearch. (#77430) --- ...gins-data-public.searchsource.serialize.md | 4 +- src/plugins/data/public/public.api.md | 3 +- src/plugins/data/public/search/fetch/types.ts | 18 ++++++--- .../public/search/legacy/call_client.test.ts | 33 ++++++++--------- .../data/public/search/legacy/call_client.ts | 4 +- .../data/public/search/legacy/call_msearch.ts | 37 +++++++++++++++++++ .../legacy/default_search_strategy.test.ts | 14 ++++--- .../search/legacy/default_search_strategy.ts | 17 +++++---- .../public/search/legacy/fetch_soon.test.ts | 32 ++++++---------- .../data/public/search/legacy/fetch_soon.ts | 2 +- .../data/public/search/legacy/types.ts | 10 +++++ .../data/public/search/search_service.ts | 13 +++++-- .../create_search_source.test.ts | 8 ++-- .../data/public/search/search_source/mocks.ts | 9 +++-- .../search_source/search_source.test.ts | 8 ++-- .../search/search_source/search_source.ts | 27 ++++---------- 16 files changed, 143 insertions(+), 96 deletions(-) create mode 100644 src/plugins/data/public/search/legacy/call_msearch.ts diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md index 73ba8eb66040b..496e1ae9677d8 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md @@ -15,13 +15,13 @@ Using `createSearchSource`, the instance can be re-created. ```typescript serialize(): { searchSourceJSON: string; - references: import("../../../../../core/public").SavedObjectReference[]; + references: import("../../../../../core/types").SavedObjectReference[]; }; ``` Returns: `{ searchSourceJSON: string; - references: import("../../../../../core/public").SavedObjectReference[]; + references: import("../../../../../core/types").SavedObjectReference[]; }` diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 9afaaeab921f7..a8fbbcb08d358 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -28,7 +28,6 @@ import { ExpressionAstFunction } from 'src/plugins/expressions/common'; import { ExpressionsSetup } from 'src/plugins/expressions/public'; import { History } from 'history'; import { Href } from 'history'; -import { HttpStart } from 'src/core/public'; import { IconType } from '@elastic/eui'; import { InjectedIntl } from '@kbn/i18n/react'; import { ISearchOptions as ISearchOptions_2 } from 'src/plugins/data/public'; @@ -2018,7 +2017,7 @@ export class SearchSource { onRequestStart(handler: (searchSource: SearchSource, options?: ISearchOptions) => Promise): void; serialize(): { searchSourceJSON: string; - references: import("../../../../../core/public").SavedObjectReference[]; + references: import("../../../../../core/types").SavedObjectReference[]; }; setField(field: K, value: SearchSourceFields[K]): this; setFields(newFields: SearchSourceFields): this; diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts index 224a597766909..cdf10d8f1a1b0 100644 --- a/src/plugins/data/public/search/fetch/types.ts +++ b/src/plugins/data/public/search/fetch/types.ts @@ -17,9 +17,9 @@ * under the License. */ -import { HttpStart } from 'src/core/public'; -import { BehaviorSubject } from 'rxjs'; +import { SearchResponse } from 'elasticsearch'; import { GetConfigFn } from '../../../common'; +import { LegacyFetchHandlers } from '../legacy/types'; /** * @internal @@ -31,9 +31,17 @@ import { GetConfigFn } from '../../../common'; export type SearchRequest = Record; export interface FetchHandlers { - config: { get: GetConfigFn }; - http: HttpStart; - loadingCount$: BehaviorSubject; + getConfig: GetConfigFn; + /** + * Callback which can be used to hook into responses, modify them, or perform + * side effects like displaying UI errors on the client. + */ + onResponse: (request: SearchRequest, response: SearchResponse) => SearchResponse; + /** + * These handlers are only used by the legacy defaultSearchStrategy and can be removed + * once that strategy has been deprecated. + */ + legacy: LegacyFetchHandlers; } export interface SearchError { diff --git a/src/plugins/data/public/search/legacy/call_client.test.ts b/src/plugins/data/public/search/legacy/call_client.test.ts index 943a02d22088d..0a7913b0a734f 100644 --- a/src/plugins/data/public/search/legacy/call_client.test.ts +++ b/src/plugins/data/public/search/legacy/call_client.test.ts @@ -17,18 +17,13 @@ * under the License. */ -import { coreMock } from '../../../../../core/public/mocks'; import { callClient } from './call_client'; import { SearchStrategySearchParams } from './types'; import { defaultSearchStrategy } from './default_search_strategy'; import { FetchHandlers } from '../fetch'; -import { handleResponse } from '../fetch/handle_response'; import { BehaviorSubject } from 'rxjs'; const mockAbortFn = jest.fn(); -jest.mock('../fetch/handle_response', () => ({ - handleResponse: jest.fn((request, response) => response), -})); jest.mock('./default_search_strategy', () => { return { @@ -50,32 +45,36 @@ jest.mock('./default_search_strategy', () => { }); describe('callClient', () => { + const handleResponse = jest.fn().mockImplementation((req, res) => res); + const handlers = { + getConfig: jest.fn(), + onResponse: handleResponse, + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, + } as FetchHandlers; + beforeEach(() => { - (handleResponse as jest.Mock).mockClear(); + handleResponse.mockClear(); }); test('Passes the additional arguments it is given to the search strategy', () => { const searchRequests = [{ _searchStrategyId: 0 }]; - const args = { - http: coreMock.createStart().http, - legacySearchService: {}, - config: { get: jest.fn() }, - loadingCount$: new BehaviorSubject(0), - } as FetchHandlers; - callClient(searchRequests, [], args); + callClient(searchRequests, [], handlers); expect(defaultSearchStrategy.search).toBeCalled(); expect((defaultSearchStrategy.search as any).mock.calls[0][0]).toEqual({ searchRequests, - ...args, + ...handlers, }); }); test('Returns the responses in the original order', async () => { const searchRequests = [{ _searchStrategyId: 1 }, { _searchStrategyId: 0 }]; - const responses = await Promise.all(callClient(searchRequests, [], {} as FetchHandlers)); + const responses = await Promise.all(callClient(searchRequests, [], handlers)); expect(responses[0]).toEqual({ id: searchRequests[0]._searchStrategyId }); expect(responses[1]).toEqual({ id: searchRequests[1]._searchStrategyId }); @@ -84,7 +83,7 @@ describe('callClient', () => { test('Calls handleResponse with each request and response', async () => { const searchRequests = [{ _searchStrategyId: 0 }, { _searchStrategyId: 1 }]; - const responses = callClient(searchRequests, [], {} as FetchHandlers); + const responses = callClient(searchRequests, [], handlers); await Promise.all(responses); expect(handleResponse).toBeCalledTimes(2); @@ -105,7 +104,7 @@ describe('callClient', () => { }, ]; - callClient(searchRequests, requestOptions, {} as FetchHandlers); + callClient(searchRequests, requestOptions, handlers); abortController.abort(); expect(mockAbortFn).toBeCalled(); diff --git a/src/plugins/data/public/search/legacy/call_client.ts b/src/plugins/data/public/search/legacy/call_client.ts index d66796b9427a1..b87affdd59c54 100644 --- a/src/plugins/data/public/search/legacy/call_client.ts +++ b/src/plugins/data/public/search/legacy/call_client.ts @@ -19,7 +19,7 @@ import { SearchResponse } from 'elasticsearch'; import { ISearchOptions } from 'src/plugins/data/common'; -import { FetchHandlers, handleResponse } from '../fetch'; +import { FetchHandlers } from '../fetch'; import { defaultSearchStrategy } from './default_search_strategy'; import { SearchRequest } from '../index'; @@ -42,7 +42,7 @@ export function callClient( }); searchRequests.forEach((request, i) => { - const response = searching.then((results) => handleResponse(request, results[i])); + const response = searching.then((results) => fetchHandlers.onResponse(request, results[i])); const { abortSignal = null } = requestOptionsMap.get(request) || {}; if (abortSignal) abortSignal.addEventListener('abort', abort); requestResponseMap.set(request, response); diff --git a/src/plugins/data/public/search/legacy/call_msearch.ts b/src/plugins/data/public/search/legacy/call_msearch.ts new file mode 100644 index 0000000000000..fd4f8a07919f8 --- /dev/null +++ b/src/plugins/data/public/search/legacy/call_msearch.ts @@ -0,0 +1,37 @@ +/* + * 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 { HttpStart } from 'src/core/public'; +import { LegacyFetchHandlers } from './types'; + +/** + * Wrapper for calling the internal msearch endpoint from the client. + * This is needed to abstract away differences in the http service + * between client & server. + * + * @internal + */ +export function getCallMsearch({ http }: { http: HttpStart }): LegacyFetchHandlers['callMsearch'] { + return async ({ body, signal }) => { + return http.post('/internal/_msearch', { + body: JSON.stringify(body), + signal, + }); + }; +} diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts index e74ab49131430..ad59e5c6c9625 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts @@ -19,8 +19,9 @@ import { HttpStart } from 'src/core/public'; import { coreMock } from '../../../../../core/public/mocks'; +import { getCallMsearch } from './call_msearch'; import { defaultSearchStrategy } from './default_search_strategy'; -import { SearchStrategySearchParams } from './types'; +import { LegacyFetchHandlers, SearchStrategySearchParams } from './types'; import { BehaviorSubject } from 'rxjs'; const { search } = defaultSearchStrategy; @@ -44,11 +45,12 @@ describe('defaultSearchStrategy', function () { index: { title: 'foo' }, }, ], - http, - config: { - get: jest.fn(), - }, - loadingCount$: new BehaviorSubject(0) as any, + getConfig: jest.fn(), + onResponse: (req, res) => res, + legacy: { + callMsearch: getCallMsearch({ http }), + loadingCount$: new BehaviorSubject(0) as any, + } as jest.Mocked, }; }); diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.ts b/src/plugins/data/public/search/legacy/default_search_strategy.ts index cbcd0da20207f..bed86cb75cca6 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.ts @@ -29,12 +29,14 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }, }; -function msearch({ searchRequests, config, http, loadingCount$ }: SearchStrategySearchParams) { +function msearch({ searchRequests, getConfig, legacy }: SearchStrategySearchParams) { + const { callMsearch, loadingCount$ } = legacy; + const requests = searchRequests.map(({ index, body }) => { return { header: { index: index.title || index, - preference: getPreference(config.get), + preference: getPreference(getConfig), }, body, }; @@ -55,12 +57,11 @@ function msearch({ searchRequests, config, http, loadingCount$ }: SearchStrategy } }; - const searching = http - .post('/internal/_msearch', { - body: JSON.stringify({ searches: requests }), - signal: abortController.signal, - }) - .then(({ body }) => body?.responses) + const searching = callMsearch({ + body: { searches: requests }, + signal: abortController.signal, + }) + .then((res: any) => res?.body?.responses) .finally(() => cleanup()); return { diff --git a/src/plugins/data/public/search/legacy/fetch_soon.test.ts b/src/plugins/data/public/search/legacy/fetch_soon.test.ts index d38a41cf5ffbc..7243ab158009a 100644 --- a/src/plugins/data/public/search/legacy/fetch_soon.test.ts +++ b/src/plugins/data/public/search/legacy/fetch_soon.test.ts @@ -67,25 +67,21 @@ describe('fetchSoon', () => { }); test('should execute asap if config is set to not batch searches', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: false }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: false }); const request = {}; const options = {}; - fetchSoon(request, options, { config } as FetchHandlers); + fetchSoon(request, options, { getConfig } as FetchHandlers); expect(callClient).toBeCalled(); }); test('should delay by 50ms if config is set to batch searches', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const request = {}; const options = {}; - fetchSoon(request, options, { config } as FetchHandlers); + fetchSoon(request, options, { getConfig } as FetchHandlers); expect(callClient).not.toBeCalled(); jest.advanceTimersByTime(0); @@ -95,14 +91,12 @@ describe('fetchSoon', () => { }); test('should send a batch of requests to callClient', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const requests = [{ foo: 1 }, { foo: 2 }]; const options = [{ bar: 1 }, { bar: 2 }]; requests.forEach((request, i) => { - fetchSoon(request, options[i] as ISearchOptions, { config } as FetchHandlers); + fetchSoon(request, options[i] as ISearchOptions, { getConfig } as FetchHandlers); }); jest.advanceTimersByTime(50); @@ -112,13 +106,11 @@ describe('fetchSoon', () => { }); test('should return the response to the corresponding call for multiple batched requests', async () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const requests = [{ _mockResponseId: 'foo' }, { _mockResponseId: 'bar' }]; const promises = requests.map((request) => { - return fetchSoon(request, {}, { config } as FetchHandlers); + return fetchSoon(request, {}, { getConfig } as FetchHandlers); }); jest.advanceTimersByTime(50); const results = await Promise.all(promises); @@ -127,18 +119,16 @@ describe('fetchSoon', () => { }); test('should wait for the previous batch to start before starting a new batch', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const firstBatch = [{ foo: 1 }, { foo: 2 }]; const secondBatch = [{ bar: 1 }, { bar: 2 }]; firstBatch.forEach((request) => { - fetchSoon(request, {}, { config } as FetchHandlers); + fetchSoon(request, {}, { getConfig } as FetchHandlers); }); jest.advanceTimersByTime(50); secondBatch.forEach((request) => { - fetchSoon(request, {}, { config } as FetchHandlers); + fetchSoon(request, {}, { getConfig } as FetchHandlers); }); expect(callClient).toBeCalledTimes(1); diff --git a/src/plugins/data/public/search/legacy/fetch_soon.ts b/src/plugins/data/public/search/legacy/fetch_soon.ts index 37c3827bb7bba..1c0573aa895d7 100644 --- a/src/plugins/data/public/search/legacy/fetch_soon.ts +++ b/src/plugins/data/public/search/legacy/fetch_soon.ts @@ -32,7 +32,7 @@ export async function fetchSoon( options: ISearchOptions, fetchHandlers: FetchHandlers ) { - const msToDelay = fetchHandlers.config.get(UI_SETTINGS.COURIER_BATCH_SEARCHES) ? 50 : 0; + const msToDelay = fetchHandlers.getConfig(UI_SETTINGS.COURIER_BATCH_SEARCHES) ? 50 : 0; return delayedFetch(request, options, fetchHandlers, msToDelay); } diff --git a/src/plugins/data/public/search/legacy/types.ts b/src/plugins/data/public/search/legacy/types.ts index ed17db464feff..740bc22a7485c 100644 --- a/src/plugins/data/public/search/legacy/types.ts +++ b/src/plugins/data/public/search/legacy/types.ts @@ -17,10 +17,20 @@ * under the License. */ +import { BehaviorSubject } from 'rxjs'; import { SearchResponse } from 'elasticsearch'; import { FetchHandlers } from '../fetch'; import { SearchRequest } from '..'; +// @internal +export interface LegacyFetchHandlers { + callMsearch: (params: { + body: SearchRequest; + signal: AbortSignal; + }) => Promise>>; + loadingCount$: BehaviorSubject; +} + export interface SearchStrategySearchParams extends FetchHandlers { searchRequests: SearchRequest[]; } diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 6b73761c5a437..c41e1f78ee74e 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -21,6 +21,8 @@ import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; import { BehaviorSubject } from 'rxjs'; import { ISearchSetup, ISearchStart, SearchEnhancements } from './types'; +import { handleResponse } from './fetch'; +import { getCallMsearch } from './legacy/call_msearch'; import { createSearchSource, SearchSource, SearchSourceDependencies } from './search_source'; import { AggsService, AggsStartDependencies } from './aggs'; import { IndexPatternsContract } from '../index_patterns/index_patterns'; @@ -49,7 +51,7 @@ export class SearchService implements Plugin { private usageCollector?: SearchUsageCollector; public setup( - { http, getStartServices, injectedMetadata, notifications, uiSettings }: CoreSetup, + { http, getStartServices, notifications, uiSettings }: CoreSetup, { expressions, usageCollection }: SearchServiceSetupDependencies ): ISearchSetup { this.usageCollector = createUsageCollector(getStartServices, usageCollection); @@ -82,7 +84,7 @@ export class SearchService implements Plugin { } public start( - { application, http, injectedMetadata, notifications, uiSettings }: CoreStart, + { application, http, notifications, uiSettings }: CoreStart, { fieldFormats, indexPatterns }: SearchServiceStartDependencies ): ISearchStart { const search = ((request, options) => { @@ -95,8 +97,11 @@ export class SearchService implements Plugin { const searchSourceDependencies: SearchSourceDependencies = { getConfig: uiSettings.get.bind(uiSettings), search, - http, - loadingCount$, + onResponse: handleResponse, + legacy: { + callMsearch: getCallMsearch({ http }), + loadingCount$, + }, }; return { diff --git a/src/plugins/data/public/search/search_source/create_search_source.test.ts b/src/plugins/data/public/search/search_source/create_search_source.test.ts index bc1c7c06c8806..6b6cfb0c9b1ca 100644 --- a/src/plugins/data/public/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/public/search/search_source/create_search_source.test.ts @@ -22,7 +22,6 @@ import { SearchSourceDependencies } from './search_source'; import { IIndexPattern } from '../../../common/index_patterns'; import { IndexPatternsContract } from '../../index_patterns/index_patterns'; import { Filter } from '../../../common/es_query/filters'; -import { coreMock } from '../../../../../core/public/mocks'; import { BehaviorSubject } from 'rxjs'; describe('createSearchSource', () => { @@ -35,8 +34,11 @@ describe('createSearchSource', () => { dependencies = { getConfig: jest.fn(), search: jest.fn(), - http: coreMock.createStart().http, - loadingCount$: new BehaviorSubject(0), + onResponse: (req, res) => res, + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, }; indexPatternContractMock = ({ diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index adf53bee33fe1..f582861e37c15 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -18,7 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; -import { httpServiceMock, uiSettingsServiceMock } from '../../../../../core/public/mocks'; +import { uiSettingsServiceMock } from '../../../../../core/public/mocks'; import { ISearchSource, SearchSource } from './search_source'; import { SearchSourceFields } from './types'; @@ -54,6 +54,9 @@ export const createSearchSourceMock = (fields?: SearchSourceFields) => new SearchSource(fields, { getConfig: uiSettingsServiceMock.createStartContract().get, search: jest.fn(), - http: httpServiceMock.createStartContract(), - loadingCount$: new BehaviorSubject(0), + onResponse: jest.fn().mockImplementation((req, res) => res), + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, }); diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts index 282a33e6d01f7..d9a9fb2f4fef3 100644 --- a/src/plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/public/search/search_source/search_source.test.ts @@ -22,7 +22,6 @@ import { GetConfigFn } from 'src/plugins/data/common'; import { SearchSource, SearchSourceDependencies } from './search_source'; import { IndexPattern, SortDirection } from '../..'; import { fetchSoon } from '../legacy'; -import { coreMock } from '../../../../../core/public/mocks'; jest.mock('../legacy', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), @@ -68,8 +67,11 @@ describe('SearchSource', () => { searchSourceDependencies = { getConfig: jest.fn(), search: mockSearchMethod, - http: coreMock.createStart().http, - loadingCount$: new BehaviorSubject(0), + onResponse: (req, res) => res, + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, }; }); diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index a39898e6a9f52..4afee223454e4 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -72,19 +72,12 @@ import { setWith } from '@elastic/safer-lodash-set'; import { uniqueId, uniq, extend, pick, difference, omit, isObject, keys, isFunction } from 'lodash'; import { map } from 'rxjs/operators'; -import { HttpStart } from 'src/core/public'; -import { BehaviorSubject } from 'rxjs'; import { normalizeSortRequest } from './normalize_sort_request'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { fieldWildcardFilter } from '../../../../kibana_utils/common'; import { IIndexPattern, ISearchGeneric } from '../..'; import { SearchSourceOptions, SearchSourceFields } from './types'; -import { - RequestFailure, - handleResponse, - getSearchParamsFromRequest, - SearchRequest, -} from '../fetch'; +import { FetchHandlers, RequestFailure, getSearchParamsFromRequest, SearchRequest } from '../fetch'; import { getEsQueryConfig, @@ -94,7 +87,6 @@ import { ISearchOptions, } from '../../../common'; import { getHighlightRequest } from '../../../common/field_formats'; -import { GetConfigFn } from '../../../common/types'; import { fetchSoon } from '../legacy'; import { extractReferences } from './extract_references'; @@ -114,11 +106,8 @@ export const searchSourceRequiredUiSettings = [ UI_SETTINGS.SORT_OPTIONS, ]; -export interface SearchSourceDependencies { - getConfig: GetConfigFn; +export interface SearchSourceDependencies extends FetchHandlers { search: ISearchGeneric; - http: HttpStart; - loadingCount$: BehaviorSubject; } /** @public **/ @@ -321,14 +310,14 @@ export class SearchSource { * @return {Observable>} */ private fetch$(searchRequest: SearchRequest, options: ISearchOptions) { - const { search, getConfig } = this.dependencies; + const { search, getConfig, onResponse } = this.dependencies; const params = getSearchParamsFromRequest(searchRequest, { getConfig, }); return search({ params, indexType: searchRequest.indexType }, options).pipe( - map(({ rawResponse }) => handleResponse(searchRequest, rawResponse)) + map(({ rawResponse }) => onResponse(searchRequest, rawResponse)) ); } @@ -337,7 +326,7 @@ export class SearchSource { * @return {Promise>} */ private async legacyFetch(searchRequest: SearchRequest, options: ISearchOptions) { - const { http, getConfig, loadingCount$ } = this.dependencies; + const { getConfig, legacy, onResponse } = this.dependencies; return await fetchSoon( searchRequest, @@ -346,9 +335,9 @@ export class SearchSource { ...options, }, { - http, - config: { get: getConfig }, - loadingCount$, + getConfig, + onResponse, + legacy, } ); }