From ecf512a048393a80a31f7085f0e7fc74a55b731f Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Tue, 26 Jan 2021 19:06:40 +0100 Subject: [PATCH 01/58] [Lens] Make Lens visualization load faster on Dashboard (#88953) * :rocket: Load indexPatternRefs only on edit mode * :white_mark_check: Fix test with new editor init flag * :bug: Avoid to save to localStorage undefined indexPattern * :white_mark_check: Adapted tests to new conditional ref loading Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../editor_frame/editor_frame.test.tsx | 8 ++++-- .../editor_frame/editor_frame.tsx | 3 +- .../editor_frame/state_helpers.ts | 15 ++++++++-- .../indexpattern_datasource/indexpattern.tsx | 5 +++- .../indexpattern_datasource/loader.test.ts | 28 +++++++++++++++++++ .../public/indexpattern_datasource/loader.ts | 17 +++++++---- x-pack/plugins/lens/public/types.ts | 7 ++++- 7 files changed, 70 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx index 76394c2901aaa3..c0728bd030a0a4 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx @@ -188,8 +188,12 @@ describe('editor_frame', () => { /> ); }); - expect(mockDatasource.initialize).toHaveBeenCalledWith(datasource1State, [], undefined); - expect(mockDatasource2.initialize).toHaveBeenCalledWith(datasource2State, [], undefined); + expect(mockDatasource.initialize).toHaveBeenCalledWith(datasource1State, [], undefined, { + isFullEditor: true, + }); + expect(mockDatasource2.initialize).toHaveBeenCalledWith(datasource2State, [], undefined, { + isFullEditor: true, + }); expect(mockDatasource3.initialize).not.toHaveBeenCalled(); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx index f908d16afe4706..b6df0caa075779 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx @@ -81,7 +81,8 @@ export function EditorFrame(props: EditorFrameProps) { props.datasourceMap, state.datasourceStates, props.doc?.references, - visualizeTriggerFieldContext + visualizeTriggerFieldContext, + { isFullEditor: true } ) .then((result) => { if (!isUnmounted) { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts index 9c5eafc300abc0..de747fde2e92c6 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts @@ -10,6 +10,7 @@ import { Datasource, DatasourcePublicAPI, FramePublicAPI, + InitializationOptions, Visualization, VisualizationDimensionGroupConfig, } from '../../types'; @@ -21,14 +22,20 @@ export async function initializeDatasources( datasourceMap: Record, datasourceStates: Record, references?: SavedObjectReference[], - initialContext?: VisualizeFieldContext + initialContext?: VisualizeFieldContext, + options?: InitializationOptions ) { const states: Record = {}; await Promise.all( Object.entries(datasourceMap).map(([datasourceId, datasource]) => { if (datasourceStates[datasourceId]) { return datasource - .initialize(datasourceStates[datasourceId].state || undefined, references, initialContext) + .initialize( + datasourceStates[datasourceId].state || undefined, + references, + initialContext, + options + ) .then((datasourceState) => { states[datasourceId] = { isLoading: false, state: datasourceState }; }); @@ -82,7 +89,9 @@ export async function persistedStateToExpression( { isLoading: false, state }, ]) ), - references + references, + undefined, + { isFullEditor: false } ); const datasourceLayers = createDatasourceLayers(datasources, datasourceStates); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx index 48592c44aa543f..22c0054cb33e02 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx @@ -18,6 +18,7 @@ import { Operation, DatasourceLayerPanelProps, PublicAPIProps, + InitializationOptions, } from '../types'; import { loadInitialState, @@ -104,7 +105,8 @@ export function getIndexPatternDatasource({ async initialize( persistedState?: IndexPatternPersistedState, references?: SavedObjectReference[], - initialContext?: VisualizeFieldContext + initialContext?: VisualizeFieldContext, + options?: InitializationOptions ) { return loadInitialState({ persistedState, @@ -114,6 +116,7 @@ export function getIndexPatternDatasource({ storage, indexPatternsService, initialContext, + options, }); }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts index 29786d9bc68f36..801496d1a5701f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts @@ -346,6 +346,7 @@ describe('loader', () => { savedObjectsClient: mockClient(), indexPatternsService: mockIndexPatternsService(), storage, + options: { isFullEditor: true }, }); expect(state).toMatchObject({ @@ -364,12 +365,35 @@ describe('loader', () => { }); }); + it('should load a default state without loading the indexPatterns when embedded', async () => { + const storage = createMockStorage(); + const savedObjectsClient = mockClient(); + const state = await loadInitialState({ + savedObjectsClient, + indexPatternsService: mockIndexPatternsService(), + storage, + options: { isFullEditor: false }, + }); + + expect(state).toMatchObject({ + currentIndexPatternId: undefined, + indexPatternRefs: [], + indexPatterns: {}, + layers: {}, + }); + + expect(storage.set).not.toHaveBeenCalled(); + + expect(savedObjectsClient.find).not.toHaveBeenCalled(); + }); + it('should load a default state when lastUsedIndexPatternId is not found in indexPatternRefs', async () => { const storage = createMockStorage({ indexPatternId: 'c' }); const state = await loadInitialState({ savedObjectsClient: mockClient(), indexPatternsService: mockIndexPatternsService(), storage, + options: { isFullEditor: true }, }); expect(state).toMatchObject({ @@ -393,6 +417,7 @@ describe('loader', () => { savedObjectsClient: mockClient(), indexPatternsService: mockIndexPatternsService(), storage: createMockStorage({ indexPatternId: '2' }), + options: { isFullEditor: true }, }); expect(state).toMatchObject({ @@ -415,6 +440,7 @@ describe('loader', () => { savedObjectsClient: mockClient(), indexPatternsService: mockIndexPatternsService(), storage, + options: { isFullEditor: true }, }); expect(state).toMatchObject({ @@ -443,6 +469,7 @@ describe('loader', () => { indexPatternId: '1', fieldName: '', }, + options: { isFullEditor: true }, }); expect(state).toMatchObject({ @@ -499,6 +526,7 @@ describe('loader', () => { savedObjectsClient: mockClient(), indexPatternsService: mockIndexPatternsService(), storage, + options: { isFullEditor: true }, }); expect(state).toMatchObject({ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts b/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts index 64c4122245ce06..52505b12be4c38 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts @@ -7,7 +7,7 @@ import _ from 'lodash'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { SavedObjectsClientContract, HttpSetup, SavedObjectReference } from 'kibana/public'; -import { StateSetter } from '../types'; +import { InitializationOptions, StateSetter } from '../types'; import { IndexPattern, IndexPatternRef, @@ -190,6 +190,7 @@ export async function loadInitialState({ storage, indexPatternsService, initialContext, + options, }: { persistedState?: IndexPatternPersistedState; references?: SavedObjectReference[]; @@ -198,8 +199,10 @@ export async function loadInitialState({ storage: IStorageWrapper; indexPatternsService: IndexPatternsService; initialContext?: VisualizeFieldContext; + options?: InitializationOptions; }): Promise { - const indexPatternRefs = await loadIndexPatternRefs(savedObjectsClient); + const { isFullEditor } = options ?? {}; + const indexPatternRefs = await (isFullEditor ? loadIndexPatternRefs(savedObjectsClient) : []); const lastUsedIndexPatternId = getLastUsedIndexPatternId(storage, indexPatternRefs); const state = @@ -210,11 +213,15 @@ export async function loadInitialState({ ? Object.values(state.layers) .map((l) => l.indexPatternId) .concat(state.currentIndexPatternId) - : [lastUsedIndexPatternId || defaultIndexPatternId || indexPatternRefs[0].id] - ); + : [lastUsedIndexPatternId || defaultIndexPatternId || indexPatternRefs[0]?.id] + ) + // take out the undefined from the list + .filter(Boolean); const currentIndexPatternId = initialContext?.indexPatternId ?? requiredPatterns[0]; - setLastUsedIndexPatternId(storage, currentIndexPatternId); + if (currentIndexPatternId) { + setLastUsedIndexPatternId(storage, currentIndexPatternId); + } const indexPatterns = await loadIndexPatterns({ indexPatternsService, diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index bba601f9423800..9feed918635b3f 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -139,6 +139,10 @@ export interface DatasourceSuggestion { export type StateSetter = (newState: T | ((prevState: T) => T)) => void; +export interface InitializationOptions { + isFullEditor?: boolean; +} + /** * Interface for the datasource registry */ @@ -151,7 +155,8 @@ export interface Datasource { initialize: ( state?: P, savedObjectReferences?: SavedObjectReference[], - initialContext?: VisualizeFieldContext + initialContext?: VisualizeFieldContext, + options?: InitializationOptions ) => Promise; // Given the current state, which parts should be saved? From 7bb8d3a7b244d3d3f8127a757f480ab6a9d7a312 Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Tue, 26 Jan 2021 13:09:53 -0600 Subject: [PATCH 02/58] [Workplace Search] Fix Private Dashboard routes (#88985) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add index route for personal dashboard * Fix links to personal source flow In ent-search, the base route was /sources so the getSourcesPath helper was not needed. In Kibana, we use the ‘/p’ route to differentiate personal from org so the helper is needed and we pass false as the isOrganization flag * Remove legacy sidebar text When I first migrated this, I left the sidebar copy in so that it was not aboandoned before the design pass. After talking with John we decided to just use the copy to the right of the sidebar so this drops that legacy copy. * Remove constants * Remove legacy sidebar link * Revert "Remove legacy sidebar text" This reverts commit 8c8a3fb63c08154fbbdbe44533a8dd8ec6b265da. * Revert "Remove constants" This reverts commit a88723ec90d10e7b03214f176a2cab133e9d3ae5. * Revert "Remove legacy sidebar link" This reverts commit 5d08a12a7d53690805727f181967bd3d82b24235. * Update TODO Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/applications/workplace_search/index.tsx | 6 ++++++ .../views/content_sources/private_sources.tsx | 11 ++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx index 65a2c7a4a44dd2..d10de7a7701711 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx @@ -78,6 +78,12 @@ export const WorkplaceSearchConfigured: React.FC = (props) => { {errorConnecting ? : } + + {/* TODO: replace Layout with PrivateSourcesLayout (needs to be created) */} + } restrictWidth readOnlyMode={readOnlyMode}> + + + } />} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx index a1a76c678866c4..c11cdaa5ec36f7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx @@ -12,7 +12,7 @@ import { EuiCallOut, EuiEmptyPrompt, EuiSpacer, EuiPanel } from '@elastic/eui'; import { LicensingLogic } from '../../../../applications/shared/licensing'; -import { ADD_SOURCE_PATH } from '../../routes'; +import { ADD_SOURCE_PATH, getSourcesPath } from '../../routes'; import noSharedSourcesIcon from '../../assets/share_circle.svg'; @@ -74,12 +74,17 @@ export const PrivateSources: React.FC = () => { sidebarLinks.push({ title: PRIVATE_LINK_TITLE, iconType: 'plusInCircle', - path: ADD_SOURCE_PATH, + path: getSourcesPath(ADD_SOURCE_PATH, false), }); } const headerAction = ( - + {PRIVATE_LINK_TITLE} ); From 0c2c451830d7f8b8ecacd8b2500e44f1cf5d7741 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 26 Jan 2021 21:56:31 +0200 Subject: [PATCH 03/58] [Security Solution][Case] Add button to go to case view after adding an alert to a case (#89214) --- .../add_to_case_action.test.tsx | 64 ++++++++++++++++--- .../timeline_actions/add_to_case_action.tsx | 23 ++++++- .../{helpers.test.ts => helpers.test.tsx} | 22 ++----- .../{helpers.ts => helpers.tsx} | 22 ++++--- .../timeline_actions/toaster_content.test.tsx | 45 +++++++++++++ .../timeline_actions/toaster_content.tsx | 46 +++++++++++++ .../timeline_actions/translations.ts | 7 ++ 7 files changed, 195 insertions(+), 34 deletions(-) rename x-pack/plugins/security_solution/public/cases/components/timeline_actions/{helpers.test.ts => helpers.test.tsx} (55%) rename x-pack/plugins/security_solution/public/cases/components/timeline_actions/{helpers.ts => helpers.tsx} (59%) create mode 100644 x-pack/plugins/security_solution/public/cases/components/timeline_actions/toaster_content.test.tsx create mode 100644 x-pack/plugins/security_solution/public/cases/components/timeline_actions/toaster_content.tsx diff --git a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.test.tsx b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.test.tsx index 0c156e247a5e0f..71d7387d8d3927 100644 --- a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.test.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.test.tsx @@ -6,18 +6,24 @@ /* eslint-disable react/display-name */ import React, { ReactNode } from 'react'; - import { mount } from 'enzyme'; +import { EuiGlobalToastList } from '@elastic/eui'; + +import { useKibana } from '../../../common/lib/kibana'; +import { useStateToaster } from '../../../common/components/toasters'; import { TestProviders } from '../../../common/mock'; import { usePostComment } from '../../containers/use_post_comment'; +import { Case } from '../../containers/types'; import { AddToCaseAction } from './add_to_case_action'; jest.mock('../../containers/use_post_comment'); -jest.mock('../../../common/lib/kibana', () => { - const originalModule = jest.requireActual('../../../common/lib/kibana'); +jest.mock('../../../common/lib/kibana'); + +jest.mock('../../../common/components/toasters', () => { + const actual = jest.requireActual('../../../common/components/toasters'); return { - ...originalModule, - useGetUserSavedObjectPermissions: jest.fn(), + ...actual, + useStateToaster: jest.fn(), }; }); @@ -44,14 +50,16 @@ jest.mock('../create/form_context', () => { onSuccess, }: { children: ReactNode; - onSuccess: ({ id }: { id: string }) => void; + onSuccess: (theCase: Partial) => void; }) => { return ( <> @@ -95,9 +103,16 @@ describe('AddToCaseAction', () => { disabled: false, }; + const mockDispatchToaster = jest.fn(); + const mockNavigateToApp = jest.fn(); + beforeEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); usePostCommentMock.mockImplementation(() => defaultPostComment); + (useStateToaster as jest.Mock).mockReturnValue([jest.fn(), mockDispatchToaster]); + (useKibana as jest.Mock).mockReturnValue({ + services: { application: { navigateToApp: mockNavigateToApp } }, + }); }); it('it renders', async () => { @@ -187,4 +202,37 @@ describe('AddToCaseAction', () => { type: 'alert', }); }); + + it('navigates to case view', async () => { + usePostCommentMock.mockImplementation(() => { + return { + ...defaultPostComment, + postComment: jest.fn().mockImplementation((caseId, data, updateCase) => updateCase()), + }; + }); + + const wrapper = mount( + + + + ); + + wrapper.find(`[data-test-subj="attach-alert-to-case-button"]`).first().simulate('click'); + wrapper.find(`[data-test-subj="add-new-case-item"]`).first().simulate('click'); + wrapper.find(`[data-test-subj="form-context-on-success"]`).first().simulate('click'); + + expect(mockDispatchToaster).toHaveBeenCalled(); + const toast = mockDispatchToaster.mock.calls[0][0].toast; + + const toastWrapper = mount( + {}} /> + ); + + toastWrapper + .find('[data-test-subj="toaster-content-case-view-link"]') + .first() + .simulate('click'); + + expect(mockNavigateToApp).toHaveBeenCalledWith('securitySolution:case', { path: '/new-case' }); + }); }); diff --git a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.tsx b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.tsx index 3ebc0654fc0199..eed4f2092fd58f 100644 --- a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.tsx @@ -20,6 +20,10 @@ import { ActionIconItem } from '../../../timelines/components/timeline/body/acti import { usePostComment } from '../../containers/use_post_comment'; import { Case } from '../../containers/types'; import { useStateToaster } from '../../../common/components/toasters'; +import { APP_ID } from '../../../../common/constants'; +import { useKibana } from '../../../common/lib/kibana'; +import { getCaseDetailsUrl } from '../../../common/components/link_to'; +import { SecurityPageName } from '../../../app/types'; import { useCreateCaseModal } from '../use_create_case_modal'; import { useAllCasesModal } from '../use_all_cases_modal'; import { createUpdateSuccessToaster } from './helpers'; @@ -39,12 +43,23 @@ const AddToCaseActionComponent: React.FC = ({ const eventId = ecsRowData._id; const eventIndex = ecsRowData._index; + const { navigateToApp } = useKibana().services.application; const [, dispatchToaster] = useStateToaster(); const [isPopoverOpen, setIsPopoverOpen] = useState(false); const openPopover = useCallback(() => setIsPopoverOpen(true), []); const closePopover = useCallback(() => setIsPopoverOpen(false), []); const { postComment } = usePostComment(); + + const onViewCaseClick = useCallback( + (id) => { + navigateToApp(`${APP_ID}:${SecurityPageName.case}`, { + path: getCaseDetailsUrl({ id }), + }); + }, + [navigateToApp] + ); + const attachAlertToCase = useCallback( (theCase: Case) => { postComment( @@ -54,10 +69,14 @@ const AddToCaseActionComponent: React.FC = ({ alertId: eventId, index: eventIndex ?? '', }, - () => dispatchToaster({ type: 'addToaster', toast: createUpdateSuccessToaster(theCase) }) + () => + dispatchToaster({ + type: 'addToaster', + toast: createUpdateSuccessToaster(theCase, onViewCaseClick), + }) ); }, - [postComment, eventId, eventIndex, dispatchToaster] + [postComment, eventId, eventIndex, dispatchToaster, onViewCaseClick] ); const { modal: createCaseModal, openModal: openCreateCaseModal } = useCreateCaseModal({ diff --git a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.test.ts b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.test.tsx similarity index 55% rename from x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.test.ts rename to x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.test.tsx index 58c9c4baf82ebf..b05dc4134cb101 100644 --- a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.test.tsx @@ -8,6 +8,7 @@ import { createUpdateSuccessToaster } from './helpers'; import { Case } from '../../containers/types'; const theCase = { + id: 'case-id', title: 'My case', settings: { syncAlerts: true, @@ -15,24 +16,13 @@ const theCase = { } as Case; describe('helpers', () => { + const onViewCaseClick = jest.fn(); + describe('createUpdateSuccessToaster', () => { it('creates the correct toast when the sync alerts is on', () => { - // We remove the id as is randomly generated - const { id, ...toast } = createUpdateSuccessToaster(theCase); - expect(toast).toEqual({ - color: 'success', - iconType: 'check', - text: 'Alerts in this case have their status synched with the case status', - title: 'An alert has been added to "My case"', - }); - }); - - it('creates the correct toast when the sync alerts is off', () => { - // We remove the id as is randomly generated - const { id, ...toast } = createUpdateSuccessToaster({ - ...theCase, - settings: { syncAlerts: false }, - }); + // We remove the id as is randomly generated and the text as it is a React component + // which is being test on toaster_content.test.tsx + const { id, text, ...toast } = createUpdateSuccessToaster(theCase, onViewCaseClick); expect(toast).toEqual({ color: 'success', iconType: 'check', diff --git a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.ts b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.tsx similarity index 59% rename from x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.ts rename to x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.tsx index abafa55c289035..b1bae8df0a0b19 100644 --- a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.ts +++ b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/helpers.tsx @@ -4,22 +4,28 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; import uuid from 'uuid'; import { AppToast } from '../../../common/components/toasters'; import { Case } from '../../containers/types'; +import { ToasterContent } from './toaster_content'; import * as i18n from './translations'; -export const createUpdateSuccessToaster = (theCase: Case): AppToast => { - const toast: AppToast = { +export const createUpdateSuccessToaster = ( + theCase: Case, + onViewCaseClick: (id: string) => void +): AppToast => { + return { id: uuid.v4(), color: 'success', iconType: 'check', title: i18n.CASE_CREATED_SUCCESS_TOAST(theCase.title), + text: ( + + ), }; - - if (theCase.settings.syncAlerts) { - return { ...toast, text: i18n.CASE_CREATED_SUCCESS_TOAST_TEXT }; - } - - return toast; }; diff --git a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/toaster_content.test.tsx b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/toaster_content.test.tsx new file mode 100644 index 00000000000000..b04ebb8903aea8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/toaster_content.test.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mount } from 'enzyme'; + +import { ToasterContent } from './toaster_content'; + +describe('ToasterContent', () => { + const onViewCaseClick = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders with syncAlerts=true', () => { + const wrapper = mount( + + ); + + expect(wrapper.find('[data-test-subj="toaster-content-case-view-link"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="toaster-content-sync-text"]').exists()).toBeTruthy(); + }); + + it('renders with syncAlerts=false', () => { + const wrapper = mount( + + ); + + expect(wrapper.find('[data-test-subj="toaster-content-case-view-link"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="toaster-content-sync-text"]').exists()).toBeFalsy(); + }); + + it('calls onViewCaseClick', () => { + const wrapper = mount( + + ); + + wrapper.find('[data-test-subj="toaster-content-case-view-link"]').first().simulate('click'); + expect(onViewCaseClick).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/toaster_content.tsx b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/toaster_content.tsx new file mode 100644 index 00000000000000..871db464d8576e --- /dev/null +++ b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/toaster_content.tsx @@ -0,0 +1,46 @@ +/* + * 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, { memo, useCallback } from 'react'; +import { EuiButtonEmpty, EuiText } from '@elastic/eui'; +import styled from 'styled-components'; + +import * as i18n from './translations'; + +const EuiTextStyled = styled(EuiText)` + ${({ theme }) => ` + margin-bottom: ${theme.eui?.paddingSizes?.s ?? 8}px; + `} +`; + +interface Props { + caseId: string; + syncAlerts: boolean; + onViewCaseClick: (id: string) => void; +} + +const ToasterContentComponent: React.FC = ({ caseId, syncAlerts, onViewCaseClick }) => { + const onClick = useCallback(() => onViewCaseClick(caseId), [caseId, onViewCaseClick]); + return ( + <> + {syncAlerts && ( + + {i18n.CASE_CREATED_SUCCESS_TOAST_TEXT} + + )} + + {i18n.VIEW_CASE} + + + ); +}; + +export const ToasterContent = memo(ToasterContentComponent); diff --git a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/translations.ts b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/translations.ts index 479323ed1301cb..dd3d6f0b50f194 100644 --- a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/translations.ts +++ b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/translations.ts @@ -53,3 +53,10 @@ export const CASE_CREATED_SUCCESS_TOAST_TEXT = i18n.translate( defaultMessage: 'Alerts in this case have their status synched with the case status', } ); + +export const VIEW_CASE = i18n.translate( + 'xpack.securitySolution.case.timeline.actions.caseCreatedSuccessToastViewCaseLink', + { + defaultMessage: 'View Case', + } +); From 87992d01da5787c0dd21f1186e8e8926cac97f07 Mon Sep 17 00:00:00 2001 From: Rashmi Kulkarni Date: Tue, 26 Jan 2021 12:49:44 -0800 Subject: [PATCH 04/58] Watcher -functional xpack test using test_user with specific permissions. (#89068) * fixes https://github.com/elastic/kibana/issues/74449 * watcher test with specific permissions * adding the false parameter Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/test/functional/apps/watcher/watcher_test.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/x-pack/test/functional/apps/watcher/watcher_test.js b/x-pack/test/functional/apps/watcher/watcher_test.js index 1dd3fb6bbcc3d1..2525f4d8f9621a 100644 --- a/x-pack/test/functional/apps/watcher/watcher_test.js +++ b/x-pack/test/functional/apps/watcher/watcher_test.js @@ -15,16 +15,15 @@ export default function ({ getService, getPageObjects }) { const retry = getService('retry'); const testSubjects = getService('testSubjects'); const log = getService('log'); + const security = getService('security'); const esSupertest = getService('esSupertest'); const PageObjects = getPageObjects(['security', 'common', 'header', 'settings', 'watcher']); - // Still flaky test :c - // https://github.com/elastic/kibana/pull/56361 - // https://github.com/elastic/kibana/pull/56304 - describe.skip('watcher_test', function () { + describe('watcher_test', function () { before('initialize tests', async () => { // There may be system watches if monitoring was previously enabled // These cannot be deleted via the UI, so we need to delete via the API + await security.testUser.setRoles(['kibana_admin', 'watcher_admin'], false); const watches = await esSupertest.get('/.watches/_search'); if (watches.status === 200) { @@ -56,6 +55,10 @@ export default function ({ getService, getPageObjects }) { }); }); + after(async () => { + await security.testUser.restoreDefaults(); + }); + it('create and save a new watch', async () => { await PageObjects.watcher.createWatch(watchID, watchName); const watch = await PageObjects.watcher.getWatch(watchID); From 0b6184769622e1e13c4890c3f7a9711b196e403c Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 26 Jan 2021 14:32:09 -0700 Subject: [PATCH 05/58] [Maps] rename file_upload to maps_file_upload (#89225) * migrate file_upload plugin to maps_file_upload * update plugins list * results of running node scripts/build_plugin_list_docs * fix build problems * remove fileUpload from limits.yml Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- docs/developer/plugin-list.asciidoc | 8 ++++---- packages/kbn-optimizer/limits.yml | 2 +- x-pack/.i18nrc.json | 2 +- x-pack/plugins/file_upload/README.md | 3 --- x-pack/plugins/maps/kibana.json | 2 +- .../public/classes/layers/file_upload_wizard/wizard.tsx | 2 +- x-pack/plugins/maps/public/kibana_services.ts | 2 +- x-pack/plugins/maps/public/plugin.ts | 4 ++-- x-pack/plugins/maps_file_upload/README.md | 3 +++ .../common/constants/file_import.ts | 0 .../{file_upload => maps_file_upload}/jest.config.js | 2 +- .../plugins/{file_upload => maps_file_upload}/kibana.json | 2 +- .../plugins/{file_upload => maps_file_upload}/mappings.ts | 0 .../public/components/index_settings.js | 0 .../public/components/json_import_progress.js | 0 .../public/components/json_index_file_picker.js | 0 .../public/components/json_upload_and_parse.js | 0 .../public/get_file_upload_component.ts | 0 .../{file_upload => maps_file_upload}/public/index.ts | 0 .../public/kibana_services.js | 0 .../{file_upload => maps_file_upload}/public/plugin.ts | 0 .../public/util/file_parser.js | 0 .../public/util/file_parser.test.js | 0 .../public/util/geo_json_clean_and_validate.js | 0 .../public/util/geo_json_clean_and_validate.test.js | 0 .../public/util/geo_processing.js | 0 .../public/util/geo_processing.test.js | 0 .../public/util/http_service.js | 0 .../public/util/indexing_service.js | 0 .../public/util/indexing_service.test.js | 0 .../public/util/size_limited_chunking.js | 0 .../public/util/size_limited_chunking.test.js | 0 .../server/client/errors.js | 0 .../{file_upload => maps_file_upload}/server/index.js | 0 .../server/kibana_server_services.js | 0 .../server/models/import_data/import_data.js | 0 .../server/models/import_data/index.js | 0 .../{file_upload => maps_file_upload}/server/plugin.js | 0 .../server/routes/file_upload.js | 0 .../server/routes/file_upload.test.js | 0 .../server/telemetry/file_upload_usage_collector.ts | 0 .../server/telemetry/index.ts | 0 .../server/telemetry/mappings.ts | 0 .../server/telemetry/telemetry.test.ts | 0 .../server/telemetry/telemetry.ts | 0 45 files changed, 16 insertions(+), 16 deletions(-) delete mode 100644 x-pack/plugins/file_upload/README.md create mode 100644 x-pack/plugins/maps_file_upload/README.md rename x-pack/plugins/{file_upload => maps_file_upload}/common/constants/file_import.ts (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/jest.config.js (84%) rename x-pack/plugins/{file_upload => maps_file_upload}/kibana.json (83%) rename x-pack/plugins/{file_upload => maps_file_upload}/mappings.ts (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/components/index_settings.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/components/json_import_progress.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/components/json_index_file_picker.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/components/json_upload_and_parse.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/get_file_upload_component.ts (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/index.ts (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/kibana_services.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/plugin.ts (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/file_parser.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/file_parser.test.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/geo_json_clean_and_validate.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/geo_json_clean_and_validate.test.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/geo_processing.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/geo_processing.test.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/http_service.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/indexing_service.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/indexing_service.test.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/size_limited_chunking.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/public/util/size_limited_chunking.test.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/client/errors.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/index.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/kibana_server_services.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/models/import_data/import_data.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/models/import_data/index.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/plugin.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/routes/file_upload.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/routes/file_upload.test.js (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/telemetry/file_upload_usage_collector.ts (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/telemetry/index.ts (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/telemetry/mappings.ts (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/telemetry/telemetry.test.ts (100%) rename x-pack/plugins/{file_upload => maps_file_upload}/server/telemetry/telemetry.ts (100%) diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index ef3492a545b6ac..7ce4896a8bce44 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -380,10 +380,6 @@ and actions. |The features plugin enhance Kibana with a per-feature privilege system. -|{kib-repo}blob/{branch}/x-pack/plugins/file_upload/README.md[fileUpload] -|Backend and core front-end react-components for GeoJson file upload. Only supports the Maps plugin. - - |{kib-repo}blob/{branch}/x-pack/plugins/fleet/README.md[fleet] |Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag --xpack.fleet.agents.tlsCheckDisabled=false) @@ -453,6 +449,10 @@ using the CURL scripts in the scripts folder. |Visualize geo data from Elasticsearch or 3rd party geo-services. +|{kib-repo}blob/{branch}/x-pack/plugins/maps_file_upload/README.md[mapsFileUpload] +|Deprecated - plugin targeted for removal and will get merged into file_upload plugin + + |{kib-repo}blob/{branch}/x-pack/plugins/maps_legacy_licensing/README.md[mapsLegacyLicensing] |This plugin provides access to the detailed tile map services from Elastic. diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 44cc4fdabb25e8..ef672d6cbeb2ef 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -25,7 +25,6 @@ pageLoadAssetSize: esUiShared: 326654 expressions: 224136 features: 31211 - fileUpload: 24717 globalSearch: 43548 globalSearchBar: 62888 globalSearchProviders: 25554 @@ -106,3 +105,4 @@ pageLoadAssetSize: stackAlerts: 29684 presentationUtil: 28545 spacesOss: 18817 + mapsFileUpload: 23775 diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 6937862d20536d..bfac437f3500a7 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -20,7 +20,7 @@ "xpack.endpoint": "plugins/endpoint", "xpack.enterpriseSearch": "plugins/enterprise_search", "xpack.features": "plugins/features", - "xpack.fileUpload": "plugins/file_upload", + "xpack.fileUpload": "plugins/maps_file_upload", "xpack.globalSearch": ["plugins/global_search"], "xpack.globalSearchBar": ["plugins/global_search_bar"], "xpack.graph": ["plugins/graph"], diff --git a/x-pack/plugins/file_upload/README.md b/x-pack/plugins/file_upload/README.md deleted file mode 100644 index 0d4b4da61ccf69..00000000000000 --- a/x-pack/plugins/file_upload/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# File upload - -Backend and core front-end react-components for GeoJson file upload. Only supports the Maps plugin. \ No newline at end of file diff --git a/x-pack/plugins/maps/kibana.json b/x-pack/plugins/maps/kibana.json index 42adf6f2a950b0..5f6f5224e32a3c 100644 --- a/x-pack/plugins/maps/kibana.json +++ b/x-pack/plugins/maps/kibana.json @@ -8,7 +8,7 @@ "features", "inspector", "data", - "fileUpload", + "mapsFileUpload", "uiActions", "navigation", "visualizations", diff --git a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx b/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx index 68fd25ce9e7aeb..54e58c876a8398 100644 --- a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx @@ -18,7 +18,7 @@ import { GeoJsonFileSource } from '../../sources/geojson_file_source'; import { VectorLayer } from '../../layers/vector_layer/vector_layer'; import { createDefaultLayerDescriptor } from '../../sources/es_search_source'; import { RenderWizardArguments } from '../../layers/layer_wizard_registry'; -import { FileUploadComponentProps } from '../../../../../file_upload/public'; +import { FileUploadComponentProps } from '../../../../../maps_file_upload/public'; export const INDEX_SETUP_STEP_ID = 'INDEX_SETUP_STEP_ID'; export const INDEXING_STEP_ID = 'INDEXING_STEP_ID'; diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index 02b875257a5ac2..99c9311a2a4548 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -25,7 +25,7 @@ export const getIndexPatternService = () => pluginsStart.data.indexPatterns; export const getAutocompleteService = () => pluginsStart.data.autocomplete; export const getInspector = () => pluginsStart.inspector; export const getFileUploadComponent = async () => { - return await pluginsStart.fileUpload.getFileUploadComponent(); + return await pluginsStart.mapsFileUpload.getFileUploadComponent(); }; export const getUiSettings = () => coreStart.uiSettings; export const getIsDarkMode = () => getUiSettings().get('theme:darkMode', false); diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 690002a771601c..dd256126fae62c 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -54,7 +54,7 @@ import { EmbeddableStart } from '../../../../src/plugins/embeddable/public'; import { MapsLegacyConfig } from '../../../../src/plugins/maps_legacy/config'; import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; import { LicensingPluginSetup, LicensingPluginStart } from '../../licensing/public'; -import { StartContract as FileUploadStartContract } from '../../file_upload/public'; +import { StartContract as FileUploadStartContract } from '../../maps_file_upload/public'; import { SavedObjectsStart } from '../../../../src/plugins/saved_objects/public'; import { getIsEnterprisePlus, @@ -77,7 +77,7 @@ export interface MapsPluginSetupDependencies { export interface MapsPluginStartDependencies { data: DataPublicPluginStart; embeddable: EmbeddableStart; - fileUpload: FileUploadStartContract; + mapsFileUpload: FileUploadStartContract; inspector: InspectorStartContract; licensing: LicensingPluginStart; navigation: NavigationPublicPluginStart; diff --git a/x-pack/plugins/maps_file_upload/README.md b/x-pack/plugins/maps_file_upload/README.md new file mode 100644 index 00000000000000..1e3343664afb83 --- /dev/null +++ b/x-pack/plugins/maps_file_upload/README.md @@ -0,0 +1,3 @@ +# Maps File upload + +Deprecated - plugin targeted for removal and will get merged into file_upload plugin diff --git a/x-pack/plugins/file_upload/common/constants/file_import.ts b/x-pack/plugins/maps_file_upload/common/constants/file_import.ts similarity index 100% rename from x-pack/plugins/file_upload/common/constants/file_import.ts rename to x-pack/plugins/maps_file_upload/common/constants/file_import.ts diff --git a/x-pack/plugins/file_upload/jest.config.js b/x-pack/plugins/maps_file_upload/jest.config.js similarity index 84% rename from x-pack/plugins/file_upload/jest.config.js rename to x-pack/plugins/maps_file_upload/jest.config.js index 6a042a4cc5c1e1..2893da079141cd 100644 --- a/x-pack/plugins/file_upload/jest.config.js +++ b/x-pack/plugins/maps_file_upload/jest.config.js @@ -7,5 +7,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../..', - roots: ['/x-pack/plugins/file_upload'], + roots: ['/x-pack/plugins/maps_file_upload'], }; diff --git a/x-pack/plugins/file_upload/kibana.json b/x-pack/plugins/maps_file_upload/kibana.json similarity index 83% rename from x-pack/plugins/file_upload/kibana.json rename to x-pack/plugins/maps_file_upload/kibana.json index 7676a01d0b0f96..f544c56cba517e 100644 --- a/x-pack/plugins/file_upload/kibana.json +++ b/x-pack/plugins/maps_file_upload/kibana.json @@ -1,5 +1,5 @@ { - "id": "fileUpload", + "id": "mapsFileUpload", "version": "8.0.0", "kibanaVersion": "kibana", "server": true, diff --git a/x-pack/plugins/file_upload/mappings.ts b/x-pack/plugins/maps_file_upload/mappings.ts similarity index 100% rename from x-pack/plugins/file_upload/mappings.ts rename to x-pack/plugins/maps_file_upload/mappings.ts diff --git a/x-pack/plugins/file_upload/public/components/index_settings.js b/x-pack/plugins/maps_file_upload/public/components/index_settings.js similarity index 100% rename from x-pack/plugins/file_upload/public/components/index_settings.js rename to x-pack/plugins/maps_file_upload/public/components/index_settings.js diff --git a/x-pack/plugins/file_upload/public/components/json_import_progress.js b/x-pack/plugins/maps_file_upload/public/components/json_import_progress.js similarity index 100% rename from x-pack/plugins/file_upload/public/components/json_import_progress.js rename to x-pack/plugins/maps_file_upload/public/components/json_import_progress.js diff --git a/x-pack/plugins/file_upload/public/components/json_index_file_picker.js b/x-pack/plugins/maps_file_upload/public/components/json_index_file_picker.js similarity index 100% rename from x-pack/plugins/file_upload/public/components/json_index_file_picker.js rename to x-pack/plugins/maps_file_upload/public/components/json_index_file_picker.js diff --git a/x-pack/plugins/file_upload/public/components/json_upload_and_parse.js b/x-pack/plugins/maps_file_upload/public/components/json_upload_and_parse.js similarity index 100% rename from x-pack/plugins/file_upload/public/components/json_upload_and_parse.js rename to x-pack/plugins/maps_file_upload/public/components/json_upload_and_parse.js diff --git a/x-pack/plugins/file_upload/public/get_file_upload_component.ts b/x-pack/plugins/maps_file_upload/public/get_file_upload_component.ts similarity index 100% rename from x-pack/plugins/file_upload/public/get_file_upload_component.ts rename to x-pack/plugins/maps_file_upload/public/get_file_upload_component.ts diff --git a/x-pack/plugins/file_upload/public/index.ts b/x-pack/plugins/maps_file_upload/public/index.ts similarity index 100% rename from x-pack/plugins/file_upload/public/index.ts rename to x-pack/plugins/maps_file_upload/public/index.ts diff --git a/x-pack/plugins/file_upload/public/kibana_services.js b/x-pack/plugins/maps_file_upload/public/kibana_services.js similarity index 100% rename from x-pack/plugins/file_upload/public/kibana_services.js rename to x-pack/plugins/maps_file_upload/public/kibana_services.js diff --git a/x-pack/plugins/file_upload/public/plugin.ts b/x-pack/plugins/maps_file_upload/public/plugin.ts similarity index 100% rename from x-pack/plugins/file_upload/public/plugin.ts rename to x-pack/plugins/maps_file_upload/public/plugin.ts diff --git a/x-pack/plugins/file_upload/public/util/file_parser.js b/x-pack/plugins/maps_file_upload/public/util/file_parser.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/file_parser.js rename to x-pack/plugins/maps_file_upload/public/util/file_parser.js diff --git a/x-pack/plugins/file_upload/public/util/file_parser.test.js b/x-pack/plugins/maps_file_upload/public/util/file_parser.test.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/file_parser.test.js rename to x-pack/plugins/maps_file_upload/public/util/file_parser.test.js diff --git a/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.js b/x-pack/plugins/maps_file_upload/public/util/geo_json_clean_and_validate.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.js rename to x-pack/plugins/maps_file_upload/public/util/geo_json_clean_and_validate.js diff --git a/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.test.js b/x-pack/plugins/maps_file_upload/public/util/geo_json_clean_and_validate.test.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.test.js rename to x-pack/plugins/maps_file_upload/public/util/geo_json_clean_and_validate.test.js diff --git a/x-pack/plugins/file_upload/public/util/geo_processing.js b/x-pack/plugins/maps_file_upload/public/util/geo_processing.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/geo_processing.js rename to x-pack/plugins/maps_file_upload/public/util/geo_processing.js diff --git a/x-pack/plugins/file_upload/public/util/geo_processing.test.js b/x-pack/plugins/maps_file_upload/public/util/geo_processing.test.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/geo_processing.test.js rename to x-pack/plugins/maps_file_upload/public/util/geo_processing.test.js diff --git a/x-pack/plugins/file_upload/public/util/http_service.js b/x-pack/plugins/maps_file_upload/public/util/http_service.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/http_service.js rename to x-pack/plugins/maps_file_upload/public/util/http_service.js diff --git a/x-pack/plugins/file_upload/public/util/indexing_service.js b/x-pack/plugins/maps_file_upload/public/util/indexing_service.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/indexing_service.js rename to x-pack/plugins/maps_file_upload/public/util/indexing_service.js diff --git a/x-pack/plugins/file_upload/public/util/indexing_service.test.js b/x-pack/plugins/maps_file_upload/public/util/indexing_service.test.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/indexing_service.test.js rename to x-pack/plugins/maps_file_upload/public/util/indexing_service.test.js diff --git a/x-pack/plugins/file_upload/public/util/size_limited_chunking.js b/x-pack/plugins/maps_file_upload/public/util/size_limited_chunking.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/size_limited_chunking.js rename to x-pack/plugins/maps_file_upload/public/util/size_limited_chunking.js diff --git a/x-pack/plugins/file_upload/public/util/size_limited_chunking.test.js b/x-pack/plugins/maps_file_upload/public/util/size_limited_chunking.test.js similarity index 100% rename from x-pack/plugins/file_upload/public/util/size_limited_chunking.test.js rename to x-pack/plugins/maps_file_upload/public/util/size_limited_chunking.test.js diff --git a/x-pack/plugins/file_upload/server/client/errors.js b/x-pack/plugins/maps_file_upload/server/client/errors.js similarity index 100% rename from x-pack/plugins/file_upload/server/client/errors.js rename to x-pack/plugins/maps_file_upload/server/client/errors.js diff --git a/x-pack/plugins/file_upload/server/index.js b/x-pack/plugins/maps_file_upload/server/index.js similarity index 100% rename from x-pack/plugins/file_upload/server/index.js rename to x-pack/plugins/maps_file_upload/server/index.js diff --git a/x-pack/plugins/file_upload/server/kibana_server_services.js b/x-pack/plugins/maps_file_upload/server/kibana_server_services.js similarity index 100% rename from x-pack/plugins/file_upload/server/kibana_server_services.js rename to x-pack/plugins/maps_file_upload/server/kibana_server_services.js diff --git a/x-pack/plugins/file_upload/server/models/import_data/import_data.js b/x-pack/plugins/maps_file_upload/server/models/import_data/import_data.js similarity index 100% rename from x-pack/plugins/file_upload/server/models/import_data/import_data.js rename to x-pack/plugins/maps_file_upload/server/models/import_data/import_data.js diff --git a/x-pack/plugins/file_upload/server/models/import_data/index.js b/x-pack/plugins/maps_file_upload/server/models/import_data/index.js similarity index 100% rename from x-pack/plugins/file_upload/server/models/import_data/index.js rename to x-pack/plugins/maps_file_upload/server/models/import_data/index.js diff --git a/x-pack/plugins/file_upload/server/plugin.js b/x-pack/plugins/maps_file_upload/server/plugin.js similarity index 100% rename from x-pack/plugins/file_upload/server/plugin.js rename to x-pack/plugins/maps_file_upload/server/plugin.js diff --git a/x-pack/plugins/file_upload/server/routes/file_upload.js b/x-pack/plugins/maps_file_upload/server/routes/file_upload.js similarity index 100% rename from x-pack/plugins/file_upload/server/routes/file_upload.js rename to x-pack/plugins/maps_file_upload/server/routes/file_upload.js diff --git a/x-pack/plugins/file_upload/server/routes/file_upload.test.js b/x-pack/plugins/maps_file_upload/server/routes/file_upload.test.js similarity index 100% rename from x-pack/plugins/file_upload/server/routes/file_upload.test.js rename to x-pack/plugins/maps_file_upload/server/routes/file_upload.test.js diff --git a/x-pack/plugins/file_upload/server/telemetry/file_upload_usage_collector.ts b/x-pack/plugins/maps_file_upload/server/telemetry/file_upload_usage_collector.ts similarity index 100% rename from x-pack/plugins/file_upload/server/telemetry/file_upload_usage_collector.ts rename to x-pack/plugins/maps_file_upload/server/telemetry/file_upload_usage_collector.ts diff --git a/x-pack/plugins/file_upload/server/telemetry/index.ts b/x-pack/plugins/maps_file_upload/server/telemetry/index.ts similarity index 100% rename from x-pack/plugins/file_upload/server/telemetry/index.ts rename to x-pack/plugins/maps_file_upload/server/telemetry/index.ts diff --git a/x-pack/plugins/file_upload/server/telemetry/mappings.ts b/x-pack/plugins/maps_file_upload/server/telemetry/mappings.ts similarity index 100% rename from x-pack/plugins/file_upload/server/telemetry/mappings.ts rename to x-pack/plugins/maps_file_upload/server/telemetry/mappings.ts diff --git a/x-pack/plugins/file_upload/server/telemetry/telemetry.test.ts b/x-pack/plugins/maps_file_upload/server/telemetry/telemetry.test.ts similarity index 100% rename from x-pack/plugins/file_upload/server/telemetry/telemetry.test.ts rename to x-pack/plugins/maps_file_upload/server/telemetry/telemetry.test.ts diff --git a/x-pack/plugins/file_upload/server/telemetry/telemetry.ts b/x-pack/plugins/maps_file_upload/server/telemetry/telemetry.ts similarity index 100% rename from x-pack/plugins/file_upload/server/telemetry/telemetry.ts rename to x-pack/plugins/maps_file_upload/server/telemetry/telemetry.ts From 46285b2257c5ad11add7412e4145d842e3f91b83 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 26 Jan 2021 22:34:43 +0100 Subject: [PATCH 06/58] [ILM] Timeline component (#88024) * cleaning up unused types and legacy logic * added new relative age logic with unit tests * initial implementation of timeline * added custom infinity icon to timeline component * added comment * move timeline color bar comment * fix nanoseconds and microsecnds bug * added policy timeline heading, removed "at least" copy for now * a few minor changes - fix up copy - fix up responsive/mobile first view of timeline - adjust minimum size of a color bar * minor refactor to css classnames and make trash can for delete more prominent * added delete icon tooltip with rough first copy * added smoke test for timeline and how it interacts with different policy states * update test and copy * convert string svg to react svg component and use euiIcon class and refactor scss * update delete icon tooltip copy and add aria-label to svg * mock EuiIcon component in jest tests because it causes issues with custom react-svg component * added comment to mock * remove setting of classname * fix typo and update delete icon tooltip content * refinements to the delete icon at the end of the timline and support dark mode Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../client_integration/app/app.test.ts | 9 + .../edit_policy/edit_policy.helpers.tsx | 7 + .../edit_policy/edit_policy.test.ts | 46 ++++ .../__jest__/components/edit_policy.test.tsx | 9 + .../common/types/policies.ts | 2 + .../sections/edit_policy/components/index.ts | 1 + .../edit_policy/components/timeline/index.ts | 6 + .../components/timeline/infinity_icon.svg.tsx | 26 +++ .../components/timeline/timeline.scss | 87 ++++++++ .../components/timeline/timeline.tsx | 208 ++++++++++++++++++ .../sections/edit_policy/edit_policy.tsx | 7 +- 11 files changed, 407 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/index.ts create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/infinity_icon.svg.tsx create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.scss create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.tsx diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts index 9052cf2847baae..1ffbae39d37050 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts @@ -23,6 +23,15 @@ const PERCENT_SIGN_25_SEQUENCE = 'test%25'; window.scrollTo = jest.fn(); +jest.mock('@elastic/eui', () => { + const original = jest.requireActual('@elastic/eui'); + + return { + ...original, + EuiIcon: 'eui-icon', // using custom react-svg icon causes issues, mocking for now. + }; +}); + describe('', () => { let testBed: AppTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx index 7206fbfd547d4d..72a0372628a223 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx @@ -41,6 +41,7 @@ jest.mock('@elastic/eui', () => { }} /> ), + EuiIcon: 'eui-icon', // using custom react-svg icon causes issues, mocking for now. }; }); @@ -236,6 +237,12 @@ export const setup = async (arg?: { appServicesContext: Partial exists('ilmTimelineHotPhase'), + hasWarmPhase: () => exists('ilmTimelineWarmPhase'), + hasColdPhase: () => exists('ilmTimelineColdPhase'), + hasDeletePhase: () => exists('ilmTimelineDeletePhase'), + }, hot: { setMaxSize, setMaxDocs, diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts index ff070a7f08bb1c..e42e503fb853a9 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts @@ -824,4 +824,50 @@ describe('', () => { expect(actions.cold.searchableSnapshotDisabledDueToRollover()).toBeTruthy(); }); }); + + describe('policy timeline', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]); + httpRequestsMockHelpers.setListNodes({ + nodesByRoles: {}, + nodesByAttributes: { test: ['123'] }, + isUsingDeprecatedDataRoleConfig: false, + }); + httpRequestsMockHelpers.setLoadSnapshotPolicies([]); + + await act(async () => { + testBed = await setup(); + }); + + const { component } = testBed; + component.update(); + }); + + test('showing all phases on the timeline', async () => { + const { actions } = testBed; + // This is how the default policy should look + expect(actions.timeline.hasHotPhase()).toBe(true); + expect(actions.timeline.hasWarmPhase()).toBe(false); + expect(actions.timeline.hasColdPhase()).toBe(false); + expect(actions.timeline.hasDeletePhase()).toBe(false); + + await actions.warm.enable(true); + expect(actions.timeline.hasHotPhase()).toBe(true); + expect(actions.timeline.hasWarmPhase()).toBe(true); + expect(actions.timeline.hasColdPhase()).toBe(false); + expect(actions.timeline.hasDeletePhase()).toBe(false); + + await actions.cold.enable(true); + expect(actions.timeline.hasHotPhase()).toBe(true); + expect(actions.timeline.hasWarmPhase()).toBe(true); + expect(actions.timeline.hasColdPhase()).toBe(true); + expect(actions.timeline.hasDeletePhase()).toBe(false); + + await actions.delete.enable(true); + expect(actions.timeline.hasHotPhase()).toBe(true); + expect(actions.timeline.hasWarmPhase()).toBe(true); + expect(actions.timeline.hasColdPhase()).toBe(true); + expect(actions.timeline.hasDeletePhase()).toBe(true); + }); + }); }); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx index c54ccb9f85edfb..6aa6c3177ca5dd 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx @@ -81,6 +81,15 @@ for (let i = 0; i < 105; i++) { } window.scrollTo = jest.fn(); +jest.mock('@elastic/eui', () => { + const original = jest.requireActual('@elastic/eui'); + + return { + ...original, + EuiIcon: 'eui-icon', // using custom react-svg icon causes issues, mocking for now. + }; +}); + let component: ReactElement; const activatePhase = async (rendered: ReactWrapper, phase: string) => { const testSubject = `enablePhaseSwitch-${phase}`; diff --git a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts index 1f4b06e80c49f2..a084f16226fda6 100644 --- a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts +++ b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts @@ -20,6 +20,8 @@ export interface Phases { delete?: SerializedDeletePhase; } +export type PhasesExceptDelete = keyof Omit; + export interface PolicyFromES { modified_date: string; name: string; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts index fa550214db4770..d22206d7ae4de1 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts @@ -11,5 +11,6 @@ export { OptionalLabel } from './optional_label'; export { PolicyJsonFlyout } from './policy_json_flyout'; export { DescribedFormRow, ToggleFieldWithDescribedFormRow } from './described_form_row'; export { FieldLoadingError } from './field_loading_error'; +export { Timeline } from './timeline'; export * from './phases'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/index.ts new file mode 100644 index 00000000000000..4664429db37d7c --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/index.ts @@ -0,0 +1,6 @@ +/* + * 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 { Timeline } from './timeline'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/infinity_icon.svg.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/infinity_icon.svg.tsx new file mode 100644 index 00000000000000..b3b1b3cc56b3d0 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/infinity_icon.svg.tsx @@ -0,0 +1,26 @@ +/* + * 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, { FunctionComponent } from 'react'; + +export const InfinityIconSvg: FunctionComponent = (props) => { + return ( + + ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.scss b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.scss new file mode 100644 index 00000000000000..452221a29a9913 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.scss @@ -0,0 +1,87 @@ +$ilmTimelineBarHeight: $euiSizeS; + +/* +* For theming we need to shade or tint to get the right color from the base EUI color +*/ +$ilmDeletePhaseBackgroundColor: tintOrShade($euiColorVis5_behindText, 80%,80%); +$ilmDeletePhaseColor: shadeOrTint($euiColorVis5, 40%, 40%); + +.ilmTimeline { + overflow: hidden; + width: 100%; + + &__phasesContainer { + /* + * Let the delete icon sit on the same line as the phase color bars + */ + display: inline-block; + width: 100%; + + &__phase:first-child { + padding-left: 0; + padding-right: $euiSizeS; + } + + &__phase:last-child { + padding-left: $euiSizeS; + padding-right: 0; + } + + &__phase:only-child { + padding-left: 0; + padding-right: 0; + } + + &__phase { + /* + * Let the phase color bars sit horizontally + */ + display: inline-block; + + padding-left: $euiSizeS; + padding-right: $euiSizeS; + } + } + + &__deleteIconContainer { + /* + * Create a bit of space between the timeline and the delete icon + */ + padding: $euiSizeM; + margin-left: $euiSizeM; + background-color: $ilmDeletePhaseBackgroundColor; + color: $ilmDeletePhaseColor; + border-radius: calc(#{$euiSizeS} / 2); + } + + &__colorBar { + display: inline-block; + height: $ilmTimelineBarHeight; + border-radius: calc(#{$ilmTimelineBarHeight} / 2); + width: 100%; + } + + &__hotPhase { + width: var(--ilm-timeline-hot-phase-width); + + &__colorBar { + background-color: $euiColorVis9; + } + } + + &__warmPhase { + width: var(--ilm-timeline-warm-phase-width); + + &__colorBar { + background-color: $euiColorVis5; + } + } + + &__coldPhase { + width: var(--ilm-timeline-cold-phase-width); + + &__colorBar { + background-color: $euiColorVis1; + } + } +} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.tsx new file mode 100644 index 00000000000000..40bab9c676de20 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.tsx @@ -0,0 +1,208 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { i18n } from '@kbn/i18n'; +import React, { FunctionComponent, useMemo } from 'react'; +import { + EuiText, + EuiIcon, + EuiIconProps, + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiIconTip, +} from '@elastic/eui'; + +import { PhasesExceptDelete } from '../../../../../../common/types'; +import { useFormData } from '../../../../../shared_imports'; + +import { FormInternal } from '../../types'; + +import { + calculateRelativeTimingMs, + normalizeTimingsToHumanReadable, + PhaseAgeInMilliseconds, +} from '../../lib'; + +import './timeline.scss'; +import { InfinityIconSvg } from './infinity_icon.svg'; + +const InfinityIcon: FunctionComponent> = (props) => ( + +); + +const toPercent = (n: number, total: number) => (n / total) * 100; + +const msTimeToOverallPercent = (ms: number, totalMs: number) => { + if (!isFinite(ms)) { + return 100; + } + if (totalMs === 0) { + return 100; + } + return toPercent(ms, totalMs); +}; + +/** + * Each phase, if active, should have a minimum width it occupies. The higher this + * base amount, the smaller the variance in phase size in the timeline. This functions + * as a min-width constraint. + */ +const SCORE_BUFFER_AMOUNT = 50; + +const i18nTexts = { + hotPhase: i18n.translate('xpack.indexLifecycleMgmt.timeline.hotPhaseSectionTitle', { + defaultMessage: 'Hot phase', + }), + warmPhase: i18n.translate('xpack.indexLifecycleMgmt.timeline.warmPhaseSectionTitle', { + defaultMessage: 'Warm phase', + }), + coldPhase: i18n.translate('xpack.indexLifecycleMgmt.timeline.coldPhaseSectionTitle', { + defaultMessage: 'Cold phase', + }), + deleteIcon: { + toolTipContent: i18n.translate('xpack.indexLifecycleMgmt.timeline.deleteIconToolTipContent', { + defaultMessage: 'Policy deletes the index after lifecycle phases complete.', + }), + }, +}; + +const calculateWidths = (inputs: PhaseAgeInMilliseconds) => { + const hotScore = msTimeToOverallPercent(inputs.phases.hot, inputs.total) + SCORE_BUFFER_AMOUNT; + const warmScore = + inputs.phases.warm != null + ? msTimeToOverallPercent(inputs.phases.warm, inputs.total) + SCORE_BUFFER_AMOUNT + : 0; + const coldScore = + inputs.phases.cold != null + ? msTimeToOverallPercent(inputs.phases.cold, inputs.total) + SCORE_BUFFER_AMOUNT + : 0; + + const totalScore = hotScore + warmScore + coldScore; + return { + hot: `${toPercent(hotScore, totalScore)}%`, + warm: `${toPercent(warmScore, totalScore)}%`, + cold: `${toPercent(coldScore, totalScore)}%`, + }; +}; + +const TimelinePhaseText: FunctionComponent<{ + phaseName: string; + durationInPhase?: React.ReactNode | string; +}> = ({ phaseName, durationInPhase }) => ( + + + + {phaseName} + + + + {typeof durationInPhase === 'string' ? ( + {durationInPhase} + ) : ( + durationInPhase + )} + + +); + +export const Timeline: FunctionComponent = () => { + const [formData] = useFormData(); + + const phaseTimingInMs = useMemo(() => { + return calculateRelativeTimingMs(formData); + }, [formData]); + + const humanReadableTimings = useMemo(() => normalizeTimingsToHumanReadable(phaseTimingInMs), [ + phaseTimingInMs, + ]); + + const widths = calculateWidths(phaseTimingInMs); + + const getDurationInPhaseContent = (phase: PhasesExceptDelete): string | React.ReactNode => + phaseTimingInMs.phases[phase] === Infinity ? ( + + ) : ( + humanReadableTimings[phase] + ); + + return ( + + + +

+ {i18n.translate('xpack.indexLifecycleMgmt.timeline.title', { + defaultMessage: 'Policy Timeline', + })} +

+
+
+ +
{ + if (el) { + el.style.setProperty('--ilm-timeline-hot-phase-width', widths.hot); + el.style.setProperty('--ilm-timeline-warm-phase-width', widths.warm ?? null); + el.style.setProperty('--ilm-timeline-cold-phase-width', widths.cold ?? null); + } + }} + > + + +
+ {/* These are the actual color bars for the timeline */} +
+
+ +
+ {formData._meta?.warm.enabled && ( +
+
+ +
+ )} + {formData._meta?.cold.enabled && ( +
+
+ +
+ )} +
+ + {formData._meta?.delete.enabled && ( + +
+ +
+
+ )} + +
+ + + ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx index d945ae8bb3e4e7..228a0f9fdb942d 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx @@ -43,6 +43,7 @@ import { DeletePhase, HotPhase, WarmPhase, + Timeline, } from './components'; import { schema, deserializer, createSerializer, createPolicyNameValidations, Form } from './form'; @@ -256,7 +257,11 @@ export const EditPolicy: React.FunctionComponent = ({ history }) => { ) : null} - + + + + + From 1e7b6f0ec25974641f3d8e96f5257ba8c518d515 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 26 Jan 2021 13:42:27 -0800 Subject: [PATCH 07/58] skip flaky suite (#88826) --- test/functional/apps/home/_navigation.ts | 80 +++++++++++++----------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/test/functional/apps/home/_navigation.ts b/test/functional/apps/home/_navigation.ts index c90398fa84afca..90d13b4b5e4171 100644 --- a/test/functional/apps/home/_navigation.ts +++ b/test/functional/apps/home/_navigation.ts @@ -15,42 +15,46 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const appsMenu = getService('appsMenu'); const esArchiver = getService('esArchiver'); - describe('Kibana browser back navigation should work', function describeIndexTests() { - before(async () => { - await esArchiver.loadIfNeeded('discover'); - await esArchiver.loadIfNeeded('logstash_functional'); - }); - - it('detect navigate back issues', async () => { - let currUrl; - // Detects bug described in issue #31238 - where back navigation would get stuck to URL encoding handling in Angular. - // Navigate to home app - await PageObjects.common.navigateToApp('home'); - const homeUrl = await browser.getCurrentUrl(); - - // Navigate to discover app - await appsMenu.clickLink('Discover'); - const discoverUrl = await browser.getCurrentUrl(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - const modifiedTimeDiscoverUrl = await browser.getCurrentUrl(); - - // Navigate to dashboard app - await appsMenu.clickLink('Dashboard'); - - // Navigating back to discover - await browser.goBack(); - currUrl = await browser.getCurrentUrl(); - expect(currUrl).to.be(modifiedTimeDiscoverUrl); - - // Navigating back from time settings - await browser.goBack(); // undo time settings - currUrl = await browser.getCurrentUrl(); - expect(currUrl.startsWith(discoverUrl)).to.be(true); - - // Navigate back home - await browser.goBack(); - currUrl = await browser.getCurrentUrl(); - expect(currUrl).to.be(homeUrl); - }); - }); + // Failing: See https://github.com/elastic/kibana/issues/88826 + describe.skip( + 'Kibana browser back navigation should work', + function describeIndexTests() { + before(async () => { + await esArchiver.loadIfNeeded('discover'); + await esArchiver.loadIfNeeded('logstash_functional'); + }); + + it('detect navigate back issues', async () => { + let currUrl; + // Detects bug described in issue #31238 - where back navigation would get stuck to URL encoding handling in Angular. + // Navigate to home app + await PageObjects.common.navigateToApp('home'); + const homeUrl = await browser.getCurrentUrl(); + + // Navigate to discover app + await appsMenu.clickLink('Discover'); + const discoverUrl = await browser.getCurrentUrl(); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + const modifiedTimeDiscoverUrl = await browser.getCurrentUrl(); + + // Navigate to dashboard app + await appsMenu.clickLink('Dashboard'); + + // Navigating back to discover + await browser.goBack(); + currUrl = await browser.getCurrentUrl(); + expect(currUrl).to.be(modifiedTimeDiscoverUrl); + + // Navigating back from time settings + await browser.goBack(); // undo time settings + currUrl = await browser.getCurrentUrl(); + expect(currUrl.startsWith(discoverUrl)).to.be(true); + + // Navigate back home + await browser.goBack(); + currUrl = await browser.getCurrentUrl(); + expect(currUrl).to.be(homeUrl); + }); + } + ); } From 2a9a9305ee4cf6b79b917ff6c8d76575af739aff Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 26 Jan 2021 14:14:08 -0800 Subject: [PATCH 08/58] Fixes linting caused by skipping flaky suite Signed-off-by: Tyler Smalley --- test/functional/apps/home/_navigation.ts | 79 ++++++++++++------------ 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/test/functional/apps/home/_navigation.ts b/test/functional/apps/home/_navigation.ts index 90d13b4b5e4171..12f97a53494192 100644 --- a/test/functional/apps/home/_navigation.ts +++ b/test/functional/apps/home/_navigation.ts @@ -16,45 +16,42 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); // Failing: See https://github.com/elastic/kibana/issues/88826 - describe.skip( - 'Kibana browser back navigation should work', - function describeIndexTests() { - before(async () => { - await esArchiver.loadIfNeeded('discover'); - await esArchiver.loadIfNeeded('logstash_functional'); - }); - - it('detect navigate back issues', async () => { - let currUrl; - // Detects bug described in issue #31238 - where back navigation would get stuck to URL encoding handling in Angular. - // Navigate to home app - await PageObjects.common.navigateToApp('home'); - const homeUrl = await browser.getCurrentUrl(); - - // Navigate to discover app - await appsMenu.clickLink('Discover'); - const discoverUrl = await browser.getCurrentUrl(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - const modifiedTimeDiscoverUrl = await browser.getCurrentUrl(); - - // Navigate to dashboard app - await appsMenu.clickLink('Dashboard'); - - // Navigating back to discover - await browser.goBack(); - currUrl = await browser.getCurrentUrl(); - expect(currUrl).to.be(modifiedTimeDiscoverUrl); - - // Navigating back from time settings - await browser.goBack(); // undo time settings - currUrl = await browser.getCurrentUrl(); - expect(currUrl.startsWith(discoverUrl)).to.be(true); - - // Navigate back home - await browser.goBack(); - currUrl = await browser.getCurrentUrl(); - expect(currUrl).to.be(homeUrl); - }); - } - ); + describe.skip('Kibana browser back navigation should work', function describeIndexTests() { + before(async () => { + await esArchiver.loadIfNeeded('discover'); + await esArchiver.loadIfNeeded('logstash_functional'); + }); + + it('detect navigate back issues', async () => { + let currUrl; + // Detects bug described in issue #31238 - where back navigation would get stuck to URL encoding handling in Angular. + // Navigate to home app + await PageObjects.common.navigateToApp('home'); + const homeUrl = await browser.getCurrentUrl(); + + // Navigate to discover app + await appsMenu.clickLink('Discover'); + const discoverUrl = await browser.getCurrentUrl(); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + const modifiedTimeDiscoverUrl = await browser.getCurrentUrl(); + + // Navigate to dashboard app + await appsMenu.clickLink('Dashboard'); + + // Navigating back to discover + await browser.goBack(); + currUrl = await browser.getCurrentUrl(); + expect(currUrl).to.be(modifiedTimeDiscoverUrl); + + // Navigating back from time settings + await browser.goBack(); // undo time settings + currUrl = await browser.getCurrentUrl(); + expect(currUrl.startsWith(discoverUrl)).to.be(true); + + // Navigate back home + await browser.goBack(); + currUrl = await browser.getCurrentUrl(); + expect(currUrl).to.be(homeUrl); + }); + }); } From 20f32d506fd72f567eda678c90a67a4ff9e75f2c Mon Sep 17 00:00:00 2001 From: Rashmi Kulkarni Date: Tue, 26 Jan 2021 14:20:42 -0800 Subject: [PATCH 09/58] JSON Body payload for the webhook connector in Alerts & Actions (#89253) * fixes https://github.com/elastic/kibana/issues/74449 Co-authored-by: Patrick Mueller --- docs/user/alerting/action-types/webhook.asciidoc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/user/alerting/action-types/webhook.asciidoc b/docs/user/alerting/action-types/webhook.asciidoc index 659c3afad6bd1c..fff6814325ea45 100644 --- a/docs/user/alerting/action-types/webhook.asciidoc +++ b/docs/user/alerting/action-types/webhook.asciidoc @@ -72,4 +72,17 @@ Password:: An optional password. If set, HTTP basic authentication is used. Cur Webhook actions have the following properties: -Body:: A json payload sent to the request URL. +Body:: A JSON payload sent to the request URL. For example: ++ +[source,text] +-- +{ + "short_description": "{{context.rule.name}}", + "description": "{{context.rule.description}}", + ... +} +-- + +Mustache template variables (the text enclosed in double braces, for example, `context.rule.name`) have +their values escaped, so that the final JSON will be valid (escaping double quote characters). +For more information on Mustache template variables, refer to <>. From b5b9cee1584997a480d6a2a2b5edafcf3fcf9976 Mon Sep 17 00:00:00 2001 From: Justin Ibarra Date: Tue, 26 Jan 2021 13:43:05 -0900 Subject: [PATCH 10/58] Update security solution generic timeline templates (#89239) * Update security solution generic timeline templates --- .../rules/prepackaged_timelines/endpoint.json | 2 +- .../rules/prepackaged_timelines/index.ndjson | 6 +++--- .../rules/prepackaged_timelines/network.json | 2 +- .../rules/prepackaged_timelines/process.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/endpoint.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/endpoint.json index 711050e1f136a8..acc5f693587980 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/endpoint.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/endpoint.json @@ -1 +1 @@ -{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"event.action","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.name","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The working directory of the process.","columnHeaderType":"not-filtered","id":"process.working_directory","category":"process","type":"string","searchable":null,"example":"/home/alice"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Absolute path to the process executable.","columnHeaderType":"not-filtered","id":"process.parent.executable","category":"process","type":"string","searchable":null,"example":"/usr/bin/ssh"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.parent.args","category":"process","type":"string","searchable":null,"example":"[\"ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"aggregatable":true,"name":null,"description":"Process id.","columnHeaderType":"not-filtered","id":"process.parent.pid","category":"process","type":"number","searchable":null,"example":"4242"},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"aggregatable":true,"name":null,"description":"Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.","columnHeaderType":"not-filtered","id":"host.name","category":"host","type":"string","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"{process.name}","queryMatch":{"displayValue":"{agent.type}","field":"agent.type","displayField":"agent.type","value":"{agent.type}","operator":":*"},"id":"timeline-1-8622010a-61fb-490d-b162-beac9c36a853","type":"template","enabled":true},{"excluded":false,"and":[],"kqlQuery":"","name":"","queryMatch":{"displayValue":"endpoint","field":"agent.type","displayField":"agent.type","value":"endpoint","operator":":"},"id":"timeline-1-4685da24-35c1-43f3-892d-1f926dbf5568","type":"default","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Endpoint Timeline","timelineType":"template","templateTimelineVersion":1,"templateTimelineId":"db366523-f1c6-4c1f-8731-6ce5ed9e5717","dateRange":{"start":1588161020848,"end":1588162280848},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735857110,"createdBy":"Elastic","updated":1594736314036,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} +{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"event.action","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.name","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The working directory of the process.","columnHeaderType":"not-filtered","id":"process.working_directory","category":"process","type":"string","searchable":null,"example":"/home/alice"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Absolute path to the process executable.","columnHeaderType":"not-filtered","id":"process.parent.executable","category":"process","type":"string","searchable":null,"example":"/usr/bin/ssh"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.parent.args","category":"process","type":"string","searchable":null,"example":"[\"ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"aggregatable":true,"name":null,"description":"Process id.","columnHeaderType":"not-filtered","id":"process.parent.pid","category":"process","type":"number","searchable":null,"example":"4242"},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"aggregatable":true,"name":null,"description":"Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.","columnHeaderType":"not-filtered","id":"host.name","category":"host","type":"string","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"","queryMatch":{"displayValue":"endpoint","field":"agent.type","displayField":"agent.type","value":"endpoint","operator":":"},"id":"timeline-1-4685da24-35c1-43f3-892d-1f926dbf5568","type":"default","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Endpoint Timeline","timelineType":"template","templateTimelineVersion":2,"templateTimelineId":"db366523-f1c6-4c1f-8731-6ce5ed9e5717","dateRange":{"start":1588161020848,"end":1588162280848},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735857110,"createdBy":"Elastic","updated":1611609999115,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/index.ndjson b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/index.ndjson index 7c074242c39d10..522430205c25aa 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/index.ndjson +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/index.ndjson @@ -7,6 +7,6 @@ // Auto generated file from scripts/regen_prepackage_timelines_index.sh // Do not hand edit. Run that script to regenerate package information instead -{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"event.action","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.name","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The working directory of the process.","columnHeaderType":"not-filtered","id":"process.working_directory","category":"process","type":"string","searchable":null,"example":"/home/alice"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Absolute path to the process executable.","columnHeaderType":"not-filtered","id":"process.parent.executable","category":"process","type":"string","searchable":null,"example":"/usr/bin/ssh"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.parent.args","category":"process","type":"string","searchable":null,"example":"[\"ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"aggregatable":true,"name":null,"description":"Process id.","columnHeaderType":"not-filtered","id":"process.parent.pid","category":"process","type":"number","searchable":null,"example":"4242"},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"aggregatable":true,"name":null,"description":"Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.","columnHeaderType":"not-filtered","id":"host.name","category":"host","type":"string","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"{process.name}","queryMatch":{"displayValue":"{agent.type}","field":"agent.type","displayField":"agent.type","value":"{agent.type}","operator":":*"},"id":"timeline-1-8622010a-61fb-490d-b162-beac9c36a853","type":"template","enabled":true},{"excluded":false,"and":[],"kqlQuery":"","name":"","queryMatch":{"displayValue":"endpoint","field":"agent.type","displayField":"agent.type","value":"endpoint","operator":":"},"id":"timeline-1-4685da24-35c1-43f3-892d-1f926dbf5568","type":"default","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Endpoint Timeline","timelineType":"template","templateTimelineVersion":1,"templateTimelineId":"db366523-f1c6-4c1f-8731-6ce5ed9e5717","dateRange":{"start":1588161020848,"end":1588162280848},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735857110,"createdBy":"Elastic","updated":1594736314036,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} -{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The action captured by the event.\n\nThis describes the information in the event. It is more specific than `event.category`.\nExamples are `group-add`, `process-started`, `file-created`. The value is\nnormally defined by the implementer.","columnHeaderType":"not-filtered","id":"event.action","category":"event","type":"string","searchable":null,"example":"user-password-change"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"IP address of the source (IPv4 or IPv6).","columnHeaderType":"not-filtered","id":"source.ip","category":"source","type":"ip","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Port of the source.","columnHeaderType":"not-filtered","id":"source.port","category":"source","type":"number","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"IP address of the destination (IPv4 or IPv6).","columnHeaderType":"not-filtered","id":"destination.ip","category":"destination","type":"ip","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"destination.port","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"host.name","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"{source.ip}","queryMatch":{"displayValue":null,"field":"source.ip","displayField":null,"value":"{source.ip}","operator":":*"},"id":"timeline-1-ec778f01-1802-40f0-9dfb-ed8de1f656cb","type":"template","enabled":true},{"excluded":false,"and":[],"kqlQuery":"","name":"{destination.ip}","queryMatch":{"displayValue":null,"field":"destination.ip","displayField":null,"value":"{destination.ip}","operator":":*"},"id":"timeline-1-e37e37c5-a6e7-4338-af30-47bfbc3c0e1e","type":"template","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Network Timeline","timelineType":"template","templateTimelineVersion":1,"templateTimelineId":"91832785-286d-4ebe-b884-1a208d111a70","dateRange":{"start":1588255858373,"end":1588256218373},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735573866,"createdBy":"Elastic","updated":1594736099397,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} -{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"event.action","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.name","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The working directory of the process.","columnHeaderType":"not-filtered","id":"process.working_directory","category":"process","type":"string","searchable":null,"example":"/home/alice"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Absolute path to the process executable.","columnHeaderType":"not-filtered","id":"process.parent.executable","category":"process","type":"string","searchable":null,"example":"/usr/bin/ssh"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.parent.args","category":"process","type":"string","searchable":null,"example":"[\"ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"aggregatable":true,"name":null,"description":"Process id.","columnHeaderType":"not-filtered","id":"process.parent.pid","category":"process","type":"number","searchable":null,"example":"4242"},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"aggregatable":true,"name":null,"description":"Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.","columnHeaderType":"not-filtered","id":"host.name","category":"host","type":"string","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"{process.name}","queryMatch":{"displayValue":null,"field":"process.name","displayField":null,"value":"{process.name}","operator":":"},"id":"timeline-1-8622010a-61fb-490d-b162-beac9c36a853","type":"template","enabled":true},{"excluded":false,"and":[],"kqlQuery":"","name":"{event.type}","queryMatch":{"displayValue":null,"field":"event.type","displayField":null,"value":"{event.type}","operator":":*"},"id":"timeline-1-4685da24-35c1-43f3-892d-1f926dbf5568","type":"template","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Process Timeline","timelineType":"template","templateTimelineVersion":1,"templateTimelineId":"76e52245-7519-4251-91ab-262fb1a1728c","dateRange":{"start":1588161020848,"end":1588162280848},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735629389,"createdBy":"Elastic","updated":1594736083598,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} +{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"event.action","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.name","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The working directory of the process.","columnHeaderType":"not-filtered","id":"process.working_directory","category":"process","type":"string","searchable":null,"example":"/home/alice"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Absolute path to the process executable.","columnHeaderType":"not-filtered","id":"process.parent.executable","category":"process","type":"string","searchable":null,"example":"/usr/bin/ssh"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.parent.args","category":"process","type":"string","searchable":null,"example":"[\"ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"aggregatable":true,"name":null,"description":"Process id.","columnHeaderType":"not-filtered","id":"process.parent.pid","category":"process","type":"number","searchable":null,"example":"4242"},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"aggregatable":true,"name":null,"description":"Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.","columnHeaderType":"not-filtered","id":"host.name","category":"host","type":"string","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"","queryMatch":{"displayValue":"endpoint","field":"agent.type","displayField":"agent.type","value":"endpoint","operator":":"},"id":"timeline-1-4685da24-35c1-43f3-892d-1f926dbf5568","type":"default","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Endpoint Timeline","timelineType":"template","templateTimelineVersion":2,"templateTimelineId":"db366523-f1c6-4c1f-8731-6ce5ed9e5717","dateRange":{"start":1588161020848,"end":1588162280848},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735857110,"createdBy":"Elastic","updated":1611609999115,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} +{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The action captured by the event.\n\nThis describes the information in the event. It is more specific than `event.category`.\nExamples are `group-add`, `process-started`, `file-created`. The value is\nnormally defined by the implementer.","columnHeaderType":"not-filtered","id":"event.action","category":"event","type":"string","searchable":null,"example":"user-password-change"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"IP address of the source (IPv4 or IPv6).","columnHeaderType":"not-filtered","id":"source.ip","category":"source","type":"ip","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Port of the source.","columnHeaderType":"not-filtered","id":"source.port","category":"source","type":"number","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"IP address of the destination (IPv4 or IPv6).","columnHeaderType":"not-filtered","id":"destination.ip","category":"destination","type":"ip","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"destination.port","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"host.name","searchable":null}],"dataProviders":[{"and":[{"enabled":true,"excluded":false,"id":"timeline-1-e37e37c5-a6e7-4338-af30-47bfbc3c0e1e","kqlQuery":"","name":"{destination.ip}","queryMatch":{"displayField":"destination.ip","displayValue":"{destination.ip}","field":"destination.ip","operator":":","value":"{destination.ip}"},"type":"template"}],"enabled":true,"excluded":false,"id":"timeline-1-ec778f01-1802-40f0-9dfb-ed8de1f656cb","kqlQuery":"","name":"{source.ip}","queryMatch":{"displayField":"source.ip","displayValue":"{source.ip}","field":"source.ip","operator":":","value":"{source.ip}"},"type":"template"}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Network Timeline","timelineType":"template","templateTimelineVersion":2,"templateTimelineId":"91832785-286d-4ebe-b884-1a208d111a70","dateRange":{"start":1588255858373,"end":1588256218373},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735573866,"createdBy":"Elastic","updated":1611609960850,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} +{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"event.action","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.name","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The working directory of the process.","columnHeaderType":"not-filtered","id":"process.working_directory","category":"process","type":"string","searchable":null,"example":"/home/alice"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Absolute path to the process executable.","columnHeaderType":"not-filtered","id":"process.parent.executable","category":"process","type":"string","searchable":null,"example":"/usr/bin/ssh"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.parent.args","category":"process","type":"string","searchable":null,"example":"[\"ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"aggregatable":true,"name":null,"description":"Process id.","columnHeaderType":"not-filtered","id":"process.parent.pid","category":"process","type":"number","searchable":null,"example":"4242"},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"aggregatable":true,"name":null,"description":"Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.","columnHeaderType":"not-filtered","id":"host.name","category":"host","type":"string","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"{process.name}","queryMatch":{"displayValue":null,"field":"process.name","displayField":null,"value":"{process.name}","operator":":"},"id":"timeline-1-8622010a-61fb-490d-b162-beac9c36a853","type":"template","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Process Timeline","timelineType":"template","templateTimelineVersion":2,"templateTimelineId":"76e52245-7519-4251-91ab-262fb1a1728c","dateRange":{"start":1588161020848,"end":1588162280848},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735629389,"createdBy":"Elastic","updated":1611609848602,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/network.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/network.json index 1634476b4e99de..6e93387579d221 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/network.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/network.json @@ -1 +1 @@ -{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The action captured by the event.\n\nThis describes the information in the event. It is more specific than `event.category`.\nExamples are `group-add`, `process-started`, `file-created`. The value is\nnormally defined by the implementer.","columnHeaderType":"not-filtered","id":"event.action","category":"event","type":"string","searchable":null,"example":"user-password-change"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"IP address of the source (IPv4 or IPv6).","columnHeaderType":"not-filtered","id":"source.ip","category":"source","type":"ip","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Port of the source.","columnHeaderType":"not-filtered","id":"source.port","category":"source","type":"number","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"IP address of the destination (IPv4 or IPv6).","columnHeaderType":"not-filtered","id":"destination.ip","category":"destination","type":"ip","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"destination.port","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"host.name","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"{source.ip}","queryMatch":{"displayValue":null,"field":"source.ip","displayField":null,"value":"{source.ip}","operator":":*"},"id":"timeline-1-ec778f01-1802-40f0-9dfb-ed8de1f656cb","type":"template","enabled":true},{"excluded":false,"and":[],"kqlQuery":"","name":"{destination.ip}","queryMatch":{"displayValue":null,"field":"destination.ip","displayField":null,"value":"{destination.ip}","operator":":*"},"id":"timeline-1-e37e37c5-a6e7-4338-af30-47bfbc3c0e1e","type":"template","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Network Timeline","timelineType":"template","templateTimelineVersion":1,"templateTimelineId":"91832785-286d-4ebe-b884-1a208d111a70","dateRange":{"start":1588255858373,"end":1588256218373},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735573866,"createdBy":"Elastic","updated":1594736099397,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} +{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The action captured by the event.\n\nThis describes the information in the event. It is more specific than `event.category`.\nExamples are `group-add`, `process-started`, `file-created`. The value is\nnormally defined by the implementer.","columnHeaderType":"not-filtered","id":"event.action","category":"event","type":"string","searchable":null,"example":"user-password-change"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"IP address of the source (IPv4 or IPv6).","columnHeaderType":"not-filtered","id":"source.ip","category":"source","type":"ip","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Port of the source.","columnHeaderType":"not-filtered","id":"source.port","category":"source","type":"number","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"IP address of the destination (IPv4 or IPv6).","columnHeaderType":"not-filtered","id":"destination.ip","category":"destination","type":"ip","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"destination.port","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"host.name","searchable":null}],"dataProviders":[{"and":[{"enabled":true,"excluded":false,"id":"timeline-1-e37e37c5-a6e7-4338-af30-47bfbc3c0e1e","kqlQuery":"","name":"{destination.ip}","queryMatch":{"displayField":"destination.ip","displayValue":"{destination.ip}","field":"destination.ip","operator":":","value":"{destination.ip}"},"type":"template"}],"enabled":true,"excluded":false,"id":"timeline-1-ec778f01-1802-40f0-9dfb-ed8de1f656cb","kqlQuery":"","name":"{source.ip}","queryMatch":{"displayField":"source.ip","displayValue":"{source.ip}","field":"source.ip","operator":":","value":"{source.ip}"},"type":"template"}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Network Timeline","timelineType":"template","templateTimelineVersion":2,"templateTimelineId":"91832785-286d-4ebe-b884-1a208d111a70","dateRange":{"start":1588255858373,"end":1588256218373},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735573866,"createdBy":"Elastic","updated":1611609960850,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/process.json index 767f38133f263b..c25873746a9e97 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/process.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_timelines/process.json @@ -1 +1 @@ -{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"event.action","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.name","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The working directory of the process.","columnHeaderType":"not-filtered","id":"process.working_directory","category":"process","type":"string","searchable":null,"example":"/home/alice"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Absolute path to the process executable.","columnHeaderType":"not-filtered","id":"process.parent.executable","category":"process","type":"string","searchable":null,"example":"/usr/bin/ssh"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.parent.args","category":"process","type":"string","searchable":null,"example":"[\"ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"aggregatable":true,"name":null,"description":"Process id.","columnHeaderType":"not-filtered","id":"process.parent.pid","category":"process","type":"number","searchable":null,"example":"4242"},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"aggregatable":true,"name":null,"description":"Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.","columnHeaderType":"not-filtered","id":"host.name","category":"host","type":"string","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"{process.name}","queryMatch":{"displayValue":null,"field":"process.name","displayField":null,"value":"{process.name}","operator":":"},"id":"timeline-1-8622010a-61fb-490d-b162-beac9c36a853","type":"template","enabled":true},{"excluded":false,"and":[],"kqlQuery":"","name":"{event.type}","queryMatch":{"displayValue":null,"field":"event.type","displayField":null,"value":"{event.type}","operator":":*"},"id":"timeline-1-4685da24-35c1-43f3-892d-1f926dbf5568","type":"template","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Process Timeline","timelineType":"template","templateTimelineVersion":1,"templateTimelineId":"76e52245-7519-4251-91ab-262fb1a1728c","dateRange":{"start":1588161020848,"end":1588162280848},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735629389,"createdBy":"Elastic","updated":1594736083598,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} +{"savedObjectId":null,"version":null,"columns":[{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"@timestamp","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"signal.rule.description","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"event.action","searchable":null},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.name","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"The working directory of the process.","columnHeaderType":"not-filtered","id":"process.working_directory","category":"process","type":"string","searchable":null,"example":"/home/alice"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments, starting with the absolute path to\nthe executable.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.args","category":"process","type":"string","searchable":null,"example":"[\"/usr/bin/ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"name":null,"columnHeaderType":"not-filtered","id":"process.pid","searchable":null},{"indexes":null,"aggregatable":true,"name":null,"description":"Absolute path to the process executable.","columnHeaderType":"not-filtered","id":"process.parent.executable","category":"process","type":"string","searchable":null,"example":"/usr/bin/ssh"},{"indexes":null,"aggregatable":true,"name":null,"description":"Array of process arguments.\n\nMay be filtered to protect sensitive information.","columnHeaderType":"not-filtered","id":"process.parent.args","category":"process","type":"string","searchable":null,"example":"[\"ssh\",\"-l\",\"user\",\"10.0.0.16\"]"},{"indexes":null,"aggregatable":true,"name":null,"description":"Process id.","columnHeaderType":"not-filtered","id":"process.parent.pid","category":"process","type":"number","searchable":null,"example":"4242"},{"indexes":null,"aggregatable":true,"name":null,"description":"Short name or login of the user.","columnHeaderType":"not-filtered","id":"user.name","category":"user","type":"string","searchable":null,"example":"albert"},{"indexes":null,"aggregatable":true,"name":null,"description":"Name of the host.\n\nIt can contain what `hostname` returns on Unix systems, the fully qualified\ndomain name, or a name specified by the user. The sender decides which value\nto use.","columnHeaderType":"not-filtered","id":"host.name","category":"host","type":"string","searchable":null}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"{process.name}","queryMatch":{"displayValue":null,"field":"process.name","displayField":null,"value":"{process.name}","operator":":"},"id":"timeline-1-8622010a-61fb-490d-b162-beac9c36a853","type":"template","enabled":true}],"description":"","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"kind":"kuery","expression":""},"serializedQuery":""}},"title":"Generic Process Timeline","timelineType":"template","templateTimelineVersion":2,"templateTimelineId":"76e52245-7519-4251-91ab-262fb1a1728c","dateRange":{"start":1588161020848,"end":1588162280848},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1594735629389,"createdBy":"Elastic","updated":1611609848602,"updatedBy":"Elastic","eventNotes":[],"globalNotes":[],"pinnedEventIds":[],"status":"immutable"} From 0fe7b9e080c67c43aefdb7ea25d5e90a80cb4ade Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 26 Jan 2021 15:27:48 -0800 Subject: [PATCH 11/58] skip flaky suite (#89031) --- test/functional/apps/management/_test_huge_fields.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/management/_test_huge_fields.js b/test/functional/apps/management/_test_huge_fields.js index ca95af8cb4205f..2ab619276d2b91 100644 --- a/test/functional/apps/management/_test_huge_fields.js +++ b/test/functional/apps/management/_test_huge_fields.js @@ -13,7 +13,8 @@ export default function ({ getService, getPageObjects }) { const security = getService('security'); const PageObjects = getPageObjects(['common', 'home', 'settings']); - describe('test large number of fields', function () { + // Failing: See https://github.com/elastic/kibana/issues/89031 + describe.skip('test large number of fields', function () { this.tags(['skipCloud']); const EXPECTED_FIELD_COUNT = '10006'; From 2c648acffda7c05cac2949eb5994c0f2066aa12b Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 26 Jan 2021 16:30:52 -0800 Subject: [PATCH 12/58] skip flaky suite (#89379) --- test/functional/apps/home/_sample_data.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/home/_sample_data.ts b/test/functional/apps/home/_sample_data.ts index a9fe2026112b69..438dd6f8adce20 100644 --- a/test/functional/apps/home/_sample_data.ts +++ b/test/functional/apps/home/_sample_data.ts @@ -20,7 +20,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const dashboardExpect = getService('dashboardExpect'); const PageObjects = getPageObjects(['common', 'header', 'home', 'dashboard', 'timePicker']); - describe('sample data', function describeIndexTests() { + // Failing: See https://github.com/elastic/kibana/issues/89379 + describe.skip('sample data', function describeIndexTests() { before(async () => { await security.testUser.setRoles(['kibana_admin', 'kibana_sample_admin']); await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { From 8250b078b4b47415435ee72fb9b04908f99c6ed5 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 27 Jan 2021 00:59:24 +0000 Subject: [PATCH 13/58] chore(NA): improve ts build refs performance on kbn bootstrap (#89333) * chore(NA): improve ts build refs performance on kbn bootstrap * chore(NA): use skipLibCheck=false by default on typechecking * docs(NA): commit core docs changes * fix(NA): eui typings --- ...lugin-core-server.kibanaresponsefactory.md | 8 +- ...ns-data-public.aggconfigs._constructor_.md | 6 +- ...na-plugin-plugins-data-public.searchbar.md | 4 +- ...plugin-plugins-data-server.plugin.start.md | 4 +- package.json | 10 +- src/core/server/server.api.md | 8 +- src/dev/typescript/run_type_check_cli.ts | 6 +- src/plugins/data/public/public.api.md | 8 +- src/plugins/data/server/server.api.md | 2 +- tsconfig.base.json | 2 + typings/@elastic/eui/index.d.ts | 10 +- typings/@elastic/eui/lib/format.d.ts | 9 -- typings/@elastic/eui/lib/services.d.ts | 9 -- yarn.lock | 119 +++++++++--------- 14 files changed, 99 insertions(+), 106 deletions(-) delete mode 100644 typings/@elastic/eui/lib/format.d.ts delete mode 100644 typings/@elastic/eui/lib/services.d.ts diff --git a/docs/development/core/server/kibana-plugin-core-server.kibanaresponsefactory.md b/docs/development/core/server/kibana-plugin-core-server.kibanaresponsefactory.md index b488baacaff256..d7eafdce017e43 100644 --- a/docs/development/core/server/kibana-plugin-core-server.kibanaresponsefactory.md +++ b/docs/development/core/server/kibana-plugin-core-server.kibanaresponsefactory.md @@ -10,7 +10,7 @@ Set of helpers used to create `KibanaResponse` to form HTTP response on an incom ```typescript kibanaResponseFactory: { - custom: | { + custom: | Buffer | Error | Stream | { message: string | Error; attributes?: Record | undefined; } | undefined>(options: CustomHttpResponseOptions) => KibanaResponse; @@ -21,9 +21,9 @@ kibanaResponseFactory: { conflict: (options?: ErrorHttpResponseOptions) => KibanaResponse; internalError: (options?: ErrorHttpResponseOptions) => KibanaResponse; customError: (options: CustomHttpResponseOptions) => KibanaResponse; - redirected: (options: RedirectResponseOptions) => KibanaResponse>; - ok: (options?: HttpResponseOptions) => KibanaResponse>; - accepted: (options?: HttpResponseOptions) => KibanaResponse>; + redirected: (options: RedirectResponseOptions) => KibanaResponse | Buffer | Stream>; + ok: (options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>; + accepted: (options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>; noContent: (options?: HttpResponseOptions) => KibanaResponse; } ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs._constructor_.md index c9e08b9712480b..6ca7a1a88b30e4 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs._constructor_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs._constructor_.md @@ -15,11 +15,11 @@ constructor(indexPattern: IndexPattern, configStates: Pick & Pick<{ + }, "schema" | "enabled" | "id" | "params"> & Pick<{ type: string | IAggType; }, "type"> & Pick<{ type: string | IAggType; - }, never>, "enabled" | "type" | "schema" | "id" | "params">[] | undefined, opts: AggConfigsOptions); + }, never>, "schema" | "type" | "enabled" | "id" | "params">[] | undefined, opts: AggConfigsOptions); ``` ## Parameters @@ -27,6 +27,6 @@ constructor(indexPattern: IndexPattern, configStates: PickIndexPattern | | -| configStates | Pick<Pick<{
type: string;
enabled?: boolean | undefined;
id?: string | undefined;
params?: {} | import("./agg_config").SerializableState | undefined;
schema?: string | undefined;
}, "enabled" | "schema" | "id" | "params"> & Pick<{
type: string | IAggType;
}, "type"> & Pick<{
type: string | IAggType;
}, never>, "enabled" | "type" | "schema" | "id" | "params">[] | undefined | | +| configStates | Pick<Pick<{
type: string;
enabled?: boolean | undefined;
id?: string | undefined;
params?: {} | import("./agg_config").SerializableState | undefined;
schema?: string | undefined;
}, "schema" | "enabled" | "id" | "params"> & Pick<{
type: string | IAggType;
}, "type"> & Pick<{
type: string | IAggType;
}, never>, "schema" | "type" | "enabled" | "id" | "params">[] | undefined | | | opts | AggConfigsOptions | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md index 2fd84730957b68..83fbc00860ca5e 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md @@ -7,7 +7,7 @@ Signature: ```typescript -SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "indexPatterns" | "dataTestSubj" | "refreshInterval" | "screenTitle" | "onRefresh" | "onRefreshChange" | "showQueryInput" | "showDatePicker" | "showAutoRefreshOnly" | "dateRangeFrom" | "dateRangeTo" | "isRefreshPaused" | "customSubmitButton" | "timeHistory" | "indicateNoData" | "onFiltersUpdated" | "trackUiMetric" | "savedQuery" | "showSaveQuery" | "onClearSavedQuery" | "showQueryBar" | "showFilterBar" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +SearchBar: React.ComponentClass, "query" | "isLoading" | "indexPatterns" | "filters" | "dataTestSubj" | "refreshInterval" | "screenTitle" | "onRefresh" | "onRefreshChange" | "showQueryInput" | "showDatePicker" | "showAutoRefreshOnly" | "dateRangeFrom" | "dateRangeTo" | "isRefreshPaused" | "customSubmitButton" | "timeHistory" | "indicateNoData" | "onFiltersUpdated" | "trackUiMetric" | "savedQuery" | "showSaveQuery" | "onClearSavedQuery" | "showQueryBar" | "showFilterBar" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; } ``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md index af7abb076d7ef9..ea3ba28a52defc 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md @@ -12,7 +12,7 @@ start(core: CoreStart): { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; indexPatterns: { - indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("../../../core/server").ElasticsearchClient) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("../../../core/server").ElasticsearchClient) => Promise; }; search: ISearchStart>; }; @@ -31,7 +31,7 @@ start(core: CoreStart): { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; indexPatterns: { - indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("../../../core/server").ElasticsearchClient) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("../../../core/server").ElasticsearchClient) => Promise; }; search: ISearchStart>; }` diff --git a/package.json b/package.json index d14c5b0a7dc5fb..42949a70141311 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "**/react-syntax-highlighter/**/highlight.js": "^10.4.1", "**/request": "^2.88.2", "**/trim": "0.0.3", - "**/typescript": "4.1.2" + "**/typescript": "4.1.3" }, "engines": { "node": "14.15.4", @@ -561,8 +561,8 @@ "@types/xml2js": "^0.4.5", "@types/yauzl": "^2.9.1", "@types/zen-observable": "^0.8.0", - "@typescript-eslint/eslint-plugin": "^4.8.1", - "@typescript-eslint/parser": "^4.8.1", + "@typescript-eslint/eslint-plugin": "^4.14.1", + "@typescript-eslint/parser": "^4.14.1", "@welldone-software/why-did-you-render": "^5.0.0", "@yarnpkg/lockfile": "^1.1.0", "abab": "^2.0.4", @@ -820,9 +820,9 @@ "topojson-client": "3.0.0", "ts-loader": "^7.0.5", "tsd": "^0.13.1", - "typescript": "4.1.2", + "typescript": "4.1.3", "typescript-fsa": "^3.0.0", - "typescript-fsa-reducers": "^1.2.1", + "typescript-fsa-reducers": "^1.2.2", "unlazy-loader": "^0.1.3", "unstated": "^2.1.1", "url-loader": "^2.2.0", diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index ceab69a6cdb186..0b058011267eb3 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -1256,7 +1256,7 @@ export type KibanaResponseFactory = typeof kibanaResponseFactory; // @public export const kibanaResponseFactory: { - custom: | { + custom: | Buffer | Error | Stream | { message: string | Error; attributes?: Record | undefined; } | undefined>(options: CustomHttpResponseOptions) => KibanaResponse; @@ -1267,9 +1267,9 @@ export const kibanaResponseFactory: { conflict: (options?: ErrorHttpResponseOptions) => KibanaResponse; internalError: (options?: ErrorHttpResponseOptions) => KibanaResponse; customError: (options: CustomHttpResponseOptions) => KibanaResponse; - redirected: (options: RedirectResponseOptions) => KibanaResponse>; - ok: (options?: HttpResponseOptions) => KibanaResponse>; - accepted: (options?: HttpResponseOptions) => KibanaResponse>; + redirected: (options: RedirectResponseOptions) => KibanaResponse | Buffer | Stream>; + ok: (options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>; + accepted: (options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>; noContent: (options?: HttpResponseOptions) => KibanaResponse; }; diff --git a/src/dev/typescript/run_type_check_cli.ts b/src/dev/typescript/run_type_check_cli.ts index c1a25a8e4bdee0..6e7ea6fcf24056 100644 --- a/src/dev/typescript/run_type_check_cli.ts +++ b/src/dev/typescript/run_type_check_cli.ts @@ -61,7 +61,7 @@ export async function runTypeCheckCli() { Options: --project [path] {dim Path to a tsconfig.json file determines the project to check} - --skip-lib-check {dim Skip type checking of all declaration files (*.d.ts)} + --skip-lib-check {dim Skip type checking of all declaration files (*.d.ts). Default is false} --help {dim Show this message} `) ); @@ -77,7 +77,9 @@ export async function runTypeCheckCli() { ...['--emitDeclarationOnly', 'false'], '--noEmit', '--pretty', - ...(opts['skip-lib-check'] ? ['--skipLibCheck'] : []), + ...(opts['skip-lib-check'] + ? ['--skipLibCheck', opts['skip-lib-check']] + : ['--skipLibCheck', 'false']), ]; const projects = filterProjectsByFlag(opts.project).filter((p) => !p.disableTypeCheck); diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 28997de4517e79..002f0333657907 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -218,11 +218,11 @@ export class AggConfigs { id?: string | undefined; params?: {} | import("./agg_config").SerializableState | undefined; schema?: string | undefined; - }, "enabled" | "schema" | "id" | "params"> & Pick<{ + }, "schema" | "enabled" | "id" | "params"> & Pick<{ type: string | IAggType; }, "type"> & Pick<{ type: string | IAggType; - }, never>, "enabled" | "type" | "schema" | "id" | "params">[] | undefined, opts: AggConfigsOptions); + }, never>, "schema" | "type" | "enabled" | "id" | "params">[] | undefined, opts: AggConfigsOptions); // (undocumented) aggs: IAggConfig[]; // (undocumented) @@ -2235,8 +2235,8 @@ export const search: { // Warning: (ae-missing-release-tag) "SearchBar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "indexPatterns" | "dataTestSubj" | "refreshInterval" | "screenTitle" | "onRefresh" | "onRefreshChange" | "showQueryInput" | "showDatePicker" | "showAutoRefreshOnly" | "dateRangeFrom" | "dateRangeTo" | "isRefreshPaused" | "customSubmitButton" | "timeHistory" | "indicateNoData" | "onFiltersUpdated" | "trackUiMetric" | "savedQuery" | "showSaveQuery" | "onClearSavedQuery" | "showQueryBar" | "showFilterBar" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +export const SearchBar: React.ComponentClass, "query" | "isLoading" | "indexPatterns" | "filters" | "dataTestSubj" | "refreshInterval" | "screenTitle" | "onRefresh" | "onRefreshChange" | "showQueryInput" | "showDatePicker" | "showAutoRefreshOnly" | "dateRangeFrom" | "dateRangeTo" | "isRefreshPaused" | "customSubmitButton" | "timeHistory" | "indicateNoData" | "onFiltersUpdated" | "trackUiMetric" | "savedQuery" | "showSaveQuery" | "onClearSavedQuery" | "showQueryBar" | "showFilterBar" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; }; // Warning: (ae-forgotten-export) The symbol "SearchBarOwnProps" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 6a96fd8209a8d6..9789f3354e9efb 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -1138,7 +1138,7 @@ export class Plugin implements Plugin_2 Promise; }; indexPatterns: { - indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("../../../core/server").ElasticsearchClient) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("../../../core/server").ElasticsearchClient) => Promise; }; search: ISearchStart>; }; diff --git a/tsconfig.base.json b/tsconfig.base.json index 247813da51cfb3..f8e07911e71cec 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -14,6 +14,8 @@ "strict": true, // save information about the project graph on disk "incremental": true, + // Do not check d.ts files by default + "skipLibCheck": true, // enables "core language features" "lib": [ "esnext", diff --git a/typings/@elastic/eui/index.d.ts b/typings/@elastic/eui/index.d.ts index 74f89608bc04f2..e5cf7864a83b29 100644 --- a/typings/@elastic/eui/index.d.ts +++ b/typings/@elastic/eui/index.d.ts @@ -6,6 +6,12 @@ * Public License, v 1. */ -import { Direction } from '@elastic/eui/src/services/sort/sort_direction'; - // TODO: Remove once typescript definitions are in EUI + +declare module '@elastic/eui/lib/services' { + export const RIGHT_ALIGNMENT: any; +} + +declare module '@elastic/eui/lib/services/format' { + export const dateFormatAliases: any; +} diff --git a/typings/@elastic/eui/lib/format.d.ts b/typings/@elastic/eui/lib/format.d.ts deleted file mode 100644 index 4be830ec2d98ce..00000000000000 --- a/typings/@elastic/eui/lib/format.d.ts +++ /dev/null @@ -1,9 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -export const dateFormatAliases: any; diff --git a/typings/@elastic/eui/lib/services.d.ts b/typings/@elastic/eui/lib/services.d.ts deleted file mode 100644 index a667d111ceb721..00000000000000 --- a/typings/@elastic/eui/lib/services.d.ts +++ /dev/null @@ -1,9 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -export const RIGHT_ALIGNMENT: any; diff --git a/yarn.lock b/yarn.lock index 174f1284a3a6b4..ed861b58773b9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6861,28 +6861,29 @@ resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg== -"@typescript-eslint/eslint-plugin@^4.8.1": - version "4.8.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.8.1.tgz#b362abe0ee478a6c6d06c14552a6497f0b480769" - integrity sha512-d7LeQ7dbUrIv5YVFNzGgaW3IQKMmnmKFneRWagRlGYOSfLJVaRbj/FrBNOBC1a3tVO+TgNq1GbHvRtg1kwL0FQ== +"@typescript-eslint/eslint-plugin@^4.14.1": + version "4.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.1.tgz#22dd301ce228aaab3416b14ead10b1db3e7d3180" + integrity sha512-5JriGbYhtqMS1kRcZTQxndz1lKMwwEXKbwZbkUZNnp6MJX0+OVXnG0kOlBZP4LUAxEyzu3cs+EXd/97MJXsGfw== dependencies: - "@typescript-eslint/experimental-utils" "4.8.1" - "@typescript-eslint/scope-manager" "4.8.1" + "@typescript-eslint/experimental-utils" "4.14.1" + "@typescript-eslint/scope-manager" "4.14.1" debug "^4.1.1" functional-red-black-tree "^1.0.1" + lodash "^4.17.15" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.8.1": - version "4.8.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.8.1.tgz#27275c20fa4336df99ebcf6195f7d7aa7aa9f22d" - integrity sha512-WigyLn144R3+lGATXW4nNcDJ9JlTkG8YdBWHkDlN0lC3gUGtDi7Pe3h5GPvFKMcRz8KbZpm9FJV9NTW8CpRHpg== +"@typescript-eslint/experimental-utils@4.14.1": + version "4.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.1.tgz#a5c945cb24dabb96747180e1cfc8487f8066f471" + integrity sha512-2CuHWOJwvpw0LofbyG5gvYjEyoJeSvVH2PnfUQSn0KQr4v8Dql2pr43ohmx4fdPQ/eVoTSFjTi/bsGEXl/zUUQ== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.8.1" - "@typescript-eslint/types" "4.8.1" - "@typescript-eslint/typescript-estree" "4.8.1" + "@typescript-eslint/scope-manager" "4.14.1" + "@typescript-eslint/types" "4.14.1" + "@typescript-eslint/typescript-estree" "4.14.1" eslint-scope "^5.0.0" eslint-utils "^2.0.0" @@ -6898,16 +6899,24 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.8.1": - version "4.8.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.8.1.tgz#4fe2fbdbb67485bafc4320b3ae91e34efe1219d1" - integrity sha512-QND8XSVetATHK9y2Ltc/XBl5Ro7Y62YuZKnPEwnNPB8E379fDsvzJ1dMJ46fg/VOmk0hXhatc+GXs5MaXuL5Uw== +"@typescript-eslint/parser@^4.14.1": + version "4.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.14.1.tgz#3bd6c24710cd557d8446625284bcc9c6d52817c6" + integrity sha512-mL3+gU18g9JPsHZuKMZ8Z0Ss9YP1S5xYZ7n68Z98GnPq02pYNQuRXL85b9GYhl6jpdvUc45Km7hAl71vybjUmw== dependencies: - "@typescript-eslint/scope-manager" "4.8.1" - "@typescript-eslint/types" "4.8.1" - "@typescript-eslint/typescript-estree" "4.8.1" + "@typescript-eslint/scope-manager" "4.14.1" + "@typescript-eslint/types" "4.14.1" + "@typescript-eslint/typescript-estree" "4.14.1" debug "^4.1.1" +"@typescript-eslint/scope-manager@4.14.1": + version "4.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.14.1.tgz#8444534254c6f370e9aa974f035ced7fe713ce02" + integrity sha512-F4bjJcSqXqHnC9JGUlnqSa3fC2YH5zTtmACS1Hk+WX/nFB0guuynVK5ev35D4XZbdKjulXBAQMyRr216kmxghw== + dependencies: + "@typescript-eslint/types" "4.14.1" + "@typescript-eslint/visitor-keys" "4.14.1" + "@typescript-eslint/scope-manager@4.3.0": version "4.3.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.3.0.tgz#c743227e087545968080d2362cfb1273842cb6a7" @@ -6916,23 +6925,29 @@ "@typescript-eslint/types" "4.3.0" "@typescript-eslint/visitor-keys" "4.3.0" -"@typescript-eslint/scope-manager@4.8.1": - version "4.8.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.8.1.tgz#e343c475f8f1d15801b546cb17d7f309b768fdce" - integrity sha512-r0iUOc41KFFbZdPAdCS4K1mXivnSZqXS5D9oW+iykQsRlTbQRfuFRSW20xKDdYiaCoH+SkSLeIF484g3kWzwOQ== - dependencies: - "@typescript-eslint/types" "4.8.1" - "@typescript-eslint/visitor-keys" "4.8.1" +"@typescript-eslint/types@4.14.1": + version "4.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.14.1.tgz#b3d2eb91dafd0fd8b3fce7c61512ac66bd0364aa" + integrity sha512-SkhzHdI/AllAgQSxXM89XwS1Tkic7csPdndUuTKabEwRcEfR8uQ/iPA3Dgio1rqsV3jtqZhY0QQni8rLswJM2w== "@typescript-eslint/types@4.3.0": version "4.3.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.3.0.tgz#1f0b2d5e140543e2614f06d48fb3ae95193c6ddf" integrity sha512-Cx9TpRvlRjOppGsU6Y6KcJnUDOelja2NNCX6AZwtVHRzaJkdytJWMuYiqi8mS35MRNA3cJSwDzXePfmhU6TANw== -"@typescript-eslint/types@4.8.1": - version "4.8.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.8.1.tgz#23829c73c5fc6f4fcd5346a7780b274f72fee222" - integrity sha512-ave2a18x2Y25q5K05K/U3JQIe2Av4+TNi/2YuzyaXLAsDx6UZkz1boZ7nR/N6Wwae2PpudTZmHFXqu7faXfHmA== +"@typescript-eslint/typescript-estree@4.14.1": + version "4.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.1.tgz#20d3b8c8e3cdc8f764bdd5e5b0606dd83da6075b" + integrity sha512-M8+7MbzKC1PvJIA8kR2sSBnex8bsR5auatLCnVlNTJczmJgqRn8M+sAlQfkEq7M4IY3WmaNJ+LJjPVRrREVSHQ== + dependencies: + "@typescript-eslint/types" "4.14.1" + "@typescript-eslint/visitor-keys" "4.14.1" + debug "^4.1.1" + globby "^11.0.1" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" "@typescript-eslint/typescript-estree@4.3.0": version "4.3.0" @@ -6948,19 +6963,13 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@4.8.1": - version "4.8.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.8.1.tgz#7307e3f2c9e95df7daa8dc0a34b8c43b7ec0dd32" - integrity sha512-bJ6Fn/6tW2g7WIkCWh3QRlaSU7CdUUK52shx36/J7T5oTQzANvi6raoTsbwGM11+7eBbeem8hCCKbyvAc0X3sQ== +"@typescript-eslint/visitor-keys@4.14.1": + version "4.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.1.tgz#e93c2ff27f47ee477a929b970ca89d60a117da91" + integrity sha512-TAblbDXOI7bd0C/9PE1G+AFo7R5uc+ty1ArDoxmrC1ah61Hn6shURKy7gLdRb1qKJmjHkqu5Oq+e4Kt0jwf1IA== dependencies: - "@typescript-eslint/types" "4.8.1" - "@typescript-eslint/visitor-keys" "4.8.1" - debug "^4.1.1" - globby "^11.0.1" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" + "@typescript-eslint/types" "4.14.1" + eslint-visitor-keys "^2.0.0" "@typescript-eslint/visitor-keys@4.3.0": version "4.3.0" @@ -6970,14 +6979,6 @@ "@typescript-eslint/types" "4.3.0" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@4.8.1": - version "4.8.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.8.1.tgz#794f68ee292d1b2e3aa9690ebedfcb3a8c90e3c3" - integrity sha512-3nrwXFdEYALQh/zW8rFwP4QltqsanCDz4CwWMPiIZmwlk9GlvBeueEIbq05SEq4ganqM0g9nh02xXgv5XI3PeQ== - dependencies: - "@typescript-eslint/types" "4.8.1" - eslint-visitor-keys "^2.0.0" - "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" @@ -28571,10 +28572,10 @@ typescript-compare@^0.0.2: dependencies: typescript-logic "^0.0.0" -typescript-fsa-reducers@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/typescript-fsa-reducers/-/typescript-fsa-reducers-1.2.1.tgz#2af1a85f7b88fb0dfb9fa59d5da51a5d7ac6543f" - integrity sha512-Qgn7zEnAU5n3YEWEL5ooEmIWZl9B4QyXD4Y/0DqpUzF0YuTrcsLa7Lht0gFXZ+xqLJXQwo3fEiTfQTDF1fBnMg== +typescript-fsa-reducers@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/typescript-fsa-reducers/-/typescript-fsa-reducers-1.2.2.tgz#1e2c8e8a50ca3e09e0d6fdf2a3b42bdd17de8094" + integrity sha512-IQ2VsIqUvmzVgWNDjxkeOxX97itl/rq+2u82jGsRdzCSFi9OtV4qf1Ec1urvj/eDlPHOaihIL7wMZzLYx9GvFg== typescript-fsa@^3.0.0: version "3.0.0" @@ -28593,10 +28594,10 @@ typescript-tuple@^2.2.1: dependencies: typescript-compare "^0.0.2" -typescript@4.1.2, typescript@^3.2.2, typescript@^3.3.3333, typescript@^3.5.3, typescript@~3.7.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9" - integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ== +typescript@4.1.3, typescript@^3.2.2, typescript@^3.3.3333, typescript@^3.5.3, typescript@~3.7.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" + integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== ua-parser-js@^0.7.18: version "0.7.22" From c6cfdee5b02d30263972bf149601323883a8c351 Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Tue, 26 Jan 2021 20:23:01 -0700 Subject: [PATCH 14/58] [core.logging] Add ops logs to the KP logging system (#88070) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../src/get_logging_config.ts | 5 +- src/core/README.md | 6 +- .../deprecation/core_deprecations.test.ts | 20 +++ .../config/deprecation/core_deprecations.ts | 12 ++ src/core/server/logging/README.md | 24 +++- src/core/server/logging/ecs.ts | 90 ++++++++++++ src/core/server/logging/index.ts | 7 + .../logging/get_ops_metrics_log.test.ts | 132 ++++++++++++++++++ .../metrics/logging/get_ops_metrics_log.ts | 78 +++++++++++ src/core/server/metrics/logging/index.ts | 9 ++ .../server/metrics/metrics_service.test.ts | 99 ++++++++++++- src/core/server/metrics/metrics_service.ts | 6 +- 12 files changed, 482 insertions(+), 6 deletions(-) create mode 100644 src/core/server/logging/ecs.ts create mode 100644 src/core/server/metrics/logging/get_ops_metrics_log.test.ts create mode 100644 src/core/server/metrics/logging/get_ops_metrics_log.ts create mode 100644 src/core/server/metrics/logging/index.ts diff --git a/packages/kbn-legacy-logging/src/get_logging_config.ts b/packages/kbn-legacy-logging/src/get_logging_config.ts index 5a28ab1271538a..280b9f815c78cb 100644 --- a/packages/kbn-legacy-logging/src/get_logging_config.ts +++ b/packages/kbn-legacy-logging/src/get_logging_config.ts @@ -28,7 +28,10 @@ export function getLoggingConfiguration(config: LegacyLoggingConfig, opsInterval } else if (config.verbose) { _.defaults(events, { log: '*', - ops: '*', + // To avoid duplicate logs, we explicitly disable this in verbose + // mode as it is already provided by the new logging config under + // the `metrics.ops` context. + ops: '!', request: '*', response: '*', error: '*', diff --git a/src/core/README.md b/src/core/README.md index e195bf30c054c8..c73c6aa56bfd0d 100644 --- a/src/core/README.md +++ b/src/core/README.md @@ -28,8 +28,10 @@ Even though the new validation system provided by the `core` is also based on Jo rules tailored to our needs (e.g. `byteSize`, `duration` etc.). That means that config values that were previously accepted by the "legacy" Kibana may be rejected by the `core` now. -Even though `core` has its own logging system it doesn't output log records directly (e.g. to file or terminal), but instead -forward them to the "legacy" Kibana so that they look the same as the rest of the log records throughout Kibana. +### Logging +`core` has its own [logging system](./server/logging/README.md) and will output log records directly (e.g. to file or terminal) when configured. When no +specific configuration is provided, logs are forwarded to the "legacy" Kibana so that they look the same as the rest of the +log records throughout Kibana. ## Core API Review To provide a stable API for plugin developers, it is important that the Core Public and Server API's are stable and diff --git a/src/core/server/config/deprecation/core_deprecations.test.ts b/src/core/server/config/deprecation/core_deprecations.test.ts index a7c6a638265239..a791362d9166f1 100644 --- a/src/core/server/config/deprecation/core_deprecations.test.ts +++ b/src/core/server/config/deprecation/core_deprecations.test.ts @@ -236,4 +236,24 @@ describe('core deprecations', () => { ).toEqual([`worker-src blob:`]); }); }); + + describe('logging.events.ops', () => { + it('warns when ops events are used', () => { + const { messages } = applyCoreDeprecations({ + logging: { events: { ops: '*' } }, + }); + expect(messages).toMatchInlineSnapshot(` + Array [ + "\\"logging.events.ops\\" has been deprecated and will be removed in 8.0. To access ops data moving forward, please enable debug logs for the \\"metrics.ops\\" context in your logging configuration.", + ] + `); + }); + + it('does not warn when other events are configured', () => { + const { messages } = applyCoreDeprecations({ + logging: { events: { log: '*' } }, + }); + expect(messages).toEqual([]); + }); + }); }); diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 6f6e6c3e0522e7..23a3518cd8eb68 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -103,6 +103,17 @@ const mapManifestServiceUrlDeprecation: ConfigDeprecation = (settings, fromPath, return settings; }; +const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, log) => { + if (has(settings, 'logging.events.ops')) { + log( + '"logging.events.ops" has been deprecated and will be removed ' + + 'in 8.0. To access ops data moving forward, please enable debug logs for the ' + + '"metrics.ops" context in your logging configuration.' + ); + } + return settings; +}; + export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unusedFromRoot }) => [ unusedFromRoot('savedObjects.indexCheckTimeout'), unusedFromRoot('server.xsrf.token'), @@ -137,4 +148,5 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unu rewriteBasePathDeprecation, cspRulesDeprecation, mapManifestServiceUrlDeprecation, + opsLoggingEventDeprecation, ]; diff --git a/src/core/server/logging/README.md b/src/core/server/logging/README.md index 8cb704f09ce8cd..cc2b6230d2d332 100644 --- a/src/core/server/logging/README.md +++ b/src/core/server/logging/README.md @@ -312,6 +312,9 @@ logging: - context: telemetry level: all appenders: [json-file-appender] + - context: metrics.ops + level: debug + appenders: [console] ``` Here is what we get with the config above: @@ -324,6 +327,7 @@ Here is what we get with the config above: | server | console, file | fatal | | optimize | console | error | | telemetry | json-file-appender | all | +| metrics.ops | console | debug | The `root` logger has a dedicated configuration node since this context is special and should always exist. By @@ -341,7 +345,25 @@ Or disable logging entirely with `off`: ```yaml logging.root.level: off ``` +### Dedicated loggers + +The `metrics.ops` logger is configured with `debug` level and will automatically output sample system and process information at a regular interval. +The metrics that are logged are a subset of the data collected and are formatted in the log message as follows: + +| Ops formatted log property | Location in metrics service | Log units +| :------------------------- | :-------------------------- | :-------------------------- | +| memory | process.memory.heap.used_in_bytes | [depends on the value](http://numeraljs.com/#format), typically MB or GB | +| uptime | process.uptime_in_millis | HH:mm:ss | +| load | os.load | [ "load for the last 1 min" "load for the last 5 min" "load for the last 15 min"] | +| delay | process.event_loop_delay | ms | + +The log interval is the same as the interval at which system and process information is refreshed and is configurable under `ops.interval`: + +```yaml +ops.interval: 5000 +``` +The minimum interval is 100ms and defaults to 5000ms. ## Usage Usage is very straightforward, one should just get a logger for a specific context and use it to log messages with @@ -478,4 +500,4 @@ TBD | meta | separate property `"meta": {"to": "v8"}` | merged in log record `{... "to": "v8"}` | | pid | `pid: 12345` | `pid: 12345` | | type | N/A | `type: log` | -| error | `{ message, name, stack }` | `{ message, name, stack, code, signal }` | \ No newline at end of file +| error | `{ message, name, stack }` | `{ message, name, stack, code, signal }` | diff --git a/src/core/server/logging/ecs.ts b/src/core/server/logging/ecs.ts new file mode 100644 index 00000000000000..0dbc403fca0b27 --- /dev/null +++ b/src/core/server/logging/ecs.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +/** + * Typings for some ECS fields which core uses internally. + * These are not a complete set of ECS typings and should not + * be used externally; the only types included here are ones + * currently used in core. + * + * @internal + */ + +export interface EcsOpsMetricsEvent { + /** + * These typings were written as of ECS 1.7.0. + * Don't change this value without checking the rest + * of the types to conform to that ECS version. + * + * https://www.elastic.co/guide/en/ecs/1.7/index.html + */ + ecs: { version: '1.7.0' }; + + // base fields + ['@timestamp']?: string; + labels?: Record; + message?: string; + tags?: string[]; + // other fields + process?: EcsProcessField; + event?: EcsEventField; +} + +interface EcsProcessField { + uptime?: number; +} + +export interface EcsEventField { + kind?: EcsEventKind; + category?: EcsEventCategory[]; + type?: EcsEventType; +} + +export enum EcsEventKind { + ALERT = 'alert', + EVENT = 'event', + METRIC = 'metric', + STATE = 'state', + PIPELINE_ERROR = 'pipeline_error', + SIGNAL = 'signal', +} + +export enum EcsEventCategory { + AUTHENTICATION = 'authentication', + CONFIGURATION = 'configuration', + DATABASE = 'database', + DRIVER = 'driver', + FILE = 'file', + HOST = 'host', + IAM = 'iam', + INTRUSION_DETECTION = 'intrusion_detection', + MALWARE = 'malware', + NETWORK = 'network', + PACKAGE = 'package', + PROCESS = 'process', + WEB = 'web', +} + +export enum EcsEventType { + ACCESS = 'access', + ADMIN = 'admin', + ALLOWED = 'allowed', + CHANGE = 'change', + CONNECTION = 'connection', + CREATION = 'creation', + DELETION = 'deletion', + DENIED = 'denied', + END = 'end', + ERROR = 'error', + GROUP = 'group', + INFO = 'info', + INSTALLATION = 'installation', + PROTOCOL = 'protocol', + START = 'start', + USER = 'user', +} diff --git a/src/core/server/logging/index.ts b/src/core/server/logging/index.ts index f024bea1bf3588..18a903af0a9fdf 100644 --- a/src/core/server/logging/index.ts +++ b/src/core/server/logging/index.ts @@ -17,6 +17,13 @@ export { LogLevelId, LogLevel, } from '@kbn/logging'; +export { + EcsOpsMetricsEvent, + EcsEventField, + EcsEventKind, + EcsEventCategory, + EcsEventType, +} from './ecs'; export { config, LoggingConfigType, diff --git a/src/core/server/metrics/logging/get_ops_metrics_log.test.ts b/src/core/server/metrics/logging/get_ops_metrics_log.test.ts new file mode 100644 index 00000000000000..820959910e764f --- /dev/null +++ b/src/core/server/metrics/logging/get_ops_metrics_log.test.ts @@ -0,0 +1,132 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import { OpsMetrics } from '..'; +import { getEcsOpsMetricsLog } from './get_ops_metrics_log'; + +function createBaseOpsMetrics(): OpsMetrics { + return { + collected_at: new Date('2020-01-01 01:00:00'), + process: { + memory: { + heap: { total_in_bytes: 1, used_in_bytes: 1, size_limit: 1 }, + resident_set_size_in_bytes: 1, + }, + event_loop_delay: 1, + pid: 1, + uptime_in_millis: 1, + }, + os: { + platform: 'darwin' as const, + platformRelease: 'test', + load: { '1m': 1, '5m': 1, '15m': 1 }, + memory: { total_in_bytes: 1, free_in_bytes: 1, used_in_bytes: 1 }, + uptime_in_millis: 1, + }, + response_times: { avg_in_millis: 1, max_in_millis: 1 }, + requests: { disconnects: 1, total: 1, statusCodes: { '200': 1 } }, + concurrent_connections: 1, + }; +} + +function createMockOpsMetrics(testMetrics: Partial): OpsMetrics { + const base = createBaseOpsMetrics(); + return { + ...base, + ...testMetrics, + }; +} +const testMetrics = ({ + process: { + memory: { heap: { used_in_bytes: 100 } }, + uptime_in_millis: 1500, + event_loop_delay: 50, + }, + os: { + load: { + '1m': 10, + '5m': 20, + '15m': 30, + }, + }, +} as unknown) as Partial; + +describe('getEcsOpsMetricsLog', () => { + it('provides correctly formatted message', () => { + const result = getEcsOpsMetricsLog(createMockOpsMetrics(testMetrics)); + expect(result.message).toMatchInlineSnapshot( + `"memory: 100.0B uptime: 0:00:01 load: [10.00,20.00,30.00] delay: 50.000"` + ); + }); + + it('correctly formats process uptime', () => { + const logMeta = getEcsOpsMetricsLog(createMockOpsMetrics(testMetrics)); + expect(logMeta.process!.uptime).toEqual(1); + }); + + it('excludes values from the message if unavailable', () => { + const baseMetrics = createBaseOpsMetrics(); + const missingMetrics = ({ + ...baseMetrics, + process: {}, + os: {}, + } as unknown) as OpsMetrics; + const logMeta = getEcsOpsMetricsLog(missingMetrics); + expect(logMeta.message).toMatchInlineSnapshot(`""`); + }); + + it('specifies correct ECS version', () => { + const logMeta = getEcsOpsMetricsLog(createBaseOpsMetrics()); + expect(logMeta.ecs.version).toBe('1.7.0'); + }); + + it('provides an ECS-compatible response', () => { + const logMeta = getEcsOpsMetricsLog(createBaseOpsMetrics()); + expect(logMeta).toMatchInlineSnapshot(` + Object { + "ecs": Object { + "version": "1.7.0", + }, + "event": Object { + "category": Array [ + "process", + "host", + ], + "kind": "metric", + "type": "info", + }, + "host": Object { + "os": Object { + "load": Object { + "15m": 1, + "1m": 1, + "5m": 1, + }, + }, + }, + "message": "memory: 1.0B load: [1.00,1.00,1.00] delay: 1.000", + "process": Object { + "eventLoopDelay": 1, + "memory": Object { + "heap": Object { + "usedInBytes": 1, + }, + }, + "uptime": 0, + }, + } + `); + }); + + it('logs ECS fields in the log meta', () => { + const logMeta = getEcsOpsMetricsLog(createBaseOpsMetrics()); + expect(logMeta.event!.kind).toBe('metric'); + expect(logMeta.event!.category).toEqual(expect.arrayContaining(['process', 'host'])); + expect(logMeta.event!.type).toBe('info'); + }); +}); diff --git a/src/core/server/metrics/logging/get_ops_metrics_log.ts b/src/core/server/metrics/logging/get_ops_metrics_log.ts new file mode 100644 index 00000000000000..361cac0bc310c5 --- /dev/null +++ b/src/core/server/metrics/logging/get_ops_metrics_log.ts @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import numeral from '@elastic/numeral'; +import { EcsOpsMetricsEvent, EcsEventKind, EcsEventCategory, EcsEventType } from '../../logging'; +import { OpsMetrics } from '..'; + +const ECS_VERSION = '1.7.0'; +/** + * Converts ops metrics into ECS-compliant `LogMeta` for logging + * + * @internal + */ +export function getEcsOpsMetricsLog(metrics: OpsMetrics): EcsOpsMetricsEvent { + const { process, os } = metrics; + const processMemoryUsedInBytes = process?.memory?.heap?.used_in_bytes; + const processMemoryUsedInBytesMsg = processMemoryUsedInBytes + ? `memory: ${numeral(processMemoryUsedInBytes).format('0.0b')} ` + : ''; + + // ECS process.uptime is in seconds: + const uptimeVal = process?.uptime_in_millis + ? Math.floor(process.uptime_in_millis / 1000) + : undefined; + + // HH:mm:ss message format for backward compatibility + const uptimeValMsg = uptimeVal ? `uptime: ${numeral(uptimeVal).format('00:00:00')} ` : ''; + + // Event loop delay is in ms + const eventLoopDelayVal = process?.event_loop_delay; + const eventLoopDelayValMsg = eventLoopDelayVal + ? `delay: ${numeral(process?.event_loop_delay).format('0.000')}` + : ''; + + const loadEntries = { + '1m': os?.load ? os?.load['1m'] : undefined, + '5m': os?.load ? os?.load['5m'] : undefined, + '15m': os?.load ? os?.load['15m'] : undefined, + }; + + const loadVals = [...Object.values(os?.load ?? [])]; + const loadValsMsg = + loadVals.length > 0 + ? `load: [${loadVals.map((val: number) => { + return numeral(val).format('0.00'); + })}] ` + : ''; + + return { + ecs: { version: ECS_VERSION }, + message: `${processMemoryUsedInBytesMsg}${uptimeValMsg}${loadValsMsg}${eventLoopDelayValMsg}`, + event: { + kind: EcsEventKind.METRIC, + category: [EcsEventCategory.PROCESS, EcsEventCategory.HOST], + type: EcsEventType.INFO, + }, + process: { + uptime: uptimeVal, + // @ts-expect-error custom fields not yet part of ECS + memory: { + heap: { + usedInBytes: processMemoryUsedInBytes, + }, + }, + eventLoopDelay: eventLoopDelayVal, + }, + host: { + os: { + load: loadEntries, + }, + }, + }; +} diff --git a/src/core/server/metrics/logging/index.ts b/src/core/server/metrics/logging/index.ts new file mode 100644 index 00000000000000..5b3f9aed56be0f --- /dev/null +++ b/src/core/server/metrics/logging/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +export { getEcsOpsMetricsLog } from './get_ops_metrics_log'; diff --git a/src/core/server/metrics/metrics_service.test.ts b/src/core/server/metrics/metrics_service.test.ts index 5ba29606d8a809..e21bad1ef4be77 100644 --- a/src/core/server/metrics/metrics_service.test.ts +++ b/src/core/server/metrics/metrics_service.test.ts @@ -13,12 +13,15 @@ import { mockOpsCollector } from './metrics_service.test.mocks'; import { MetricsService } from './metrics_service'; import { mockCoreContext } from '../core_context.mock'; import { httpServiceMock } from '../http/http_service.mock'; +import { loggingSystemMock } from '../logging/logging_system.mock'; import { take } from 'rxjs/operators'; const testInterval = 100; const dummyMetrics = { metricA: 'value', metricB: 'otherValue' }; +const logger = loggingSystemMock.create(); + describe('MetricsService', () => { const httpMock = httpServiceMock.createInternalSetupContract(); let metricsService: MetricsService; @@ -29,7 +32,7 @@ describe('MetricsService', () => { const configService = configServiceMock.create({ atPath: { interval: moment.duration(testInterval) }, }); - const coreContext = mockCoreContext.create({ configService }); + const coreContext = mockCoreContext.create({ logger, configService }); metricsService = new MetricsService(coreContext); }); @@ -118,6 +121,100 @@ describe('MetricsService', () => { expect(await nextEmission()).toEqual({ metric: 'first' }); expect(await nextEmission()).toEqual({ metric: 'second' }); }); + + it('logs the metrics at every interval', async () => { + const firstMetrics = { + process: { + memory: { heap: { used_in_bytes: 100 } }, + uptime_in_millis: 1500, + event_loop_delay: 50, + }, + os: { + load: { + '1m': 10, + '5m': 20, + '15m': 30, + }, + }, + }; + const secondMetrics = { + process: { + memory: { heap: { used_in_bytes: 200 } }, + uptime_in_millis: 3000, + event_loop_delay: 100, + }, + os: { + load: { + '1m': 20, + '5m': 30, + '15m': 40, + }, + }, + }; + + const opsLogger = logger.get('metrics', 'ops'); + + mockOpsCollector.collect + .mockResolvedValueOnce(firstMetrics) + .mockResolvedValueOnce(secondMetrics); + await metricsService.setup({ http: httpMock }); + const { getOpsMetrics$ } = await metricsService.start(); + + const nextEmission = async () => { + jest.advanceTimersByTime(testInterval); + const emission = await getOpsMetrics$().pipe(take(1)).toPromise(); + await new Promise((resolve) => process.nextTick(resolve)); + return emission; + }; + + await nextEmission(); + const opsLogs = loggingSystemMock.collect(opsLogger).debug; + expect(opsLogs.length).toEqual(2); + expect(opsLogs[0][1]).not.toEqual(opsLogs[1][1]); + }); + + it('omits metrics from log message if they are missing or malformed', async () => { + const opsLogger = logger.get('metrics', 'ops'); + mockOpsCollector.collect.mockResolvedValueOnce({ secondMetrics: 'metrics' }); + await metricsService.setup({ http: httpMock }); + await metricsService.start(); + expect(loggingSystemMock.collect(opsLogger).debug[0]).toMatchInlineSnapshot(` + Array [ + "", + Object { + "ecs": Object { + "version": "1.7.0", + }, + "event": Object { + "category": Array [ + "process", + "host", + ], + "kind": "metric", + "type": "info", + }, + "host": Object { + "os": Object { + "load": Object { + "15m": undefined, + "1m": undefined, + "5m": undefined, + }, + }, + }, + "process": Object { + "eventLoopDelay": undefined, + "memory": Object { + "heap": Object { + "usedInBytes": undefined, + }, + }, + "uptime": undefined, + }, + }, + ] + `); + }); }); describe('#stop', () => { diff --git a/src/core/server/metrics/metrics_service.ts b/src/core/server/metrics/metrics_service.ts index 24b2b1b67a07a3..460035ad2e2989 100644 --- a/src/core/server/metrics/metrics_service.ts +++ b/src/core/server/metrics/metrics_service.ts @@ -15,6 +15,7 @@ import { InternalHttpServiceSetup } from '../http'; import { InternalMetricsServiceSetup, InternalMetricsServiceStart, OpsMetrics } from './types'; import { OpsMetricsCollector } from './ops_metrics_collector'; import { opsConfig, OpsConfigType } from './ops_config'; +import { getEcsOpsMetricsLog } from './logging'; interface MetricsServiceSetupDeps { http: InternalHttpServiceSetup; @@ -24,6 +25,7 @@ interface MetricsServiceSetupDeps { export class MetricsService implements CoreService { private readonly logger: Logger; + private readonly opsMetricsLogger: Logger; private metricsCollector?: OpsMetricsCollector; private collectInterval?: NodeJS.Timeout; private metrics$ = new ReplaySubject(1); @@ -31,6 +33,7 @@ export class MetricsService constructor(private readonly coreContext: CoreContext) { this.logger = coreContext.logger.get('metrics'); + this.opsMetricsLogger = coreContext.logger.get('metrics', 'ops'); } public async setup({ http }: MetricsServiceSetupDeps): Promise { @@ -69,8 +72,9 @@ export class MetricsService } private async refreshMetrics() { - this.logger.debug('Refreshing metrics'); const metrics = await this.metricsCollector!.collect(); + const { message, ...meta } = getEcsOpsMetricsLog(metrics); + this.opsMetricsLogger.debug(message!, meta); this.metricsCollector!.reset(); this.metrics$.next(metrics); } From 3fe2e95e350ce8d13272df633d97aa2eabc62a07 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 22:53:14 -0500 Subject: [PATCH 15/58] Rename conversion function, extract to module scope and add tests. (#89018) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/requests/get_network_events.test.ts | 12 +++++++++++- .../uptime/server/lib/requests/get_network_events.ts | 12 +++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts index 2d590e80ca42d2..e1c62f34695181 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts @@ -5,9 +5,19 @@ */ import { getUptimeESMockClient } from './helper'; -import { getNetworkEvents } from './get_network_events'; +import { getNetworkEvents, secondsToMillis } from './get_network_events'; describe('getNetworkEvents', () => { + describe('secondsToMillis conversion', () => { + it('returns -1 for -1 value', () => { + expect(secondsToMillis(-1)).toBe(-1); + }); + + it('returns a value of seconds as milliseconds', () => { + expect(secondsToMillis(10)).toBe(10_000); + }); + }); + let mockHits: any; beforeEach(() => { diff --git a/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts b/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts index ec1fffd62350d9..6b1bca8f2d7b72 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts @@ -12,6 +12,10 @@ interface GetNetworkEventsParams { stepIndex: string; } +export const secondsToMillis = (seconds: number) => + // -1 is a special case where a value was unavailable + seconds === -1 ? -1 : seconds * 1000; + export const getNetworkEvents: UMElasticsearchQueryFn< GetNetworkEventsParams, { events: NetworkEvent[]; total: number } @@ -35,17 +39,15 @@ export const getNetworkEvents: UMElasticsearchQueryFn< const { body: result } = await uptimeEsClient.search({ body: params }); - const microToMillis = (micro: number): number => (micro === -1 ? -1 : micro * 1000); - return { total: result.hits.total.value, events: result.hits.hits.map((event: any) => { - const requestSentTime = microToMillis(event._source.synthetics.payload.request_sent_time); - const loadEndTime = microToMillis(event._source.synthetics.payload.load_end_time); + const requestSentTime = secondsToMillis(event._source.synthetics.payload.request_sent_time); + const loadEndTime = secondsToMillis(event._source.synthetics.payload.load_end_time); const requestStartTime = event._source.synthetics.payload.response && event._source.synthetics.payload.response.timing - ? microToMillis(event._source.synthetics.payload.response.timing.request_time) + ? secondsToMillis(event._source.synthetics.payload.response.timing.request_time) : undefined; return { From 053628cae862103b8c27bc60656bf45d76dc3f5d Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Wed, 27 Jan 2021 09:54:56 +0100 Subject: [PATCH 16/58] [APM] Optimize API test order (#88654) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fake_mocha_types.d.ts | 2 + .../snapshots/decorate_snapshot_ui.test.ts | 63 ++- .../lib/snapshots/decorate_snapshot_ui.ts | 89 ++-- .../test/apm_api_integration/basic/config.ts | 8 +- .../basic/tests/alerts/chart_preview.ts | 124 ----- .../apm_api_integration/basic/tests/index.ts | 72 --- .../tests/metrics_charts/metrics_charts.ts | 439 ---------------- .../basic/tests/service_maps/service_maps.ts | 32 -- .../basic/tests/services/annotations.ts | 48 -- .../basic/tests/services/throughput.ts | 85 --- .../basic/tests/services/top_services.ts | 259 --------- .../tests/settings/agent_configuration.ts | 489 ----------------- .../anomaly_detection/no_access_user.ts | 43 -- .../settings/anomaly_detection/read_user.ts | 46 -- .../settings/anomaly_detection/write_user.ts | 50 -- .../basic/tests/settings/custom_link.ts | 35 -- .../basic/tests/transactions/breakdown.ts | 123 ----- .../basic/tests/transactions/latency.ts | 102 ---- .../test/apm_api_integration/common/config.ts | 17 +- .../apm_api_integration/common/registry.ts | 160 ++++++ .../test/apm_api_integration/configs/index.ts | 25 + .../tests/alerts/chart_preview.ts | 70 +++ .../tests/correlations/slow_transactions.ts | 88 ++++ .../csm/__snapshots__/page_load_dist.snap | 8 +- .../tests/csm/__snapshots__/page_views.snap | 8 +- .../tests/csm/csm_services.ts | 40 ++ .../{trial => }/tests/csm/has_rum_data.ts | 39 +- .../{trial => }/tests/csm/js_errors.ts | 39 +- .../tests/csm/long_task_metrics.ts | 47 +- .../tests/csm/page_load_dist.ts | 58 ++ .../tests/csm/page_views.ts | 58 ++ .../tests/csm/url_search.ts | 82 +++ .../{trial => }/tests/csm/web_core_vitals.ts | 51 +- .../{basic => }/tests/feature_controls.ts | 5 +- .../test/apm_api_integration/tests/index.ts | 70 +++ .../tests/metrics_charts/metrics_charts.ts | 446 ++++++++++++++++ .../tests/observability_overview/has_data.ts | 37 +- .../observability_overview.ts | 42 +- .../__snapshots__/service_maps.snap | 6 +- .../tests/service_maps/service_maps.ts | 155 +++--- .../service_overview/dependencies/es_utils.ts | 0 .../service_overview/dependencies/index.ts | 44 +- .../tests/service_overview/error_groups.ts | 27 +- .../tests/service_overview/instances.ts | 65 +-- .../services/__snapshots__/throughput.snap | 2 +- .../{basic => }/tests/services/agent_name.ts | 35 +- .../{trial => }/tests/services/annotations.ts | 30 +- .../tests/services/service_details.ts | 27 +- .../tests/services/service_icons.ts | 63 ++- .../tests/services/throughput.ts | 82 +++ .../tests/services/top_services.ts | 364 +++++++++++++ .../tests/services/transaction_types.ts | 27 +- .../tests/settings/agent_configuration.ts | 495 ++++++++++++++++++ .../tests/settings/anomaly_detection/basic.ts | 53 ++ .../anomaly_detection/no_access_user.ts | 44 ++ .../settings/anomaly_detection/read_user.ts | 46 ++ .../settings/anomaly_detection/write_user.ts | 56 ++ .../tests/settings/custom_link.ts | 183 +++++++ .../traces/__snapshots__/top_traces.snap | 2 +- .../{basic => }/tests/traces/top_traces.ts | 36 +- .../transactions/__snapshots__/breakdown.snap | 4 +- .../__snapshots__/error_rate.snap | 2 +- .../transactions/__snapshots__/latency.snap | 46 ++ .../__snapshots__/top_transaction_groups.snap | 2 +- .../__snapshots__/transaction_charts.snap | 0 .../__snapshots__/transactions_charts.snap | 0 .../tests/transactions/breakdown.ts | 118 +++++ .../tests/transactions/distribution.ts | 26 +- .../tests/transactions/error_rate.ts | 43 +- .../tests/transactions/latency.ts | 243 +++++++++ .../tests/transactions/throughput.ts | 53 +- .../transactions/top_transaction_groups.ts | 26 +- .../transactions_groups_overview.ts | 27 +- .../test/apm_api_integration/trial/config.ts | 8 +- .../tests/correlations/slow_transactions.ts | 95 ---- .../trial/tests/csm/csm_services.ts | 47 -- .../trial/tests/csm/page_load_dist.ts | 64 --- .../trial/tests/csm/page_views.ts | 64 --- .../trial/tests/csm/url_search.ts | 89 ---- .../apm_api_integration/trial/tests/index.ts | 50 -- .../trial/tests/services/top_services.ts | 131 ----- .../anomaly_detection/no_access_user.ts | 41 -- .../settings/anomaly_detection/read_user.ts | 43 -- .../settings/anomaly_detection/write_user.ts | 53 -- .../trial/tests/settings/custom_link.ts | 159 ------ .../transactions/__snapshots__/latency.snap | 46 -- .../trial/tests/transactions/latency.ts | 159 ------ 87 files changed, 3447 insertions(+), 3533 deletions(-) delete mode 100644 x-pack/test/apm_api_integration/basic/tests/alerts/chart_preview.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/index.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/metrics_charts/metrics_charts.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/services/annotations.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/services/throughput.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/services/top_services.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/no_access_user.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/read_user.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/write_user.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/transactions/breakdown.ts delete mode 100644 x-pack/test/apm_api_integration/basic/tests/transactions/latency.ts create mode 100644 x-pack/test/apm_api_integration/common/registry.ts create mode 100644 x-pack/test/apm_api_integration/configs/index.ts create mode 100644 x-pack/test/apm_api_integration/tests/alerts/chart_preview.ts create mode 100644 x-pack/test/apm_api_integration/tests/correlations/slow_transactions.ts rename x-pack/test/apm_api_integration/{trial => }/tests/csm/__snapshots__/page_load_dist.snap (95%) rename x-pack/test/apm_api_integration/{trial => }/tests/csm/__snapshots__/page_views.snap (90%) create mode 100644 x-pack/test/apm_api_integration/tests/csm/csm_services.ts rename x-pack/test/apm_api_integration/{trial => }/tests/csm/has_rum_data.ts (53%) rename x-pack/test/apm_api_integration/{trial => }/tests/csm/js_errors.ts (72%) rename x-pack/test/apm_api_integration/{trial => }/tests/csm/long_task_metrics.ts (50%) create mode 100644 x-pack/test/apm_api_integration/tests/csm/page_load_dist.ts create mode 100644 x-pack/test/apm_api_integration/tests/csm/page_views.ts create mode 100644 x-pack/test/apm_api_integration/tests/csm/url_search.ts rename x-pack/test/apm_api_integration/{trial => }/tests/csm/web_core_vitals.ts (55%) rename x-pack/test/apm_api_integration/{basic => }/tests/feature_controls.ts (98%) create mode 100644 x-pack/test/apm_api_integration/tests/index.ts create mode 100644 x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.ts rename x-pack/test/apm_api_integration/{basic => }/tests/observability_overview/has_data.ts (67%) rename x-pack/test/apm_api_integration/{basic => }/tests/observability_overview/observability_overview.ts (69%) rename x-pack/test/apm_api_integration/{trial => }/tests/service_maps/__snapshots__/service_maps.snap (99%) rename x-pack/test/apm_api_integration/{trial => }/tests/service_maps/service_maps.ts (58%) rename x-pack/test/apm_api_integration/{basic => }/tests/service_overview/dependencies/es_utils.ts (100%) rename x-pack/test/apm_api_integration/{basic => }/tests/service_overview/dependencies/index.ts (91%) rename x-pack/test/apm_api_integration/{basic => }/tests/service_overview/error_groups.ts (94%) rename x-pack/test/apm_api_integration/{basic => }/tests/service_overview/instances.ts (83%) rename x-pack/test/apm_api_integration/{basic => }/tests/services/__snapshots__/throughput.snap (96%) rename x-pack/test/apm_api_integration/{basic => }/tests/services/agent_name.ts (55%) rename x-pack/test/apm_api_integration/{trial => }/tests/services/annotations.ts (92%) rename x-pack/test/apm_api_integration/{basic => }/tests/services/service_details.ts (87%) rename x-pack/test/apm_api_integration/{basic => }/tests/services/service_icons.ts (53%) create mode 100644 x-pack/test/apm_api_integration/tests/services/throughput.ts create mode 100644 x-pack/test/apm_api_integration/tests/services/top_services.ts rename x-pack/test/apm_api_integration/{basic => }/tests/services/transaction_types.ts (75%) create mode 100644 x-pack/test/apm_api_integration/tests/settings/agent_configuration.ts create mode 100644 x-pack/test/apm_api_integration/tests/settings/anomaly_detection/basic.ts create mode 100644 x-pack/test/apm_api_integration/tests/settings/anomaly_detection/no_access_user.ts create mode 100644 x-pack/test/apm_api_integration/tests/settings/anomaly_detection/read_user.ts create mode 100644 x-pack/test/apm_api_integration/tests/settings/anomaly_detection/write_user.ts create mode 100644 x-pack/test/apm_api_integration/tests/settings/custom_link.ts rename x-pack/test/apm_api_integration/{basic => }/tests/traces/__snapshots__/top_traces.snap (99%) rename x-pack/test/apm_api_integration/{basic => }/tests/traces/top_traces.ts (81%) rename x-pack/test/apm_api_integration/{basic => }/tests/transactions/__snapshots__/breakdown.snap (98%) rename x-pack/test/apm_api_integration/{basic => }/tests/transactions/__snapshots__/error_rate.snap (95%) create mode 100644 x-pack/test/apm_api_integration/tests/transactions/__snapshots__/latency.snap rename x-pack/test/apm_api_integration/{basic => }/tests/transactions/__snapshots__/top_transaction_groups.snap (96%) rename x-pack/test/apm_api_integration/{basic => }/tests/transactions/__snapshots__/transaction_charts.snap (100%) rename x-pack/test/apm_api_integration/{trial => }/tests/transactions/__snapshots__/transactions_charts.snap (100%) create mode 100644 x-pack/test/apm_api_integration/tests/transactions/breakdown.ts rename x-pack/test/apm_api_integration/{basic => }/tests/transactions/distribution.ts (85%) rename x-pack/test/apm_api_integration/{basic => }/tests/transactions/error_rate.ts (71%) create mode 100644 x-pack/test/apm_api_integration/tests/transactions/latency.ts rename x-pack/test/apm_api_integration/{basic => }/tests/transactions/throughput.ts (54%) rename x-pack/test/apm_api_integration/{basic => }/tests/transactions/top_transaction_groups.ts (80%) rename x-pack/test/apm_api_integration/{basic => }/tests/transactions/transactions_groups_overview.ts (94%) delete mode 100644 x-pack/test/apm_api_integration/trial/tests/correlations/slow_transactions.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/csm/csm_services.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/csm/page_load_dist.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/csm/page_views.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/csm/url_search.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/index.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/services/top_services.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/no_access_user.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/read_user.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/write_user.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/settings/custom_link.ts delete mode 100644 x-pack/test/apm_api_integration/trial/tests/transactions/__snapshots__/latency.snap delete mode 100644 x-pack/test/apm_api_integration/trial/tests/transactions/latency.ts diff --git a/packages/kbn-test/src/functional_test_runner/fake_mocha_types.d.ts b/packages/kbn-test/src/functional_test_runner/fake_mocha_types.d.ts index 6efc8774b0139b..e78cbbb3aed022 100644 --- a/packages/kbn-test/src/functional_test_runner/fake_mocha_types.d.ts +++ b/packages/kbn-test/src/functional_test_runner/fake_mocha_types.d.ts @@ -20,6 +20,8 @@ export interface Suite { title: string; file?: string; parent?: Suite; + eachTest: (cb: (test: Test) => void) => void; + root: boolean; } export interface Test { diff --git a/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.test.ts b/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.test.ts index 2a238cdeb53854..a8b0252e6f51c0 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.test.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.test.ts @@ -6,21 +6,44 @@ * Public License, v 1. */ -import { Test } from '../../fake_mocha_types'; +import { Suite, Test } from '../../fake_mocha_types'; import { Lifecycle } from '../lifecycle'; import { decorateSnapshotUi, expectSnapshot } from './decorate_snapshot_ui'; import path from 'path'; import fs from 'fs'; +const createMockSuite = ({ tests, root = true }: { tests: Test[]; root?: boolean }) => { + const suite = { + tests, + root, + eachTest: (cb: (test: Test) => void) => { + suite.tests.forEach((test) => cb(test)); + }, + } as Suite; + + return suite; +}; + const createMockTest = ({ title = 'Test', passed = true, -}: { title?: string; passed?: boolean } = {}) => { - return { + filename = __filename, + parent, +}: { title?: string; passed?: boolean; filename?: string; parent?: Suite } = {}) => { + const test = ({ + file: filename, fullTitle: () => title, isPassed: () => passed, - parent: {}, - } as Test; + } as unknown) as Test; + + if (parent) { + parent.tests.push(test); + test.parent = parent; + } else { + test.parent = createMockSuite({ tests: [test] }); + } + + return test; }; describe('decorateSnapshotUi', () => { @@ -211,7 +234,7 @@ exports[\`Test2 1\`] = \`"bar"\`; expectSnapshot('bar').toMatch(); }).not.toThrow(); - const afterTestSuite = lifecycle.afterTestSuite.trigger({}); + const afterTestSuite = lifecycle.afterTestSuite.trigger(test.parent); await expect(afterTestSuite).resolves.toBe(undefined); }); @@ -225,7 +248,7 @@ exports[\`Test2 1\`] = \`"bar"\`; expectSnapshot('foo').toMatch(); }).not.toThrow(); - const afterTestSuite = lifecycle.afterTestSuite.trigger({}); + const afterTestSuite = lifecycle.afterTestSuite.trigger(test.parent); await expect(afterTestSuite).rejects.toMatchInlineSnapshot(` [Error: 1 obsolete snapshot(s) found: @@ -234,6 +257,32 @@ exports[\`Test2 1\`] = \`"bar"\`; Run tests again with \`--updateSnapshots\` to remove them.] `); }); + + it('does not throw on unused when some tests are skipped', async () => { + const root = createMockSuite({ tests: [] }); + + const test = createMockTest({ + title: 'Test', + parent: root, + passed: true, + }); + + createMockTest({ + title: 'Test2', + parent: root, + passed: false, + }); + + await lifecycle.beforeEachTest.trigger(test); + + expect(() => { + expectSnapshot('foo').toMatch(); + }).not.toThrow(); + + const afterTestSuite = lifecycle.afterTestSuite.trigger(root); + + await expect(afterTestSuite).resolves.toBeUndefined(); + }); }); }); }); diff --git a/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.ts b/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.ts index 2111f1a6e5e900..4a52299ecf6d1c 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.ts @@ -16,9 +16,8 @@ import path from 'path'; import prettier from 'prettier'; import babelTraverse from '@babel/traverse'; import { once } from 'lodash'; -import callsites from 'callsites'; import { Lifecycle } from '../lifecycle'; -import { Test } from '../../fake_mocha_types'; +import { Suite, Test } from '../../fake_mocha_types'; type ISnapshotState = InstanceType; @@ -33,12 +32,12 @@ const globalState: { updateSnapshot: SnapshotUpdateState; registered: boolean; currentTest: Test | null; - snapshots: Array<{ tests: Test[]; file: string; snapshotState: ISnapshotState }>; + snapshotStates: Record; } = { updateSnapshot: 'none', registered: false, currentTest: null, - snapshots: [], + snapshotStates: {}, }; const modifyStackTracePrepareOnce = once(() => { @@ -73,7 +72,7 @@ export function decorateSnapshotUi({ isCi: boolean; }) { globalState.registered = true; - globalState.snapshots.length = 0; + globalState.snapshotStates = {}; globalState.currentTest = null; if (isCi) { @@ -102,32 +101,36 @@ export function decorateSnapshotUi({ globalState.currentTest = test; }); - lifecycle.afterTestSuite.add(function (testSuite) { + lifecycle.afterTestSuite.add(function (testSuite: Suite) { // save snapshot & check unused after top-level test suite completes - if (testSuite.parent?.parent) { + if (!testSuite.root) { return; } - const unused: string[] = []; + testSuite.eachTest((test) => { + const file = test.file; - globalState.snapshots.forEach((snapshot) => { - const { tests, snapshotState } = snapshot; - tests.forEach((test) => { - const title = test.fullTitle(); - // If test is failed or skipped, mark snapshots as used. Otherwise, - // running a test in isolation will generate false positives. - if (!test.isPassed()) { - snapshotState.markSnapshotsAsCheckedForTest(title); - } - }); + if (!file) { + return; + } + + const snapshotState = globalState.snapshotStates[file]; + + if (snapshotState && !test.isPassed()) { + snapshotState.markSnapshotsAsCheckedForTest(test.fullTitle()); + } + }); + + const unused: string[] = []; - if (globalState.updateSnapshot !== 'all') { - unused.push(...snapshotState.getUncheckedKeys()); - } else { - snapshotState.removeUncheckedKeys(); + Object.values(globalState.snapshotStates).forEach((state) => { + if (globalState.updateSnapshot === 'all') { + state.removeUncheckedKeys(); } - snapshotState.save(); + unused.push(...state.getUncheckedKeys()); + + state.save(); }); if (unused.length) { @@ -138,7 +141,7 @@ export function decorateSnapshotUi({ ); } - globalState.snapshots.length = 0; + globalState.snapshotStates = {}; }); } @@ -161,43 +164,29 @@ function getSnapshotState(file: string, updateSnapshot: SnapshotUpdateState) { export function expectSnapshot(received: any) { if (!globalState.registered) { - throw new Error( - 'Mocha hooks were not registered before expectSnapshot was used. Call `registerMochaHooksForSnapshots` in your top-level describe().' - ); - } - - if (!globalState.currentTest) { - throw new Error('expectSnapshot can only be called inside of an it()'); + throw new Error('expectSnapshot UI was not initialized before calling expectSnapshot()'); } - const [, fileOfTest] = callsites().map((site) => site.getFileName()); + const test = globalState.currentTest; - if (!fileOfTest) { - throw new Error("Couldn't infer a filename for the current test"); + if (!test) { + throw new Error('expectSnapshot can only be called inside of an it()'); } - let snapshot = globalState.snapshots.find(({ file }) => file === fileOfTest); - - if (!snapshot) { - snapshot = { - file: fileOfTest, - tests: [], - snapshotState: getSnapshotState(fileOfTest, globalState.updateSnapshot), - }; - globalState.snapshots.unshift(snapshot!); + if (!test.file) { + throw new Error('File for test not found'); } - if (!snapshot) { - throw new Error('Snapshot is undefined'); - } + let snapshotState = globalState.snapshotStates[test.file]; - if (!snapshot.tests.includes(globalState.currentTest)) { - snapshot.tests.push(globalState.currentTest); + if (!snapshotState) { + snapshotState = getSnapshotState(test.file, globalState.updateSnapshot); + globalState.snapshotStates[test.file] = snapshotState; } const context: SnapshotContext = { - snapshotState: snapshot.snapshotState, - currentTestName: globalState.currentTest.fullTitle(), + snapshotState, + currentTestName: test.fullTitle(), }; return { diff --git a/x-pack/test/apm_api_integration/basic/config.ts b/x-pack/test/apm_api_integration/basic/config.ts index 03b8b21bf3232e..f3e6ec29f3df2a 100644 --- a/x-pack/test/apm_api_integration/basic/config.ts +++ b/x-pack/test/apm_api_integration/basic/config.ts @@ -4,10 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createTestConfig } from '../common/config'; +import { configs } from '../configs'; -export default createTestConfig({ - license: 'basic', - name: 'X-Pack APM API integration tests (basic)', - testFiles: [require.resolve('./tests')], -}); +export default configs.basic; diff --git a/x-pack/test/apm_api_integration/basic/tests/alerts/chart_preview.ts b/x-pack/test/apm_api_integration/basic/tests/alerts/chart_preview.ts deleted file mode 100644 index 46c0dbeb8940ff..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/alerts/chart_preview.ts +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { format } from 'url'; -import archives from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const supertest = getService('supertest'); - const archiveName = 'apm_8.0.0'; - const { end } = archives[archiveName]; - const start = new Date(Date.parse(end) - 600000).toISOString(); - - describe('Alerting chart previews', () => { - describe('GET /api/apm/alerts/chart_preview/transaction_error_rate', () => { - const url = format({ - pathname: '/api/apm/alerts/chart_preview/transaction_error_rate', - query: { - start, - end, - transactionType: 'request', - serviceName: 'opbeans-java', - }, - }); - - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await supertest.get(url); - - expect(response.status).to.be(200); - expect(response.body).to.eql([]); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - it('returns the correct data', async () => { - const response = await supertest.get(url); - - expect(response.status).to.be(200); - expect( - response.body.some((item: { x: number; y: number | null }) => item.x && item.y) - ).to.equal(true); - }); - }); - }); - - describe('GET /api/apm/alerts/chart_preview/transaction_error_count', () => { - const url = format({ - pathname: '/api/apm/alerts/chart_preview/transaction_error_count', - query: { - start, - end, - serviceName: 'opbeans-java', - }, - }); - - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await supertest.get(url); - - expect(response.status).to.be(200); - expect(response.body).to.eql([]); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - it('returns the correct data', async () => { - const response = await supertest.get(url); - - expect(response.status).to.be(200); - expect( - response.body.some((item: { x: number; y: number | null }) => item.x && item.y) - ).to.equal(true); - }); - }); - }); - - describe('GET /api/apm/alerts/chart_preview/transaction_duration', () => { - const url = format({ - pathname: '/api/apm/alerts/chart_preview/transaction_duration', - query: { - start, - end, - serviceName: 'opbeans-java', - transactionType: 'request', - }, - }); - - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await supertest.get(url); - - expect(response.status).to.be(200); - expect(response.body).to.eql([]); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - it('returns the correct data', async () => { - const response = await supertest.get(url); - - expect(response.status).to.be(200); - expect( - response.body.some((item: { x: number; y: number | null }) => item.x && item.y) - ).to.equal(true); - }); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/basic/tests/index.ts b/x-pack/test/apm_api_integration/basic/tests/index.ts deleted file mode 100644 index 4e66c6e6f76c39..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/index.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { FtrProviderContext } from '../../common/ftr_provider_context'; - -export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderContext) { - describe('APM specs (basic)', function () { - this.tags('ciGroup1'); - - loadTestFile(require.resolve('./feature_controls')); - - describe('Alerts', function () { - loadTestFile(require.resolve('./alerts/chart_preview')); - }); - - describe('Service Maps', function () { - loadTestFile(require.resolve('./service_maps/service_maps')); - }); - - describe('Services', function () { - loadTestFile(require.resolve('./services/agent_name')); - loadTestFile(require.resolve('./services/annotations')); - loadTestFile(require.resolve('./services/throughput')); - loadTestFile(require.resolve('./services/top_services')); - loadTestFile(require.resolve('./services/transaction_types')); - loadTestFile(require.resolve('./services/service_details')); - loadTestFile(require.resolve('./services/service_icons')); - }); - - describe('Service overview', function () { - loadTestFile(require.resolve('./service_overview/error_groups')); - loadTestFile(require.resolve('./service_overview/dependencies')); - loadTestFile(require.resolve('./service_overview/instances')); - }); - - describe('Settings', function () { - loadTestFile(require.resolve('./settings/custom_link')); - loadTestFile(require.resolve('./settings/agent_configuration')); - - describe('Anomaly detection', function () { - loadTestFile(require.resolve('./settings/anomaly_detection/no_access_user')); - loadTestFile(require.resolve('./settings/anomaly_detection/read_user')); - loadTestFile(require.resolve('./settings/anomaly_detection/write_user')); - }); - }); - - describe('Traces', function () { - loadTestFile(require.resolve('./traces/top_traces')); - }); - - describe('Transactions', function () { - loadTestFile(require.resolve('./transactions/top_transaction_groups')); - loadTestFile(require.resolve('./transactions/latency')); - loadTestFile(require.resolve('./transactions/throughput')); - loadTestFile(require.resolve('./transactions/error_rate')); - loadTestFile(require.resolve('./transactions/breakdown')); - loadTestFile(require.resolve('./transactions/distribution')); - loadTestFile(require.resolve('./transactions/transactions_groups_overview')); - }); - - describe('Observability overview', function () { - loadTestFile(require.resolve('./observability_overview/has_data')); - loadTestFile(require.resolve('./observability_overview/observability_overview')); - }); - - describe('Metrics', function () { - loadTestFile(require.resolve('./metrics_charts/metrics_charts')); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/basic/tests/metrics_charts/metrics_charts.ts b/x-pack/test/apm_api_integration/basic/tests/metrics_charts/metrics_charts.ts deleted file mode 100644 index d52aa2727d651e..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/metrics_charts/metrics_charts.ts +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import expect from '@kbn/expect'; -import { first } from 'lodash'; -import { MetricsChartsByAgentAPIResponse } from '../../../../../plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent'; -import { GenericMetricsChart } from '../../../../../plugins/apm/server/lib/metrics/transform_metrics_chart'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -interface ChartResponse { - body: MetricsChartsByAgentAPIResponse; - status: number; -} - -export default function ApiTest({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - describe('when data is loaded', () => { - before(() => esArchiver.load('metrics_8.0.0')); - after(() => esArchiver.unload('metrics_8.0.0')); - - describe('for opbeans-node', () => { - const start = encodeURIComponent('2020-09-08T14:50:00.000Z'); - const end = encodeURIComponent('2020-09-08T14:55:00.000Z'); - const uiFilters = encodeURIComponent(JSON.stringify({})); - const agentName = 'nodejs'; - - describe('returns metrics data', () => { - let chartsResponse: ChartResponse; - before(async () => { - chartsResponse = await supertest.get( - `/api/apm/services/opbeans-node/metrics/charts?start=${start}&end=${end}&uiFilters=${uiFilters}&agentName=${agentName}` - ); - }); - it('contains CPU usage and System memory usage chart data', async () => { - expect(chartsResponse.status).to.be(200); - expectSnapshot(chartsResponse.body.charts.map((chart) => chart.title)).toMatchInline(` - Array [ - "CPU usage", - "System memory usage", - ] - `); - }); - - describe('CPU usage', () => { - let cpuUsageChart: GenericMetricsChart | undefined; - before(() => { - cpuUsageChart = chartsResponse.body.charts.find(({ key }) => key === 'cpu_usage_chart'); - }); - - it('has correct series', () => { - expect(cpuUsageChart).to.not.empty(); - expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "System max", - "System average", - "Process max", - "Process average", - ] - `); - }); - - it('has correct series overall values', () => { - expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 0.714, - 0.3877, - 0.75, - 0.2543, - ] - `); - }); - }); - - describe("System memory usage (using 'system.memory' fields to calculate the memory usage)", () => { - let systemMemoryUsageChart: GenericMetricsChart | undefined; - before(() => { - systemMemoryUsageChart = chartsResponse.body.charts.find( - ({ key }) => key === 'memory_usage_chart' - ); - }); - - it('has correct series', () => { - expect(systemMemoryUsageChart).to.not.empty(); - expectSnapshot(systemMemoryUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "Max", - "Average", - ] - `); - }); - - it('has correct series overall values', () => { - expectSnapshot(systemMemoryUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 0.722093920925555, - 0.718173546796348, - ] - `); - }); - }); - }); - }); - - describe('for opbeans-java', () => { - const uiFilters = encodeURIComponent(JSON.stringify({})); - const agentName = 'java'; - - describe('returns metrics data', () => { - const start = encodeURIComponent('2020-09-08T14:55:30.000Z'); - const end = encodeURIComponent('2020-09-08T15:00:00.000Z'); - - let chartsResponse: ChartResponse; - before(async () => { - chartsResponse = await supertest.get( - `/api/apm/services/opbeans-java/metrics/charts?start=${start}&end=${end}&uiFilters=${uiFilters}&agentName=${agentName}` - ); - }); - - it('has correct chart data', async () => { - expect(chartsResponse.status).to.be(200); - expectSnapshot(chartsResponse.body.charts.map((chart) => chart.title)).toMatchInline(` - Array [ - "CPU usage", - "System memory usage", - "Heap Memory", - "Non-Heap Memory", - "Thread Count", - "Garbage collection per minute", - "Garbage collection time spent per minute", - ] - `); - }); - - describe('CPU usage', () => { - let cpuUsageChart: GenericMetricsChart | undefined; - before(() => { - cpuUsageChart = chartsResponse.body.charts.find(({ key }) => key === 'cpu_usage_chart'); - }); - - it('has correct series', () => { - expect(cpuUsageChart).to.not.empty(); - expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "System max", - "System average", - "Process max", - "Process average", - ] - `); - }); - - it('has correct series overall values', () => { - expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 0.203, - 0.178777777777778, - 0.01, - 0.009, - ] - `); - }); - - it('has the correct rate', async () => { - const yValues = cpuUsageChart?.series.map((serie) => first(serie.data)?.y); - expectSnapshot(yValues).toMatchInline(` - Array [ - 0.193, - 0.193, - 0.009, - 0.009, - ] - `); - }); - }); - - describe("System memory usage (using 'system.process.cgroup' fields to calculate the memory usage)", () => { - let systemMemoryUsageChart: GenericMetricsChart | undefined; - before(() => { - systemMemoryUsageChart = chartsResponse.body.charts.find( - ({ key }) => key === 'memory_usage_chart' - ); - }); - - it('has correct series', () => { - expect(systemMemoryUsageChart).to.not.empty(); - expectSnapshot(systemMemoryUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "Max", - "Average", - ] - `); - }); - - it('has correct series overall values', () => { - expectSnapshot(systemMemoryUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 0.707924703557837, - 0.705395980841182, - ] - `); - }); - - it('has the correct rate', async () => { - const yValues = systemMemoryUsageChart?.series.map((serie) => first(serie.data)?.y); - expectSnapshot(yValues).toMatchInline(` - Array [ - 0.707924703557837, - 0.707924703557837, - ] - `); - }); - }); - - describe('Heap Memory', () => { - let cpuUsageChart: GenericMetricsChart | undefined; - before(() => { - cpuUsageChart = chartsResponse.body.charts.find( - ({ key }) => key === 'heap_memory_area_chart' - ); - }); - - it('has correct series', () => { - expect(cpuUsageChart).to.not.empty(); - expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "Avg. used", - "Avg. committed", - "Avg. limit", - ] - `); - }); - - it('has correct series overall values', () => { - expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 222501617.777778, - 374341632, - 1560281088, - ] - `); - }); - - it('has the correct rate', async () => { - const yValues = cpuUsageChart?.series.map((serie) => first(serie.data)?.y); - expectSnapshot(yValues).toMatchInline(` - Array [ - 211472896, - 374341632, - 1560281088, - ] - `); - }); - }); - - describe('Non-Heap Memory', () => { - let cpuUsageChart: GenericMetricsChart | undefined; - before(() => { - cpuUsageChart = chartsResponse.body.charts.find( - ({ key }) => key === 'non_heap_memory_area_chart' - ); - }); - - it('has correct series', () => { - expect(cpuUsageChart).to.not.empty(); - expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "Avg. used", - "Avg. committed", - ] - `); - }); - - it('has correct series overall values', () => { - expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 138573397.333333, - 147677639.111111, - ] - `); - }); - - it('has the correct rate', async () => { - const yValues = cpuUsageChart?.series.map((serie) => first(serie.data)?.y); - expectSnapshot(yValues).toMatchInline(` - Array [ - 138162752, - 147386368, - ] - `); - }); - }); - - describe('Thread Count', () => { - let cpuUsageChart: GenericMetricsChart | undefined; - before(() => { - cpuUsageChart = chartsResponse.body.charts.find( - ({ key }) => key === 'thread_count_line_chart' - ); - }); - - it('has correct series', () => { - expect(cpuUsageChart).to.not.empty(); - expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "Avg. count", - "Max count", - ] - `); - }); - - it('has correct series overall values', () => { - expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 44.4444444444444, - 45, - ] - `); - }); - - it('has the correct rate', async () => { - const yValues = cpuUsageChart?.series.map((serie) => first(serie.data)?.y); - expectSnapshot(yValues).toMatchInline(` - Array [ - 44, - 44, - ] - `); - }); - }); - - describe('Garbage collection per minute', () => { - let cpuUsageChart: GenericMetricsChart | undefined; - before(() => { - cpuUsageChart = chartsResponse.body.charts.find( - ({ key }) => key === 'gc_rate_line_chart' - ); - }); - - it('has correct series', () => { - expect(cpuUsageChart).to.not.empty(); - expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "G1 Old Generation", - "G1 Young Generation", - ] - `); - }); - - it('has correct series overall values', () => { - expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 0, - 15, - ] - `); - }); - }); - - describe('Garbage collection time spent per minute', () => { - let cpuUsageChart: GenericMetricsChart | undefined; - before(() => { - cpuUsageChart = chartsResponse.body.charts.find( - ({ key }) => key === 'gc_time_line_chart' - ); - }); - - it('has correct series', () => { - expect(cpuUsageChart).to.not.empty(); - expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "G1 Old Generation", - "G1 Young Generation", - ] - `); - }); - - it('has correct series overall values', () => { - expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 0, - 187.5, - ] - `); - }); - }); - }); - - // 9223372036854771712 = memory limit for a c-group when no memory limit is specified - it('calculates system memory usage using system total field when cgroup limit is equal to 9223372036854771712', async () => { - const start = encodeURIComponent('2020-09-08T15:00:30.000Z'); - const end = encodeURIComponent('2020-09-08T15:05:00.000Z'); - - const chartsResponse: ChartResponse = await supertest.get( - `/api/apm/services/opbeans-java/metrics/charts?start=${start}&end=${end}&uiFilters=${uiFilters}&agentName=${agentName}` - ); - - const systemMemoryUsageChart = chartsResponse.body.charts.find( - ({ key }) => key === 'memory_usage_chart' - ); - - expect(systemMemoryUsageChart).to.not.empty(); - expectSnapshot(systemMemoryUsageChart?.series.map(({ title }) => title)).toMatchInline(` - Array [ - "Max", - "Average", - ] - `); - expectSnapshot(systemMemoryUsageChart?.series.map(({ overallValue }) => overallValue)) - .toMatchInline(` - Array [ - 0.114523896426499, - 0.114002376090415, - ] - `); - - const yValues = systemMemoryUsageChart?.series.map((serie) => first(serie.data)?.y); - expectSnapshot(yValues).toMatchInline(` - Array [ - 0.11383724014064, - 0.11383724014064, - ] - `); - }); - }); - }); -} 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 deleted file mode 100644 index f44b1561f2a5aa..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import archives_metadata from '../../../common/fixtures/es_archiver/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(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); - - 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/annotations.ts b/x-pack/test/apm_api_integration/basic/tests/services/annotations.ts deleted file mode 100644 index 3136dcef2e985d..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/services/annotations.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { JsonObject } from 'src/plugins/kibana_utils/common'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function annotationApiTests({ getService }: FtrProviderContext) { - const supertestWrite = getService('supertestAsApmAnnotationsWriteUser'); - - function request({ method, url, data }: { method: string; url: string; data?: JsonObject }) { - switch (method.toLowerCase()) { - case 'post': - return supertestWrite.post(url).send(data).set('kbn-xsrf', 'foo'); - - default: - throw new Error(`Unsupported method ${method}`); - } - } - - describe('APM annotations with a basic license', () => { - describe('when creating an annotation', () => { - it('fails with a 403 forbidden', async () => { - const response = await request({ - url: '/api/apm/services/opbeans-java/annotation', - method: 'POST', - data: { - '@timestamp': new Date().toISOString(), - message: 'New deployment', - tags: ['foo'], - service: { - version: '1.1', - environment: 'production', - }, - }, - }); - - expect(response.status).to.be(403); - expect(response.body.message).to.be( - 'Annotations require at least a gold license or a trial license.' - ); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/basic/tests/services/throughput.ts b/x-pack/test/apm_api_integration/basic/tests/services/throughput.ts deleted file mode 100644 index 07a1442d751b4e..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/services/throughput.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import expect from '@kbn/expect'; -import qs from 'querystring'; -import { first, last } from 'lodash'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -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]; - - describe('Throughput', () => { - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-java/throughput?${qs.stringify({ - start: metadata.start, - end: metadata.end, - uiFilters: encodeURIComponent('{}'), - transactionType: 'request', - })}` - ); - expect(response.status).to.be(200); - expect(response.body.throughput.length).to.be(0); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - describe('returns the service throughput', () => { - let throughputResponse: { - throughput: Array<{ x: number; y: number | null }>; - }; - before(async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-java/throughput?${qs.stringify({ - start: metadata.start, - end: metadata.end, - uiFilters: encodeURIComponent('{}'), - transactionType: 'request', - })}` - ); - throughputResponse = response.body; - }); - - it('returns some data', () => { - expect(throughputResponse.throughput.length).to.be.greaterThan(0); - - const nonNullDataPoints = throughputResponse.throughput.filter(({ y }) => y !== null); - - expect(nonNullDataPoints.length).to.be.greaterThan(0); - }); - - it('has the correct start date', () => { - expectSnapshot( - new Date(first(throughputResponse.throughput)?.x ?? NaN).toISOString() - ).toMatchInline(`"2020-12-08T13:57:30.000Z"`); - }); - - it('has the correct end date', () => { - expectSnapshot( - new Date(last(throughputResponse.throughput)?.x ?? NaN).toISOString() - ).toMatchInline(`"2020-12-08T14:27:30.000Z"`); - }); - - it('has the correct number of buckets', () => { - expectSnapshot(throughputResponse.throughput.length).toMatchInline(`61`); - }); - - it('has the correct throughput', () => { - expectSnapshot(throughputResponse.throughput).toMatch(); - }); - }); - }); - }); -} 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 deleted file mode 100644 index 98bfe84cf56ee1..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/services/top_services.ts +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { isEmpty, pick, sortBy } from 'lodash'; -import { APIReturnType } from '../../../../../plugins/apm/public/services/rest/createCallApmApi'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - const archiveName = 'apm_8.0.0'; - - const range = archives_metadata[archiveName]; - - // url parameters - const start = encodeURIComponent(range.start); - const end = encodeURIComponent(range.end); - - const uiFilters = encodeURIComponent(JSON.stringify({})); - - describe('APM Services Overview', () => { - describe('when data is not loaded ', () => { - it('handles the empty state', async () => { - const response = await supertest.get( - `/api/apm/services?start=${start}&end=${end}&uiFilters=${uiFilters}` - ); - - expect(response.status).to.be(200); - expect(response.body.hasHistoricalData).to.be(false); - expect(response.body.hasLegacyData).to.be(false); - expect(response.body.items.length).to.be(0); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - describe('and fetching a list of services', () => { - let response: { - status: number; - body: APIReturnType<'GET /api/apm/services'>; - }; - - let sortedItems: typeof response.body.items; - - before(async () => { - response = await supertest.get( - `/api/apm/services?start=${start}&end=${end}&uiFilters=${uiFilters}` - ); - sortedItems = sortBy(response.body.items, 'serviceName'); - }); - - it('the response is successful', () => { - expect(response.status).to.eql(200); - }); - - it('returns hasHistoricalData: true', () => { - expect(response.body.hasHistoricalData).to.be(true); - }); - - it('returns hasLegacyData: false', () => { - expect(response.body.hasLegacyData).to.be(false); - }); - - it('returns the correct service names', () => { - expectSnapshot(sortedItems.map((item) => item.serviceName)).toMatchInline(` - Array [ - "kibana", - "kibana-frontend", - "opbeans-dotnet", - "opbeans-go", - "opbeans-java", - "opbeans-node", - "opbeans-python", - "opbeans-ruby", - "opbeans-rum", - ] - `); - }); - - it('returns the correct metrics averages', () => { - expectSnapshot( - sortedItems.map((item) => - pick( - item, - 'transactionErrorRate.value', - 'avgResponseTime.value', - 'transactionsPerMinute.value' - ) - ) - ).toMatchInline(` - Array [ - Object { - "avgResponseTime": Object { - "value": 420419.34550767, - }, - "transactionErrorRate": Object { - "value": 0, - }, - "transactionsPerMinute": Object { - "value": 45.6333333333333, - }, - }, - Object { - "avgResponseTime": Object { - "value": 2382833.33333333, - }, - "transactionErrorRate": Object { - "value": null, - }, - "transactionsPerMinute": Object { - "value": 0.2, - }, - }, - Object { - "avgResponseTime": Object { - "value": 631521.83908046, - }, - "transactionErrorRate": Object { - "value": 0.0229885057471264, - }, - "transactionsPerMinute": Object { - "value": 2.9, - }, - }, - Object { - "avgResponseTime": Object { - "value": 27946.1484375, - }, - "transactionErrorRate": Object { - "value": 0.015625, - }, - "transactionsPerMinute": Object { - "value": 4.26666666666667, - }, - }, - Object { - "avgResponseTime": Object { - "value": 237339.813333333, - }, - "transactionErrorRate": Object { - "value": 0.16, - }, - "transactionsPerMinute": Object { - "value": 2.5, - }, - }, - Object { - "avgResponseTime": Object { - "value": 24920.1052631579, - }, - "transactionErrorRate": Object { - "value": 0.0210526315789474, - }, - "transactionsPerMinute": Object { - "value": 3.16666666666667, - }, - }, - Object { - "avgResponseTime": Object { - "value": 29542.6607142857, - }, - "transactionErrorRate": Object { - "value": 0.0357142857142857, - }, - "transactionsPerMinute": Object { - "value": 1.86666666666667, - }, - }, - Object { - "avgResponseTime": Object { - "value": 70518.9328358209, - }, - "transactionErrorRate": Object { - "value": 0.0373134328358209, - }, - "transactionsPerMinute": Object { - "value": 4.46666666666667, - }, - }, - Object { - "avgResponseTime": Object { - "value": 2319812.5, - }, - "transactionErrorRate": Object { - "value": null, - }, - "transactionsPerMinute": Object { - "value": 0.533333333333333, - }, - }, - ] - `); - }); - - it('returns environments', () => { - expectSnapshot(sortedItems.map((item) => item.environments ?? [])).toMatchInline(` - Array [ - Array [ - "production", - ], - Array [ - "production", - ], - Array [ - "production", - ], - Array [ - "testing", - ], - Array [ - "production", - ], - Array [ - "testing", - ], - Array [], - Array [], - Array [ - "testing", - ], - ] - `); - }); - - it(`RUM services don't report any transaction error rates`, () => { - // RUM transactions don't have event.outcome set, - // so they should not have an error rate - - const rumServices = sortedItems.filter((item) => item.agentName === 'rum-js'); - - expect(rumServices.length).to.be.greaterThan(0); - - expect(rumServices.every((item) => isEmpty(item.transactionErrorRate?.value))); - }); - - it('non-RUM services all report transaction error rates', () => { - const nonRumServices = sortedItems.filter((item) => item.agentName !== 'rum-js'); - - expect( - nonRumServices.every((item) => { - return ( - typeof item.transactionErrorRate?.value === 'number' && - item.transactionErrorRate.timeseries.length > 0 - ); - }) - ).to.be(true); - }); - }); - }); - }); -} 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 deleted file mode 100644 index 1817c7c4511fae..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { omit, orderBy } from 'lodash'; -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'; - -export default function agentConfigurationTests({ getService }: FtrProviderContext) { - const supertestRead = getService('supertestAsApmReadUser'); - const supertestWrite = getService('supertestAsApmWriteUser'); - 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`) - .set('kbn-xsrf', 'foo'); - } - - function getEnvironments(serviceName: string) { - return supertestRead - .get(`/api/apm/settings/agent-configuration/environments?serviceName=${serviceName}`) - .set('kbn-xsrf', 'foo'); - } - - function getAgentName(serviceName: string) { - return supertestRead - .get(`/api/apm/settings/agent-configuration/agent_name?serviceName=${serviceName}`) - .set('kbn-xsrf', 'foo'); - } - - function searchConfigurations(configuration: AgentConfigSearchParams) { - return supertestRead - .post(`/api/apm/settings/agent-configuration/search`) - .send(configuration) - .set('kbn-xsrf', 'foo'); - } - - function getAllConfigurations() { - return supertestRead.get(`/api/apm/settings/agent-configuration`).set('kbn-xsrf', 'foo'); - } - - async function createConfiguration(config: AgentConfigurationIntake, { user = 'write' } = {}) { - log.debug('creating configuration', config.service); - const supertestClient = user === 'read' ? supertestRead : supertestWrite; - - const res = await supertestClient - .put(`/api/apm/settings/agent-configuration`) - .send(config) - .set('kbn-xsrf', 'foo'); - - throwOnError(res); - - return res; - } - - async function updateConfiguration(config: AgentConfigurationIntake, { user = 'write' } = {}) { - log.debug('updating configuration', config.service); - const supertestClient = user === 'read' ? supertestRead : supertestWrite; - - const res = await supertestClient - .put(`/api/apm/settings/agent-configuration?overwrite=true`) - .send(config) - .set('kbn-xsrf', 'foo'); - - throwOnError(res); - - return res; - } - - async function deleteConfiguration( - { service }: AgentConfigurationIntake, - { user = 'write' } = {} - ) { - log.debug('deleting configuration', service); - const supertestClient = user === 'read' ? supertestRead : supertestWrite; - - const res = await supertestClient - .delete(`/api/apm/settings/agent-configuration`) - .send({ service }) - .set('kbn-xsrf', 'foo'); - - throwOnError(res); - - return res; - } - - function throwOnError(res: any) { - const { statusCode, req, body } = res; - if (statusCode !== 200) { - const e = new Error(` - Endpoint: ${req.method} ${req.path} - Service: ${JSON.stringify(res.request._data.service)} - Status code: ${statusCode} - Response: ${body.message}`); - - // @ts-ignore - e.res = res; - - throw e; - } - } - - describe('agent configuration', () => { - describe('when no data is loaded', () => { - it('handles the empty state for services', async () => { - const { body } = await getServices(); - expect(body).to.eql(['ALL_OPTION_VALUE']); - }); - - it('handles the empty state for environments', async () => { - const { body } = await getEnvironments('myservice'); - expect(body).to.eql([{ name: 'ALL_OPTION_VALUE', alreadyConfigured: false }]); - }); - - it('handles the empty state for agent names', async () => { - const { body } = await getAgentName('myservice'); - expect(body).to.eql({}); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - it('returns all services', async () => { - const { body } = await getServices(); - expectSnapshot(body).toMatchInline(` - Array [ - "ALL_OPTION_VALUE", - "kibana", - "kibana-frontend", - "opbeans-dotnet", - "opbeans-go", - "opbeans-java", - "opbeans-node", - "opbeans-python", - "opbeans-ruby", - "opbeans-rum", - ] - `); - }); - - it('returns the environments, all unconfigured', async () => { - const { body } = await getEnvironments('opbeans-node'); - - 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 () => { - const { body } = await getAgentName('opbeans-node'); - expect(body).to.eql({ agentName: 'nodejs' }); - }); - }); - - describe('as a read-only user', () => { - const newConfig = { service: {}, settings: { transaction_sample_rate: '0.55' } }; - it('throws when attempting to create config', async () => { - try { - await createConfiguration(newConfig, { user: 'read' }); - - // ensure that `createConfiguration` throws - expect(true).to.be(false); - } catch (e) { - expect(e.res.statusCode).to.be(403); - } - }); - - describe('when a configuration already exists', () => { - before(async () => createConfiguration(newConfig)); - after(async () => deleteConfiguration(newConfig)); - - it('throws when attempting to update config', async () => { - try { - await updateConfiguration(newConfig, { user: 'read' }); - - // ensure that `updateConfiguration` throws - expect(true).to.be(false); - } catch (e) { - expect(e.res.statusCode).to.be(403); - } - }); - - it('throws when attempting to delete config', async () => { - try { - await deleteConfiguration(newConfig, { user: 'read' }); - - // ensure that `deleteConfiguration` throws - expect(true).to.be(false); - } catch (e) { - expect(e.res.statusCode).to.be(403); - } - }); - }); - }); - - describe('when creating one configuration', () => { - const newConfig = { - service: {}, - settings: { transaction_sample_rate: '0.55' }, - }; - - const searchParams = { - service: { name: 'myservice', environment: 'development' }, - etag: '7312bdcc34999629a3d39df24ed9b2a7553c0c39', - }; - - it('can create and delete config', async () => { - // assert that config does not exist - const res1 = await searchConfigurations(searchParams); - expect(res1.status).to.equal(404); - - // assert that config was created - await createConfiguration(newConfig); - const res2 = await searchConfigurations(searchParams); - expect(res2.status).to.equal(200); - - // assert that config was deleted - await deleteConfiguration(newConfig); - const res3 = await searchConfigurations(searchParams); - expect(res3.status).to.equal(404); - }); - - describe('when a configuration exists', () => { - before(async () => createConfiguration(newConfig)); - after(async () => deleteConfiguration(newConfig)); - - it('can find the config', async () => { - const { status, body } = await searchConfigurations(searchParams); - expect(status).to.equal(200); - expect(body._source.service).to.eql({}); - expect(body._source.settings).to.eql({ transaction_sample_rate: '0.55' }); - }); - - it('can list the config', async () => { - const { status, body } = await getAllConfigurations(); - expect(status).to.equal(200); - expect(omitTimestamp(body)).to.eql([ - { - service: {}, - settings: { transaction_sample_rate: '0.55' }, - applied_by_agent: false, - etag: 'eb88a8997666cc4b33745ef355a1bbd7c4782f2d', - }, - ]); - }); - - it('can update the config', async () => { - await updateConfiguration({ service: {}, settings: { transaction_sample_rate: '0.85' } }); - const { status, body } = await searchConfigurations(searchParams); - expect(status).to.equal(200); - expect(body._source.service).to.eql({}); - expect(body._source.settings).to.eql({ transaction_sample_rate: '0.85' }); - }); - }); - }); - - describe('when creating multiple configurations', () => { - const configs = [ - { - service: {}, - settings: { transaction_sample_rate: '0.1' }, - }, - { - service: { name: 'my_service' }, - settings: { transaction_sample_rate: '0.2' }, - }, - { - service: { name: 'my_service', environment: 'development' }, - settings: { transaction_sample_rate: '0.3' }, - }, - { - service: { environment: 'production' }, - settings: { transaction_sample_rate: '0.4' }, - }, - { - service: { environment: 'development' }, - settings: { transaction_sample_rate: '0.5' }, - }, - ]; - - before(async () => { - await Promise.all(configs.map((config) => createConfiguration(config))); - }); - - after(async () => { - await Promise.all(configs.map((config) => deleteConfiguration(config))); - }); - - const agentsRequests = [ - { - service: { name: 'non_existing_service', environment: 'non_existing_env' }, - expectedSettings: { transaction_sample_rate: '0.1' }, - }, - { - service: { name: 'my_service', environment: 'non_existing_env' }, - expectedSettings: { transaction_sample_rate: '0.2' }, - }, - { - service: { name: 'my_service', environment: 'production' }, - expectedSettings: { transaction_sample_rate: '0.2' }, - }, - { - service: { name: 'my_service', environment: 'development' }, - expectedSettings: { transaction_sample_rate: '0.3' }, - }, - { - service: { name: 'non_existing_service', environment: 'production' }, - expectedSettings: { transaction_sample_rate: '0.4' }, - }, - { - service: { name: 'non_existing_service', environment: 'development' }, - expectedSettings: { transaction_sample_rate: '0.5' }, - }, - ]; - - it('can list all configs', async () => { - const { status, body } = await getAllConfigurations(); - expect(status).to.equal(200); - expect(orderBy(omitTimestamp(body), ['settings.transaction_sample_rate'])).to.eql([ - { - service: {}, - settings: { transaction_sample_rate: '0.1' }, - applied_by_agent: false, - etag: '0758cb18817de60cca29e07480d472694239c4c3', - }, - { - service: { name: 'my_service' }, - settings: { transaction_sample_rate: '0.2' }, - applied_by_agent: false, - etag: 'e04737637056fdf1763bf0ef0d3fcb86e89ae5fc', - }, - { - service: { name: 'my_service', environment: 'development' }, - settings: { transaction_sample_rate: '0.3' }, - applied_by_agent: false, - etag: 'af4dac62621b6762e6281481d1f7523af1124120', - }, - { - service: { environment: 'production' }, - settings: { transaction_sample_rate: '0.4' }, - applied_by_agent: false, - etag: '8d1bf8e6b778b60af351117e2cf53fb1ee570068', - }, - { - service: { environment: 'development' }, - settings: { transaction_sample_rate: '0.5' }, - applied_by_agent: false, - etag: '4ce40da57e3c71daca704121c784b911ec05ae81', - }, - ]); - }); - - for (const agentRequest of agentsRequests) { - it(`${agentRequest.service.name} / ${agentRequest.service.environment}`, async () => { - const { status, body } = await searchConfigurations({ - service: agentRequest.service, - etag: 'abc', - }); - - expect(status).to.equal(200); - expect(body._source.settings).to.eql(agentRequest.expectedSettings); - }); - } - }); - - describe('when an agent retrieves a configuration', () => { - const config = { - service: { name: 'myservice', environment: 'development' }, - settings: { transaction_sample_rate: '0.9' }, - }; - const configProduction = { - service: { name: 'myservice', environment: 'production' }, - settings: { transaction_sample_rate: '0.9' }, - }; - let etag: string; - - before(async () => { - log.debug('creating agent configuration'); - await createConfiguration(config); - await createConfiguration(configProduction); - }); - - after(async () => { - await deleteConfiguration(config); - await deleteConfiguration(configProduction); - }); - - it(`should have 'applied_by_agent=false' before supplying etag`, async () => { - const res1 = await searchConfigurations({ - service: { name: 'myservice', environment: 'development' }, - }); - - etag = res1.body._source.etag; - - const res2 = await searchConfigurations({ - service: { name: 'myservice', environment: 'development' }, - etag, - }); - - expect(res1.body._source.applied_by_agent).to.be(false); - expect(res2.body._source.applied_by_agent).to.be(false); - }); - - it(`should have 'applied_by_agent=true' after supplying etag`, async () => { - await searchConfigurations({ - service: { name: 'myservice', environment: 'development' }, - etag, - }); - - async function hasBeenAppliedByAgent() { - const { body } = await searchConfigurations({ - service: { name: 'myservice', environment: 'development' }, - }); - - return body._source.applied_by_agent; - } - - // wait until `applied_by_agent` has been updated in elasticsearch - expect(await waitFor(hasBeenAppliedByAgent)).to.be(true); - }); - it(`should have 'applied_by_agent=false' before marking as applied`, async () => { - const res1 = await searchConfigurations({ - service: { name: 'myservice', environment: 'production' }, - }); - - expect(res1.body._source.applied_by_agent).to.be(false); - }); - it(`should have 'applied_by_agent=true' when 'mark_as_applied_by_agent' attribute is true`, async () => { - await searchConfigurations({ - service: { name: 'myservice', environment: 'production' }, - mark_as_applied_by_agent: true, - }); - - async function hasBeenAppliedByAgent() { - const { body } = await searchConfigurations({ - service: { name: 'myservice', environment: 'production' }, - }); - - return body._source.applied_by_agent; - } - - // wait until `applied_by_agent` has been updated in elasticsearch - expect(await waitFor(hasBeenAppliedByAgent)).to.be(true); - }); - }); - }); -} - -async function waitFor(cb: () => Promise, retries = 50): Promise { - if (retries === 0) { - throw new Error(`Maximum number of retries reached`); - } - - const res = await cb(); - if (!res) { - await new Promise((resolve) => setTimeout(resolve, 100)); - return waitFor(cb, retries - 1); - } - return res; -} - -function omitTimestamp(configs: AgentConfigurationIntake[]) { - return configs.map((config: AgentConfigurationIntake) => omit(config, '@timestamp')); -} diff --git a/x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/no_access_user.ts b/x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/no_access_user.ts deleted file mode 100644 index 5630bd195b6cd1..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/no_access_user.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; - -export default function apiTest({ getService }: FtrProviderContext) { - const noAccessUser = getService('supertestAsNoAccessUser'); - - function getAnomalyDetectionJobs() { - return noAccessUser.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); - } - - function createAnomalyDetectionJobs(environments: string[]) { - return noAccessUser - .post(`/api/apm/settings/anomaly-detection/jobs`) - .send({ environments }) - .set('kbn-xsrf', 'foo'); - } - - describe('when user does not have read access to ML', () => { - describe('when calling the endpoint for listing jobs', () => { - it('returns an error because the user does not have access', async () => { - const { body } = await getAnomalyDetectionJobs(); - - expect(body.statusCode).to.be(403); - expect(body.error).to.be('Forbidden'); - }); - }); - - describe('when calling create endpoint', () => { - it('returns an error because the user does not have access', async () => { - const { body } = await createAnomalyDetectionJobs(['production', 'staging']); - - expect(body.statusCode).to.be(403); - expect(body.error).to.be('Forbidden'); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/read_user.ts b/x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/read_user.ts deleted file mode 100644 index 30e097e791eaad..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/read_user.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; - -export default function apiTest({ getService }: FtrProviderContext) { - const apmReadUser = getService('supertestAsApmReadUser'); - - function getAnomalyDetectionJobs() { - return apmReadUser.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); - } - - function createAnomalyDetectionJobs(environments: string[]) { - return apmReadUser - .post(`/api/apm/settings/anomaly-detection/jobs`) - .send({ environments }) - .set('kbn-xsrf', 'foo'); - } - - describe('when user has read access to ML', () => { - describe('when calling the endpoint for listing jobs', () => { - it('returns an error because the user is on basic license', async () => { - const { body } = await getAnomalyDetectionJobs(); - - expect(body.statusCode).to.be(403); - expect(body.error).to.be('Forbidden'); - - expectSnapshot(body.message).toMatchInline( - `"To use anomaly detection, you must be subscribed to an Elastic Platinum license. With it, you'll be able to monitor your services with the aid of machine learning."` - ); - }); - }); - - describe('when calling create endpoint', () => { - it('returns an error because the user does not have access', async () => { - const { body } = await createAnomalyDetectionJobs(['production', 'staging']); - expect(body.statusCode).to.be(403); - expect(body.error).to.be('Forbidden'); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/write_user.ts b/x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/write_user.ts deleted file mode 100644 index 15659229a19170..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/write_user.ts +++ /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 expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; - -export default function apiTest({ getService }: FtrProviderContext) { - const apmWriteUser = getService('supertestAsApmWriteUser'); - - function getAnomalyDetectionJobs() { - return apmWriteUser.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); - } - - function createAnomalyDetectionJobs(environments: string[]) { - return apmWriteUser - .post(`/api/apm/settings/anomaly-detection/jobs`) - .send({ environments }) - .set('kbn-xsrf', 'foo'); - } - - describe('when user has write access to ML', () => { - describe('when calling the endpoint for listing jobs', () => { - it('returns an error because the user is on basic license', async () => { - const { body } = await getAnomalyDetectionJobs(); - - expect(body.statusCode).to.be(403); - expect(body.error).to.be('Forbidden'); - expectSnapshot(body.message).toMatchInline( - `"To use anomaly detection, you must be subscribed to an Elastic Platinum license. With it, you'll be able to monitor your services with the aid of machine learning."` - ); - }); - }); - - describe('when calling create endpoint', () => { - it('returns an error because the user is on basic license', async () => { - const { body } = await createAnomalyDetectionJobs(['production', 'staging']); - - expect(body.statusCode).to.be(403); - expect(body.error).to.be('Forbidden'); - - expectSnapshot(body.message).toMatchInline( - `"To use anomaly detection, you must be subscribed to an Elastic Platinum license. With it, you'll be able to monitor your services with the aid of machine learning."` - ); - }); - }); - }); -} 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 deleted file mode 100644 index 8ac5566fc2c495..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import expect from '@kbn/expect'; -import { CustomLink } from '../../../../../plugins/apm/common/custom_link/custom_link_types'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function customLinksTests({ getService }: FtrProviderContext) { - const supertestWrite = getService('supertestAsApmWriteUser'); - - describe('custom links', () => { - it('is only be available to users with Gold license (or higher)', async () => { - const customLink = { - url: 'https://elastic.co', - label: 'with filters', - filters: [ - { key: 'service.name', value: 'baz' }, - { key: 'transaction.type', value: 'qux' }, - ], - } as CustomLink; - const response = await supertestWrite - .post(`/api/apm/settings/custom_links`) - .send(customLink) - .set('kbn-xsrf', 'foo'); - - expect(response.status).to.be(403); - - expectSnapshot(response.body.message).toMatchInline( - `"To create custom links, you must be subscribed to an Elastic Gold license or above. With it, you'll have the ability to create custom links to improve your workflow when analyzing your services."` - ); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/breakdown.ts b/x-pack/test/apm_api_integration/basic/tests/transactions/breakdown.ts deleted file mode 100644 index 947defca05d949..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/breakdown.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import expect from '@kbn/expect'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -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]; - - const start = encodeURIComponent(metadata.start); - const end = encodeURIComponent(metadata.end); - const transactionType = 'request'; - const transactionName = 'GET /api'; - const uiFilters = encodeURIComponent(JSON.stringify({})); - - describe('Breakdown', () => { - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-node/transaction/charts/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` - ); - expect(response.status).to.be(200); - expect(response.body).to.eql({ timeseries: [] }); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - it('returns the transaction breakdown for a service', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-node/transaction/charts/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` - ); - - expect(response.status).to.be(200); - expectSnapshot(response.body).toMatch(); - }); - it('returns the transaction breakdown for a transaction group', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-node/transaction/charts/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}&transactionName=${transactionName}` - ); - - 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]; - - const nonNullDataPoints = data.filter((y: number | null) => y !== null); - - expectSnapshot(nonNullDataPoints.length).toMatchInline(`61`); - - 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": "2020-12-08T13:57:30.000Z", - "y": null, - }, - Object { - "x": "2020-12-08T13:58:00.000Z", - "y": null, - }, - Object { - "x": "2020-12-08T13:58:30.000Z", - "y": 1, - }, - Object { - "x": "2020-12-08T13:59:00.000Z", - "y": 1, - }, - Object { - "x": "2020-12-08T13:59:30.000Z", - "y": null, - }, - ] - `); - - expectSnapshot(title).toMatchInline(`"app"`); - expectSnapshot(color).toMatchInline(`"#54b399"`); - 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( - `/api/apm/services/opbeans-node/transaction/charts/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` - ); - - expect(response.status).to.be(200); - expectSnapshot(response.body.timeseries.map((serie: { title: string }) => serie.title)) - .toMatchInline(` - Array [ - "app", - "http", - "postgresql", - "redis", - ] - `); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/latency.ts b/x-pack/test/apm_api_integration/basic/tests/transactions/latency.ts deleted file mode 100644 index 3088f4fd481d73..00000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/latency.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import expect from '@kbn/expect'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { PromiseReturnType } from '../../../../../plugins/observability/typings/common'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; - -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(metadata.start); - const end = encodeURIComponent(metadata.end); - const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'testing' })); - - describe('Latency', () => { - describe('when data is not loaded ', () => { - it('returns 400 when latencyAggregationType is not informed', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=request` - ); - - expect(response.status).to.be(400); - }); - - it('returns 400 when transactionType is not informed', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&latencyAggregationType=avg` - ); - - expect(response.status).to.be(400); - }); - - it('handles the empty state', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&latencyAggregationType=avg&transactionType=request` - ); - - expect(response.status).to.be(200); - - expect(response.body.overallAvgDuration).to.be(null); - expect(response.body.latencyTimeseries.length).to.be(0); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - let response: PromiseReturnType; - - describe('average latency type', () => { - before(async () => { - response = await supertest.get( - `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=request&latencyAggregationType=avg` - ); - }); - - it('returns average duration and timeseries', async () => { - expect(response.status).to.be(200); - expect(response.body.overallAvgDuration).not.to.be(null); - expect(response.body.latencyTimeseries.length).to.be.eql(61); - }); - }); - - describe('95th percentile latency type', () => { - before(async () => { - response = await supertest.get( - `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=request&latencyAggregationType=p95` - ); - }); - - it('returns average duration and timeseries', async () => { - expect(response.status).to.be(200); - expect(response.body.overallAvgDuration).not.to.be(null); - expect(response.body.latencyTimeseries.length).to.be.eql(61); - }); - }); - - describe('99th percentile latency type', () => { - before(async () => { - response = await supertest.get( - `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=request&latencyAggregationType=p99` - ); - }); - - it('returns average duration and timeseries', async () => { - expect(response.status).to.be(200); - expect(response.body.overallAvgDuration).not.to.be(null); - expect(response.body.latencyTimeseries.length).to.be.eql(61); - }); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/common/config.ts b/x-pack/test/apm_api_integration/common/config.ts index f94bd6bd3be6f9..08333de15ec6de 100644 --- a/x-pack/test/apm_api_integration/common/config.ts +++ b/x-pack/test/apm_api_integration/common/config.ts @@ -11,11 +11,12 @@ import path from 'path'; import { InheritedFtrProviderContext, InheritedServices } from './ftr_provider_context'; import { PromiseReturnType } from '../../../plugins/observability/typings/common'; import { createApmUser, APM_TEST_PASSWORD, ApmUser } from './authentication'; +import { APMFtrConfigName } from '../configs'; +import { registry } from './registry'; -interface Settings { +interface Config { + name: APMFtrConfigName; license: 'basic' | 'trial'; - testFiles: string[]; - name: string; } const supertestAsApmUser = (kibanaServer: UrlObject, apmUser: ApmUser) => async ( @@ -34,8 +35,8 @@ const supertestAsApmUser = (kibanaServer: UrlObject, apmUser: ApmUser) => async return supertestAsPromised(url); }; -export function createTestConfig(settings: Settings) { - const { testFiles, license, name } = settings; +export function createTestConfig(config: Config) { + const { license, name } = config; return async ({ readConfigFile }: FtrConfigProviderContext) => { const xPackAPITestsConfig = await readConfigFile( @@ -47,8 +48,10 @@ export function createTestConfig(settings: Settings) { const supertestAsApmReadUser = supertestAsApmUser(servers.kibana, ApmUser.apmReadUser); + registry.init(config.name); + return { - testFiles, + testFiles: [require.resolve('../tests')], servers, esArchiver: { directory: path.resolve(__dirname, './fixtures/es_archiver'), @@ -69,7 +72,7 @@ export function createTestConfig(settings: Settings) { ), }, junit: { - reportName: name, + reportName: `APM API Integration tests (${name})`, }, esTestCluster: { ...xPackAPITestsConfig.get('esTestCluster'), diff --git a/x-pack/test/apm_api_integration/common/registry.ts b/x-pack/test/apm_api_integration/common/registry.ts new file mode 100644 index 00000000000000..8c918eae5a5a8a --- /dev/null +++ b/x-pack/test/apm_api_integration/common/registry.ts @@ -0,0 +1,160 @@ +/* + * 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 { castArray, groupBy } from 'lodash'; +import callsites from 'callsites'; +import { maybe } from '../../../plugins/apm/common/utils/maybe'; +import { joinByKey } from '../../../plugins/apm/common/utils/join_by_key'; +import { APMFtrConfigName } from '../configs'; +import { FtrProviderContext } from './ftr_provider_context'; + +type ArchiveName = + | 'apm_8.0.0' + | '8.0.0' + | 'metrics_8.0.0' + | 'ml_8.0.0' + | 'observability_overview' + | 'rum_8.0.0' + | 'rum_test_data'; + +interface RunCondition { + config: APMFtrConfigName; + archives: ArchiveName[]; +} + +const callbacks: Array< + RunCondition & { + runs: Array<{ + cb: () => void; + }>; + } +> = []; + +let configName: APMFtrConfigName | undefined; + +let running: boolean = false; + +export const registry = { + init: (config: APMFtrConfigName) => { + configName = config; + callbacks.length = 0; + running = false; + }, + when: ( + title: string, + conditions: RunCondition | RunCondition[], + callback: (condition: RunCondition) => void + ) => { + const allConditions = castArray(conditions); + + if (!allConditions.length) { + throw new Error('At least one condition should be defined'); + } + + if (running) { + throw new Error("Can't add tests when running"); + } + + const frame = maybe(callsites()[1]); + + const file = frame?.getFileName(); + + if (!file) { + throw new Error('Could not infer file for suite'); + } + + allConditions.forEach((matchedCondition) => { + callbacks.push({ + ...matchedCondition, + runs: [ + { + cb: () => { + const suite = describe(title, () => { + callback(matchedCondition); + }); + + suite.file = file; + suite.eachTest((test) => { + test.file = file; + }); + }, + }, + ], + }); + }); + }, + run: (context: FtrProviderContext) => { + if (!configName) { + throw new Error(`registry was not init() before running`); + } + running = true; + const esArchiver = context.getService('esArchiver'); + const logger = context.getService('log'); + const logWithTimer = () => { + const start = process.hrtime(); + + return (message: string) => { + const diff = process.hrtime(start); + const time = `${Math.round(diff[0] * 1000 + diff[1] / 1e6)}ms`; + logger.info(`(${time}) ${message}`); + }; + }; + + const groups = joinByKey(callbacks, ['config', 'archives'], (a, b) => ({ + ...a, + ...b, + runs: a.runs.concat(b.runs), + })); + + callbacks.length = 0; + + const byConfig = groupBy(groups, 'config'); + + Object.keys(byConfig).forEach((config) => { + const groupsForConfig = byConfig[config]; + // register suites for other configs, but skip them so tests are marked as such + // and their snapshots are not marked as obsolete + (config === configName ? describe : describe.skip)(config, () => { + groupsForConfig.forEach((group) => { + const { runs, ...condition } = group; + + const runBefore = async () => { + const log = logWithTimer(); + for (const archiveName of condition.archives) { + log(`Loading ${archiveName}`); + await esArchiver.load(archiveName); + } + if (condition.archives.length) { + log('Loaded all archives'); + } + }; + + const runAfter = async () => { + const log = logWithTimer(); + for (const archiveName of condition.archives) { + log(`Unloading ${archiveName}`); + await esArchiver.unload(archiveName); + } + if (condition.archives.length) { + log('Unloaded all archives'); + } + }; + + describe(condition.archives.join(',') || 'no data', () => { + before(runBefore); + + runs.forEach((run) => { + run.cb(); + }); + + after(runAfter); + }); + }); + }); + }); + + running = false; + }, +}; diff --git a/x-pack/test/apm_api_integration/configs/index.ts b/x-pack/test/apm_api_integration/configs/index.ts new file mode 100644 index 00000000000000..4bda5419c87294 --- /dev/null +++ b/x-pack/test/apm_api_integration/configs/index.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { mapValues } from 'lodash'; +import { createTestConfig } from '../common/config'; + +const apmFtrConfigs = { + basic: { + license: 'basic' as const, + }, + trial: { + license: 'trial' as const, + }, +}; + +export type APMFtrConfigName = keyof typeof apmFtrConfigs; + +export const configs = mapValues(apmFtrConfigs, (value, key) => { + return createTestConfig({ + name: key as APMFtrConfigName, + ...value, + }); +}); diff --git a/x-pack/test/apm_api_integration/tests/alerts/chart_preview.ts b/x-pack/test/apm_api_integration/tests/alerts/chart_preview.ts new file mode 100644 index 00000000000000..2b14e3b8a4a75e --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/alerts/chart_preview.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { format } from 'url'; +import archives from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const archiveName = 'apm_8.0.0'; + const { end } = archives[archiveName]; + const start = new Date(Date.parse(end) - 600000).toISOString(); + + const apis = [ + { + pathname: '/api/apm/alerts/chart_preview/transaction_error_rate', + params: { transactionType: 'request' }, + }, + { pathname: '/api/apm/alerts/chart_preview/transaction_error_count', params: {} }, + { + pathname: '/api/apm/alerts/chart_preview/transaction_duration', + params: { transactionType: 'request' }, + }, + ]; + + apis.forEach((api) => { + const url = format({ + pathname: api.pathname, + query: { + start, + end, + serviceName: 'opbeans-java', + ...api.params, + }, + }); + + registry.when( + `GET ${api.pathname} without data loaded`, + { config: 'basic', archives: [] }, + () => { + it('handles the empty state', async () => { + const response = await supertest.get(url); + + expect(response.status).to.be(200); + expect(response.body).to.eql([]); + }); + } + ); + + registry.when( + `GET ${api.pathname} with data loaded`, + { config: 'basic', archives: [archiveName] }, + () => { + it('returns the correct data', async () => { + const response = await supertest.get(url); + + expect(response.status).to.be(200); + expect( + response.body.some((item: { x: number; y: number | null }) => item.x && item.y) + ).to.equal(true); + }); + } + ); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/correlations/slow_transactions.ts b/x-pack/test/apm_api_integration/tests/correlations/slow_transactions.ts new file mode 100644 index 00000000000000..2439943a664eac --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/correlations/slow_transactions.ts @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { format } from 'url'; +import { APIReturnType } from '../../../../plugins/apm/public/services/rest/createCallApmApi'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const archiveName = 'apm_8.0.0'; + const range = archives_metadata[archiveName]; + + const url = format({ + pathname: `/api/apm/correlations/slow_transactions`, + query: { + start: range.start, + end: range.end, + durationPercentile: 95, + fieldNames: + 'user.username,user.id,host.ip,user_agent.name,kubernetes.pod.uuid,url.domain,container.id,service.node.name', + }, + }); + + registry.when('without data', { config: 'trial', archives: [] }, () => { + it('handles the empty state', async () => { + const response = await supertest.get(url); + + expect(response.status).to.be(200); + expect(response.body.response).to.be(undefined); + }); + }); + + registry.when('with data and default args', { config: 'trial', archives: ['apm_8.0.0'] }, () => { + type ResponseBody = APIReturnType<'GET /api/apm/correlations/slow_transactions'>; + let response: { + status: number; + body: NonNullable; + }; + + before(async () => { + response = await supertest.get(url); + }); + + it('returns successfully', () => { + expect(response.status).to.eql(200); + }); + + it('returns significant terms', () => { + const sorted = response.body?.significantTerms?.sort(); + expectSnapshot(sorted?.map((term) => term.fieldName)).toMatchInline(` + Array [ + "user_agent.name", + "url.domain", + "host.ip", + "service.node.name", + "container.id", + "url.domain", + "user_agent.name", + ] + `); + }); + + it('returns a distribution per term', () => { + expectSnapshot(response.body?.significantTerms?.map((term) => term.distribution.length)) + .toMatchInline(` + Array [ + 11, + 11, + 11, + 11, + 11, + 11, + 11, + ] + `); + }); + + it('returns overall distribution', () => { + expectSnapshot(response.body?.overall?.distribution.length).toMatchInline(`11`); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/__snapshots__/page_load_dist.snap b/x-pack/test/apm_api_integration/tests/csm/__snapshots__/page_load_dist.snap similarity index 95% rename from x-pack/test/apm_api_integration/trial/tests/csm/__snapshots__/page_load_dist.snap rename to x-pack/test/apm_api_integration/tests/csm/__snapshots__/page_load_dist.snap index c8681866169a55..e21069ba2f0a6e 100644 --- a/x-pack/test/apm_api_integration/trial/tests/csm/__snapshots__/page_load_dist.snap +++ b/x-pack/test/apm_api_integration/tests/csm/__snapshots__/page_load_dist.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM specs (trial) CSM UX page load dist when there is data returns page load distribution 1`] = ` +exports[`APM API tests trial 8.0.0,rum_8.0.0 UX page load dist with data returns page load distribution 1`] = ` Object { "maxDuration": 54.46, "minDuration": 0, @@ -456,7 +456,7 @@ Object { } `; -exports[`APM specs (trial) CSM UX page load dist when there is data returns page load distribution with breakdown 1`] = ` +exports[`APM API tests trial 8.0.0,rum_8.0.0 UX page load dist with data returns page load distribution with breakdown 1`] = ` Array [ Object { "data": Array [ @@ -819,6 +819,6 @@ Array [ ] `; -exports[`APM specs (trial) CSM UX page load dist when there is no data returns empty list 1`] = `Object {}`; +exports[`APM API tests trial no data UX page load dist without data returns empty list 1`] = `Object {}`; -exports[`APM specs (trial) CSM UX page load dist when there is no data returns empty list with breakdowns 1`] = `Object {}`; +exports[`APM API tests trial no data UX page load dist without data returns empty list with breakdowns 1`] = `Object {}`; diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/__snapshots__/page_views.snap b/x-pack/test/apm_api_integration/tests/csm/__snapshots__/page_views.snap similarity index 90% rename from x-pack/test/apm_api_integration/trial/tests/csm/__snapshots__/page_views.snap rename to x-pack/test/apm_api_integration/tests/csm/__snapshots__/page_views.snap index 76e5180ba2141c..01d0d7fb6139c3 100644 --- a/x-pack/test/apm_api_integration/trial/tests/csm/__snapshots__/page_views.snap +++ b/x-pack/test/apm_api_integration/tests/csm/__snapshots__/page_views.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM specs (trial) CSM CSM page views when there is data returns page views 1`] = ` +exports[`APM API tests trial 8.0.0,rum_8.0.0 CSM page views with data returns page views 1`] = ` Object { "items": Array [ Object { @@ -128,7 +128,7 @@ Object { } `; -exports[`APM specs (trial) CSM CSM page views when there is data returns page views with breakdown 1`] = ` +exports[`APM API tests trial 8.0.0,rum_8.0.0 CSM page views with data returns page views with breakdown 1`] = ` Object { "items": Array [ Object { @@ -265,14 +265,14 @@ Object { } `; -exports[`APM specs (trial) CSM CSM page views when there is no data returns empty list 1`] = ` +exports[`APM API tests trial no data CSM page views without data returns empty list 1`] = ` Object { "items": Array [], "topItems": Array [], } `; -exports[`APM specs (trial) CSM CSM page views when there is no data returns empty list with breakdowns 1`] = ` +exports[`APM API tests trial no data CSM page views without data returns empty list with breakdowns 1`] = ` Object { "items": Array [], "topItems": Array [], diff --git a/x-pack/test/apm_api_integration/tests/csm/csm_services.ts b/x-pack/test/apm_api_integration/tests/csm/csm_services.ts new file mode 100644 index 00000000000000..6460c0832a9476 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/csm/csm_services.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function rumServicesApiTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + registry.when('CSM Services without data', { config: 'trial', archives: [] }, () => { + it('returns empty list', async () => { + const response = await supertest.get( + '/api/apm/rum-client/services?start=2020-06-28T10%3A24%3A46.055Z&end=2020-07-29T10%3A24%3A46.055Z&uiFilters=%7B%22agentName%22%3A%5B%22js-base%22%2C%22rum-js%22%5D%7D' + ); + + expect(response.status).to.be(200); + expect(response.body).to.eql([]); + }); + }); + + registry.when( + 'CSM services with data', + { config: 'trial', archives: ['8.0.0', 'rum_8.0.0'] }, + () => { + it('returns rum services list', async () => { + const response = await supertest.get( + '/api/apm/rum-client/services?start=2020-06-28T10%3A24%3A46.055Z&end=2020-07-29T10%3A24%3A46.055Z&uiFilters=%7B%22agentName%22%3A%5B%22js-base%22%2C%22rum-js%22%5D%7D' + ); + + expect(response.status).to.be(200); + + expectSnapshot(response.body).toMatchInline(`Array []`); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/has_rum_data.ts b/x-pack/test/apm_api_integration/tests/csm/has_rum_data.ts similarity index 53% rename from x-pack/test/apm_api_integration/trial/tests/csm/has_rum_data.ts rename to x-pack/test/apm_api_integration/tests/csm/has_rum_data.ts index f2033e03f5821e..66f99dd29df5a5 100644 --- a/x-pack/test/apm_api_integration/trial/tests/csm/has_rum_data.ts +++ b/x-pack/test/apm_api_integration/tests/csm/has_rum_data.ts @@ -5,38 +5,31 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; export default function rumHasDataApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - describe('CSM has rum data api', () => { - describe('when there is no data', () => { - it('returns empty list', async () => { - const response = await supertest.get( - '/api/apm/observability_overview/has_rum_data?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=' - ); + registry.when('has_rum_data without data', { config: 'trial', archives: [] }, () => { + it('returns empty list', async () => { + const response = await supertest.get( + '/api/apm/observability_overview/has_rum_data?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=' + ); - expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` + expect(response.status).to.be(200); + expectSnapshot(response.body).toMatchInline(` Object { "hasData": false, } `); - }); }); + }); - describe('when there is data', () => { - before(async () => { - await esArchiver.load('8.0.0'); - await esArchiver.load('rum_8.0.0'); - }); - after(async () => { - await esArchiver.unload('8.0.0'); - await esArchiver.unload('rum_8.0.0'); - }); - + registry.when( + 'has RUM data with data', + { config: 'trial', archives: ['8.0.0', 'rum_8.0.0'] }, + () => { it('returns that it has data and service name with most traffice', async () => { const response = await supertest.get( '/api/apm/observability_overview/has_rum_data?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=' @@ -51,6 +44,6 @@ export default function rumHasDataApiTests({ getService }: FtrProviderContext) { } `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/js_errors.ts b/x-pack/test/apm_api_integration/tests/csm/js_errors.ts similarity index 72% rename from x-pack/test/apm_api_integration/trial/tests/csm/js_errors.ts rename to x-pack/test/apm_api_integration/tests/csm/js_errors.ts index 6abb701f98a1c6..dcadc8424ef7e9 100644 --- a/x-pack/test/apm_api_integration/trial/tests/csm/js_errors.ts +++ b/x-pack/test/apm_api_integration/tests/csm/js_errors.ts @@ -5,40 +5,33 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; export default function rumJsErrorsApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - describe('CSM js errors', () => { - describe('when there is no data', () => { - it('returns no js errors', async () => { - const response = await supertest.get( - '/api/apm/rum-client/js-errors?pageSize=5&pageIndex=0&start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D' - ); + registry.when('CSM JS errors with data', { config: 'trial', archives: [] }, () => { + it('returns no js errors', async () => { + const response = await supertest.get( + '/api/apm/rum-client/js-errors?pageSize=5&pageIndex=0&start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D' + ); - expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` + expect(response.status).to.be(200); + expectSnapshot(response.body).toMatchInline(` Object { "totalErrorGroups": 0, "totalErrorPages": 0, "totalErrors": 0, } `); - }); }); + }); - describe('when there is data', () => { - before(async () => { - await esArchiver.load('8.0.0'); - await esArchiver.load('rum_test_data'); - }); - after(async () => { - await esArchiver.unload('8.0.0'); - await esArchiver.unload('rum_test_data'); - }); - + registry.when( + 'CSM JS errors without data', + { config: 'trial', archives: ['8.0.0', 'rum_test_data'] }, + () => { it('returns js errors', async () => { const response = await supertest.get( '/api/apm/rum-client/js-errors?start=2021-01-18T12%3A20%3A17.202Z&end=2021-01-18T12%3A25%3A17.203Z&uiFilters=%7B%22environment%22%3A%22ENVIRONMENT_ALL%22%2C%22serviceName%22%3A%5B%22elastic-co-frontend%22%5D%7D&pageSize=5&pageIndex=0' @@ -81,6 +74,6 @@ export default function rumJsErrorsApiTests({ getService }: FtrProviderContext) } `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/long_task_metrics.ts b/x-pack/test/apm_api_integration/tests/csm/long_task_metrics.ts similarity index 50% rename from x-pack/test/apm_api_integration/trial/tests/csm/long_task_metrics.ts rename to x-pack/test/apm_api_integration/tests/csm/long_task_metrics.ts index 6db5de24baa991..0da0889c11775b 100644 --- a/x-pack/test/apm_api_integration/trial/tests/csm/long_task_metrics.ts +++ b/x-pack/test/apm_api_integration/tests/csm/long_task_metrics.ts @@ -5,38 +5,31 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; export default function rumServicesApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - describe('CSM long task metrics', () => { - describe('when there is no data', () => { - it('returns empty list', async () => { - const response = await supertest.get( - '/api/apm/rum-client/long-task-metrics?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D' - ); - - expect(response.status).to.be(200); - expect(response.body).to.eql({ - longestLongTask: 0, - noOfLongTasks: 0, - sumOfLongTasks: 0, - }); + registry.when('CSM long task metrics without data', { config: 'trial', archives: [] }, () => { + it('returns empty list', async () => { + const response = await supertest.get( + '/api/apm/rum-client/long-task-metrics?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D' + ); + + expect(response.status).to.be(200); + expect(response.body).to.eql({ + longestLongTask: 0, + noOfLongTasks: 0, + sumOfLongTasks: 0, }); }); + }); - describe('when there is data', () => { - before(async () => { - await esArchiver.load('8.0.0'); - await esArchiver.load('rum_8.0.0'); - }); - after(async () => { - await esArchiver.unload('8.0.0'); - await esArchiver.unload('rum_8.0.0'); - }); - + registry.when( + 'CSM long task metrics with data', + { config: 'trial', archives: ['8.0.0', 'rum_8.0.0'] }, + () => { it('returns web core vitals values', async () => { const response = await supertest.get( '/api/apm/rum-client/long-task-metrics?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D' @@ -52,6 +45,6 @@ export default function rumServicesApiTests({ getService }: FtrProviderContext) } `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/tests/csm/page_load_dist.ts b/x-pack/test/apm_api_integration/tests/csm/page_load_dist.ts new file mode 100644 index 00000000000000..28fa9cb87f5162 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/csm/page_load_dist.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function rumServicesApiTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + registry.when('UX page load dist without data', { config: 'trial', archives: [] }, () => { + it('returns empty list', async () => { + const response = await supertest.get( + '/api/apm/rum-client/page-load-distribution?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D' + ); + + expect(response.status).to.be(200); + expectSnapshot(response.body).toMatch(); + }); + + it('returns empty list with breakdowns', async () => { + const response = await supertest.get( + '/api/apm/rum-client/page-load-distribution/breakdown?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D&breakdown=Browser' + ); + + expect(response.status).to.be(200); + expectSnapshot(response.body).toMatch(); + }); + }); + + registry.when( + 'UX page load dist with data', + { config: 'trial', archives: ['8.0.0', 'rum_8.0.0'] }, + () => { + it('returns page load distribution', async () => { + const response = await supertest.get( + '/api/apm/rum-client/page-load-distribution?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D' + ); + + expect(response.status).to.be(200); + + expectSnapshot(response.body).toMatch(); + }); + it('returns page load distribution with breakdown', async () => { + const response = await supertest.get( + '/api/apm/rum-client/page-load-distribution/breakdown?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D&breakdown=Browser' + ); + + expect(response.status).to.be(200); + + expectSnapshot(response.body).toMatch(); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/tests/csm/page_views.ts b/x-pack/test/apm_api_integration/tests/csm/page_views.ts new file mode 100644 index 00000000000000..43f9d278f694a5 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/csm/page_views.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function rumServicesApiTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + registry.when('CSM page views without data', { config: 'trial', archives: [] }, () => { + it('returns empty list', async () => { + const response = await supertest.get( + '/api/apm/rum-client/page-view-trends?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D' + ); + + expect(response.status).to.be(200); + expectSnapshot(response.body).toMatch(); + }); + + it('returns empty list with breakdowns', async () => { + const response = await supertest.get( + '/api/apm/rum-client/page-view-trends?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D&breakdowns=%7B%22name%22%3A%22Browser%22%2C%22fieldName%22%3A%22user_agent.name%22%2C%22type%22%3A%22category%22%7D' + ); + + expect(response.status).to.be(200); + expectSnapshot(response.body).toMatch(); + }); + }); + + registry.when( + 'CSM page views with data', + { config: 'trial', archives: ['8.0.0', 'rum_8.0.0'] }, + () => { + it('returns page views', async () => { + const response = await supertest.get( + '/api/apm/rum-client/page-view-trends?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D' + ); + + expect(response.status).to.be(200); + + expectSnapshot(response.body).toMatch(); + }); + it('returns page views with breakdown', async () => { + const response = await supertest.get( + '/api/apm/rum-client/page-view-trends?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D&breakdowns=%7B%22name%22%3A%22Browser%22%2C%22fieldName%22%3A%22user_agent.name%22%2C%22type%22%3A%22category%22%7D' + ); + + expect(response.status).to.be(200); + + expectSnapshot(response.body).toMatch(); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/tests/csm/url_search.ts b/x-pack/test/apm_api_integration/tests/csm/url_search.ts new file mode 100644 index 00000000000000..906f1783cb90e4 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/csm/url_search.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function rumServicesApiTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + registry.when('CSM url search api without data', { config: 'trial', archives: [] }, () => { + it('returns empty list', async () => { + const response = await supertest.get( + '/api/apm/rum-client/url-search?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D&percentile=50' + ); + + expect(response.status).to.be(200); + expectSnapshot(response.body).toMatchInline(` + Object { + "items": Array [], + "total": 0, + } + `); + }); + }); + + registry.when( + 'CSM url search api with data', + { config: 'trial', archives: ['8.0.0', 'rum_8.0.0'] }, + () => { + it('returns top urls when no query', async () => { + const response = await supertest.get( + '/api/apm/rum-client/url-search?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D&percentile=50' + ); + + expect(response.status).to.be(200); + + expectSnapshot(response.body).toMatchInline(` + Object { + "items": Array [ + Object { + "count": 5, + "pld": 4924000, + "url": "http://localhost:5601/nfw/app/csm?rangeFrom=now-15m&rangeTo=now&serviceName=kibana-frontend-8_0_0", + }, + Object { + "count": 1, + "pld": 2760000, + "url": "http://localhost:5601/nfw/app/home", + }, + ], + "total": 2, + } + `); + }); + + it('returns specific results against query', async () => { + const response = await supertest.get( + '/api/apm/rum-client/url-search?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D&urlQuery=csm&percentile=50' + ); + + expect(response.status).to.be(200); + + expectSnapshot(response.body).toMatchInline(` + Object { + "items": Array [ + Object { + "count": 5, + "pld": 4924000, + "url": "http://localhost:5601/nfw/app/csm?rangeFrom=now-15m&rangeTo=now&serviceName=kibana-frontend-8_0_0", + }, + ], + "total": 1, + } + `); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/web_core_vitals.ts b/x-pack/test/apm_api_integration/tests/csm/web_core_vitals.ts similarity index 55% rename from x-pack/test/apm_api_integration/trial/tests/csm/web_core_vitals.ts rename to x-pack/test/apm_api_integration/tests/csm/web_core_vitals.ts index 50c261d2d37ad6..3574ef065eef7d 100644 --- a/x-pack/test/apm_api_integration/trial/tests/csm/web_core_vitals.ts +++ b/x-pack/test/apm_api_integration/tests/csm/web_core_vitals.ts @@ -5,41 +5,34 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; export default function rumServicesApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - describe('CSM web core vitals', () => { - describe('when there is no data', () => { - it('returns empty list', async () => { - const response = await supertest.get( - '/api/apm/rum-client/web-core-vitals?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D&percentile=50' - ); + registry.when('CSM web core vitals without data', { config: 'trial', archives: [] }, () => { + it('returns empty list', async () => { + const response = await supertest.get( + '/api/apm/rum-client/web-core-vitals?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D&percentile=50' + ); - expect(response.status).to.be(200); - expect(response.body).to.eql({ - coreVitalPages: 0, - cls: null, - tbt: 0, - lcpRanks: [100, 0, 0], - fidRanks: [100, 0, 0], - clsRanks: [100, 0, 0], - }); + expect(response.status).to.be(200); + expect(response.body).to.eql({ + coreVitalPages: 0, + cls: null, + tbt: 0, + lcpRanks: [100, 0, 0], + fidRanks: [100, 0, 0], + clsRanks: [100, 0, 0], }); }); + }); - describe('when there is data', () => { - before(async () => { - await esArchiver.load('8.0.0'); - await esArchiver.load('rum_8.0.0'); - }); - after(async () => { - await esArchiver.unload('8.0.0'); - await esArchiver.unload('rum_8.0.0'); - }); - + registry.when( + 'CSM web core vitals with data', + { config: 'trial', archives: ['8.0.0', 'rum_8.0.0'] }, + () => { it('returns web core vitals values', async () => { const response = await supertest.get( '/api/apm/rum-client/web-core-vitals?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D&percentile=50' @@ -73,6 +66,6 @@ export default function rumServicesApiTests({ getService }: FtrProviderContext) } `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts b/x-pack/test/apm_api_integration/tests/feature_controls.ts similarity index 98% rename from x-pack/test/apm_api_integration/basic/tests/feature_controls.ts rename to x-pack/test/apm_api_integration/tests/feature_controls.ts index 35025fcbfd107c..7a65d8114c73ff 100644 --- a/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts +++ b/x-pack/test/apm_api_integration/tests/feature_controls.ts @@ -5,7 +5,8 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { FtrProviderContext } from '../common/ftr_provider_context'; +import { registry } from '../common/registry'; export default function featureControlsTests({ getService }: FtrProviderContext) { const supertest = getService('supertestAsApmWriteUser'); @@ -270,7 +271,7 @@ export default function featureControlsTests({ getService }: FtrProviderContext) } } - describe('apm feature controls', () => { + registry.when('apm feature controls', { config: 'basic', archives: [] }, () => { const config = { service: { name: 'test-service' }, settings: { transaction_sample_rate: '0.5' }, diff --git a/x-pack/test/apm_api_integration/tests/index.ts b/x-pack/test/apm_api_integration/tests/index.ts new file mode 100644 index 00000000000000..eef82c714b2d06 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/index.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../common/ftr_provider_context'; +import { registry } from '../common/registry'; + +export default function apmApiIntegrationTests(providerContext: FtrProviderContext) { + const { loadTestFile } = providerContext; + + describe('APM API tests', function () { + this.tags('ciGroup1'); + loadTestFile(require.resolve('./alerts/chart_preview')); + + loadTestFile(require.resolve('./correlations/slow_transactions')); + + loadTestFile(require.resolve('./csm/csm_services')); + loadTestFile(require.resolve('./csm/has_rum_data')); + loadTestFile(require.resolve('./csm/js_errors')); + loadTestFile(require.resolve('./csm/long_task_metrics')); + loadTestFile(require.resolve('./csm/page_load_dist')); + loadTestFile(require.resolve('./csm/page_views')); + loadTestFile(require.resolve('./csm/url_search')); + loadTestFile(require.resolve('./csm/web_core_vitals')); + + loadTestFile(require.resolve('./metrics_charts/metrics_charts')); + + loadTestFile(require.resolve('./observability_overview/has_data')); + loadTestFile(require.resolve('./observability_overview/observability_overview')); + + loadTestFile(require.resolve('./service_maps/service_maps')); + + loadTestFile(require.resolve('./service_overview/dependencies')); + loadTestFile(require.resolve('./service_overview/error_groups')); + loadTestFile(require.resolve('./service_overview/instances')); + + loadTestFile(require.resolve('./services/agent_name')); + loadTestFile(require.resolve('./services/annotations')); + loadTestFile(require.resolve('./services/service_details')); + loadTestFile(require.resolve('./services/service_icons')); + loadTestFile(require.resolve('./services/throughput')); + loadTestFile(require.resolve('./services/top_services')); + loadTestFile(require.resolve('./services/transaction_types')); + + loadTestFile(require.resolve('./settings/anomaly_detection/basic')); + loadTestFile(require.resolve('./settings/anomaly_detection/no_access_user')); + loadTestFile(require.resolve('./settings/anomaly_detection/read_user')); + loadTestFile(require.resolve('./settings/anomaly_detection/write_user')); + + loadTestFile(require.resolve('./settings/agent_configuration')); + + loadTestFile(require.resolve('./settings/custom_link')); + + loadTestFile(require.resolve('./traces/top_traces')); + + loadTestFile(require.resolve('./transactions/breakdown')); + loadTestFile(require.resolve('./transactions/distribution')); + loadTestFile(require.resolve('./transactions/error_rate')); + loadTestFile(require.resolve('./transactions/latency')); + loadTestFile(require.resolve('./transactions/throughput')); + loadTestFile(require.resolve('./transactions/top_transaction_groups')); + loadTestFile(require.resolve('./transactions/transactions_groups_overview')); + + loadTestFile(require.resolve('./feature_controls')); + + registry.run(providerContext); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.ts b/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.ts new file mode 100644 index 00000000000000..dda46f00d7c725 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.ts @@ -0,0 +1,446 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import expect from '@kbn/expect'; +import { first } from 'lodash'; +import { MetricsChartsByAgentAPIResponse } from '../../../../plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent'; +import { GenericMetricsChart } from '../../../../plugins/apm/server/lib/metrics/transform_metrics_chart'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +interface ChartResponse { + body: MetricsChartsByAgentAPIResponse; + status: number; +} + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + registry.when( + 'Metrics charts when data is loaded', + { config: 'basic', archives: ['metrics_8.0.0'] }, + () => { + describe('for opbeans-node', () => { + const start = encodeURIComponent('2020-09-08T14:50:00.000Z'); + const end = encodeURIComponent('2020-09-08T14:55:00.000Z'); + const uiFilters = encodeURIComponent(JSON.stringify({})); + const agentName = 'nodejs'; + + describe('returns metrics data', () => { + let chartsResponse: ChartResponse; + before(async () => { + chartsResponse = await supertest.get( + `/api/apm/services/opbeans-node/metrics/charts?start=${start}&end=${end}&uiFilters=${uiFilters}&agentName=${agentName}` + ); + }); + it('contains CPU usage and System memory usage chart data', async () => { + expect(chartsResponse.status).to.be(200); + expectSnapshot(chartsResponse.body.charts.map((chart) => chart.title)).toMatchInline(` + Array [ + "CPU usage", + "System memory usage", + ] + `); + }); + + describe('CPU usage', () => { + let cpuUsageChart: GenericMetricsChart | undefined; + before(() => { + cpuUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'cpu_usage_chart' + ); + }); + + it('has correct series', () => { + expect(cpuUsageChart).to.not.empty(); + expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` + Array [ + "System max", + "System average", + "Process max", + "Process average", + ] + `); + }); + + it('has correct series overall values', () => { + expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 0.714, + 0.3877, + 0.75, + 0.2543, + ] + `); + }); + }); + + describe("System memory usage (using 'system.memory' fields to calculate the memory usage)", () => { + let systemMemoryUsageChart: GenericMetricsChart | undefined; + before(() => { + systemMemoryUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'memory_usage_chart' + ); + }); + + it('has correct series', () => { + expect(systemMemoryUsageChart).to.not.empty(); + expectSnapshot(systemMemoryUsageChart?.series.map(({ title }) => title)) + .toMatchInline(` + Array [ + "Max", + "Average", + ] + `); + }); + + it('has correct series overall values', () => { + expectSnapshot(systemMemoryUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 0.722093920925555, + 0.718173546796348, + ] + `); + }); + }); + }); + }); + + describe('for opbeans-java', () => { + const uiFilters = encodeURIComponent(JSON.stringify({})); + const agentName = 'java'; + + describe('returns metrics data', () => { + const start = encodeURIComponent('2020-09-08T14:55:30.000Z'); + const end = encodeURIComponent('2020-09-08T15:00:00.000Z'); + + let chartsResponse: ChartResponse; + before(async () => { + chartsResponse = await supertest.get( + `/api/apm/services/opbeans-java/metrics/charts?start=${start}&end=${end}&uiFilters=${uiFilters}&agentName=${agentName}` + ); + }); + + it('has correct chart data', async () => { + expect(chartsResponse.status).to.be(200); + expectSnapshot(chartsResponse.body.charts.map((chart) => chart.title)).toMatchInline(` + Array [ + "CPU usage", + "System memory usage", + "Heap Memory", + "Non-Heap Memory", + "Thread Count", + "Garbage collection per minute", + "Garbage collection time spent per minute", + ] + `); + }); + + describe('CPU usage', () => { + let cpuUsageChart: GenericMetricsChart | undefined; + before(() => { + cpuUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'cpu_usage_chart' + ); + }); + + it('has correct series', () => { + expect(cpuUsageChart).to.not.empty(); + expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` + Array [ + "System max", + "System average", + "Process max", + "Process average", + ] + `); + }); + + it('has correct series overall values', () => { + expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 0.203, + 0.178777777777778, + 0.01, + 0.009, + ] + `); + }); + + it('has the correct rate', async () => { + const yValues = cpuUsageChart?.series.map((serie) => first(serie.data)?.y); + expectSnapshot(yValues).toMatchInline(` + Array [ + 0.193, + 0.193, + 0.009, + 0.009, + ] + `); + }); + }); + + describe("System memory usage (using 'system.process.cgroup' fields to calculate the memory usage)", () => { + let systemMemoryUsageChart: GenericMetricsChart | undefined; + before(() => { + systemMemoryUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'memory_usage_chart' + ); + }); + + it('has correct series', () => { + expect(systemMemoryUsageChart).to.not.empty(); + expectSnapshot(systemMemoryUsageChart?.series.map(({ title }) => title)) + .toMatchInline(` + Array [ + "Max", + "Average", + ] + `); + }); + + it('has correct series overall values', () => { + expectSnapshot(systemMemoryUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 0.707924703557837, + 0.705395980841182, + ] + `); + }); + + it('has the correct rate', async () => { + const yValues = systemMemoryUsageChart?.series.map((serie) => first(serie.data)?.y); + expectSnapshot(yValues).toMatchInline(` + Array [ + 0.707924703557837, + 0.707924703557837, + ] + `); + }); + }); + + describe('Heap Memory', () => { + let cpuUsageChart: GenericMetricsChart | undefined; + before(() => { + cpuUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'heap_memory_area_chart' + ); + }); + + it('has correct series', () => { + expect(cpuUsageChart).to.not.empty(); + expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` + Array [ + "Avg. used", + "Avg. committed", + "Avg. limit", + ] + `); + }); + + it('has correct series overall values', () => { + expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 222501617.777778, + 374341632, + 1560281088, + ] + `); + }); + + it('has the correct rate', async () => { + const yValues = cpuUsageChart?.series.map((serie) => first(serie.data)?.y); + expectSnapshot(yValues).toMatchInline(` + Array [ + 211472896, + 374341632, + 1560281088, + ] + `); + }); + }); + + describe('Non-Heap Memory', () => { + let cpuUsageChart: GenericMetricsChart | undefined; + before(() => { + cpuUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'non_heap_memory_area_chart' + ); + }); + + it('has correct series', () => { + expect(cpuUsageChart).to.not.empty(); + expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` + Array [ + "Avg. used", + "Avg. committed", + ] + `); + }); + + it('has correct series overall values', () => { + expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 138573397.333333, + 147677639.111111, + ] + `); + }); + + it('has the correct rate', async () => { + const yValues = cpuUsageChart?.series.map((serie) => first(serie.data)?.y); + expectSnapshot(yValues).toMatchInline(` + Array [ + 138162752, + 147386368, + ] + `); + }); + }); + + describe('Thread Count', () => { + let cpuUsageChart: GenericMetricsChart | undefined; + before(() => { + cpuUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'thread_count_line_chart' + ); + }); + + it('has correct series', () => { + expect(cpuUsageChart).to.not.empty(); + expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` + Array [ + "Avg. count", + "Max count", + ] + `); + }); + + it('has correct series overall values', () => { + expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 44.4444444444444, + 45, + ] + `); + }); + + it('has the correct rate', async () => { + const yValues = cpuUsageChart?.series.map((serie) => first(serie.data)?.y); + expectSnapshot(yValues).toMatchInline(` + Array [ + 44, + 44, + ] + `); + }); + }); + + describe('Garbage collection per minute', () => { + let cpuUsageChart: GenericMetricsChart | undefined; + before(() => { + cpuUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'gc_rate_line_chart' + ); + }); + + it('has correct series', () => { + expect(cpuUsageChart).to.not.empty(); + expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` + Array [ + "G1 Old Generation", + "G1 Young Generation", + ] + `); + }); + + it('has correct series overall values', () => { + expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 0, + 15, + ] + `); + }); + }); + + describe('Garbage collection time spent per minute', () => { + let cpuUsageChart: GenericMetricsChart | undefined; + before(() => { + cpuUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'gc_time_line_chart' + ); + }); + + it('has correct series', () => { + expect(cpuUsageChart).to.not.empty(); + expectSnapshot(cpuUsageChart?.series.map(({ title }) => title)).toMatchInline(` + Array [ + "G1 Old Generation", + "G1 Young Generation", + ] + `); + }); + + it('has correct series overall values', () => { + expectSnapshot(cpuUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 0, + 187.5, + ] + `); + }); + }); + }); + + // 9223372036854771712 = memory limit for a c-group when no memory limit is specified + it('calculates system memory usage using system total field when cgroup limit is equal to 9223372036854771712', async () => { + const start = encodeURIComponent('2020-09-08T15:00:30.000Z'); + const end = encodeURIComponent('2020-09-08T15:05:00.000Z'); + + const chartsResponse: ChartResponse = await supertest.get( + `/api/apm/services/opbeans-java/metrics/charts?start=${start}&end=${end}&uiFilters=${uiFilters}&agentName=${agentName}` + ); + + const systemMemoryUsageChart = chartsResponse.body.charts.find( + ({ key }) => key === 'memory_usage_chart' + ); + + expect(systemMemoryUsageChart).to.not.empty(); + expectSnapshot(systemMemoryUsageChart?.series.map(({ title }) => title)).toMatchInline(` + Array [ + "Max", + "Average", + ] + `); + expectSnapshot(systemMemoryUsageChart?.series.map(({ overallValue }) => overallValue)) + .toMatchInline(` + Array [ + 0.114523896426499, + 0.114002376090415, + ] + `); + + const yValues = systemMemoryUsageChart?.series.map((serie) => first(serie.data)?.y); + expectSnapshot(yValues).toMatchInline(` + Array [ + 0.11383724014064, + 0.11383724014064, + ] + `); + }); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts b/x-pack/test/apm_api_integration/tests/observability_overview/has_data.ts similarity index 67% rename from x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts rename to x-pack/test/apm_api_integration/tests/observability_overview/has_data.ts index 6d0d2d30426251..9c88f75c6adbd0 100644 --- a/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts +++ b/x-pack/test/apm_api_integration/tests/observability_overview/has_data.ts @@ -4,40 +4,45 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; 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', () => { + registry.when( + 'Observability overview when data is not loaded', + { config: 'basic', archives: [] }, + () => { it('returns false when there is no data', async () => { const response = await supertest.get('/api/apm/observability_overview/has_data'); expect(response.status).to.be(200); expect(response.body).to.eql(false); }); - }); - describe('when only onboarding data is loaded', () => { - before(() => esArchiver.load('observability_overview')); - after(() => esArchiver.unload('observability_overview')); + } + ); + + registry.when( + 'Observability overview when only onboarding data is loaded', + { config: 'basic', archives: ['observability_overview'] }, + () => { it('returns false when there is only onboarding data', async () => { const response = await supertest.get('/api/apm/observability_overview/has_data'); expect(response.status).to.be(200); expect(response.body).to.eql(false); }); - }); - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); + } + ); + registry.when( + 'Observability overview when APM data is loaded', + { config: 'basic', archives: ['apm_8.0.0'] }, + () => { 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'); expect(response.status).to.be(200); expect(response.body).to.eql(true); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts similarity index 69% rename from x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts rename to x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts index f7c459029c7f59..7c9d8fa8b0f91b 100644 --- a/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts +++ b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; 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]; @@ -19,22 +19,28 @@ export default function ApiTest({ getService }: FtrProviderContext) { const end = encodeURIComponent(metadata.end); const bucketSize = '60s'; - describe('Observability overview', () => { - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await supertest.get( - `/api/apm/observability_overview?start=${start}&end=${end}&bucketSize=${bucketSize}` - ); - expect(response.status).to.be(200); + registry.when( + 'Observability overview when data is not loaded', + { config: 'basic', archives: [] }, + () => { + describe('when data is not loaded', () => { + it('handles the empty state', async () => { + const response = await supertest.get( + `/api/apm/observability_overview?start=${start}&end=${end}&bucketSize=${bucketSize}` + ); + expect(response.status).to.be(200); - expect(response.body.serviceCount).to.be(0); - expect(response.body.transactionCoordinates.length).to.be(0); + expect(response.body.serviceCount).to.be(0); + expect(response.body.transactionCoordinates.length).to.be(0); + }); }); - }); - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); + } + ); + registry.when( + 'Observability overview when data is loaded', + { config: 'basic', archives: [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}` @@ -80,6 +86,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { ] `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap b/x-pack/test/apm_api_integration/tests/service_maps/__snapshots__/service_maps.snap similarity index 99% rename from x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap rename to x-pack/test/apm_api_integration/tests/service_maps/__snapshots__/service_maps.snap index 7639822eaa6f9c..69bc039b67ed21 100644 --- a/x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap +++ b/x-pack/test/apm_api_integration/tests/service_maps/__snapshots__/service_maps.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM specs (trial) Service Maps Service Maps with a trial license /api/apm/service-map when there is data returns service map elements filtering by environment not defined 1`] = ` +exports[`APM API tests trial apm_8.0.0 Service Map with data /api/apm/service-map returns service map elements filtering by environment not defined 1`] = ` Object { "elements": Array [ Object { @@ -514,7 +514,7 @@ Object { } `; -exports[`APM specs (trial) Service Maps Service Maps with a trial license /api/apm/service-map when there is data returns the correct data 3`] = ` +exports[`APM API tests trial apm_8.0.0 Service Map with data /api/apm/service-map returns the correct data 3`] = ` Array [ Object { "data": Object { @@ -1741,7 +1741,7 @@ Array [ ] `; -exports[`APM specs (trial) Service Maps Service Maps with a trial license when there is data with anomalies with the default apm user returns the correct anomaly stats 3`] = ` +exports[`APM API tests trial apm_8.0.0 Service Map with data /api/apm/service-map with ML data with the default apm user returns the correct anomaly stats 3`] = ` Object { "elements": Array [ Object { diff --git a/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts similarity index 58% rename from x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts rename to x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts index 02acd34ad56662..a15f0442c7cde6 100644 --- a/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts +++ b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts @@ -7,57 +7,85 @@ import querystring from 'querystring'; import expect from '@kbn/expect'; import { isEmpty, uniq } from 'lodash'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { PromiseReturnType } from '../../../../../plugins/observability/typings/common'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { PromiseReturnType } from '../../../../plugins/observability/typings/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; export default function serviceMapsApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const supertestAsApmReadUserWithoutMlAccess = getService('supertestAsApmReadUserWithoutMlAccess'); - 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', () => { + registry.when('Service map with a basic license', { config: 'basic', archives: [] }, () => { + 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); + + 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."` + ); + }); + }); + + registry.when('Service map without data', { config: 'trial', archives: [] }, () => { 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=${start}&end=${end}`); + it('returns an empty list', async () => { + 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); - }); + expect(response.status).to.be(200); + expect(response.body.elements.length).to.be(0); }); + }); - describe('when there is data', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); + describe('/api/apm/service-map/service/{serviceName}', () => { + it('returns an object with nulls', async () => { + const q = querystring.stringify({ + start: metadata.start, + end: metadata.end, + uiFilters: encodeURIComponent('{}'), + }); + const response = await supertest.get(`/api/apm/service-map/service/opbeans-node?${q}`); - let response: PromiseReturnType; + expect(response.status).to.be(200); - before(async () => { - response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); - }); + 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); + }); + }); + }); - it('returns service map elements', () => { - expect(response.status).to.be(200); - expect(response.body.elements.length).to.be.greaterThan(0); - }); + registry.when('Service Map with data', { config: 'trial', archives: ['apm_8.0.0'] }, () => { + describe('/api/apm/service-map', () => { + 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); + }); - it('returns the correct data', () => { - const elements: Array<{ data: Record }> = response.body.elements; + 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']) - ).sort(); + const serviceNames = uniq( + elements + .filter((element) => element.data['service.name'] !== undefined) + .map((element) => element.data['service.name']) + ).sort(); - expectSnapshot(serviceNames).toMatchInline(` + expectSnapshot(serviceNames).toMatchInline(` Array [ "kibana", "kibana-frontend", @@ -71,13 +99,13 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) ] `); - const externalDestinations = uniq( - elements - .filter((element) => element.data.target?.startsWith('>')) - .map((element) => element.data.target) - ).sort(); + const externalDestinations = uniq( + elements + .filter((element) => element.data.target?.startsWith('>')) + .map((element) => element.data.target) + ).sort(); - expectSnapshot(externalDestinations).toMatchInline(` + expectSnapshot(externalDestinations).toMatchInline(` Array [ ">elasticsearch", ">feeds.elastic.co:443", @@ -86,51 +114,26 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) ] `); - expectSnapshot(elements).toMatch(); - }); - - it('returns service map elements filtering by environment not defined', async () => { - const ENVIRONMENT_NOT_DEFINED = 'ENVIRONMENT_NOT_DEFINED'; - const { body, status } = await supertest.get( - `/api/apm/service-map?start=${start}&end=${end}&environment=${ENVIRONMENT_NOT_DEFINED}` - ); - expect(status).to.be(200); - const environments = new Set(); - body.elements.forEach((element: { data: Record }) => { - environments.add(element.data['service.environment']); - }); - - expect(environments.has(ENVIRONMENT_NOT_DEFINED)).to.eql(true); - expectSnapshot(body).toMatch(); - }); + expectSnapshot(elements).toMatch(); }); - }); - - describe('/api/apm/service-map/service/{serviceName}', () => { - describe('when there is no data', () => { - it('returns an object with nulls', async () => { - const q = querystring.stringify({ - start: metadata.start, - end: metadata.end, - uiFilters: encodeURIComponent('{}'), - }); - const response = await supertest.get(`/api/apm/service-map/service/opbeans-node?${q}`); - expect(response.status).to.be(200); - - 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); + it('returns service map elements filtering by environment not defined', async () => { + const ENVIRONMENT_NOT_DEFINED = 'ENVIRONMENT_NOT_DEFINED'; + const { body, status } = await supertest.get( + `/api/apm/service-map?start=${start}&end=${end}&environment=${ENVIRONMENT_NOT_DEFINED}` + ); + expect(status).to.be(200); + const environments = new Set(); + body.elements.forEach((element: { data: Record }) => { + environments.add(element.data['service.environment']); }); + + expect(environments.has(ENVIRONMENT_NOT_DEFINED)).to.eql(true); + expectSnapshot(body).toMatch(); }); }); - describe('when there is data with anomalies', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - + describe('/api/apm/service-map with ML data', () => { describe('with the default apm user', () => { let response: PromiseReturnType; diff --git a/x-pack/test/apm_api_integration/basic/tests/service_overview/dependencies/es_utils.ts b/x-pack/test/apm_api_integration/tests/service_overview/dependencies/es_utils.ts similarity index 100% rename from x-pack/test/apm_api_integration/basic/tests/service_overview/dependencies/es_utils.ts rename to x-pack/test/apm_api_integration/tests/service_overview/dependencies/es_utils.ts diff --git a/x-pack/test/apm_api_integration/basic/tests/service_overview/dependencies/index.ts b/x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.ts similarity index 91% rename from x-pack/test/apm_api_integration/basic/tests/service_overview/dependencies/index.ts rename to x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.ts index aeb5d1256796a4..b3e7e0672fc7fe 100644 --- a/x-pack/test/apm_api_integration/basic/tests/service_overview/dependencies/index.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.ts @@ -8,26 +8,28 @@ import expect from '@kbn/expect'; import url from 'url'; import { sortBy, pick, last } from 'lodash'; import { ValuesType } from 'utility-types'; -import { Maybe } from '../../../../../../plugins/apm/typings/common'; -import { isFiniteNumber } from '../../../../../../plugins/apm/common/utils/is_finite_number'; -import { APIReturnType } from '../../../../../../plugins/apm/public/services/rest/createCallApmApi'; -import { ENVIRONMENT_ALL } from '../../../../../../plugins/apm/common/environment_filter_values'; -import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; -import archives from '../../../../common/fixtures/es_archiver/archives_metadata'; +import { registry } from '../../../common/registry'; +import { Maybe } from '../../../../../plugins/apm/typings/common'; +import { isFiniteNumber } from '../../../../../plugins/apm/common/utils/is_finite_number'; +import { APIReturnType } from '../../../../../plugins/apm/public/services/rest/createCallApmApi'; +import { ENVIRONMENT_ALL } from '../../../../../plugins/apm/common/environment_filter_values'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import archives from '../../../common/fixtures/es_archiver/archives_metadata'; import { apmDependenciesMapping, createServiceDependencyDocs } from './es_utils'; const round = (num: Maybe): string => (isFiniteNumber(num) ? num.toPrecision(4) : ''); export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); const es = getService('es'); const archiveName = 'apm_8.0.0'; const { start, end } = archives[archiveName]; - describe('Service overview dependencies', () => { - describe('when data is not loaded', () => { + registry.when( + 'Service overview dependencies when data is not loaded', + { config: 'basic', archives: [] }, + () => { it('handles the empty state', async () => { const response = await supertest.get( url.format({ @@ -44,9 +46,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); expect(response.body).to.eql([]); }); - }); + } + ); - describe('when specific data is loaded', () => { + registry.when( + 'Service overview dependencies when specific data is loaded', + { config: 'basic', archives: [] }, + () => { let response: { status: number; body: APIReturnType<'GET /api/apm/services/{serviceName}/dependencies'>; @@ -285,17 +291,19 @@ export default function ApiTest({ getService }: FtrProviderContext) { impact: 0, }); }); - }); + } + ); - describe('when data is loaded', () => { + registry.when( + 'Service overview dependencies when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { let response: { status: number; body: APIReturnType<'GET /api/apm/services/{serviceName}/dependencies'>; }; before(async () => { - await esArchiver.load(archiveName); - response = await supertest.get( url.format({ pathname: `/api/apm/services/opbeans-java/dependencies`, @@ -309,8 +317,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); }); - after(() => esArchiver.unload(archiveName)); - it('returns a successful response', () => { expect(response.status).to.be(200); }); @@ -380,6 +386,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { ] `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/service_overview/error_groups.ts b/x-pack/test/apm_api_integration/tests/service_overview/error_groups.ts similarity index 94% rename from x-pack/test/apm_api_integration/basic/tests/service_overview/error_groups.ts rename to x-pack/test/apm_api_integration/tests/service_overview/error_groups.ts index 7d1c05960f3e64..fc649c60103c81 100644 --- a/x-pack/test/apm_api_integration/basic/tests/service_overview/error_groups.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/error_groups.ts @@ -7,18 +7,20 @@ import expect from '@kbn/expect'; import qs from 'querystring'; import { pick, uniqBy } from 'lodash'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import archives from '../../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import archives from '../../common/fixtures/es_archiver/archives_metadata'; +import { registry } from '../../common/registry'; export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); const archiveName = 'apm_8.0.0'; const { start, end } = archives[archiveName]; - describe('Service overview error groups', () => { - describe('when data is not loaded', () => { + registry.when( + 'Service overview error groups when data is not loaded', + { config: 'basic', archives: [] }, + () => { it('handles the empty state', async () => { const response = await supertest.get( `/api/apm/services/opbeans-java/error_groups?${qs.stringify({ @@ -41,12 +43,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { is_aggregation_accurate: true, }); }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); + } + ); + registry.when( + 'Service overview error groups when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { it('returns the correct data', async () => { const response = await supertest.get( `/api/apm/services/opbeans-java/error_groups?${qs.stringify({ @@ -220,6 +223,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(uniqBy(items, 'group_id').length).to.eql(totalItems); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/service_overview/instances.ts b/x-pack/test/apm_api_integration/tests/service_overview/instances.ts similarity index 83% rename from x-pack/test/apm_api_integration/basic/tests/service_overview/instances.ts rename to x-pack/test/apm_api_integration/tests/service_overview/instances.ts index 2227a8c09a6cfc..08d60f90900b83 100644 --- a/x-pack/test/apm_api_integration/basic/tests/service_overview/instances.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/instances.ts @@ -7,14 +7,14 @@ import expect from '@kbn/expect'; import url from 'url'; import { pick, sortBy } from 'lodash'; -import { isFiniteNumber } from '../../../../../plugins/apm/common/utils/is_finite_number'; -import { APIReturnType } from '../../../../../plugins/apm/public/services/rest/createCallApmApi'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import archives from '../../../common/fixtures/es_archiver/archives_metadata'; +import { isFiniteNumber } from '../../../../plugins/apm/common/utils/is_finite_number'; +import { APIReturnType } from '../../../../plugins/apm/public/services/rest/createCallApmApi'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import archives from '../../common/fixtures/es_archiver/archives_metadata'; +import { registry } from '../../common/registry'; export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); const archiveName = 'apm_8.0.0'; const { start, end } = archives[archiveName]; @@ -24,31 +24,36 @@ export default function ApiTest({ getService }: FtrProviderContext) { body: APIReturnType<'GET /api/apm/services/{serviceName}/service_overview_instances'>; } - describe('Service overview instances', () => { - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response: Response = await supertest.get( - url.format({ - pathname: `/api/apm/services/opbeans-java/service_overview_instances`, - query: { - start, - end, - numBuckets: 20, - transactionType: 'request', - uiFilters: '{}', - }, - }) - ); - - expect(response.status).to.be(200); - expect(response.body).to.eql([]); - }); - }); + registry.when( + 'Service overview instances when data is not loaded', + { config: 'basic', archives: [] }, + () => { + describe('when data is not loaded', () => { + it('handles the empty state', async () => { + const response: Response = await supertest.get( + url.format({ + pathname: `/api/apm/services/opbeans-java/service_overview_instances`, + query: { + start, + end, + numBuckets: 20, + transactionType: 'request', + uiFilters: '{}', + }, + }) + ); - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); + expect(response.status).to.be(200); + expect(response.body).to.eql([]); + }); + }); + } + ); + registry.when( + 'Service overview instances when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { describe('fetching java data', () => { let response: Response; @@ -209,6 +214,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(values); }); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/services/__snapshots__/throughput.snap b/x-pack/test/apm_api_integration/tests/services/__snapshots__/throughput.snap similarity index 96% rename from x-pack/test/apm_api_integration/basic/tests/services/__snapshots__/throughput.snap rename to x-pack/test/apm_api_integration/tests/services/__snapshots__/throughput.snap index fe7f434aad2e14..f23601fccb1747 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/__snapshots__/throughput.snap +++ b/x-pack/test/apm_api_integration/tests/services/__snapshots__/throughput.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM specs (basic) Services Throughput when data is loaded returns the service throughput has the correct throughput 1`] = ` +exports[`APM API tests basic apm_8.0.0 Throughput when data is loaded has the correct throughput 1`] = ` Array [ Object { "x": 1607435850000, diff --git a/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts b/x-pack/test/apm_api_integration/tests/services/agent_name.ts similarity index 55% rename from x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts rename to x-pack/test/apm_api_integration/tests/services/agent_name.ts index cea8fb5da24287..538d7a448ea30c 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts +++ b/x-pack/test/apm_api_integration/tests/services/agent_name.ts @@ -5,34 +5,33 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import archives from '../../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import archives from '../../common/fixtures/es_archiver/archives_metadata'; +import { registry } from '../../common/registry'; export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); const archiveName = 'apm_8.0.0'; const range = archives[archiveName]; const start = encodeURIComponent(range.start); const end = encodeURIComponent(range.end); - describe('Agent name', () => { - describe('when data is not loaded ', () => { - it('handles the empty state', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-node/agent_name?start=${start}&end=${end}` - ); + registry.when('Agent name when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles the empty state', async () => { + const response = await supertest.get( + `/api/apm/services/opbeans-node/agent_name?start=${start}&end=${end}` + ); - expect(response.status).to.be(200); - expect(response.body).to.eql({}); - }); + expect(response.status).to.be(200); + expect(response.body).to.eql({}); }); + }); - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - + registry.when( + 'Agent name when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { it('returns the agent name', async () => { const response = await supertest.get( `/api/apm/services/opbeans-node/agent_name?start=${start}&end=${end}` @@ -42,6 +41,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.body).to.eql({ agentName: 'nodejs' }); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/trial/tests/services/annotations.ts b/x-pack/test/apm_api_integration/tests/services/annotations.ts similarity index 92% rename from x-pack/test/apm_api_integration/trial/tests/services/annotations.ts rename to x-pack/test/apm_api_integration/tests/services/annotations.ts index c2ddc10c5f1d2c..4ff690fa01aa11 100644 --- a/x-pack/test/apm_api_integration/trial/tests/services/annotations.ts +++ b/x-pack/test/apm_api_integration/tests/services/annotations.ts @@ -7,7 +7,8 @@ import expect from '@kbn/expect'; import { merge, cloneDeep, isPlainObject } from 'lodash'; import { JsonObject } from 'src/plugins/kibana_utils/common'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; const DEFAULT_INDEX_NAME = 'observability-annotations'; @@ -40,7 +41,32 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { } } - describe('APM annotations with a trial license', () => { + registry.when('Annotations with a basic license', { config: 'basic', archives: [] }, () => { + describe('when creating an annotation', () => { + it('fails with a 403 forbidden', async () => { + const response = await request({ + url: '/api/apm/services/opbeans-java/annotation', + method: 'POST', + data: { + '@timestamp': new Date().toISOString(), + message: 'New deployment', + tags: ['foo'], + service: { + version: '1.1', + environment: 'production', + }, + }, + }); + + expect(response.status).to.be(403); + expect(response.body.message).to.be( + 'Annotations require at least a gold license or a trial license.' + ); + }); + }); + }); + + registry.when('Annotations with a trial license', { config: 'trial', archives: [] }, () => { describe('when creating an annotation', () => { afterEach(async () => { const indexExists = (await es.indices.exists({ index: DEFAULT_INDEX_NAME })).body; diff --git a/x-pack/test/apm_api_integration/basic/tests/services/service_details.ts b/x-pack/test/apm_api_integration/tests/services/service_details.ts similarity index 87% rename from x-pack/test/apm_api_integration/basic/tests/services/service_details.ts rename to x-pack/test/apm_api_integration/tests/services/service_details.ts index 54bd16e6f78c4d..77155c907f3b14 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/service_details.ts +++ b/x-pack/test/apm_api_integration/tests/services/service_details.ts @@ -6,18 +6,20 @@ import expect from '@kbn/expect'; import url from 'url'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import archives from '../../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import archives from '../../common/fixtures/es_archiver/archives_metadata'; +import { registry } from '../../common/registry'; export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); const archiveName = 'apm_8.0.0'; const { start, end } = archives[archiveName]; - describe('Service details', () => { - describe('when data is not loaded ', () => { + registry.when( + 'Service details when data is not loaded', + { config: 'basic', archives: [] }, + () => { it('handles the empty state', async () => { const response = await supertest.get( url.format({ @@ -29,12 +31,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); expect(response.body).to.eql({}); }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); + } + ); + registry.when( + 'Service details when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { it('returns java service details', async () => { const response = await supertest.get( url.format({ @@ -116,6 +119,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { } `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/services/service_icons.ts b/x-pack/test/apm_api_integration/tests/services/service_icons.ts similarity index 53% rename from x-pack/test/apm_api_integration/basic/tests/services/service_icons.ts rename to x-pack/test/apm_api_integration/tests/services/service_icons.ts index 4b79de14551d6c..7926a2744e45c6 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/service_icons.ts +++ b/x-pack/test/apm_api_integration/tests/services/service_icons.ts @@ -6,35 +6,34 @@ import expect from '@kbn/expect'; import url from 'url'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import archives from '../../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import archives from '../../common/fixtures/es_archiver/archives_metadata'; +import { registry } from '../../common/registry'; export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); const archiveName = 'apm_8.0.0'; const { start, end } = archives[archiveName]; - describe('Service icons', () => { - describe('when data is not loaded ', () => { - it('handles the empty state', async () => { - const response = await supertest.get( - url.format({ - pathname: `/api/apm/services/opbeans-java/metadata/icons`, - query: { start, end }, - }) - ); + registry.when('Service icons when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles the empty state', async () => { + const response = await supertest.get( + url.format({ + pathname: `/api/apm/services/opbeans-java/metadata/icons`, + query: { start, end }, + }) + ); - expect(response.status).to.be(200); - expect(response.body).to.eql({}); - }); + expect(response.status).to.be(200); + expect(response.body).to.eql({}); }); + }); - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - + registry.when( + 'Service icons when data is not loaded', + { config: 'basic', archives: [archiveName] }, + () => { it('returns java service icons', async () => { const response = await supertest.get( url.format({ @@ -46,11 +45,11 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); expectSnapshot(response.body).toMatchInline(` - Object { - "agentName": "java", - "containerType": "Kubernetes", - } - `); + Object { + "agentName": "java", + "containerType": "Kubernetes", + } + `); }); it('returns python service icons', async () => { @@ -64,13 +63,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); expectSnapshot(response.body).toMatchInline(` - Object { - "agentName": "python", - "cloudProvider": "gcp", - "containerType": "Kubernetes", - } - `); + Object { + "agentName": "python", + "cloudProvider": "gcp", + "containerType": "Kubernetes", + } + `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/tests/services/throughput.ts b/x-pack/test/apm_api_integration/tests/services/throughput.ts new file mode 100644 index 00000000000000..fa94cbf6007098 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/services/throughput.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import expect from '@kbn/expect'; +import qs from 'querystring'; +import { first, last } from 'lodash'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + + registry.when('Throughput when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles the empty state', async () => { + const response = await supertest.get( + `/api/apm/services/opbeans-java/throughput?${qs.stringify({ + start: metadata.start, + end: metadata.end, + uiFilters: encodeURIComponent('{}'), + transactionType: 'request', + })}` + ); + expect(response.status).to.be(200); + expect(response.body.throughput.length).to.be(0); + }); + }); + + registry.when( + 'Throughput when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { + let throughputResponse: { + throughput: Array<{ x: number; y: number | null }>; + }; + before(async () => { + const response = await supertest.get( + `/api/apm/services/opbeans-java/throughput?${qs.stringify({ + start: metadata.start, + end: metadata.end, + uiFilters: encodeURIComponent('{}'), + transactionType: 'request', + })}` + ); + throughputResponse = response.body; + }); + + it('returns some data', () => { + expect(throughputResponse.throughput.length).to.be.greaterThan(0); + + const nonNullDataPoints = throughputResponse.throughput.filter(({ y }) => y !== null); + + expect(nonNullDataPoints.length).to.be.greaterThan(0); + }); + + it('has the correct start date', () => { + expectSnapshot( + new Date(first(throughputResponse.throughput)?.x ?? NaN).toISOString() + ).toMatchInline(`"2020-12-08T13:57:30.000Z"`); + }); + + it('has the correct end date', () => { + expectSnapshot( + new Date(last(throughputResponse.throughput)?.x ?? NaN).toISOString() + ).toMatchInline(`"2020-12-08T14:27:30.000Z"`); + }); + + it('has the correct number of buckets', () => { + expectSnapshot(throughputResponse.throughput.length).toMatchInline(`61`); + }); + + it('has the correct throughput', () => { + expectSnapshot(throughputResponse.throughput).toMatch(); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/tests/services/top_services.ts b/x-pack/test/apm_api_integration/tests/services/top_services.ts new file mode 100644 index 00000000000000..42797e3e7c87a8 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/services/top_services.ts @@ -0,0 +1,364 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { sortBy, pick, isEmpty } from 'lodash'; +import { APIReturnType } from '../../../../plugins/apm/public/services/rest/createCallApmApi'; +import { PromiseReturnType } from '../../../../plugins/observability/typings/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { registry } from '../../common/registry'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const supertestAsApmReadUserWithoutMlAccess = getService('supertestAsApmReadUserWithoutMlAccess'); + + const archiveName = 'apm_8.0.0'; + + const range = archives_metadata[archiveName]; + + // url parameters + const start = encodeURIComponent(range.start); + const end = encodeURIComponent(range.end); + + const uiFilters = encodeURIComponent(JSON.stringify({})); + + registry.when( + 'APM Services Overview with a basic license when data is not loaded', + { config: 'basic', archives: [] }, + () => { + it('handles the empty state', async () => { + const response = await supertest.get( + `/api/apm/services?start=${start}&end=${end}&uiFilters=${uiFilters}` + ); + + expect(response.status).to.be(200); + expect(response.body.hasHistoricalData).to.be(false); + expect(response.body.hasLegacyData).to.be(false); + expect(response.body.items.length).to.be(0); + }); + } + ); + + registry.when( + 'APM Services Overview with a basic license when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { + let response: { + status: number; + body: APIReturnType<'GET /api/apm/services'>; + }; + + let sortedItems: typeof response.body.items; + + before(async () => { + response = await supertest.get( + `/api/apm/services?start=${start}&end=${end}&uiFilters=${uiFilters}` + ); + sortedItems = sortBy(response.body.items, 'serviceName'); + }); + + it('the response is successful', () => { + expect(response.status).to.eql(200); + }); + + it('returns hasHistoricalData: true', () => { + expect(response.body.hasHistoricalData).to.be(true); + }); + + it('returns hasLegacyData: false', () => { + expect(response.body.hasLegacyData).to.be(false); + }); + + it('returns the correct service names', () => { + expectSnapshot(sortedItems.map((item) => item.serviceName)).toMatchInline(` + Array [ + "kibana", + "kibana-frontend", + "opbeans-dotnet", + "opbeans-go", + "opbeans-java", + "opbeans-node", + "opbeans-python", + "opbeans-ruby", + "opbeans-rum", + ] + `); + }); + + it('returns the correct metrics averages', () => { + expectSnapshot( + sortedItems.map((item) => + pick( + item, + 'transactionErrorRate.value', + 'avgResponseTime.value', + 'transactionsPerMinute.value' + ) + ) + ).toMatchInline(` + Array [ + Object { + "avgResponseTime": Object { + "value": 420419.34550767, + }, + "transactionErrorRate": Object { + "value": 0, + }, + "transactionsPerMinute": Object { + "value": 45.6333333333333, + }, + }, + Object { + "avgResponseTime": Object { + "value": 2382833.33333333, + }, + "transactionErrorRate": Object { + "value": null, + }, + "transactionsPerMinute": Object { + "value": 0.2, + }, + }, + Object { + "avgResponseTime": Object { + "value": 631521.83908046, + }, + "transactionErrorRate": Object { + "value": 0.0229885057471264, + }, + "transactionsPerMinute": Object { + "value": 2.9, + }, + }, + Object { + "avgResponseTime": Object { + "value": 27946.1484375, + }, + "transactionErrorRate": Object { + "value": 0.015625, + }, + "transactionsPerMinute": Object { + "value": 4.26666666666667, + }, + }, + Object { + "avgResponseTime": Object { + "value": 237339.813333333, + }, + "transactionErrorRate": Object { + "value": 0.16, + }, + "transactionsPerMinute": Object { + "value": 2.5, + }, + }, + Object { + "avgResponseTime": Object { + "value": 24920.1052631579, + }, + "transactionErrorRate": Object { + "value": 0.0210526315789474, + }, + "transactionsPerMinute": Object { + "value": 3.16666666666667, + }, + }, + Object { + "avgResponseTime": Object { + "value": 29542.6607142857, + }, + "transactionErrorRate": Object { + "value": 0.0357142857142857, + }, + "transactionsPerMinute": Object { + "value": 1.86666666666667, + }, + }, + Object { + "avgResponseTime": Object { + "value": 70518.9328358209, + }, + "transactionErrorRate": Object { + "value": 0.0373134328358209, + }, + "transactionsPerMinute": Object { + "value": 4.46666666666667, + }, + }, + Object { + "avgResponseTime": Object { + "value": 2319812.5, + }, + "transactionErrorRate": Object { + "value": null, + }, + "transactionsPerMinute": Object { + "value": 0.533333333333333, + }, + }, + ] + `); + }); + + it('returns environments', () => { + expectSnapshot(sortedItems.map((item) => item.environments ?? [])).toMatchInline(` + Array [ + Array [ + "production", + ], + Array [ + "production", + ], + Array [ + "production", + ], + Array [ + "testing", + ], + Array [ + "production", + ], + Array [ + "testing", + ], + Array [], + Array [], + Array [ + "testing", + ], + ] + `); + }); + + it(`RUM services don't report any transaction error rates`, () => { + // RUM transactions don't have event.outcome set, + // so they should not have an error rate + + const rumServices = sortedItems.filter((item) => item.agentName === 'rum-js'); + + expect(rumServices.length).to.be.greaterThan(0); + + expect(rumServices.every((item) => isEmpty(item.transactionErrorRate?.value))); + }); + + it('non-RUM services all report transaction error rates', () => { + const nonRumServices = sortedItems.filter((item) => item.agentName !== 'rum-js'); + + expect( + nonRumServices.every((item) => { + return ( + typeof item.transactionErrorRate?.value === 'number' && + item.transactionErrorRate.timeseries.length > 0 + ); + }) + ).to.be(true); + }); + } + ); + + registry.when( + 'APM Services overview with a trial license when data is loaded', + { config: 'trial', archives: [archiveName] }, + () => { + describe('with the default APM read user', () => { + describe('and fetching a list of services', () => { + let response: { + status: number; + body: APIReturnType<'GET /api/apm/services'>; + }; + + before(async () => { + response = await supertest.get( + `/api/apm/services?start=${start}&end=${end}&uiFilters=${uiFilters}` + ); + }); + + it('the response is successful', () => { + expect(response.status).to.eql(200); + }); + + it('there is at least one service', () => { + expect(response.body.items.length).to.be.greaterThan(0); + }); + + it('some items have a health status set', () => { + // Under the assumption that the loaded archive has + // at least one APM ML job, and the time range is longer + // than 15m, at least one items should have a health status + // set. Note that we currently have a bug where healthy + // services report as unknown (so without any health status): + // https://github.com/elastic/kibana/issues/77083 + + const healthStatuses = sortBy(response.body.items, 'serviceName').map( + (item: any) => item.healthStatus + ); + + expect(healthStatuses.filter(Boolean).length).to.be.greaterThan(0); + + expectSnapshot(healthStatuses).toMatchInline(` + Array [ + "healthy", + "healthy", + "healthy", + "healthy", + "healthy", + "healthy", + "healthy", + "healthy", + "healthy", + ] + `); + }); + }); + }); + + describe('with a user that does not have access to ML', () => { + let response: PromiseReturnType; + before(async () => { + response = await supertestAsApmReadUserWithoutMlAccess.get( + `/api/apm/services?start=${start}&end=${end}&uiFilters=${uiFilters}` + ); + }); + + it('the response is successful', () => { + expect(response.status).to.eql(200); + }); + + it('there is at least one service', () => { + expect(response.body.items.length).to.be.greaterThan(0); + }); + + it('contains no health statuses', () => { + const definedHealthStatuses = response.body.items + .map((item: any) => item.healthStatus) + .filter(Boolean); + + expect(definedHealthStatuses.length).to.be(0); + }); + }); + + describe('and fetching a list of services with a filter', () => { + let response: PromiseReturnType; + before(async () => { + response = await supertest.get( + `/api/apm/services?start=${start}&end=${end}&uiFilters=${encodeURIComponent( + `{"kuery":"service.name:opbeans-java","environment":"ENVIRONMENT_ALL"}` + )}` + ); + }); + + it('does not return health statuses for services that are not found in APM data', () => { + expect(response.status).to.be(200); + + expect(response.body.items.length).to.be(1); + + expect(response.body.items[0].serviceName).to.be('opbeans-java'); + }); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts b/x-pack/test/apm_api_integration/tests/services/transaction_types.ts similarity index 75% rename from x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts rename to x-pack/test/apm_api_integration/tests/services/transaction_types.ts index fcfe1660d58e2d..c45f4083ef8dab 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts +++ b/x-pack/test/apm_api_integration/tests/services/transaction_types.ts @@ -5,12 +5,12 @@ */ import expect from '@kbn/expect'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; 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]; @@ -19,8 +19,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { const start = encodeURIComponent(metadata.start); const end = encodeURIComponent(metadata.end); - describe('Transaction types', () => { - describe('when data is not loaded ', () => { + registry.when( + 'Transaction types when data is not loaded', + { config: 'basic', archives: [] }, + () => { it('handles empty state', async () => { const response = await supertest.get( `/api/apm/services/opbeans-node/transaction_types?start=${start}&end=${end}` @@ -30,12 +32,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.body.transactionTypes.length).to.be(0); }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); + } + ); + registry.when( + 'Transaction types when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { it('handles empty state', async () => { const response = await supertest.get( `/api/apm/services/opbeans-node/transaction_types?start=${start}&end=${end}` @@ -53,6 +56,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { } `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/tests/settings/agent_configuration.ts b/x-pack/test/apm_api_integration/tests/settings/agent_configuration.ts new file mode 100644 index 00000000000000..0b58dd5908c60a --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/settings/agent_configuration.ts @@ -0,0 +1,495 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { omit, orderBy } from 'lodash'; +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'; +import { registry } from '../../common/registry'; + +export default function agentConfigurationTests({ getService }: FtrProviderContext) { + const supertestRead = getService('supertestAsApmReadUser'); + const supertestWrite = getService('supertestAsApmWriteUser'); + const log = getService('log'); + + const archiveName = 'apm_8.0.0'; + + function getServices() { + return supertestRead + .get(`/api/apm/settings/agent-configuration/services`) + .set('kbn-xsrf', 'foo'); + } + + function getEnvironments(serviceName: string) { + return supertestRead + .get(`/api/apm/settings/agent-configuration/environments?serviceName=${serviceName}`) + .set('kbn-xsrf', 'foo'); + } + + function getAgentName(serviceName: string) { + return supertestRead + .get(`/api/apm/settings/agent-configuration/agent_name?serviceName=${serviceName}`) + .set('kbn-xsrf', 'foo'); + } + + function searchConfigurations(configuration: AgentConfigSearchParams) { + return supertestRead + .post(`/api/apm/settings/agent-configuration/search`) + .send(configuration) + .set('kbn-xsrf', 'foo'); + } + + function getAllConfigurations() { + return supertestRead.get(`/api/apm/settings/agent-configuration`).set('kbn-xsrf', 'foo'); + } + + async function createConfiguration(config: AgentConfigurationIntake, { user = 'write' } = {}) { + log.debug('creating configuration', config.service); + const supertestClient = user === 'read' ? supertestRead : supertestWrite; + + const res = await supertestClient + .put(`/api/apm/settings/agent-configuration`) + .send(config) + .set('kbn-xsrf', 'foo'); + + throwOnError(res); + + return res; + } + + async function updateConfiguration(config: AgentConfigurationIntake, { user = 'write' } = {}) { + log.debug('updating configuration', config.service); + const supertestClient = user === 'read' ? supertestRead : supertestWrite; + + const res = await supertestClient + .put(`/api/apm/settings/agent-configuration?overwrite=true`) + .send(config) + .set('kbn-xsrf', 'foo'); + + throwOnError(res); + + return res; + } + + async function deleteConfiguration( + { service }: AgentConfigurationIntake, + { user = 'write' } = {} + ) { + log.debug('deleting configuration', service); + const supertestClient = user === 'read' ? supertestRead : supertestWrite; + + const res = await supertestClient + .delete(`/api/apm/settings/agent-configuration`) + .send({ service }) + .set('kbn-xsrf', 'foo'); + + throwOnError(res); + + return res; + } + + function throwOnError(res: any) { + const { statusCode, req, body } = res; + if (statusCode !== 200) { + const e = new Error(` + Endpoint: ${req.method} ${req.path} + Service: ${JSON.stringify(res.request._data.service)} + Status code: ${statusCode} + Response: ${body.message}`); + + // @ts-ignore + e.res = res; + + throw e; + } + } + + registry.when( + 'agent configuration when no data is loaded', + { config: 'basic', archives: [] }, + () => { + it('handles the empty state for services', async () => { + const { body } = await getServices(); + expect(body).to.eql(['ALL_OPTION_VALUE']); + }); + + it('handles the empty state for environments', async () => { + const { body } = await getEnvironments('myservice'); + expect(body).to.eql([{ name: 'ALL_OPTION_VALUE', alreadyConfigured: false }]); + }); + + it('handles the empty state for agent names', async () => { + const { body } = await getAgentName('myservice'); + expect(body).to.eql({}); + }); + + describe('as a read-only user', () => { + const newConfig = { service: {}, settings: { transaction_sample_rate: '0.55' } }; + it('throws when attempting to create config', async () => { + try { + await createConfiguration(newConfig, { user: 'read' }); + + // ensure that `createConfiguration` throws + expect(true).to.be(false); + } catch (e) { + expect(e.res.statusCode).to.be(403); + } + }); + + describe('when a configuration already exists', () => { + before(async () => createConfiguration(newConfig)); + after(async () => deleteConfiguration(newConfig)); + + it('throws when attempting to update config', async () => { + try { + await updateConfiguration(newConfig, { user: 'read' }); + + // ensure that `updateConfiguration` throws + expect(true).to.be(false); + } catch (e) { + expect(e.res.statusCode).to.be(403); + } + }); + + it('throws when attempting to delete config', async () => { + try { + await deleteConfiguration(newConfig, { user: 'read' }); + + // ensure that `deleteConfiguration` throws + expect(true).to.be(false); + } catch (e) { + expect(e.res.statusCode).to.be(403); + } + }); + }); + }); + + describe('when creating one configuration', () => { + const newConfig = { + service: {}, + settings: { transaction_sample_rate: '0.55' }, + }; + + const searchParams = { + service: { name: 'myservice', environment: 'development' }, + etag: '7312bdcc34999629a3d39df24ed9b2a7553c0c39', + }; + + it('can create and delete config', async () => { + // assert that config does not exist + const res1 = await searchConfigurations(searchParams); + expect(res1.status).to.equal(404); + + // assert that config was created + await createConfiguration(newConfig); + const res2 = await searchConfigurations(searchParams); + expect(res2.status).to.equal(200); + + // assert that config was deleted + await deleteConfiguration(newConfig); + const res3 = await searchConfigurations(searchParams); + expect(res3.status).to.equal(404); + }); + + describe('when a configuration exists', () => { + before(async () => createConfiguration(newConfig)); + after(async () => deleteConfiguration(newConfig)); + + it('can find the config', async () => { + const { status, body } = await searchConfigurations(searchParams); + expect(status).to.equal(200); + expect(body._source.service).to.eql({}); + expect(body._source.settings).to.eql({ transaction_sample_rate: '0.55' }); + }); + + it('can list the config', async () => { + const { status, body } = await getAllConfigurations(); + expect(status).to.equal(200); + expect(omitTimestamp(body)).to.eql([ + { + service: {}, + settings: { transaction_sample_rate: '0.55' }, + applied_by_agent: false, + etag: 'eb88a8997666cc4b33745ef355a1bbd7c4782f2d', + }, + ]); + }); + + it('can update the config', async () => { + await updateConfiguration({ + service: {}, + settings: { transaction_sample_rate: '0.85' }, + }); + const { status, body } = await searchConfigurations(searchParams); + expect(status).to.equal(200); + expect(body._source.service).to.eql({}); + expect(body._source.settings).to.eql({ transaction_sample_rate: '0.85' }); + }); + }); + }); + + describe('when creating multiple configurations', () => { + const configs = [ + { + service: {}, + settings: { transaction_sample_rate: '0.1' }, + }, + { + service: { name: 'my_service' }, + settings: { transaction_sample_rate: '0.2' }, + }, + { + service: { name: 'my_service', environment: 'development' }, + settings: { transaction_sample_rate: '0.3' }, + }, + { + service: { environment: 'production' }, + settings: { transaction_sample_rate: '0.4' }, + }, + { + service: { environment: 'development' }, + settings: { transaction_sample_rate: '0.5' }, + }, + ]; + + before(async () => { + await Promise.all(configs.map((config) => createConfiguration(config))); + }); + + after(async () => { + await Promise.all(configs.map((config) => deleteConfiguration(config))); + }); + + const agentsRequests = [ + { + service: { name: 'non_existing_service', environment: 'non_existing_env' }, + expectedSettings: { transaction_sample_rate: '0.1' }, + }, + { + service: { name: 'my_service', environment: 'non_existing_env' }, + expectedSettings: { transaction_sample_rate: '0.2' }, + }, + { + service: { name: 'my_service', environment: 'production' }, + expectedSettings: { transaction_sample_rate: '0.2' }, + }, + { + service: { name: 'my_service', environment: 'development' }, + expectedSettings: { transaction_sample_rate: '0.3' }, + }, + { + service: { name: 'non_existing_service', environment: 'production' }, + expectedSettings: { transaction_sample_rate: '0.4' }, + }, + { + service: { name: 'non_existing_service', environment: 'development' }, + expectedSettings: { transaction_sample_rate: '0.5' }, + }, + ]; + + it('can list all configs', async () => { + const { status, body } = await getAllConfigurations(); + expect(status).to.equal(200); + expect(orderBy(omitTimestamp(body), ['settings.transaction_sample_rate'])).to.eql([ + { + service: {}, + settings: { transaction_sample_rate: '0.1' }, + applied_by_agent: false, + etag: '0758cb18817de60cca29e07480d472694239c4c3', + }, + { + service: { name: 'my_service' }, + settings: { transaction_sample_rate: '0.2' }, + applied_by_agent: false, + etag: 'e04737637056fdf1763bf0ef0d3fcb86e89ae5fc', + }, + { + service: { name: 'my_service', environment: 'development' }, + settings: { transaction_sample_rate: '0.3' }, + applied_by_agent: false, + etag: 'af4dac62621b6762e6281481d1f7523af1124120', + }, + { + service: { environment: 'production' }, + settings: { transaction_sample_rate: '0.4' }, + applied_by_agent: false, + etag: '8d1bf8e6b778b60af351117e2cf53fb1ee570068', + }, + { + service: { environment: 'development' }, + settings: { transaction_sample_rate: '0.5' }, + applied_by_agent: false, + etag: '4ce40da57e3c71daca704121c784b911ec05ae81', + }, + ]); + }); + + for (const agentRequest of agentsRequests) { + it(`${agentRequest.service.name} / ${agentRequest.service.environment}`, async () => { + const { status, body } = await searchConfigurations({ + service: agentRequest.service, + etag: 'abc', + }); + + expect(status).to.equal(200); + expect(body._source.settings).to.eql(agentRequest.expectedSettings); + }); + } + }); + + describe('when an agent retrieves a configuration', () => { + const config = { + service: { name: 'myservice', environment: 'development' }, + settings: { transaction_sample_rate: '0.9' }, + }; + const configProduction = { + service: { name: 'myservice', environment: 'production' }, + settings: { transaction_sample_rate: '0.9' }, + }; + let etag: string; + + before(async () => { + log.debug('creating agent configuration'); + await createConfiguration(config); + await createConfiguration(configProduction); + }); + + after(async () => { + await deleteConfiguration(config); + await deleteConfiguration(configProduction); + }); + + it(`should have 'applied_by_agent=false' before supplying etag`, async () => { + const res1 = await searchConfigurations({ + service: { name: 'myservice', environment: 'development' }, + }); + + etag = res1.body._source.etag; + + const res2 = await searchConfigurations({ + service: { name: 'myservice', environment: 'development' }, + etag, + }); + + expect(res1.body._source.applied_by_agent).to.be(false); + expect(res2.body._source.applied_by_agent).to.be(false); + }); + + it(`should have 'applied_by_agent=true' after supplying etag`, async () => { + await searchConfigurations({ + service: { name: 'myservice', environment: 'development' }, + etag, + }); + + async function hasBeenAppliedByAgent() { + const { body } = await searchConfigurations({ + service: { name: 'myservice', environment: 'development' }, + }); + + return body._source.applied_by_agent; + } + + // wait until `applied_by_agent` has been updated in elasticsearch + expect(await waitFor(hasBeenAppliedByAgent)).to.be(true); + }); + it(`should have 'applied_by_agent=false' before marking as applied`, async () => { + const res1 = await searchConfigurations({ + service: { name: 'myservice', environment: 'production' }, + }); + + expect(res1.body._source.applied_by_agent).to.be(false); + }); + it(`should have 'applied_by_agent=true' when 'mark_as_applied_by_agent' attribute is true`, async () => { + await searchConfigurations({ + service: { name: 'myservice', environment: 'production' }, + mark_as_applied_by_agent: true, + }); + + async function hasBeenAppliedByAgent() { + const { body } = await searchConfigurations({ + service: { name: 'myservice', environment: 'production' }, + }); + + return body._source.applied_by_agent; + } + + // wait until `applied_by_agent` has been updated in elasticsearch + expect(await waitFor(hasBeenAppliedByAgent)).to.be(true); + }); + }); + } + ); + + registry.when( + 'agent configuration when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { + it('returns all services', async () => { + const { body } = await getServices(); + expectSnapshot(body).toMatchInline(` + Array [ + "ALL_OPTION_VALUE", + "kibana", + "kibana-frontend", + "opbeans-dotnet", + "opbeans-go", + "opbeans-java", + "opbeans-node", + "opbeans-python", + "opbeans-ruby", + "opbeans-rum", + ] + `); + }); + + it('returns the environments, all unconfigured', async () => { + const { body } = await getEnvironments('opbeans-node'); + + 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 () => { + const { body } = await getAgentName('opbeans-node'); + expect(body).to.eql({ agentName: 'nodejs' }); + }); + } + ); +} + +async function waitFor(cb: () => Promise, retries = 50): Promise { + if (retries === 0) { + throw new Error(`Maximum number of retries reached`); + } + + const res = await cb(); + if (!res) { + await new Promise((resolve) => setTimeout(resolve, 100)); + return waitFor(cb, retries - 1); + } + return res; +} + +function omitTimestamp(configs: AgentConfigurationIntake[]) { + return configs.map((config: AgentConfigurationIntake) => omit(config, '@timestamp')); +} diff --git a/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/basic.ts b/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/basic.ts new file mode 100644 index 00000000000000..269375ef080def --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/basic.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { registry } from '../../../common/registry'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +export default function apiTest({ getService }: FtrProviderContext) { + const noAccessUser = getService('supertestAsNoAccessUser'); + const readUser = getService('supertestAsApmReadUser'); + const writeUser = getService('supertestAsApmWriteUser'); + + type SupertestAsUser = typeof noAccessUser | typeof readUser | typeof writeUser; + + function getJobs(user: SupertestAsUser) { + return user.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); + } + + function createJobs(user: SupertestAsUser, environments: string[]) { + return user + .post(`/api/apm/settings/anomaly-detection/jobs`) + .send({ environments }) + .set('kbn-xsrf', 'foo'); + } + + async function expectForbidden(user: SupertestAsUser) { + const { body: getJobsBody } = await getJobs(user); + expect(getJobsBody.statusCode).to.be(403); + expect(getJobsBody.error).to.be('Forbidden'); + + const { body: createJobsBody } = await createJobs(user, ['production', 'staging']); + + expect(createJobsBody.statusCode).to.be(403); + expect(getJobsBody.error).to.be('Forbidden'); + } + + registry.when('ML jobs return a 403 for', { config: 'basic', archives: [] }, () => { + it('user without access', async () => { + await expectForbidden(noAccessUser); + }); + + it('read user', async () => { + await expectForbidden(readUser); + }); + + it('write user', async () => { + await expectForbidden(writeUser); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/no_access_user.ts b/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/no_access_user.ts new file mode 100644 index 00000000000000..4878d5031f040f --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/no_access_user.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { registry } from '../../../common/registry'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +export default function apiTest({ getService }: FtrProviderContext) { + const noAccessUser = getService('supertestAsNoAccessUser'); + + function getJobs() { + return noAccessUser.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); + } + + function createJobs(environments: string[]) { + return noAccessUser + .post(`/api/apm/settings/anomaly-detection/jobs`) + .send({ environments }) + .set('kbn-xsrf', 'foo'); + } + + registry.when('ML jobs', { config: 'trial', archives: [] }, () => { + describe('when user does not have read access to ML', () => { + describe('when calling the endpoint for listing jobs', () => { + it('returns an error because the user does not have access', async () => { + const { body } = await getJobs(); + expect(body.statusCode).to.be(403); + expect(body.error).to.be('Forbidden'); + }); + }); + + describe('when calling create endpoint', () => { + it('returns an error because the user does not have access', async () => { + const { body } = await createJobs(['production', 'staging']); + expect(body.statusCode).to.be(403); + expect(body.error).to.be('Forbidden'); + }); + }); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/read_user.ts b/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/read_user.ts new file mode 100644 index 00000000000000..a5fabe66af6f54 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/read_user.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { registry } from '../../../common/registry'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +export default function apiTest({ getService }: FtrProviderContext) { + const apmReadUser = getService('supertestAsApmReadUser'); + + function getJobs() { + return apmReadUser.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); + } + + function createJobs(environments: string[]) { + return apmReadUser + .post(`/api/apm/settings/anomaly-detection/jobs`) + .send({ environments }) + .set('kbn-xsrf', 'foo'); + } + + registry.when('ML jobs', { config: 'trial', archives: [] }, () => { + describe('when user has read access to ML', () => { + describe('when calling the endpoint for listing jobs', () => { + it('returns a list of jobs', async () => { + const { body } = await getJobs(); + + expect(body.jobs.length).to.be(0); + expect(body.hasLegacyJobs).to.be(false); + }); + }); + + describe('when calling create endpoint', () => { + it('returns an error because the user does not have access', async () => { + const { body } = await createJobs(['production', 'staging']); + + expect(body.statusCode).to.be(403); + expect(body.error).to.be('Forbidden'); + }); + }); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/write_user.ts b/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/write_user.ts new file mode 100644 index 00000000000000..5260d234eb9c7c --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/settings/anomaly_detection/write_user.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 expect from '@kbn/expect'; +import { registry } from '../../../common/registry'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +export default function apiTest({ getService }: FtrProviderContext) { + const apmWriteUser = getService('supertestAsApmWriteUser'); + + function getJobs() { + return apmWriteUser.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); + } + + function createJobs(environments: string[]) { + return apmWriteUser + .post(`/api/apm/settings/anomaly-detection/jobs`) + .send({ environments }) + .set('kbn-xsrf', 'foo'); + } + + function deleteJobs(jobIds: string[]) { + return apmWriteUser.post(`/api/ml/jobs/delete_jobs`).send({ jobIds }).set('kbn-xsrf', 'foo'); + } + + registry.when('ML jobs', { config: 'trial', archives: [] }, () => { + describe('when user has write access to ML', () => { + after(async () => { + const res = await getJobs(); + const jobIds = res.body.jobs.map((job: any) => job.job_id); + await deleteJobs(jobIds); + }); + + describe('when calling the endpoint for listing jobs', () => { + it('returns a list of jobs', async () => { + const { body } = await getJobs(); + expect(body.jobs.length).to.be(0); + expect(body.hasLegacyJobs).to.be(false); + }); + }); + + describe('when calling create endpoint', () => { + it('creates two jobs', async () => { + await createJobs(['production', 'staging']); + + const { body } = await getJobs(); + expect(body.hasLegacyJobs).to.be(false); + expect(body.jobs.map((job: any) => job.environment)).to.eql(['production', 'staging']); + }); + }); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/settings/custom_link.ts b/x-pack/test/apm_api_integration/tests/settings/custom_link.ts new file mode 100644 index 00000000000000..3df905eabeacee --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/settings/custom_link.ts @@ -0,0 +1,183 @@ +/* + * 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 URL from 'url'; +import expect from '@kbn/expect'; +import { CustomLink } from '../../../../plugins/apm/common/custom_link/custom_link_types'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function customLinksTests({ getService }: FtrProviderContext) { + const supertestRead = getService('supertest'); + const supertestWrite = getService('supertestAsApmWriteUser'); + const log = getService('log'); + + const archiveName = 'apm_8.0.0'; + + registry.when('Custom links with a basic license', { config: 'basic', archives: [] }, () => { + it('returns a 403 forbidden', async () => { + const customLink = { + url: 'https://elastic.co', + label: 'with filters', + filters: [ + { key: 'service.name', value: 'baz' }, + { key: 'transaction.type', value: 'qux' }, + ], + } as CustomLink; + const response = await supertestWrite + .post(`/api/apm/settings/custom_links`) + .send(customLink) + .set('kbn-xsrf', 'foo'); + + expect(response.status).to.be(403); + + expectSnapshot(response.body.message).toMatchInline( + `"To create custom links, you must be subscribed to an Elastic Gold license or above. With it, you'll have the ability to create custom links to improve your workflow when analyzing your services."` + ); + }); + }); + + registry.when( + 'Custom links with a trial license and data', + { config: 'trial', archives: [archiveName] }, + () => { + before(async () => { + const customLink = { + url: 'https://elastic.co', + label: 'with filters', + filters: [ + { key: 'service.name', value: 'baz' }, + { key: 'transaction.type', value: 'qux' }, + ], + } as CustomLink; + await createCustomLink(customLink); + }); + it('fetches a custom link', async () => { + const { status, body } = await searchCustomLinks({ + 'service.name': 'baz', + 'transaction.type': 'qux', + }); + const { label, url, filters } = body[0]; + + expect(status).to.equal(200); + expect({ label, url, filters }).to.eql({ + label: 'with filters', + url: 'https://elastic.co', + filters: [ + { key: 'service.name', value: 'baz' }, + { key: 'transaction.type', value: 'qux' }, + ], + }); + }); + it('updates a custom link', async () => { + let { status, body } = await searchCustomLinks({ + 'service.name': 'baz', + 'transaction.type': 'qux', + }); + expect(status).to.equal(200); + await updateCustomLink(body[0].id, { + label: 'foo', + url: 'https://elastic.co?service.name={{service.name}}', + filters: [ + { key: 'service.name', value: 'quz' }, + { key: 'transaction.name', value: 'bar' }, + ], + }); + ({ status, body } = await searchCustomLinks({ + 'service.name': 'quz', + 'transaction.name': 'bar', + })); + const { label, url, filters } = body[0]; + expect(status).to.equal(200); + expect({ label, url, filters }).to.eql({ + label: 'foo', + url: 'https://elastic.co?service.name={{service.name}}', + filters: [ + { key: 'service.name', value: 'quz' }, + { key: 'transaction.name', value: 'bar' }, + ], + }); + }); + it('deletes a custom link', async () => { + let { status, body } = await searchCustomLinks({ + 'service.name': 'quz', + 'transaction.name': 'bar', + }); + expect(status).to.equal(200); + await deleteCustomLink(body[0].id); + ({ status, body } = await searchCustomLinks({ + 'service.name': 'quz', + 'transaction.name': 'bar', + })); + expect(status).to.equal(200); + expect(body).to.eql([]); + }); + + describe('transaction', () => { + it('fetches a transaction sample', async () => { + const response = await supertestRead.get( + '/api/apm/settings/custom_links/transaction?service.name=opbeans-java' + ); + expect(response.status).to.be(200); + expect(response.body.service.name).to.eql('opbeans-java'); + }); + }); + } + ); + + function searchCustomLinks(filters?: any) { + const path = URL.format({ + pathname: `/api/apm/settings/custom_links`, + query: filters, + }); + return supertestRead.get(path).set('kbn-xsrf', 'foo'); + } + + async function createCustomLink(customLink: CustomLink) { + log.debug('creating configuration', customLink); + const res = await supertestWrite + .post(`/api/apm/settings/custom_links`) + .send(customLink) + .set('kbn-xsrf', 'foo'); + + throwOnError(res); + + return res; + } + + async function updateCustomLink(id: string, customLink: CustomLink) { + log.debug('updating configuration', id, customLink); + const res = await supertestWrite + .put(`/api/apm/settings/custom_links/${id}`) + .send(customLink) + .set('kbn-xsrf', 'foo'); + + throwOnError(res); + + return res; + } + + async function deleteCustomLink(id: string) { + log.debug('deleting configuration', id); + const res = await supertestWrite + .delete(`/api/apm/settings/custom_links/${id}`) + .set('kbn-xsrf', 'foo'); + + throwOnError(res); + + return res; + } + + function throwOnError(res: any) { + const { statusCode, req, body } = res; + if (statusCode !== 200) { + throw new Error(` + Endpoint: ${req.method} ${req.path} + Service: ${JSON.stringify(res.request._data.service)} + Status code: ${statusCode} + Response: ${body.message}`); + } + } +} diff --git a/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap b/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.snap similarity index 99% rename from x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap rename to x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.snap index 56e82d752dccdc..c8104b9858027c 100644 --- a/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap +++ b/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM specs (basic) Traces Top traces when data is loaded returns the correct buckets 1`] = ` +exports[`APM API tests basic apm_8.0.0 Top traces when data is loaded returns the correct buckets 1`] = ` Array [ Object { "averageResponseTime": 1733, diff --git a/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts b/x-pack/test/apm_api_integration/tests/traces/top_traces.ts similarity index 81% rename from x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts rename to x-pack/test/apm_api_integration/tests/traces/top_traces.ts index 2ce3ba38382926..4754b3faa20ad2 100644 --- a/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts +++ b/x-pack/test/apm_api_integration/tests/traces/top_traces.ts @@ -5,12 +5,12 @@ */ import expect from '@kbn/expect'; import { sortBy } from 'lodash'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; 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]; @@ -20,28 +20,28 @@ export default function ApiTest({ getService }: FtrProviderContext) { const end = encodeURIComponent(metadata.end); const uiFilters = encodeURIComponent(JSON.stringify({})); - describe('Top traces', () => { - describe('when data is not loaded ', () => { - it('handles empty state', async () => { - const response = await supertest.get( - `/api/apm/traces?start=${start}&end=${end}&uiFilters=${uiFilters}` - ); + registry.when('Top traces when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles empty state', async () => { + const response = await supertest.get( + `/api/apm/traces?start=${start}&end=${end}&uiFilters=${uiFilters}` + ); - expect(response.status).to.be(200); - expect(response.body.items.length).to.be(0); - expect(response.body.isAggregationAccurate).to.be(true); - }); + expect(response.status).to.be(200); + expect(response.body.items.length).to.be(0); + expect(response.body.isAggregationAccurate).to.be(true); }); + }); - describe('when data is loaded', () => { + registry.when( + 'Top traces when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { let response: any; before(async () => { - await esArchiver.load(archiveName); response = await supertest.get( `/api/apm/traces?start=${start}&end=${end}&uiFilters=${uiFilters}` ); }); - after(() => esArchiver.unload(archiveName)); it('returns the correct status code', async () => { expect(response.status).to.be(200); @@ -116,6 +116,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { ] `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/breakdown.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/breakdown.snap similarity index 98% rename from x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/breakdown.snap rename to x-pack/test/apm_api_integration/tests/transactions/__snapshots__/breakdown.snap index 25aa68d2a86b1f..cfdd27b594956e 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/breakdown.snap +++ b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/breakdown.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM specs (basic) Transactions Breakdown when data is loaded returns the transaction breakdown for a service 1`] = ` +exports[`APM API tests basic apm_8.0.0 when data is loaded returns the transaction breakdown for a service 1`] = ` Object { "timeseries": Array [ Object { @@ -1019,7 +1019,7 @@ Object { } `; -exports[`APM specs (basic) Transactions Breakdown when data is loaded returns the transaction breakdown for a transaction group 9`] = ` +exports[`APM API tests basic apm_8.0.0 when data is loaded returns the transaction breakdown for a transaction group 9`] = ` Array [ Object { "x": 1607435850000, diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/error_rate.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/error_rate.snap similarity index 95% rename from x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/error_rate.snap rename to x-pack/test/apm_api_integration/tests/transactions/__snapshots__/error_rate.snap index 3b67a86ba84e8e..d97d39cda1b8d4 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/error_rate.snap +++ b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/error_rate.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM specs (basic) Transactions Error rate when data is loaded returns the transaction error rate has the correct error rate 1`] = ` +exports[`APM API tests basic apm_8.0.0 Error rate when data is loaded returns the transaction error rate has the correct error rate 1`] = ` Array [ Object { "x": 1607435850000, diff --git a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/latency.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/latency.snap new file mode 100644 index 00000000000000..a384ca2c9364e8 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/latency.snap @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`APM API tests trial apm_8.0.0 Transaction latency with a trial license when data is loaded when not defined environments seleted should return the correct anomaly boundaries 1`] = ` +Array [ + Object { + "x": 1607436000000, + "y": 0, + "y0": 0, + }, + Object { + "x": 1607436900000, + "y": 0, + "y0": 0, + }, +] +`; + +exports[`APM API tests trial apm_8.0.0 Transaction latency with a trial license when data is loaded with environment selected and empty kuery filter should return a non-empty anomaly series 1`] = ` +Array [ + Object { + "x": 1607436000000, + "y": 1625128.56211579, + "y0": 7533.02707532227, + }, + Object { + "x": 1607436900000, + "y": 1660982.24115757, + "y0": 5732.00699123528, + }, +] +`; + +exports[`APM API tests trial apm_8.0.0 Transaction latency with a trial license when data is loaded with environment selected in uiFilters should return a non-empty anomaly series 1`] = ` +Array [ + Object { + "x": 1607436000000, + "y": 1625128.56211579, + "y0": 7533.02707532227, + }, + Object { + "x": 1607436900000, + "y": 1660982.24115757, + "y0": 5732.00699123528, + }, +] +`; diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/top_transaction_groups.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/top_transaction_groups.snap similarity index 96% rename from x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/top_transaction_groups.snap rename to x-pack/test/apm_api_integration/tests/transactions/__snapshots__/top_transaction_groups.snap index 473305f3e39afc..67a02e416de512 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/top_transaction_groups.snap +++ b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/top_transaction_groups.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM specs (basic) Transactions Top transaction groups when data is loaded returns the correct buckets (when ignoring samples) 1`] = ` +exports[`APM API tests basic apm_8.0.0 Top transaction groups when data is loaded returns the correct buckets (when ignoring samples) 1`] = ` Array [ Object { "averageResponseTime": 2722.75, diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/transaction_charts.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transaction_charts.snap similarity index 100% rename from x-pack/test/apm_api_integration/basic/tests/transactions/__snapshots__/transaction_charts.snap rename to x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transaction_charts.snap diff --git a/x-pack/test/apm_api_integration/trial/tests/transactions/__snapshots__/transactions_charts.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_charts.snap similarity index 100% rename from x-pack/test/apm_api_integration/trial/tests/transactions/__snapshots__/transactions_charts.snap rename to x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_charts.snap diff --git a/x-pack/test/apm_api_integration/tests/transactions/breakdown.ts b/x-pack/test/apm_api_integration/tests/transactions/breakdown.ts new file mode 100644 index 00000000000000..4a9dcf9273003d --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/transactions/breakdown.ts @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import expect from '@kbn/expect'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + 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({})); + + registry.when('Breakdown when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles the empty state', async () => { + const response = await supertest.get( + `/api/apm/services/opbeans-node/transaction/charts/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` + ); + expect(response.status).to.be(200); + expect(response.body).to.eql({ timeseries: [] }); + }); + }); + + registry.when('when data is loaded', { config: 'basic', archives: [archiveName] }, () => { + it('returns the transaction breakdown for a service', async () => { + const response = await supertest.get( + `/api/apm/services/opbeans-node/transaction/charts/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` + ); + + expect(response.status).to.be(200); + expectSnapshot(response.body).toMatch(); + }); + it('returns the transaction breakdown for a transaction group', async () => { + const response = await supertest.get( + `/api/apm/services/opbeans-node/transaction/charts/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}&transactionName=${transactionName}` + ); + + 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]; + + const nonNullDataPoints = data.filter((y: number | null) => y !== null); + + expectSnapshot(nonNullDataPoints.length).toMatchInline(`61`); + + 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": "2020-12-08T13:57:30.000Z", + "y": null, + }, + Object { + "x": "2020-12-08T13:58:00.000Z", + "y": null, + }, + Object { + "x": "2020-12-08T13:58:30.000Z", + "y": 1, + }, + Object { + "x": "2020-12-08T13:59:00.000Z", + "y": 1, + }, + Object { + "x": "2020-12-08T13:59:30.000Z", + "y": null, + }, + ] + `); + + expectSnapshot(title).toMatchInline(`"app"`); + expectSnapshot(color).toMatchInline(`"#54b399"`); + 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( + `/api/apm/services/opbeans-node/transaction/charts/breakdown?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` + ); + + expect(response.status).to.be(200); + expectSnapshot(response.body.timeseries.map((serie: { title: string }) => serie.title)) + .toMatchInline(` + Array [ + "app", + "http", + "postgresql", + "redis", + ] + `); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/distribution.ts b/x-pack/test/apm_api_integration/tests/transactions/distribution.ts similarity index 85% rename from x-pack/test/apm_api_integration/basic/tests/transactions/distribution.ts rename to x-pack/test/apm_api_integration/tests/transactions/distribution.ts index 890b6af728d5ab..5d918b479111f1 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/distribution.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/distribution.ts @@ -6,12 +6,12 @@ import expect from '@kbn/expect'; import qs from 'querystring'; import { isEmpty } from 'lodash'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; 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]; @@ -24,8 +24,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { transactionType: 'request', })}`; - describe('Transaction groups distribution', () => { - describe('when data is not loaded ', () => { + registry.when( + 'Transaction groups distribution when data is not loaded', + { config: 'basic', archives: [] }, + () => { it('handles empty state', async () => { const response = await supertest.get(url); @@ -34,15 +36,17 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.body.noHits).to.be(true); expect(response.body.buckets.length).to.be(0); }); - }); + } + ); - describe('when data is loaded', () => { + registry.when( + 'Transaction groups distribution when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { let response: any; before(async () => { - await esArchiver.load(archiveName); response = await supertest.get(url); }); - after(() => esArchiver.unload(archiveName)); it('returns the correct metadata', () => { expect(response.status).to.be(200); @@ -91,6 +95,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { ] `); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/error_rate.ts b/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts similarity index 71% rename from x-pack/test/apm_api_integration/basic/tests/transactions/error_rate.ts rename to x-pack/test/apm_api_integration/tests/transactions/error_rate.ts index 22d9a7eba7fbfe..487f2efbae4008 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/error_rate.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts @@ -6,12 +6,12 @@ import expect from '@kbn/expect'; import { first, last } from 'lodash'; import { format } from 'url'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); const archiveName = 'apm_8.0.0'; @@ -20,28 +20,27 @@ export default function ApiTest({ getService }: FtrProviderContext) { const uiFilters = '{}'; const transactionType = 'request'; - describe('Error rate', () => { - const url = format({ - pathname: '/api/apm/services/opbeans-java/transactions/charts/error_rate', - query: { start, end, uiFilters, transactionType }, - }); + const url = format({ + pathname: '/api/apm/services/opbeans-java/transactions/charts/error_rate', + query: { start, end, uiFilters, transactionType }, + }); - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await supertest.get(url); - expect(response.status).to.be(200); + registry.when('Error rate when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles the empty state', async () => { + const response = await supertest.get(url); + expect(response.status).to.be(200); - expect(response.body.noHits).to.be(true); + expect(response.body.noHits).to.be(true); - expect(response.body.transactionErrorRate.length).to.be(0); - expect(response.body.average).to.be(null); - }); + expect(response.body.transactionErrorRate.length).to.be(0); + expect(response.body.average).to.be(null); }); + }); - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - + registry.when( + 'Error rate when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { describe('returns the transaction error rate', () => { let errorRateResponse: { transactionErrorRate: Array<{ x: number; y: number | null }>; @@ -89,6 +88,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(errorRateResponse.transactionErrorRate).toMatch(); }); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/tests/transactions/latency.ts b/x-pack/test/apm_api_integration/tests/transactions/latency.ts new file mode 100644 index 00000000000000..c860b0e75495cc --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/transactions/latency.ts @@ -0,0 +1,243 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { PromiseReturnType } from '../../../../plugins/observability/typings/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { registry } from '../../common/registry'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + const archiveName = 'apm_8.0.0'; + + const range = archives_metadata[archiveName]; + + // url parameters + const start = encodeURIComponent(range.start); + const end = encodeURIComponent(range.end); + + registry.when( + 'Latency with a basic license when data is not loaded ', + { config: 'basic', archives: [] }, + () => { + const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'testing' })); + it('returns 400 when latencyAggregationType is not informed', async () => { + const response = await supertest.get( + `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=request` + ); + + expect(response.status).to.be(400); + }); + + it('returns 400 when transactionType is not informed', async () => { + const response = await supertest.get( + `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&latencyAggregationType=avg` + ); + + expect(response.status).to.be(400); + }); + + it('handles the empty state', async () => { + const response = await supertest.get( + `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&latencyAggregationType=avg&transactionType=request` + ); + + expect(response.status).to.be(200); + + expect(response.body.overallAvgDuration).to.be(null); + expect(response.body.latencyTimeseries.length).to.be(0); + }); + } + ); + + registry.when( + 'Latency with a basic license when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { + let response: PromiseReturnType; + + const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'testing' })); + + describe('average latency type', () => { + before(async () => { + response = await supertest.get( + `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=request&latencyAggregationType=avg` + ); + }); + + it('returns average duration and timeseries', async () => { + expect(response.status).to.be(200); + expect(response.body.overallAvgDuration).not.to.be(null); + expect(response.body.latencyTimeseries.length).to.be.eql(61); + }); + }); + + describe('95th percentile latency type', () => { + before(async () => { + response = await supertest.get( + `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=request&latencyAggregationType=p95` + ); + }); + + it('returns average duration and timeseries', async () => { + expect(response.status).to.be(200); + expect(response.body.overallAvgDuration).not.to.be(null); + expect(response.body.latencyTimeseries.length).to.be.eql(61); + }); + }); + + describe('99th percentile latency type', () => { + before(async () => { + response = await supertest.get( + `/api/apm/services/opbeans-node/transactions/charts/latency?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=request&latencyAggregationType=p99` + ); + }); + + it('returns average duration and timeseries', async () => { + expect(response.status).to.be(200); + expect(response.body.overallAvgDuration).not.to.be(null); + expect(response.body.latencyTimeseries.length).to.be.eql(61); + }); + }); + } + ); + + registry.when( + 'Transaction latency with a trial license when data is loaded', + { config: 'trial', archives: [archiveName] }, + () => { + let response: PromiseReturnType; + + const transactionType = 'request'; + + describe('without environment', () => { + const uiFilters = encodeURIComponent(JSON.stringify({})); + before(async () => { + response = await supertest.get( + `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` + ); + }); + it('should return an error response', () => { + expect(response.status).to.eql(400); + }); + }); + + describe('without uiFilters', () => { + before(async () => { + response = await supertest.get( + `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&latencyAggregationType=avg` + ); + }); + it('should return an error response', () => { + expect(response.status).to.eql(400); + }); + }); + + describe('with environment selected in uiFilters', () => { + const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'production' })); + before(async () => { + response = await supertest.get( + `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` + ); + }); + + it('should have a successful response', () => { + expect(response.status).to.eql(200); + }); + + it('should return the ML job id for anomalies of the selected environment', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries).to.have.property('jobId'); + expectSnapshot(response.body.anomalyTimeseries.jobId).toMatchInline( + `"apm-production-1369-high_mean_transaction_duration"` + ); + }); + + it('should return a non-empty anomaly series', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries.anomalyBoundaries?.length).to.be.greaterThan(0); + expectSnapshot(response.body.anomalyTimeseries.anomalyBoundaries).toMatch(); + }); + }); + + describe('when not defined environments seleted', () => { + const uiFilters = encodeURIComponent( + JSON.stringify({ environment: 'ENVIRONMENT_NOT_DEFINED' }) + ); + before(async () => { + response = await supertest.get( + `/api/apm/services/opbeans-python/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` + ); + }); + + it('should have a successful response', () => { + expect(response.status).to.eql(200); + }); + + it('should return the ML job id for anomalies with no defined environment', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries).to.have.property('jobId'); + expectSnapshot(response.body.anomalyTimeseries.jobId).toMatchInline( + `"apm-environment_not_defined-5626-high_mean_transaction_duration"` + ); + }); + + it('should return the correct anomaly boundaries', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expectSnapshot(response.body.anomalyTimeseries.anomalyBoundaries).toMatch(); + }); + }); + + describe('with all environments selected', () => { + const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'ENVIRONMENT_ALL' })); + before(async () => { + response = await supertest.get( + `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` + ); + }); + + it('should have a successful response', () => { + expect(response.status).to.eql(200); + }); + + it('should not return anomaly timeseries data', () => { + expect(response.body).to.not.have.property('anomalyTimeseries'); + }); + }); + + describe('with environment selected and empty kuery filter', () => { + const uiFilters = encodeURIComponent( + JSON.stringify({ kuery: '', environment: 'production' }) + ); + before(async () => { + response = await supertest.get( + `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` + ); + }); + + it('should have a successful response', () => { + expect(response.status).to.eql(200); + }); + + it('should return the ML job id for anomalies of the selected environment', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries).to.have.property('jobId'); + expectSnapshot(response.body.anomalyTimeseries.jobId).toMatchInline( + `"apm-production-1369-high_mean_transaction_duration"` + ); + }); + + it('should return a non-empty anomaly series', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries.anomalyBoundaries?.length).to.be.greaterThan(0); + expectSnapshot(response.body.anomalyTimeseries.anomalyBoundaries).toMatch(); + }); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/throughput.ts b/x-pack/test/apm_api_integration/tests/transactions/throughput.ts similarity index 54% rename from x-pack/test/apm_api_integration/basic/tests/transactions/throughput.ts rename to x-pack/test/apm_api_integration/tests/transactions/throughput.ts index 1013f3a19d71fe..475bef4e9b549f 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/throughput.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/throughput.ts @@ -5,13 +5,13 @@ */ import expect from '@kbn/expect'; import url from 'url'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { PromiseReturnType } from '../../../../../plugins/observability/typings/common'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { PromiseReturnType } from '../../../../plugins/observability/typings/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; 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]; @@ -20,31 +20,30 @@ export default function ApiTest({ getService }: FtrProviderContext) { const { start, end } = metadata; const uiFilters = JSON.stringify({ environment: 'testing' }); - describe('Throughput', () => { - describe('when data is not loaded ', () => { - it('handles the empty state', async () => { - const response = await supertest.get( - url.format({ - pathname: `/api/apm/services/opbeans-node/transactions/charts/throughput`, - query: { - start, - end, - uiFilters, - transactionType: 'request', - }, - }) - ); + registry.when('Throughput when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles the empty state', async () => { + const response = await supertest.get( + url.format({ + pathname: `/api/apm/services/opbeans-node/transactions/charts/throughput`, + query: { + start, + end, + uiFilters, + transactionType: 'request', + }, + }) + ); - expect(response.status).to.be(200); + expect(response.status).to.be(200); - expect(response.body.throughputTimeseries.length).to.be(0); - }); + expect(response.body.throughputTimeseries.length).to.be(0); }); + }); - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - + registry.when( + 'Throughput when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { let response: PromiseReturnType; before(async () => { @@ -66,6 +65,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.body.throughputTimeseries.length).to.be.greaterThan(0); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/top_transaction_groups.ts b/x-pack/test/apm_api_integration/tests/transactions/top_transaction_groups.ts similarity index 80% rename from x-pack/test/apm_api_integration/basic/tests/transactions/top_transaction_groups.ts rename to x-pack/test/apm_api_integration/tests/transactions/top_transaction_groups.ts index dac36ae8b3303d..70afb2ee384c43 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/top_transaction_groups.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/top_transaction_groups.ts @@ -5,8 +5,9 @@ */ import expect from '@kbn/expect'; import { sortBy } from 'lodash'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; function sortTransactionGroups(items: any[]) { return sortBy(items, 'impact'); @@ -14,7 +15,6 @@ function sortTransactionGroups(items: any[]) { 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]; @@ -25,8 +25,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { const uiFilters = encodeURIComponent(JSON.stringify({})); const transactionType = 'request'; - describe('Top transaction groups', () => { - describe('when data is not loaded ', () => { + registry.when( + 'Top transaction groups when data is not loaded', + { config: 'basic', archives: [] }, + () => { it('handles empty state', async () => { const response = await supertest.get( `/api/apm/services/opbeans-node/transactions/groups?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` @@ -37,17 +39,19 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.body.isAggregationAccurate).to.be(true); expect(response.body.items.length).to.be(0); }); - }); + } + ); - describe('when data is loaded', () => { + registry.when( + 'Top transaction groups when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { let response: any; before(async () => { - await esArchiver.load(archiveName); response = await supertest.get( `/api/apm/services/opbeans-node/transactions/groups?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` ); }); - after(() => esArchiver.unload(archiveName)); it('returns the correct metadata', () => { expect(response.status).to.be(200); @@ -62,6 +66,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('returns the correct buckets (when ignoring samples)', async () => { expectSnapshot(sortTransactionGroups(response.body.items)).toMatch(); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/basic/tests/transactions/transactions_groups_overview.ts b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_overview.ts similarity index 94% rename from x-pack/test/apm_api_integration/basic/tests/transactions/transactions_groups_overview.ts rename to x-pack/test/apm_api_integration/tests/transactions/transactions_groups_overview.ts index be978b2a82618d..8818aaccdec015 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transactions/transactions_groups_overview.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_overview.ts @@ -7,18 +7,20 @@ import expect from '@kbn/expect'; import { pick, uniqBy, sortBy } from 'lodash'; import url from 'url'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import archives from '../../../common/fixtures/es_archiver/archives_metadata'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import archives from '../../common/fixtures/es_archiver/archives_metadata'; +import { registry } from '../../common/registry'; export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); const archiveName = 'apm_8.0.0'; const { start, end } = archives[archiveName]; - describe('Transactions groups overview', () => { - describe('when data is not loaded', () => { + registry.when( + 'Transaction groups overview when data is not loaded', + { config: 'basic', archives: [] }, + () => { it('handles the empty state', async () => { const response = await supertest.get( url.format({ @@ -45,12 +47,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { isAggregationAccurate: true, }); }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); + } + ); + registry.when( + 'Top transaction groups when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { it('returns the correct data', async () => { const response = await supertest.get( url.format({ @@ -264,6 +267,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(uniqBy(items, 'name').length).to.eql(totalItems); }); - }); - }); + } + ); } diff --git a/x-pack/test/apm_api_integration/trial/config.ts b/x-pack/test/apm_api_integration/trial/config.ts index 94a6f808603c11..ba9ef4ca425971 100644 --- a/x-pack/test/apm_api_integration/trial/config.ts +++ b/x-pack/test/apm_api_integration/trial/config.ts @@ -4,10 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createTestConfig } from '../common/config'; +import { configs } from '../configs'; -export default createTestConfig({ - license: 'trial', - name: 'X-Pack APM API integration tests (trial)', - testFiles: [require.resolve('./tests')], -}); +export default configs.trial; diff --git a/x-pack/test/apm_api_integration/trial/tests/correlations/slow_transactions.ts b/x-pack/test/apm_api_integration/trial/tests/correlations/slow_transactions.ts deleted file mode 100644 index 9a868373292f66..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/correlations/slow_transactions.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { format } from 'url'; -import { APIReturnType } from '../../../../../plugins/apm/public/services/rest/createCallApmApi'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - const archiveName = 'apm_8.0.0'; - const range = archives_metadata[archiveName]; - - describe('Slow durations', () => { - const url = format({ - pathname: `/api/apm/correlations/slow_transactions`, - query: { - start: range.start, - end: range.end, - durationPercentile: 95, - fieldNames: - 'user.username,user.id,host.ip,user_agent.name,kubernetes.pod.uuid,url.domain,container.id,service.node.name', - }, - }); - - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await supertest.get(url); - - expect(response.status).to.be(200); - expect(response.body.response).to.be(undefined); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - describe('making request with default args', () => { - type ResponseBody = APIReturnType<'GET /api/apm/correlations/slow_transactions'>; - let response: { - status: number; - body: NonNullable; - }; - - before(async () => { - response = await supertest.get(url); - }); - - it('returns successfully', () => { - expect(response.status).to.eql(200); - }); - - it('returns significant terms', () => { - const sorted = response.body?.significantTerms?.sort(); - expectSnapshot(sorted?.map((term) => term.fieldName)).toMatchInline(` - Array [ - "user_agent.name", - "url.domain", - "host.ip", - "service.node.name", - "container.id", - "url.domain", - "user_agent.name", - ] - `); - }); - - it('returns a distribution per term', () => { - expectSnapshot(response.body?.significantTerms?.map((term) => term.distribution.length)) - .toMatchInline(` - Array [ - 11, - 11, - 11, - 11, - 11, - 11, - 11, - ] - `); - }); - - it('returns overall distribution', () => { - expectSnapshot(response.body?.overall?.distribution.length).toMatchInline(`11`); - }); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/csm_services.ts b/x-pack/test/apm_api_integration/trial/tests/csm/csm_services.ts deleted file mode 100644 index 05c6439508ecea..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/csm/csm_services.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function rumServicesApiTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - describe('CSM Services', () => { - describe('when there is no data', () => { - it('returns empty list', async () => { - const response = await supertest.get( - '/api/apm/rum-client/services?start=2020-06-28T10%3A24%3A46.055Z&end=2020-07-29T10%3A24%3A46.055Z&uiFilters=%7B%22agentName%22%3A%5B%22js-base%22%2C%22rum-js%22%5D%7D' - ); - - expect(response.status).to.be(200); - expect(response.body).to.eql([]); - }); - }); - - describe('when there is data', () => { - before(async () => { - await esArchiver.load('8.0.0'); - await esArchiver.load('rum_8.0.0'); - }); - after(async () => { - await esArchiver.unload('8.0.0'); - await esArchiver.unload('rum_8.0.0'); - }); - - it('returns rum services list', async () => { - const response = await supertest.get( - '/api/apm/rum-client/services?start=2020-06-28T10%3A24%3A46.055Z&end=2020-07-29T10%3A24%3A46.055Z&uiFilters=%7B%22agentName%22%3A%5B%22js-base%22%2C%22rum-js%22%5D%7D' - ); - - expect(response.status).to.be(200); - - expectSnapshot(response.body).toMatchInline(`Array []`); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/page_load_dist.ts b/x-pack/test/apm_api_integration/trial/tests/csm/page_load_dist.ts deleted file mode 100644 index fa5fcbcb6a7c3c..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/csm/page_load_dist.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function rumServicesApiTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - describe('UX page load dist', () => { - describe('when there is no data', () => { - it('returns empty list', async () => { - const response = await supertest.get( - '/api/apm/rum-client/page-load-distribution?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D' - ); - - expect(response.status).to.be(200); - expectSnapshot(response.body).toMatch(); - }); - it('returns empty list with breakdowns', async () => { - const response = await supertest.get( - '/api/apm/rum-client/page-load-distribution/breakdown?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D&breakdown=Browser' - ); - - expect(response.status).to.be(200); - expectSnapshot(response.body).toMatch(); - }); - }); - - describe('when there is data', () => { - before(async () => { - await esArchiver.load('8.0.0'); - await esArchiver.load('rum_8.0.0'); - }); - after(async () => { - await esArchiver.unload('8.0.0'); - await esArchiver.unload('rum_8.0.0'); - }); - - it('returns page load distribution', async () => { - const response = await supertest.get( - '/api/apm/rum-client/page-load-distribution?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D' - ); - - expect(response.status).to.be(200); - - expectSnapshot(response.body).toMatch(); - }); - it('returns page load distribution with breakdown', async () => { - const response = await supertest.get( - '/api/apm/rum-client/page-load-distribution/breakdown?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D&breakdown=Browser' - ); - - expect(response.status).to.be(200); - - expectSnapshot(response.body).toMatch(); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/page_views.ts b/x-pack/test/apm_api_integration/trial/tests/csm/page_views.ts deleted file mode 100644 index 5d910862843d55..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/csm/page_views.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function rumServicesApiTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - describe('CSM page views', () => { - describe('when there is no data', () => { - it('returns empty list', async () => { - const response = await supertest.get( - '/api/apm/rum-client/page-view-trends?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D' - ); - - expect(response.status).to.be(200); - expectSnapshot(response.body).toMatch(); - }); - it('returns empty list with breakdowns', async () => { - const response = await supertest.get( - '/api/apm/rum-client/page-view-trends?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D&breakdowns=%7B%22name%22%3A%22Browser%22%2C%22fieldName%22%3A%22user_agent.name%22%2C%22type%22%3A%22category%22%7D' - ); - - expect(response.status).to.be(200); - expectSnapshot(response.body).toMatch(); - }); - }); - - describe('when there is data', () => { - before(async () => { - await esArchiver.load('8.0.0'); - await esArchiver.load('rum_8.0.0'); - }); - after(async () => { - await esArchiver.unload('8.0.0'); - await esArchiver.unload('rum_8.0.0'); - }); - - it('returns page views', async () => { - const response = await supertest.get( - '/api/apm/rum-client/page-view-trends?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D' - ); - - expect(response.status).to.be(200); - - expectSnapshot(response.body).toMatch(); - }); - it('returns page views with breakdown', async () => { - const response = await supertest.get( - '/api/apm/rum-client/page-view-trends?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D&breakdowns=%7B%22name%22%3A%22Browser%22%2C%22fieldName%22%3A%22user_agent.name%22%2C%22type%22%3A%22category%22%7D' - ); - - expect(response.status).to.be(200); - - expectSnapshot(response.body).toMatch(); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/url_search.ts b/x-pack/test/apm_api_integration/trial/tests/csm/url_search.ts deleted file mode 100644 index 961c783434639c..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/csm/url_search.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function rumServicesApiTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - describe('CSM url search api', () => { - describe('when there is no data', () => { - it('returns empty list', async () => { - const response = await supertest.get( - '/api/apm/rum-client/url-search?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D&percentile=50' - ); - - expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "items": Array [], - "total": 0, - } - `); - }); - }); - - describe('when there is data', () => { - before(async () => { - await esArchiver.load('8.0.0'); - await esArchiver.load('rum_8.0.0'); - }); - after(async () => { - await esArchiver.unload('8.0.0'); - await esArchiver.unload('rum_8.0.0'); - }); - - it('returns top urls when no query', async () => { - const response = await supertest.get( - '/api/apm/rum-client/url-search?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D&percentile=50' - ); - - expect(response.status).to.be(200); - - expectSnapshot(response.body).toMatchInline(` - Object { - "items": Array [ - Object { - "count": 5, - "pld": 4924000, - "url": "http://localhost:5601/nfw/app/csm?rangeFrom=now-15m&rangeTo=now&serviceName=kibana-frontend-8_0_0", - }, - Object { - "count": 1, - "pld": 2760000, - "url": "http://localhost:5601/nfw/app/home", - }, - ], - "total": 2, - } - `); - }); - - it('returns specific results against query', async () => { - const response = await supertest.get( - '/api/apm/rum-client/url-search?start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D&urlQuery=csm&percentile=50' - ); - - expect(response.status).to.be(200); - - expectSnapshot(response.body).toMatchInline(` - Object { - "items": Array [ - Object { - "count": 5, - "pld": 4924000, - "url": "http://localhost:5601/nfw/app/csm?rangeFrom=now-15m&rangeTo=now&serviceName=kibana-frontend-8_0_0", - }, - ], - "total": 1, - } - `); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/index.ts b/x-pack/test/apm_api_integration/trial/tests/index.ts deleted file mode 100644 index c8ee858d9ceb04..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/index.ts +++ /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 { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; - -export default function observabilityApiIntegrationTests({ loadTestFile }: FtrProviderContext) { - describe('APM specs (trial)', function () { - this.tags('ciGroup1'); - - describe('Services', function () { - loadTestFile(require.resolve('./services/annotations')); - loadTestFile(require.resolve('./services/top_services.ts')); - }); - - describe('Transactions', function () { - loadTestFile(require.resolve('./transactions/latency')); - }); - - describe('Settings', function () { - loadTestFile(require.resolve('./settings/custom_link.ts')); - describe('Anomaly detection', function () { - loadTestFile(require.resolve('./settings/anomaly_detection/no_access_user')); - loadTestFile(require.resolve('./settings/anomaly_detection/read_user')); - loadTestFile(require.resolve('./settings/anomaly_detection/write_user')); - }); - }); - - describe('Service Maps', function () { - loadTestFile(require.resolve('./service_maps/service_maps')); - }); - - describe('CSM', function () { - loadTestFile(require.resolve('./csm/csm_services.ts')); - loadTestFile(require.resolve('./csm/web_core_vitals.ts')); - loadTestFile(require.resolve('./csm/long_task_metrics.ts')); - loadTestFile(require.resolve('./csm/url_search.ts')); - loadTestFile(require.resolve('./csm/page_views.ts')); - loadTestFile(require.resolve('./csm/js_errors.ts')); - loadTestFile(require.resolve('./csm/has_rum_data.ts')); - loadTestFile(require.resolve('./csm/page_load_dist.ts')); - }); - - describe('Correlations', function () { - loadTestFile(require.resolve('./correlations/slow_transactions')); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/services/top_services.ts b/x-pack/test/apm_api_integration/trial/tests/services/top_services.ts deleted file mode 100644 index e37d98b41b7afd..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/services/top_services.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { sortBy } from 'lodash'; -import { APIReturnType } from '../../../../../plugins/apm/public/services/rest/createCallApmApi'; -import { PromiseReturnType } from '../../../../../plugins/observability/typings/common'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const supertestAsApmReadUserWithoutMlAccess = getService('supertestAsApmReadUserWithoutMlAccess'); - const esArchiver = getService('esArchiver'); - - const archiveName = 'apm_8.0.0'; - - const range = archives_metadata[archiveName]; - - // url parameters - const start = encodeURIComponent(range.start); - const end = encodeURIComponent(range.end); - - const uiFilters = encodeURIComponent(JSON.stringify({})); - - describe('APM Services Overview', () => { - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - describe('with the default APM read user', () => { - describe('and fetching a list of services', () => { - let response: { - status: number; - body: APIReturnType<'GET /api/apm/services'>; - }; - - before(async () => { - response = await supertest.get( - `/api/apm/services?start=${start}&end=${end}&uiFilters=${uiFilters}` - ); - }); - - it('the response is successful', () => { - expect(response.status).to.eql(200); - }); - - it('there is at least one service', () => { - expect(response.body.items.length).to.be.greaterThan(0); - }); - - it('some items have a health status set', () => { - // Under the assumption that the loaded archive has - // at least one APM ML job, and the time range is longer - // than 15m, at least one items should have a health status - // set. Note that we currently have a bug where healthy - // services report as unknown (so without any health status): - // https://github.com/elastic/kibana/issues/77083 - - const healthStatuses = sortBy(response.body.items, 'serviceName').map( - (item: any) => item.healthStatus - ); - - expect(healthStatuses.filter(Boolean).length).to.be.greaterThan(0); - - expectSnapshot(healthStatuses).toMatchInline(` - Array [ - "healthy", - "healthy", - "healthy", - "healthy", - "healthy", - "healthy", - "healthy", - "healthy", - "healthy", - ] - `); - }); - }); - }); - - describe('with a user that does not have access to ML', () => { - let response: PromiseReturnType; - before(async () => { - response = await supertestAsApmReadUserWithoutMlAccess.get( - `/api/apm/services?start=${start}&end=${end}&uiFilters=${uiFilters}` - ); - }); - - it('the response is successful', () => { - expect(response.status).to.eql(200); - }); - - it('there is at least one service', () => { - expect(response.body.items.length).to.be.greaterThan(0); - }); - - it('contains no health statuses', () => { - const definedHealthStatuses = response.body.items - .map((item: any) => item.healthStatus) - .filter(Boolean); - - expect(definedHealthStatuses.length).to.be(0); - }); - }); - - describe('and fetching a list of services with a filter', () => { - let response: PromiseReturnType; - before(async () => { - response = await supertest.get( - `/api/apm/services?start=${start}&end=${end}&uiFilters=${encodeURIComponent( - `{"kuery":"service.name:opbeans-java","environment":"ENVIRONMENT_ALL"}` - )}` - ); - }); - - it('does not return health statuses for services that are not found in APM data', () => { - expect(response.status).to.be(200); - - expect(response.body.items.length).to.be(1); - - expect(response.body.items[0].serviceName).to.be('opbeans-java'); - }); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/no_access_user.ts b/x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/no_access_user.ts deleted file mode 100644 index a917bdb3cea23a..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/no_access_user.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; - -export default function apiTest({ getService }: FtrProviderContext) { - const noAccessUser = getService('supertestAsNoAccessUser'); - - function getJobs() { - return noAccessUser.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); - } - - function createJobs(environments: string[]) { - return noAccessUser - .post(`/api/apm/settings/anomaly-detection/jobs`) - .send({ environments }) - .set('kbn-xsrf', 'foo'); - } - - describe('when user does not have read access to ML', () => { - describe('when calling the endpoint for listing jobs', () => { - it('returns an error because the user does not have access', async () => { - const { body } = await getJobs(); - expect(body.statusCode).to.be(403); - expect(body.error).to.be('Forbidden'); - }); - }); - - describe('when calling create endpoint', () => { - it('returns an error because the user does not have access', async () => { - const { body } = await createJobs(['production', 'staging']); - expect(body.statusCode).to.be(403); - expect(body.error).to.be('Forbidden'); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/read_user.ts b/x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/read_user.ts deleted file mode 100644 index 2265c4dc0a41d4..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/read_user.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; - -export default function apiTest({ getService }: FtrProviderContext) { - const apmReadUser = getService('supertestAsApmReadUser'); - - function getJobs() { - return apmReadUser.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); - } - - function createJobs(environments: string[]) { - return apmReadUser - .post(`/api/apm/settings/anomaly-detection/jobs`) - .send({ environments }) - .set('kbn-xsrf', 'foo'); - } - - describe('when user has read access to ML', () => { - describe('when calling the endpoint for listing jobs', () => { - it('returns a list of jobs', async () => { - const { body } = await getJobs(); - - expect(body.jobs.length).to.be(0); - expect(body.hasLegacyJobs).to.be(false); - }); - }); - - describe('when calling create endpoint', () => { - it('returns an error because the user does not have access', async () => { - const { body } = await createJobs(['production', 'staging']); - - expect(body.statusCode).to.be(403); - expect(body.error).to.be('Forbidden'); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/write_user.ts b/x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/write_user.ts deleted file mode 100644 index 720d66e1efcc8a..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/settings/anomaly_detection/write_user.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; - -export default function apiTest({ getService }: FtrProviderContext) { - const apmWriteUser = getService('supertestAsApmWriteUser'); - - function getJobs() { - return apmWriteUser.get(`/api/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo'); - } - - function createJobs(environments: string[]) { - return apmWriteUser - .post(`/api/apm/settings/anomaly-detection/jobs`) - .send({ environments }) - .set('kbn-xsrf', 'foo'); - } - - function deleteJobs(jobIds: string[]) { - return apmWriteUser.post(`/api/ml/jobs/delete_jobs`).send({ jobIds }).set('kbn-xsrf', 'foo'); - } - - describe('when user has write access to ML', () => { - after(async () => { - const res = await getJobs(); - const jobIds = res.body.jobs.map((job: any) => job.job_id); - await deleteJobs(jobIds); - }); - - describe('when calling the endpoint for listing jobs', () => { - it('returns a list of jobs', async () => { - const { body } = await getJobs(); - expect(body.jobs.length).to.be(0); - expect(body.hasLegacyJobs).to.be(false); - }); - }); - - describe('when calling create endpoint', () => { - it('creates two jobs', async () => { - await createJobs(['production', 'staging']); - - const { body } = await getJobs(); - expect(body.hasLegacyJobs).to.be(false); - expect(body.jobs.map((job: any) => job.environment)).to.eql(['production', 'staging']); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/settings/custom_link.ts b/x-pack/test/apm_api_integration/trial/tests/settings/custom_link.ts deleted file mode 100644 index bcfe8fce4b948c..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/settings/custom_link.ts +++ /dev/null @@ -1,159 +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 URL from 'url'; -import expect from '@kbn/expect'; -import { CustomLink } from '../../../../../plugins/apm/common/custom_link/custom_link_types'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function customLinksTests({ getService }: FtrProviderContext) { - const supertestRead = getService('supertest'); - const supertestWrite = getService('supertestAsApmWriteUser'); - 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`, - query: filters, - }); - return supertestRead.get(path).set('kbn-xsrf', 'foo'); - } - - async function createCustomLink(customLink: CustomLink) { - log.debug('creating configuration', customLink); - const res = await supertestWrite - .post(`/api/apm/settings/custom_links`) - .send(customLink) - .set('kbn-xsrf', 'foo'); - - throwOnError(res); - - return res; - } - - async function updateCustomLink(id: string, customLink: CustomLink) { - log.debug('updating configuration', id, customLink); - const res = await supertestWrite - .put(`/api/apm/settings/custom_links/${id}`) - .send(customLink) - .set('kbn-xsrf', 'foo'); - - throwOnError(res); - - return res; - } - - async function deleteCustomLink(id: string) { - log.debug('deleting configuration', id); - const res = await supertestWrite - .delete(`/api/apm/settings/custom_links/${id}`) - .set('kbn-xsrf', 'foo'); - - throwOnError(res); - - return res; - } - - function throwOnError(res: any) { - const { statusCode, req, body } = res; - if (statusCode !== 200) { - throw new Error(` - Endpoint: ${req.method} ${req.path} - Service: ${JSON.stringify(res.request._data.service)} - Status code: ${statusCode} - Response: ${body.message}`); - } - } - - describe('custom links', () => { - before(async () => { - const customLink = { - url: 'https://elastic.co', - label: 'with filters', - filters: [ - { key: 'service.name', value: 'baz' }, - { key: 'transaction.type', value: 'qux' }, - ], - } as CustomLink; - await createCustomLink(customLink); - }); - it('fetches a custom link', async () => { - const { status, body } = await searchCustomLinks({ - 'service.name': 'baz', - 'transaction.type': 'qux', - }); - const { label, url, filters } = body[0]; - - expect(status).to.equal(200); - expect({ label, url, filters }).to.eql({ - label: 'with filters', - url: 'https://elastic.co', - filters: [ - { key: 'service.name', value: 'baz' }, - { key: 'transaction.type', value: 'qux' }, - ], - }); - }); - it('updates a custom link', async () => { - let { status, body } = await searchCustomLinks({ - 'service.name': 'baz', - 'transaction.type': 'qux', - }); - expect(status).to.equal(200); - await updateCustomLink(body[0].id, { - label: 'foo', - url: 'https://elastic.co?service.name={{service.name}}', - filters: [ - { key: 'service.name', value: 'quz' }, - { key: 'transaction.name', value: 'bar' }, - ], - }); - ({ status, body } = await searchCustomLinks({ - 'service.name': 'quz', - 'transaction.name': 'bar', - })); - const { label, url, filters } = body[0]; - expect(status).to.equal(200); - expect({ label, url, filters }).to.eql({ - label: 'foo', - url: 'https://elastic.co?service.name={{service.name}}', - filters: [ - { key: 'service.name', value: 'quz' }, - { key: 'transaction.name', value: 'bar' }, - ], - }); - }); - it('deletes a custom link', async () => { - let { status, body } = await searchCustomLinks({ - 'service.name': 'quz', - 'transaction.name': 'bar', - }); - expect(status).to.equal(200); - await deleteCustomLink(body[0].id); - ({ status, body } = await searchCustomLinks({ - 'service.name': 'quz', - 'transaction.name': 'bar', - })); - expect(status).to.equal(200); - expect(body).to.eql([]); - }); - - describe('transaction', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - it('fetches a transaction sample', async () => { - const response = await supertestRead.get( - '/api/apm/settings/custom_links/transaction?service.name=opbeans-java' - ); - expect(response.status).to.be(200); - expect(response.body.service.name).to.eql('opbeans-java'); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/trial/tests/transactions/__snapshots__/latency.snap b/x-pack/test/apm_api_integration/trial/tests/transactions/__snapshots__/latency.snap deleted file mode 100644 index 9475670387a080..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/transactions/__snapshots__/latency.snap +++ /dev/null @@ -1,46 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`APM specs (trial) Transactions Latency when data is loaded and fetching transaction charts with uiFilters when not defined environments seleted should return the correct anomaly boundaries 1`] = ` -Array [ - Object { - "x": 1607436000000, - "y": 0, - "y0": 0, - }, - Object { - "x": 1607436900000, - "y": 0, - "y0": 0, - }, -] -`; - -exports[`APM specs (trial) Transactions Latency when data is loaded and fetching transaction charts with uiFilters with environment selected and empty kuery filter should return a non-empty anomaly series 1`] = ` -Array [ - Object { - "x": 1607436000000, - "y": 1625128.56211579, - "y0": 7533.02707532227, - }, - Object { - "x": 1607436900000, - "y": 1660982.24115757, - "y0": 5732.00699123528, - }, -] -`; - -exports[`APM specs (trial) Transactions Latency when data is loaded and fetching transaction charts with uiFilters with environment selected in uiFilters should return a non-empty anomaly series 1`] = ` -Array [ - Object { - "x": 1607436000000, - "y": 1625128.56211579, - "y0": 7533.02707532227, - }, - Object { - "x": 1607436900000, - "y": 1660982.24115757, - "y0": 5732.00699123528, - }, -] -`; diff --git a/x-pack/test/apm_api_integration/trial/tests/transactions/latency.ts b/x-pack/test/apm_api_integration/trial/tests/transactions/latency.ts deleted file mode 100644 index e0b9559be72083..00000000000000 --- a/x-pack/test/apm_api_integration/trial/tests/transactions/latency.ts +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { PromiseReturnType } from '../../../../../plugins/observability/typings/common'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import archives_metadata from '../../../common/fixtures/es_archiver/archives_metadata'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - const archiveName = 'apm_8.0.0'; - - const range = archives_metadata[archiveName]; - - // url parameters - const start = encodeURIComponent(range.start); - const end = encodeURIComponent(range.end); - const transactionType = 'request'; - - describe('Latency', () => { - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - describe('and fetching transaction charts with uiFilters', () => { - let response: PromiseReturnType; - - describe('without environment', () => { - const uiFilters = encodeURIComponent(JSON.stringify({})); - before(async () => { - response = await supertest.get( - `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` - ); - }); - it('should return an error response', () => { - expect(response.status).to.eql(400); - }); - }); - - describe('without uiFilters', () => { - before(async () => { - response = await supertest.get( - `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&latencyAggregationType=avg` - ); - }); - it('should return an error response', () => { - expect(response.status).to.eql(400); - }); - }); - - describe('with environment selected in uiFilters', () => { - const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'production' })); - before(async () => { - response = await supertest.get( - `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` - ); - }); - - it('should have a successful response', () => { - expect(response.status).to.eql(200); - }); - - it('should return the ML job id for anomalies of the selected environment', () => { - expect(response.body).to.have.property('anomalyTimeseries'); - expect(response.body.anomalyTimeseries).to.have.property('jobId'); - expectSnapshot(response.body.anomalyTimeseries.jobId).toMatchInline( - `"apm-production-1369-high_mean_transaction_duration"` - ); - }); - - it('should return a non-empty anomaly series', () => { - expect(response.body).to.have.property('anomalyTimeseries'); - expect(response.body.anomalyTimeseries.anomalyBoundaries?.length).to.be.greaterThan(0); - expectSnapshot(response.body.anomalyTimeseries.anomalyBoundaries).toMatch(); - }); - }); - - describe('when not defined environments seleted', () => { - const uiFilters = encodeURIComponent( - JSON.stringify({ environment: 'ENVIRONMENT_NOT_DEFINED' }) - ); - before(async () => { - response = await supertest.get( - `/api/apm/services/opbeans-python/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` - ); - }); - - it('should have a successful response', () => { - expect(response.status).to.eql(200); - }); - - it('should return the ML job id for anomalies with no defined environment', () => { - expect(response.body).to.have.property('anomalyTimeseries'); - expect(response.body.anomalyTimeseries).to.have.property('jobId'); - expectSnapshot(response.body.anomalyTimeseries.jobId).toMatchInline( - `"apm-environment_not_defined-5626-high_mean_transaction_duration"` - ); - }); - - it('should return the correct anomaly boundaries', () => { - expect(response.body).to.have.property('anomalyTimeseries'); - expectSnapshot(response.body.anomalyTimeseries.anomalyBoundaries).toMatch(); - }); - }); - - describe('with all environments selected', () => { - const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'ENVIRONMENT_ALL' })); - before(async () => { - response = await supertest.get( - `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` - ); - }); - - it('should have a successful response', () => { - expect(response.status).to.eql(200); - }); - - it('should not return anomaly timeseries data', () => { - expect(response.body).to.not.have.property('anomalyTimeseries'); - }); - }); - - describe('with environment selected and empty kuery filter', () => { - const uiFilters = encodeURIComponent( - JSON.stringify({ kuery: '', environment: 'production' }) - ); - before(async () => { - response = await supertest.get( - `/api/apm/services/opbeans-java/transactions/charts/latency?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}&latencyAggregationType=avg` - ); - }); - - it('should have a successful response', () => { - expect(response.status).to.eql(200); - }); - - it('should return the ML job id for anomalies of the selected environment', () => { - expect(response.body).to.have.property('anomalyTimeseries'); - expect(response.body.anomalyTimeseries).to.have.property('jobId'); - expectSnapshot(response.body.anomalyTimeseries.jobId).toMatchInline( - `"apm-production-1369-high_mean_transaction_duration"` - ); - }); - - it('should return a non-empty anomaly series', () => { - expect(response.body).to.have.property('anomalyTimeseries'); - expect(response.body.anomalyTimeseries.anomalyBoundaries?.length).to.be.greaterThan(0); - expectSnapshot(response.body.anomalyTimeseries.anomalyBoundaries).toMatch(); - }); - }); - }); - }); - }); -} From 64e9cf0440e1e60b25a8b04939cb9d0097efcb53 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Wed, 27 Jan 2021 12:45:49 +0200 Subject: [PATCH 17/58] Cleanup OSS code from visualizations wizard (#89092) * Cleanup OSS code from visualizations wizard * Remove unecessary translations * Remove unused translation * Fix functional test * Disable the functional test for OSS * Remove from oss correctly :D * Fix ci --- .github/CODEOWNERS | 2 - .i18nrc.json | 2 - docs/developer/plugin-list.asciidoc | 10 --- .../deprecation/deprecation_factory.test.ts | 85 +------------------ .../src/deprecation/deprecation_factory.ts | 26 ------ packages/kbn-config/src/deprecation/index.ts | 2 +- packages/kbn-config/src/index.ts | 1 - packages/kbn-optimizer/limits.yml | 2 - src/plugins/lens_oss/README.md | 6 -- src/plugins/lens_oss/common/constants.ts | 12 --- src/plugins/lens_oss/common/index.ts | 9 -- src/plugins/lens_oss/config.ts | 15 ---- src/plugins/lens_oss/kibana.json | 10 --- src/plugins/lens_oss/public/index.ts | 11 --- src/plugins/lens_oss/public/plugin.ts | 32 ------- src/plugins/lens_oss/public/vis_type_alias.ts | 37 -------- src/plugins/lens_oss/server/index.ts | 21 ----- src/plugins/lens_oss/tsconfig.json | 20 ----- src/plugins/maps_oss/README.md | 6 -- src/plugins/maps_oss/common/constants.ts | 12 --- src/plugins/maps_oss/common/index.ts | 9 -- src/plugins/maps_oss/config.ts | 15 ---- src/plugins/maps_oss/kibana.json | 10 --- src/plugins/maps_oss/public/index.ts | 11 --- src/plugins/maps_oss/public/plugin.ts | 32 ------- src/plugins/maps_oss/public/vis_type_alias.ts | 33 ------- src/plugins/maps_oss/server/index.ts | 21 ----- .../vis_types/vis_type_alias_registry.ts | 7 -- .../group_selection/group_selection.test.tsx | 40 --------- .../group_selection/group_selection.tsx | 26 ------ .../functional/apps/visualize/_chart_types.ts | 18 +--- test/functional/apps/visualize/index.ts | 6 +- tsconfig.json | 2 - tsconfig.refs.json | 1 - x-pack/plugins/lens/kibana.json | 2 +- x-pack/plugins/lens/public/plugin.ts | 3 - x-pack/plugins/lens/tsconfig.json | 1 - x-pack/plugins/maps/kibana.json | 2 +- x-pack/plugins/maps/public/plugin.ts | 4 - .../translations/translations/ja-JP.json | 8 -- .../translations/translations/zh-CN.json | 8 -- 41 files changed, 10 insertions(+), 570 deletions(-) delete mode 100644 src/plugins/lens_oss/README.md delete mode 100644 src/plugins/lens_oss/common/constants.ts delete mode 100644 src/plugins/lens_oss/common/index.ts delete mode 100644 src/plugins/lens_oss/config.ts delete mode 100644 src/plugins/lens_oss/kibana.json delete mode 100644 src/plugins/lens_oss/public/index.ts delete mode 100644 src/plugins/lens_oss/public/plugin.ts delete mode 100644 src/plugins/lens_oss/public/vis_type_alias.ts delete mode 100644 src/plugins/lens_oss/server/index.ts delete mode 100644 src/plugins/lens_oss/tsconfig.json delete mode 100644 src/plugins/maps_oss/README.md delete mode 100644 src/plugins/maps_oss/common/constants.ts delete mode 100644 src/plugins/maps_oss/common/index.ts delete mode 100644 src/plugins/maps_oss/config.ts delete mode 100644 src/plugins/maps_oss/kibana.json delete mode 100644 src/plugins/maps_oss/public/index.ts delete mode 100644 src/plugins/maps_oss/public/plugin.ts delete mode 100644 src/plugins/maps_oss/public/vis_type_alias.ts delete mode 100644 src/plugins/maps_oss/server/index.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b47d78ea6d691a..0630937d5ac4b5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -13,7 +13,6 @@ /src/plugins/advanced_settings/ @elastic/kibana-app /src/plugins/charts/ @elastic/kibana-app /src/plugins/discover/ @elastic/kibana-app -/src/plugins/lens_oss/ @elastic/kibana-app /src/plugins/management/ @elastic/kibana-app /src/plugins/kibana_legacy/ @elastic/kibana-app /src/plugins/timelion/ @elastic/kibana-app @@ -127,7 +126,6 @@ /x-pack/test/functional/es_archives/maps/ @elastic/kibana-gis /x-pack/test/visual_regression/tests/maps/index.js @elastic/kibana-gis #CC# /src/plugins/maps_legacy/ @elastic/kibana-gis -#CC# /src/plugins/maps_oss/ @elastic/kibana-gis #CC# /x-pack/plugins/file_upload @elastic/kibana-gis #CC# /x-pack/plugins/maps_legacy_licensing @elastic/kibana-gis /src/plugins/tile_map/ @elastic/kibana-gis diff --git a/.i18nrc.json b/.i18nrc.json index b425dd99857dc3..0cdcae08e54e0a 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -61,8 +61,6 @@ "visTypeVislib": "src/plugins/vis_type_vislib", "visTypeXy": "src/plugins/vis_type_xy", "visualizations": "src/plugins/visualizations", - "lensOss": "src/plugins/lens_oss", - "mapsOss": "src/plugins/maps_oss", "visualize": "src/plugins/visualize", "apmOss": "src/plugins/apm_oss", "usageCollection": "src/plugins/usage_collection" diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 7ce4896a8bce44..fd4ed75352b1f7 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -130,11 +130,6 @@ in Kibana, e.g. visualizations. It has the form of a flyout panel. |The legacyExport plugin adds support for the legacy saved objects export format. -|{kib-repo}blob/{branch}/src/plugins/lens_oss/README.md[lensOss] -|The lens_oss plugin registers the lens visualization on OSS. -It is registered as disabled. The x-pack plugin should unregister this. - - |{kib-repo}blob/{branch}/src/plugins/management/README.md[management] |This plugins contains the "Stack Management" page framework. It offers navigation and an API to link individual managment section into it. This plugin does not contain any individual @@ -145,11 +140,6 @@ management section itself. |Internal objects used by the Coordinate, Region, and Vega visualizations. -|{kib-repo}blob/{branch}/src/plugins/maps_oss/README.md[mapsOss] -|The maps_oss plugin registers the maps visualization on OSS. -It is registered as disabled. The x-pack plugin should unregister this. - - |{kib-repo}blob/{branch}/src/plugins/navigation/README.md[navigation] |The navigation plugins exports the TopNavMenu component. It also provides a stateful version of it on the start contract. diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts index 5184494dd74bf0..1c13c539c3746c 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.test.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts @@ -7,7 +7,7 @@ */ import { ConfigDeprecationLogger } from './types'; -import { configDeprecationFactory, copyFromRoot } from './deprecation_factory'; +import { configDeprecationFactory } from './deprecation_factory'; describe('DeprecationFactory', () => { const { rename, unused, renameFromRoot, unusedFromRoot } = configDeprecationFactory; @@ -239,89 +239,6 @@ describe('DeprecationFactory', () => { }); }); - describe('copyFromRoot', () => { - it('copies a property to a different namespace', () => { - const rawConfig = { - originplugin: { - deprecated: 'toberenamed', - valid: 'valid', - }, - destinationplugin: { - property: 'value', - }, - }; - const processed = copyFromRoot('originplugin.deprecated', 'destinationplugin.renamed')( - rawConfig, - 'does-not-matter', - logger - ); - expect(processed).toEqual({ - originplugin: { - deprecated: 'toberenamed', - valid: 'valid', - }, - destinationplugin: { - renamed: 'toberenamed', - property: 'value', - }, - }); - expect(deprecationMessages.length).toEqual(0); - }); - - it('does not alter config if origin property is not present', () => { - const rawConfig = { - myplugin: { - new: 'new', - valid: 'valid', - }, - someOtherPlugin: { - property: 'value', - }, - }; - const processed = copyFromRoot('myplugin.deprecated', 'myplugin.new')( - rawConfig, - 'does-not-matter', - logger - ); - expect(processed).toEqual({ - myplugin: { - new: 'new', - valid: 'valid', - }, - someOtherPlugin: { - property: 'value', - }, - }); - expect(deprecationMessages.length).toEqual(0); - }); - - it('does not alter config if they both exist', () => { - const rawConfig = { - myplugin: { - deprecated: 'deprecated', - renamed: 'renamed', - }, - someOtherPlugin: { - property: 'value', - }, - }; - const processed = copyFromRoot('myplugin.deprecated', 'someOtherPlugin.property')( - rawConfig, - 'does-not-matter', - logger - ); - expect(processed).toEqual({ - myplugin: { - deprecated: 'deprecated', - renamed: 'renamed', - }, - someOtherPlugin: { - property: 'value', - }, - }); - }); - }); - describe('unused', () => { it('removes the unused property from the config and logs a warning is present', () => { const rawConfig = { diff --git a/packages/kbn-config/src/deprecation/deprecation_factory.ts b/packages/kbn-config/src/deprecation/deprecation_factory.ts index 40e29f97391569..04826446dc1adf 100644 --- a/packages/kbn-config/src/deprecation/deprecation_factory.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.ts @@ -45,26 +45,6 @@ const _rename = ( return config; }; -const _copy = ( - config: Record, - rootPath: string, - originKey: string, - destinationKey: string -) => { - const originPath = getPath(rootPath, originKey); - const originValue = get(config, originPath); - if (originValue === undefined) { - return config; - } - - const destinationPath = getPath(rootPath, destinationKey); - const destinationValue = get(config, destinationPath); - if (destinationValue === undefined) { - set(config, destinationPath, originValue); - } - return config; -}; - const _unused = ( config: Record, rootPath: string, @@ -89,12 +69,6 @@ const renameFromRoot = (oldKey: string, newKey: string, silent?: boolean): Confi log ) => _rename(config, '', log, oldKey, newKey, silent); -export const copyFromRoot = (originKey: string, destinationKey: string): ConfigDeprecation => ( - config, - rootPath, - log -) => _copy(config, '', originKey, destinationKey); - const unused = (unusedKey: string): ConfigDeprecation => (config, rootPath, log) => _unused(config, rootPath, log, unusedKey); diff --git a/packages/kbn-config/src/deprecation/index.ts b/packages/kbn-config/src/deprecation/index.ts index 87ec43d1fb09fa..6deebd27399bb1 100644 --- a/packages/kbn-config/src/deprecation/index.ts +++ b/packages/kbn-config/src/deprecation/index.ts @@ -13,5 +13,5 @@ export { ConfigDeprecationFactory, ConfigDeprecationProvider, } from './types'; -export { configDeprecationFactory, copyFromRoot } from './deprecation_factory'; +export { configDeprecationFactory } from './deprecation_factory'; export { applyDeprecations } from './apply_deprecations'; diff --git a/packages/kbn-config/src/index.ts b/packages/kbn-config/src/index.ts index e1743270f62c77..a803e3fd2dc8ea 100644 --- a/packages/kbn-config/src/index.ts +++ b/packages/kbn-config/src/index.ts @@ -14,7 +14,6 @@ export { ConfigDeprecationLogger, ConfigDeprecationProvider, ConfigDeprecationWithContext, - copyFromRoot, } from './deprecation'; export { RawConfigurationProvider, RawConfigService, getConfigFromFiles } from './raw'; diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index ef672d6cbeb2ef..1a4fb390d0c179 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -44,7 +44,6 @@ pageLoadAssetSize: kibanaReact: 161921 kibanaUtils: 198829 lens: 96624 - lensOss: 19341 licenseManagement: 41817 licensing: 39008 lists: 202261 @@ -53,7 +52,6 @@ pageLoadAssetSize: maps: 183610 mapsLegacy: 116817 mapsLegacyLicensing: 20214 - mapsOss: 19284 ml: 82187 monitoring: 50000 navigation: 37269 diff --git a/src/plugins/lens_oss/README.md b/src/plugins/lens_oss/README.md deleted file mode 100644 index 187da2497026e9..00000000000000 --- a/src/plugins/lens_oss/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# lens_oss - -The lens_oss plugin registers the lens visualization on OSS. -It is registered as disabled. The x-pack plugin should unregister this. - -`visualizations.unregisterAlias('lensOss')` \ No newline at end of file diff --git a/src/plugins/lens_oss/common/constants.ts b/src/plugins/lens_oss/common/constants.ts deleted file mode 100644 index 0ff5cdd78bb1ba..00000000000000 --- a/src/plugins/lens_oss/common/constants.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -export const APP_NAME = 'lens'; -export const PLUGIN_ID_OSS = 'lensOss'; -export const APP_PATH = '#/'; -export const APP_ICON = 'lensApp'; diff --git a/src/plugins/lens_oss/common/index.ts b/src/plugins/lens_oss/common/index.ts deleted file mode 100644 index 7f60b8508dc279..00000000000000 --- a/src/plugins/lens_oss/common/index.ts +++ /dev/null @@ -1,9 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -export * from './constants'; diff --git a/src/plugins/lens_oss/config.ts b/src/plugins/lens_oss/config.ts deleted file mode 100644 index 58c50f0104f466..00000000000000 --- a/src/plugins/lens_oss/config.ts +++ /dev/null @@ -1,15 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { schema, TypeOf } from '@kbn/config-schema'; - -export const configSchema = schema.object({ - enabled: schema.boolean({ defaultValue: true }), -}); - -export type ConfigSchema = TypeOf; diff --git a/src/plugins/lens_oss/kibana.json b/src/plugins/lens_oss/kibana.json deleted file mode 100644 index 3e3d3585f37fb8..00000000000000 --- a/src/plugins/lens_oss/kibana.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "lensOss", - "version": "kibana", - "ui": true, - "server": true, - "requiredPlugins": [ - "visualizations" - ], - "extraPublicDirs": ["common/constants"] -} diff --git a/src/plugins/lens_oss/public/index.ts b/src/plugins/lens_oss/public/index.ts deleted file mode 100644 index 2f68f6d183a22d..00000000000000 --- a/src/plugins/lens_oss/public/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { LensOSSPlugin } from './plugin'; - -export const plugin = () => new LensOSSPlugin(); diff --git a/src/plugins/lens_oss/public/plugin.ts b/src/plugins/lens_oss/public/plugin.ts deleted file mode 100644 index 5a441614b7e247..00000000000000 --- a/src/plugins/lens_oss/public/plugin.ts +++ /dev/null @@ -1,32 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { DocLinksStart, CoreSetup } from 'src/core/public'; -import { VisualizationsSetup } from '../../visualizations/public'; -import { getLensAliasConfig } from './vis_type_alias'; - -export interface LensPluginSetupDependencies { - visualizations: VisualizationsSetup; -} - -export interface LensPluginStartDependencies { - docLinks: DocLinksStart; -} - -export class LensOSSPlugin { - setup( - core: CoreSetup, - { visualizations }: LensPluginSetupDependencies - ) { - core.getStartServices().then(([coreStart]) => { - visualizations.registerAlias(getLensAliasConfig(coreStart.docLinks)); - }); - } - - start() {} -} diff --git a/src/plugins/lens_oss/public/vis_type_alias.ts b/src/plugins/lens_oss/public/vis_type_alias.ts deleted file mode 100644 index b9806bbf3b4e53..00000000000000 --- a/src/plugins/lens_oss/public/vis_type_alias.ts +++ /dev/null @@ -1,37 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { VisTypeAlias } from 'src/plugins/visualizations/public'; -import { DocLinksStart } from 'src/core/public'; -import { APP_NAME, PLUGIN_ID_OSS, APP_PATH, APP_ICON } from '../common'; - -export const getLensAliasConfig = ({ links }: DocLinksStart): VisTypeAlias => ({ - aliasPath: APP_PATH, - aliasApp: APP_NAME, - name: PLUGIN_ID_OSS, - title: i18n.translate('lensOss.visTypeAlias.title', { - defaultMessage: 'Lens', - }), - description: i18n.translate('lensOss.visTypeAlias.description', { - defaultMessage: - 'Create visualizations with our drag-and-drop editor. Switch between visualization types at any time. Best for most visualizations.', - }), - icon: APP_ICON, - stage: 'production', - disabled: true, - note: i18n.translate('lensOss.visTypeAlias.note', { - defaultMessage: 'Recommended for most users.', - }), - promoTooltip: { - description: i18n.translate('lensOss.visTypeAlias.promoTooltip.description', { - defaultMessage: 'Try Lens for free with Elastic. Learn more.', - }), - link: `${links.visualize.lens}?blade=kibanaossvizwizard`, - }, -}); diff --git a/src/plugins/lens_oss/server/index.ts b/src/plugins/lens_oss/server/index.ts deleted file mode 100644 index d13a9b2caaeb29..00000000000000 --- a/src/plugins/lens_oss/server/index.ts +++ /dev/null @@ -1,21 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { PluginConfigDescriptor } from 'kibana/server'; -import { copyFromRoot } from '@kbn/config'; -import { configSchema, ConfigSchema } from '../config'; - -export const config: PluginConfigDescriptor = { - schema: configSchema, - deprecations: () => [copyFromRoot('xpack.lens.enabled', 'lens_oss.enabled')], -}; - -export const plugin = () => ({ - setup() {}, - start() {}, -}); diff --git a/src/plugins/lens_oss/tsconfig.json b/src/plugins/lens_oss/tsconfig.json deleted file mode 100644 index d7bbc593fa87be..00000000000000 --- a/src/plugins/lens_oss/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "composite": true, - "outDir": "./target/types", - "emitDeclarationOnly": true, - "declaration": true, - "declarationMap": true - }, - "include": [ - "common/**/*", - "public/**/*", - "server/**/*", - "*.ts" - ], - "references": [ - { "path": "../../core/tsconfig.json" }, - { "path": "../visualizations/tsconfig.json" } - ] -} diff --git a/src/plugins/maps_oss/README.md b/src/plugins/maps_oss/README.md deleted file mode 100644 index ed91de500fbfb0..00000000000000 --- a/src/plugins/maps_oss/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# maps_oss - -The maps_oss plugin registers the maps visualization on OSS. -It is registered as disabled. The x-pack plugin should unregister this. - -`visualizations.unregisterAlias('mapsOss')` \ No newline at end of file diff --git a/src/plugins/maps_oss/common/constants.ts b/src/plugins/maps_oss/common/constants.ts deleted file mode 100644 index db29f541a03df2..00000000000000 --- a/src/plugins/maps_oss/common/constants.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -export const APP_NAME = 'maps'; -export const PLUGIN_ID_OSS = 'mapsOss'; -export const APP_PATH = '/map'; -export const APP_ICON = 'gisApp'; diff --git a/src/plugins/maps_oss/common/index.ts b/src/plugins/maps_oss/common/index.ts deleted file mode 100644 index 7f60b8508dc279..00000000000000 --- a/src/plugins/maps_oss/common/index.ts +++ /dev/null @@ -1,9 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -export * from './constants'; diff --git a/src/plugins/maps_oss/config.ts b/src/plugins/maps_oss/config.ts deleted file mode 100644 index 58c50f0104f466..00000000000000 --- a/src/plugins/maps_oss/config.ts +++ /dev/null @@ -1,15 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { schema, TypeOf } from '@kbn/config-schema'; - -export const configSchema = schema.object({ - enabled: schema.boolean({ defaultValue: true }), -}); - -export type ConfigSchema = TypeOf; diff --git a/src/plugins/maps_oss/kibana.json b/src/plugins/maps_oss/kibana.json deleted file mode 100644 index 19770dcffaadd7..00000000000000 --- a/src/plugins/maps_oss/kibana.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "mapsOss", - "version": "kibana", - "ui": true, - "server": true, - "requiredPlugins": [ - "visualizations" - ], - "extraPublicDirs": ["common/constants"] -} diff --git a/src/plugins/maps_oss/public/index.ts b/src/plugins/maps_oss/public/index.ts deleted file mode 100644 index 1d27dc4b6d9964..00000000000000 --- a/src/plugins/maps_oss/public/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { MapsOSSPlugin } from './plugin'; - -export const plugin = () => new MapsOSSPlugin(); diff --git a/src/plugins/maps_oss/public/plugin.ts b/src/plugins/maps_oss/public/plugin.ts deleted file mode 100644 index 5e27ae34257bf7..00000000000000 --- a/src/plugins/maps_oss/public/plugin.ts +++ /dev/null @@ -1,32 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { DocLinksStart, CoreSetup } from 'src/core/public'; -import { VisualizationsSetup } from '../../visualizations/public'; -import { getMapsAliasConfig } from './vis_type_alias'; - -export interface MapsPluginSetupDependencies { - visualizations: VisualizationsSetup; -} - -export interface MapsPluginStartDependencies { - docLinks: DocLinksStart; -} - -export class MapsOSSPlugin { - setup( - core: CoreSetup, - { visualizations }: MapsPluginSetupDependencies - ) { - core.getStartServices().then(([coreStart]) => { - visualizations.registerAlias(getMapsAliasConfig(coreStart.docLinks)); - }); - } - - start() {} -} diff --git a/src/plugins/maps_oss/public/vis_type_alias.ts b/src/plugins/maps_oss/public/vis_type_alias.ts deleted file mode 100644 index a27c628755cf6b..00000000000000 --- a/src/plugins/maps_oss/public/vis_type_alias.ts +++ /dev/null @@ -1,33 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { VisTypeAlias } from 'src/plugins/visualizations/public'; -import { DocLinksStart } from 'src/core/public'; -import { APP_NAME, PLUGIN_ID_OSS, APP_PATH, APP_ICON } from '../common'; - -export const getMapsAliasConfig = ({ links }: DocLinksStart): VisTypeAlias => ({ - aliasPath: APP_PATH, - aliasApp: APP_NAME, - name: PLUGIN_ID_OSS, - title: i18n.translate('mapsOss.visTypeAlias.title', { - defaultMessage: 'Maps', - }), - description: i18n.translate('mapsOss.visTypeAlias.description', { - defaultMessage: 'Plot and style your geo data in a multi layer map.', - }), - icon: APP_ICON, - stage: 'production', - disabled: true, - promoTooltip: { - description: i18n.translate('mapsOss.visTypeAlias.promoTooltip.description', { - defaultMessage: 'Try maps for free with Elastic. Learn more.', - }), - link: `${links.visualize.maps}?blade=kibanaossvizwizard`, - }, -}); diff --git a/src/plugins/maps_oss/server/index.ts b/src/plugins/maps_oss/server/index.ts deleted file mode 100644 index 8f07beee705a6a..00000000000000 --- a/src/plugins/maps_oss/server/index.ts +++ /dev/null @@ -1,21 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { PluginConfigDescriptor } from 'kibana/server'; -import { copyFromRoot } from '@kbn/config'; -import { configSchema, ConfigSchema } from '../config'; - -export const config: PluginConfigDescriptor = { - schema: configSchema, - deprecations: () => [copyFromRoot('xpack.maps.enabled', 'maps_oss.enabled')], -}; - -export const plugin = () => ({ - setup() {}, - start() {}, -}); diff --git a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts index 839d2b1f57c344..cb6bc624801d9b 100644 --- a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts +++ b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts @@ -31,11 +31,6 @@ export interface VisualizationsAppExtension { toListItem: (savedObject: SavedObject) => VisualizationListItem; } -export interface VisTypeAliasPromoTooltip { - description: string; - link: string; -} - export interface VisTypeAlias { aliasPath: string; aliasApp: string; @@ -43,10 +38,8 @@ export interface VisTypeAlias { title: string; icon: string; promotion?: boolean; - promoTooltip?: VisTypeAliasPromoTooltip; description: string; note?: string; - disabled?: boolean; getSupportedTriggers?: () => string[]; stage: VisualizationStage; diff --git a/src/plugins/visualizations/public/wizard/group_selection/group_selection.test.tsx b/src/plugins/visualizations/public/wizard/group_selection/group_selection.test.tsx index 74163296e31fdd..396be30aca6d07 100644 --- a/src/plugins/visualizations/public/wizard/group_selection/group_selection.test.tsx +++ b/src/plugins/visualizations/public/wizard/group_selection/group_selection.test.tsx @@ -39,11 +39,6 @@ describe('GroupSelection', () => { title: 'Vis with alias Url', aliasApp: 'aliasApp', aliasPath: '#/aliasApp', - disabled: true, - promoTooltip: { - description: 'Learn More', - link: '#/anotherUrl', - }, description: 'Vis with alias Url', stage: 'production', group: VisGroups.PROMOTED, @@ -227,41 +222,6 @@ describe('GroupSelection', () => { ]); }); - it('should render disabled aliases with a disabled class', () => { - const wrapper = mountWithIntl( - - ); - expect(wrapper.find('[data-test-subj="visType-visWithAliasUrl"]').exists()).toBe(true); - expect( - wrapper - .find('[data-test-subj="visType-visWithAliasUrl"]') - .at(1) - .hasClass('euiCard-isDisabled') - ).toBe(true); - }); - - it('should render a basic badge with link for disabled aliases with promoTooltip', () => { - const wrapper = mountWithIntl( - - ); - expect(wrapper.find('[data-test-subj="visTypeBadge"]').exists()).toBe(true); - expect(wrapper.find('[data-test-subj="visTypeBadge"]').at(0).prop('tooltipContent')).toBe( - 'Learn More' - ); - }); - it('should not show tools experimental visualizations if showExperimentalis false', () => { const expVis = { name: 'visExp', diff --git a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx index 9b61b2c415e9fa..594e37f6a76087 100644 --- a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx +++ b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx @@ -48,10 +48,6 @@ interface VisCardProps { showExperimental?: boolean | undefined; } -function isVisTypeAlias(type: BaseVisType | VisTypeAlias): type is VisTypeAlias { - return 'aliasPath' in type; -} - function GroupSelection(props: GroupSelectionProps) { const visualizeGuideLink = props.docLinks.links.dashboard.guide; const promotedVisGroups = useMemo( @@ -185,29 +181,8 @@ const VisGroup = ({ visType, onVisTypeSelected }: VisCardProps) => { const onClick = useCallback(() => { onVisTypeSelected(visType); }, [onVisTypeSelected, visType]); - const shouldDisableCard = isVisTypeAlias(visType) && visType.disabled; - const betaBadgeContent = - shouldDisableCard && 'promoTooltip' in visType ? ( - - - - ) : undefined; return ( - {betaBadgeContent} { } onClick={onClick} - isDisabled={shouldDisableCard} data-test-subj={`visType-${visType.name}`} data-vis-stage={!('aliasPath' in visType) ? visType.stage : 'alias'} aria-label={`visType-${visType.name}`} diff --git a/test/functional/apps/visualize/_chart_types.ts b/test/functional/apps/visualize/_chart_types.ts index 55b68b7370148b..69403f20905949 100644 --- a/test/functional/apps/visualize/_chart_types.ts +++ b/test/functional/apps/visualize/_chart_types.ts @@ -12,21 +12,17 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { - const deployment = getService('deployment'); const log = getService('log'); const PageObjects = getPageObjects(['visualize']); - let isOss = true; describe('chart types', function () { before(async function () { log.debug('navigateToApp visualize'); - isOss = await deployment.isOss(); await PageObjects.visualize.navigateToNewVisualization(); }); it('should show the promoted vis types for the first step', async function () { const expectedChartTypes = ['Custom visualization', 'Lens', 'Maps', 'TSVB']; - log.debug('oss= ' + isOss); // find all the chart types and make sure there all there const chartTypes = (await PageObjects.visualize.getPromotedVisTypes()).sort(); @@ -37,9 +33,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should show the correct agg based chart types', async function () { await PageObjects.visualize.clickAggBasedVisualizations(); - let expectedChartTypes = [ + const expectedChartTypes = [ 'Area', - 'Coordinate Map', 'Data table', 'Gauge', 'Goal', @@ -48,21 +43,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'Line', 'Metric', 'Pie', - 'Region Map', 'Tag cloud', 'Timelion', 'Vertical bar', ]; - if (!isOss) { - expectedChartTypes = _.remove(expectedChartTypes, function (n) { - return n !== 'Coordinate Map'; - }); - expectedChartTypes = _.remove(expectedChartTypes, function (n) { - return n !== 'Region Map'; - }); - expectedChartTypes.sort(); - } - log.debug('oss= ' + isOss); // find all the chart types and make sure there all there const chartTypes = (await PageObjects.visualize.getChartTypes()).sort(); diff --git a/test/functional/apps/visualize/index.ts b/test/functional/apps/visualize/index.ts index 8dd28544196933..4170ada692e67a 100644 --- a/test/functional/apps/visualize/index.ts +++ b/test/functional/apps/visualize/index.ts @@ -67,11 +67,15 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { this.tags('ciGroup9'); loadTestFile(require.resolve('./_embedding_chart')); - loadTestFile(require.resolve('./_chart_types')); loadTestFile(require.resolve('./_area_chart')); loadTestFile(require.resolve('./_data_table')); loadTestFile(require.resolve('./_data_table_nontimeindex')); loadTestFile(require.resolve('./_data_table_notimeindex_filters')); + + // this check is not needed when the CI doesn't run anymore for the OSS + if (!isOss) { + loadTestFile(require.resolve('./_chart_types')); + } }); describe('', function () { diff --git a/tsconfig.json b/tsconfig.json index b6742bffeab55c..e7856aa0c87470 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,6 @@ "src/plugins/kibana_react/**/*", "src/plugins/kibana_usage_collection/**/*", "src/plugins/kibana_utils/**/*", - "src/plugins/lens_oss/**/*", "src/plugins/management/**/*", "src/plugins/navigation/**/*", "src/plugins/newsfeed/**/*", @@ -81,7 +80,6 @@ { "path": "./src/plugins/kibana_react/tsconfig.json" }, { "path": "./src/plugins/kibana_usage_collection/tsconfig.json" }, { "path": "./src/plugins/kibana_utils/tsconfig.json" }, - { "path": "./src/plugins/lens_oss/tsconfig.json" }, { "path": "./src/plugins/management/tsconfig.json" }, { "path": "./src/plugins/navigation/tsconfig.json" }, { "path": "./src/plugins/newsfeed/tsconfig.json" }, diff --git a/tsconfig.refs.json b/tsconfig.refs.json index 1bce19e2ee44aa..5edfd4231a6d59 100644 --- a/tsconfig.refs.json +++ b/tsconfig.refs.json @@ -22,7 +22,6 @@ { "path": "./src/plugins/kibana_react/tsconfig.json" }, { "path": "./src/plugins/kibana_usage_collection/tsconfig.json" }, { "path": "./src/plugins/kibana_utils/tsconfig.json" }, - { "path": "./src/plugins/lens_oss/tsconfig.json" }, { "path": "./src/plugins/management/tsconfig.json" }, { "path": "./src/plugins/navigation/tsconfig.json" }, { "path": "./src/plugins/newsfeed/tsconfig.json" }, diff --git a/x-pack/plugins/lens/kibana.json b/x-pack/plugins/lens/kibana.json index dc0a92ac702d03..9df3f41fbd855b 100644 --- a/x-pack/plugins/lens/kibana.json +++ b/x-pack/plugins/lens/kibana.json @@ -19,5 +19,5 @@ "optionalPlugins": ["usageCollection", "taskManager", "globalSearch", "savedObjectsTagging"], "configPath": ["xpack", "lens"], "extraPublicDirs": ["common/constants"], - "requiredBundles": ["savedObjects", "kibanaUtils", "kibanaReact", "embeddable", "lensOss", "presentationUtil"] + "requiredBundles": ["savedObjects", "kibanaUtils", "kibanaReact", "embeddable", "presentationUtil"] } diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts index cdffdb342fd237..3fb7186aeac59a 100644 --- a/x-pack/plugins/lens/public/plugin.ts +++ b/x-pack/plugins/lens/public/plugin.ts @@ -39,7 +39,6 @@ import { VISUALIZE_FIELD_TRIGGER, } from '../../../../src/plugins/ui_actions/public'; import { getEditPath, NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../common'; -import { PLUGIN_ID_OSS } from '../../../../src/plugins/lens_oss/common/constants'; import { EditorFrameStart } from './types'; import { getLensAliasConfig } from './vis_type_alias'; import { visualizeFieldAction } from './trigger_actions/visualize_field_actions'; @@ -208,8 +207,6 @@ export class LensPlugin { start(core: CoreStart, startDependencies: LensPluginStartDependencies): LensPublicStart { const frameStart = this.editorFrameService.start(core, startDependencies); this.createEditorFrame = frameStart.createInstance; - // unregisters the OSS alias - startDependencies.visualizations.unRegisterAlias(PLUGIN_ID_OSS); // unregisters the Visualize action and registers the lens one if (startDependencies.uiActions.hasAction(ACTION_VISUALIZE_FIELD)) { startDependencies.uiActions.unregisterAction(ACTION_VISUALIZE_FIELD); diff --git a/x-pack/plugins/lens/tsconfig.json b/x-pack/plugins/lens/tsconfig.json index 7ac5a2980d0baf..636d2f44b02173 100644 --- a/x-pack/plugins/lens/tsconfig.json +++ b/x-pack/plugins/lens/tsconfig.json @@ -35,7 +35,6 @@ { "path": "../../../src/plugins/kibana_utils/tsconfig.json" }, { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, { "path": "../../../src/plugins/embeddable/tsconfig.json"}, - { "path": "../../../src/plugins/lens_oss/tsconfig.json"}, { "path": "../../../src/plugins/presentation_util/tsconfig.json"}, ] } \ No newline at end of file diff --git a/x-pack/plugins/maps/kibana.json b/x-pack/plugins/maps/kibana.json index 5f6f5224e32a3c..2536601d0e6b19 100644 --- a/x-pack/plugins/maps/kibana.json +++ b/x-pack/plugins/maps/kibana.json @@ -23,5 +23,5 @@ "ui": true, "server": true, "extraPublicDirs": ["common/constants"], - "requiredBundles": ["kibanaReact", "kibanaUtils", "home", "mapsOss", "presentationUtil"] + "requiredBundles": ["kibanaReact", "kibanaUtils", "home", "presentationUtil"] } diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index dd256126fae62c..4173328a41d571 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -34,7 +34,6 @@ import { VisualizationsStart, } from '../../../../src/plugins/visualizations/public'; import { APP_ICON_SOLUTION, APP_ID, MAP_SAVED_OBJECT_TYPE } from '../common/constants'; -import { PLUGIN_ID_OSS } from '../../../../src/plugins/maps_oss/common/constants'; import { VISUALIZE_GEO_FIELD_TRIGGER } from '../../../../src/plugins/ui_actions/public'; import { createMapsUrlGenerator, @@ -162,9 +161,6 @@ export class MapsPlugin setLicensingPluginStart(plugins.licensing); setStartServices(core, plugins); - // unregisters the OSS alias - plugins.visualizations.unRegisterAlias(PLUGIN_ID_OSS); - if (core.application.capabilities.maps.show) { plugins.uiActions.addTriggerAction(VISUALIZE_GEO_FIELD_TRIGGER, visualizeGeoFieldAction); } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e28b41e0ce5e37..da9228335a3f3b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3032,10 +3032,6 @@ "kibanaOverview.manageData.sectionTitle": "データを管理", "kibanaOverview.more.title": "Elasticではさまざまなことが可能です", "kibanaOverview.news.title": "新機能", - "lensOss.visTypeAlias.description": "ドラッグアンドドロップエディターでビジュアライゼーションを作成します。いつでもビジュアライゼーションタイプを切り替えることができます。ほとんどのビジュアライゼーションに最適です。", - "lensOss.visTypeAlias.note": "ほとんどのユーザーに推奨されます。", - "lensOss.visTypeAlias.promoTooltip.description": "Elastic では Lens を無料でお試しいただけます。詳細情報", - "lensOss.visTypeAlias.title": "レンズ", "management.breadcrumb": "スタック管理", "management.landing.header": "Stack Management {version}へようこそ", "management.landing.subhead": "インデックス、インデックスパターン、保存されたオブジェクト、Kibanaの設定、その他を管理します。", @@ -3089,9 +3085,6 @@ "maps_legacy.wmsOptions.wmsStylesLabel": "WMSスタイル", "maps_legacy.wmsOptions.wmsUrlLabel": "WMS URL", "maps_legacy.wmsOptions.wmsVersionLabel": "WMS バージョン", - "mapsOss.visTypeAlias.description": "マルチレイヤーマップで地理データをプロットしてスタイル設定できます。", - "mapsOss.visTypeAlias.promoTooltip.description": "Elastic では Maps を無料でお試しいただけます。詳細情報", - "mapsOss.visTypeAlias.title": "マップ", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "doc['field_name'] 構文を使用して、スクリプトからフィールド値にアクセスします", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "戻らずに値を発行します。", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "フィールド「{fieldName}」の値を取得します", @@ -4692,7 +4685,6 @@ "visualizations.initializeWithoutIndexPatternErrorMessage": "インデックスパターンなしで集約を初期化しようとしています", "visualizations.newVisWizard.aggBasedGroupDescription": "クラシック Visualize ライブラリを使用して、アグリゲーションに基づいてグラフを作成します。", "visualizations.newVisWizard.aggBasedGroupTitle": "アグリゲーションに基づく", - "visualizations.newVisWizard.basicTitle": "基本", "visualizations.newVisWizard.chooseSourceTitle": "ソースの選択", "visualizations.newVisWizard.experimentalTitle": "実験的", "visualizations.newVisWizard.experimentalTooltip": "このビジュアライゼーションは今後のリリースで変更または削除される可能性があり、SLA のサポート対象になりません。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 49fd9ce095f66d..679edaf9e0cdd7 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3036,10 +3036,6 @@ "kibanaOverview.manageData.sectionTitle": "管理您的数据", "kibanaOverview.more.title": "Elastic 让您事半功倍", "kibanaOverview.news.title": "最新动态", - "lensOss.visTypeAlias.description": "使用我们支持拖放的编辑器来创建可视化。随时在可视化类型之间切换。绝大多数可视化的最佳选择。", - "lensOss.visTypeAlias.note": "适合绝大多数用户。", - "lensOss.visTypeAlias.promoTooltip.description": "免费试用 Elastic 的 Lens。了解详情。", - "lensOss.visTypeAlias.title": "Lens", "management.breadcrumb": "Stack Management", "management.landing.header": "欢迎使用 Stack Management {version}", "management.landing.subhead": "管理您的索引、索引模式、已保存对象、Kibana 设置等等。", @@ -3093,9 +3089,6 @@ "maps_legacy.wmsOptions.wmsStylesLabel": "WMS 样式", "maps_legacy.wmsOptions.wmsUrlLabel": "WMS url", "maps_legacy.wmsOptions.wmsVersionLabel": "WMS 版本", - "mapsOss.visTypeAlias.description": "在多层地图中绘制地理数据并设置其样式。", - "mapsOss.visTypeAlias.promoTooltip.description": "免费试用 Elastic 的地图。了解详情。", - "mapsOss.visTypeAlias.title": "地图", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "使用 doc['field_name'] 语法,从脚本中访问字段值", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "发出值,而不返回值。", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "检索字段“{fieldName}”的值", @@ -4697,7 +4690,6 @@ "visualizations.initializeWithoutIndexPatternErrorMessage": "正在尝试在不使用索引模式的情况下初始化聚合", "visualizations.newVisWizard.aggBasedGroupDescription": "使用我们的经典可视化库,基于聚合创建图表。", "visualizations.newVisWizard.aggBasedGroupTitle": "基于聚合", - "visualizations.newVisWizard.basicTitle": "基本级", "visualizations.newVisWizard.chooseSourceTitle": "选择源", "visualizations.newVisWizard.experimentalTitle": "实验性", "visualizations.newVisWizard.experimentalTooltip": "未来版本可能会更改或删除此可视化,其不受支持 SLA 的约束。", From b8947e3e1574d69cc91b297743908b48daf6acba Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Wed, 27 Jan 2021 11:52:13 +0100 Subject: [PATCH 18/58] [Search Sessions] Make search session indicator UI opt-in, refactor per-app capabilities (#88699) --- .../kibana-plugin-plugins-data-public.md | 1 + ...nosearchsessionstoragecapabilitymessage.md | 13 ++++ .../public/application/dashboard_router.tsx | 1 + .../embeddable/dashboard_container.tsx | 3 +- .../hooks/use_dashboard_state_manager.ts | 15 ++++- .../dashboard/public/application/types.ts | 1 + src/plugins/data/public/index.ts | 1 + src/plugins/data/public/public.api.md | 35 ++++++----- src/plugins/data/public/search/index.ts | 1 + .../data/public/search/session/i18n.ts | 20 +++++++ .../data/public/search/session/index.ts | 1 + .../data/public/search/session/mocks.ts | 4 +- .../search/session/session_service.test.ts | 60 ++++++++++++++++++- .../public/search/session/session_service.ts | 59 ++++++++++++++---- .../public/application/angular/discover.js | 14 ++++- ...onnected_search_session_indicator.test.tsx | 37 +++++++++--- .../connected_search_session_indicator.tsx | 29 +++------ .../config.ts | 1 + .../services/index.ts | 4 +- ...nd_to_background.ts => search_sessions.ts} | 26 +++++--- .../async_search/sessions_in_space.ts | 57 +++++++++++++++++- .../tests/apps/discover/sessions_in_space.ts | 59 +++++++++++++++++- .../tests/apps/lens/index.ts | 22 +++++++ .../tests/apps/lens/search_sessions.ts | 35 +++++++++++ 24 files changed, 424 insertions(+), 75 deletions(-) create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.nosearchsessionstoragecapabilitymessage.md create mode 100644 src/plugins/data/public/search/session/i18n.ts rename x-pack/test/send_search_to_background_integration/services/{send_to_background.ts => search_sessions.ts} (81%) create mode 100644 x-pack/test/send_search_to_background_integration/tests/apps/lens/index.ts create mode 100644 x-pack/test/send_search_to_background_integration/tests/apps/lens/search_sessions.ts diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index 65a722868b37f6..4bbc76b78ba030 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -125,6 +125,7 @@ | [isPartialResponse](./kibana-plugin-plugins-data-public.ispartialresponse.md) | | | [isQuery](./kibana-plugin-plugins-data-public.isquery.md) | | | [isTimeRange](./kibana-plugin-plugins-data-public.istimerange.md) | | +| [noSearchSessionStorageCapabilityMessage](./kibana-plugin-plugins-data-public.nosearchsessionstoragecapabilitymessage.md) | Message to display in case storing session session is disabled due to turned off capability | | [parseSearchSourceJSON](./kibana-plugin-plugins-data-public.parsesearchsourcejson.md) | | | [QueryStringInput](./kibana-plugin-plugins-data-public.querystringinput.md) | | | [search](./kibana-plugin-plugins-data-public.search.md) | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.nosearchsessionstoragecapabilitymessage.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.nosearchsessionstoragecapabilitymessage.md new file mode 100644 index 00000000000000..2bb0a0db8f9b3e --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.nosearchsessionstoragecapabilitymessage.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [noSearchSessionStorageCapabilityMessage](./kibana-plugin-plugins-data-public.nosearchsessionstoragecapabilitymessage.md) + +## noSearchSessionStorageCapabilityMessage variable + +Message to display in case storing session session is disabled due to turned off capability + +Signature: + +```typescript +noSearchSessionStorageCapabilityMessage: string +``` diff --git a/src/plugins/dashboard/public/application/dashboard_router.tsx b/src/plugins/dashboard/public/application/dashboard_router.tsx index 9141f2e592fd78..5206c76f50be28 100644 --- a/src/plugins/dashboard/public/application/dashboard_router.tsx +++ b/src/plugins/dashboard/public/application/dashboard_router.tsx @@ -104,6 +104,7 @@ export async function mountApp({ mapsCapabilities: { save: Boolean(coreStart.application.capabilities.maps?.save) }, createShortUrl: Boolean(coreStart.application.capabilities.dashboard.createShortUrl), visualizeCapabilities: { save: Boolean(coreStart.application.capabilities.visualize?.save) }, + storeSearchSession: Boolean(coreStart.application.capabilities.dashboard.storeSearchSession), }, }; diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx index fa520ec22497b7..780eb1bad8c2bd 100644 --- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx @@ -89,7 +89,7 @@ export interface InheritedChildInput extends IndexSignature { export type DashboardReactContextValue = KibanaReactContextValue; export type DashboardReactContext = KibanaReactContext; -const defaultCapabilities = { +const defaultCapabilities: DashboardCapabilities = { show: false, createNew: false, saveQuery: false, @@ -97,6 +97,7 @@ const defaultCapabilities = { hideWriteControls: true, mapsCapabilities: { save: false }, visualizeCapabilities: { save: false }, + storeSearchSession: true, }; export class DashboardContainer extends Container { diff --git a/src/plugins/dashboard/public/application/hooks/use_dashboard_state_manager.ts b/src/plugins/dashboard/public/application/hooks/use_dashboard_state_manager.ts index a4044e8668e59d..93fbb50950850e 100644 --- a/src/plugins/dashboard/public/application/hooks/use_dashboard_state_manager.ts +++ b/src/plugins/dashboard/public/application/hooks/use_dashboard_state_manager.ts @@ -16,6 +16,7 @@ import { useKibana } from '../../services/kibana_react'; import { connectToQueryState, esFilters, + noSearchSessionStorageCapabilityMessage, QueryState, syncQueryStateWithUrl, } from '../../services/data'; @@ -159,13 +160,22 @@ export const useDashboardStateManager = ( stateManager.isNew() ); - searchSession.setSearchSessionInfoProvider( + searchSession.enableStorage( createSessionRestorationDataProvider({ data: dataPlugin, getDashboardTitle: () => dashboardTitle, getDashboardId: () => savedDashboard?.id || '', getAppState: () => stateManager.getAppState(), - }) + }), + { + isDisabled: () => + dashboardCapabilities.storeSearchSession + ? { disabled: false } + : { + disabled: true, + reasonText: noSearchSessionStorageCapabilityMessage, + }, + } ); setDashboardStateManager(stateManager); @@ -192,6 +202,7 @@ export const useDashboardStateManager = ( toasts, uiSettings, usageCollection, + dashboardCapabilities.storeSearchSession, ]); return { dashboardStateManager, viewMode, setViewMode }; diff --git a/src/plugins/dashboard/public/application/types.ts b/src/plugins/dashboard/public/application/types.ts index 61e16beed61f44..e4f9388a919d15 100644 --- a/src/plugins/dashboard/public/application/types.ts +++ b/src/plugins/dashboard/public/application/types.ts @@ -55,6 +55,7 @@ export interface DashboardCapabilities { saveQuery: boolean; createNew: boolean; show: boolean; + storeSearchSession: boolean; } export interface DashboardAppServices { diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index ff3e2ebc89a417..fc8c44e8d1870d 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -384,6 +384,7 @@ export { SearchTimeoutError, TimeoutErrorMode, PainlessError, + noSearchSessionStorageCapabilityMessage, } from './search'; export type { diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 002f0333657907..9e493f46b0781b 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1834,6 +1834,11 @@ export enum METRIC_TYPES { TOP_HITS = "top_hits" } +// Warning: (ae-missing-release-tag) "noSearchSessionStorageCapabilityMessage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const noSearchSessionStorageCapabilityMessage: string; + // Warning: (ae-missing-release-tag) "OptionedParamType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -2629,21 +2634,21 @@ export const UI_SETTINGS: { // src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:399:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:399:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:399:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:399:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:414:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:418:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:419:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:422:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:426:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:400:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:400:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:400:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:400:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:403:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:414:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:415:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:419:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:420:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:427:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts // src/plugins/data/public/search/session/session_service.ts:41:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts index 1deffc9c2d55eb..3d87411883a67c 100644 --- a/src/plugins/data/public/search/index.ts +++ b/src/plugins/data/public/search/index.ts @@ -37,6 +37,7 @@ export { SearchSessionState, SessionsClient, ISessionsClient, + noSearchSessionStorageCapabilityMessage, } from './session'; export { getEsPreference } from './es_search'; diff --git a/src/plugins/data/public/search/session/i18n.ts b/src/plugins/data/public/search/session/i18n.ts new file mode 100644 index 00000000000000..2ee36b46dfd5ac --- /dev/null +++ b/src/plugins/data/public/search/session/i18n.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; + +/** + * Message to display in case storing + * session session is disabled due to turned off capability + */ +export const noSearchSessionStorageCapabilityMessage = i18n.translate( + 'data.searchSessionIndicator.noCapability', + { + defaultMessage: "You don't have permissions to create search sessions.", + } +); diff --git a/src/plugins/data/public/search/session/index.ts b/src/plugins/data/public/search/session/index.ts index ab311d56fe096b..f3f0c34c1be75e 100644 --- a/src/plugins/data/public/search/session/index.ts +++ b/src/plugins/data/public/search/session/index.ts @@ -9,3 +9,4 @@ export { SessionService, ISessionService, SearchSessionInfoProvider } from './session_service'; export { SearchSessionState } from './search_session_state'; export { SessionsClient, ISessionsClient } from './sessions_client'; +export { noSearchSessionStorageCapabilityMessage } from './i18n'; diff --git a/src/plugins/data/public/search/session/mocks.ts b/src/plugins/data/public/search/session/mocks.ts index 6a7a207b90d463..679898e3e51dd7 100644 --- a/src/plugins/data/public/search/session/mocks.ts +++ b/src/plugins/data/public/search/session/mocks.ts @@ -29,7 +29,6 @@ export function getSessionServiceMock(): jest.Mocked { getSessionId: jest.fn(), getSession$: jest.fn(() => new BehaviorSubject(undefined).asObservable()), state$: new BehaviorSubject(SearchSessionState.None).asObservable(), - setSearchSessionInfoProvider: jest.fn(), trackSearch: jest.fn((searchDescriptor) => () => {}), destroy: jest.fn(), onRefresh$: new Subject(), @@ -40,5 +39,8 @@ export function getSessionServiceMock(): jest.Mocked { save: jest.fn(), isCurrentSession: jest.fn(), getSearchOptions: jest.fn(), + enableStorage: jest.fn(), + isSessionStorageReady: jest.fn(() => true), + getSearchSessionIndicatorUiConfig: jest.fn(() => ({ isDisabled: () => ({ disabled: false }) })), }; } diff --git a/src/plugins/data/public/search/session/session_service.test.ts b/src/plugins/data/public/search/session/session_service.test.ts index 7797d92c4e07db..21c38c68e6a833 100644 --- a/src/plugins/data/public/search/session/session_service.test.ts +++ b/src/plugins/data/public/search/session/session_service.test.ts @@ -113,7 +113,7 @@ describe('Session service', () => { sessionId, }); - sessionService.setSearchSessionInfoProvider({ + sessionService.enableStorage({ getName: async () => 'Name', getUrlGeneratorData: async () => ({ urlGeneratorId: 'id', @@ -156,4 +156,62 @@ describe('Session service', () => { expect(sessionService.isCurrentSession('some-other')).toBeFalsy(); expect(sessionService.isCurrentSession(sessionId)).toBeTruthy(); }); + + test('enableStorage() enables storage capabilities', async () => { + sessionService.start(); + await expect(() => sessionService.save()).rejects.toThrowErrorMatchingInlineSnapshot( + `"No info provider for current session"` + ); + + expect(sessionService.isSessionStorageReady()).toBe(false); + + sessionService.enableStorage({ + getName: async () => 'Name', + getUrlGeneratorData: async () => ({ + urlGeneratorId: 'id', + initialState: {}, + restoreState: {}, + }), + }); + + expect(sessionService.isSessionStorageReady()).toBe(true); + + await expect(() => sessionService.save()).resolves; + + sessionService.clear(); + expect(sessionService.isSessionStorageReady()).toBe(false); + }); + + test('can provide config for search session indicator', () => { + expect(sessionService.getSearchSessionIndicatorUiConfig().isDisabled().disabled).toBe(false); + sessionService.enableStorage( + { + getName: async () => 'Name', + getUrlGeneratorData: async () => ({ + urlGeneratorId: 'id', + initialState: {}, + restoreState: {}, + }), + }, + { + isDisabled: () => ({ disabled: true, reasonText: 'text' }), + } + ); + + expect(sessionService.getSearchSessionIndicatorUiConfig().isDisabled().disabled).toBe(true); + + sessionService.clear(); + expect(sessionService.getSearchSessionIndicatorUiConfig().isDisabled().disabled).toBe(false); + }); + + test('save() throws in case getUrlGeneratorData returns throws', async () => { + sessionService.enableStorage({ + getName: async () => 'Name', + getUrlGeneratorData: async () => { + throw new Error('Haha'); + }, + }); + sessionService.start(); + await expect(() => sessionService.save()).rejects.toMatchInlineSnapshot(`[Error: Haha]`); + }); }); diff --git a/src/plugins/data/public/search/session/session_service.ts b/src/plugins/data/public/search/session/session_service.ts index 6269398036e769..23129a9afc4603 100644 --- a/src/plugins/data/public/search/session/session_service.ts +++ b/src/plugins/data/public/search/session/session_service.ts @@ -43,6 +43,20 @@ export interface SearchSessionInfoProvider; } +/** + * Configure a "Search session indicator" UI + */ +export interface SearchSessionIndicatorUiConfig { + /** + * App controls if "Search session indicator" UI should be disabled. + * reasonText will appear in a tooltip. + * + * Could be used, for example, to disable "Search session indicator" UI + * in case user doesn't have permissions to store a search session + */ + isDisabled: () => { disabled: true; reasonText: string } | { disabled: false }; +} + /** * Responsible for tracking a current search session. Supports only a single session at a time. */ @@ -51,6 +65,7 @@ export class SessionService { private readonly state: SessionStateContainer; private searchSessionInfoProvider?: SearchSessionInfoProvider; + private searchSessionIndicatorUiConfig?: Partial; private subscription = new Subscription(); private curApp?: string; @@ -102,17 +117,6 @@ export class SessionService { }); } - /** - * Set a provider of info about current session - * This will be used for creating a search session saved object - * @param searchSessionInfoProvider - */ - public setSearchSessionInfoProvider( - searchSessionInfoProvider: SearchSessionInfoProvider | undefined - ) { - this.searchSessionInfoProvider = searchSessionInfoProvider; - } - /** * Used to track pending searches within current session * @@ -185,7 +189,8 @@ export class SessionService { */ public clear() { this.state.transitions.clear(); - this.setSearchSessionInfoProvider(undefined); + this.searchSessionInfoProvider = undefined; + this.searchSessionIndicatorUiConfig = undefined; } private refresh$ = new Subject(); @@ -269,4 +274,34 @@ export class SessionService { isStored: isCurrentSession ? this.isStored() : false, }; } + + /** + * Provide an info about current session which is needed for storing a search session. + * To opt-into "Search session indicator" UI app has to call {@link enableStorage}. + * + * @param searchSessionInfoProvider - info provider for saving a search session + * @param searchSessionIndicatorUiConfig - config for "Search session indicator" UI + */ + public enableStorage( + searchSessionInfoProvider: SearchSessionInfoProvider, + searchSessionIndicatorUiConfig?: SearchSessionIndicatorUiConfig + ) { + this.searchSessionInfoProvider = searchSessionInfoProvider; + this.searchSessionIndicatorUiConfig = searchSessionIndicatorUiConfig; + } + + /** + * If the current app explicitly called {@link enableStorage} and provided all configuration needed + * for storing its search sessions + */ + public isSessionStorageReady(): boolean { + return !!this.searchSessionInfoProvider; + } + + public getSearchSessionIndicatorUiConfig(): SearchSessionIndicatorUiConfig { + return { + isDisabled: () => ({ disabled: false }), + ...this.searchSessionIndicatorUiConfig, + }; + } } diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js index 946baa7f4ecb15..5c26680c7cc458 100644 --- a/src/plugins/discover/public/application/angular/discover.js +++ b/src/plugins/discover/public/application/angular/discover.js @@ -18,6 +18,7 @@ import { connectToQueryState, esFilters, indexPatterns as indexPatternsUtils, + noSearchSessionStorageCapabilityMessage, syncQueryStateWithUrl, } from '../../../../data/public'; import { getSortArray } from './doc_table'; @@ -284,12 +285,21 @@ function discoverController($route, $scope, Promise) { } }); - data.search.session.setSearchSessionInfoProvider( + data.search.session.enableStorage( createSearchSessionRestorationDataProvider({ appStateContainer, data, getSavedSearch: () => savedSearch, - }) + }), + { + isDisabled: () => + capabilities.discover.storeSearchSession + ? { disabled: false } + : { + disabled: true, + reasonText: noSearchSessionStorageCapabilityMessage, + }, + } ); $scope.setIndexPattern = async (id) => { diff --git a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx index 2c74f9c995a5af..f4bb7577bee537 100644 --- a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx +++ b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.test.tsx @@ -28,6 +28,12 @@ timeFilter.getRefreshInterval.mockImplementation(() => refreshInterval$.getValue beforeEach(() => { refreshInterval$.next({ value: 0, pause: true }); + sessionService.isSessionStorageReady.mockImplementation(() => true); + sessionService.getSearchSessionIndicatorUiConfig.mockImplementation(() => ({ + isDisabled: () => ({ + disabled: false, + }), + })); }); test("shouldn't show indicator in case no active search session", async () => { @@ -45,6 +51,22 @@ test("shouldn't show indicator in case no active search session", async () => { expect(container).toMatchInlineSnapshot(`
`); }); +test("shouldn't show indicator in case app hasn't opt-in", async () => { + const SearchSessionIndicator = createConnectedSearchSessionIndicator({ + sessionService, + application: coreStart.application, + timeFilter, + }); + const { getByTestId, container } = render(); + sessionService.isSessionStorageReady.mockImplementation(() => false); + + // make sure `searchSessionIndicator` isn't appearing after some time (lazy-loading) + await expect( + waitFor(() => getByTestId('searchSessionIndicator'), { timeout: 100 }) + ).rejects.toThrow(); + expect(container).toMatchInlineSnapshot(`
`); +}); + test('should show indicator in case there is an active search session', async () => { const state$ = new BehaviorSubject(SearchSessionState.Loading); const SearchSessionIndicator = createConnectedSearchSessionIndicator({ @@ -57,7 +79,7 @@ test('should show indicator in case there is an active search session', async () await waitFor(() => getByTestId('searchSessionIndicator')); }); -test('should be disabled when permissions are off', async () => { +test('should be disabled in case uiConfig says so ', async () => { const state$ = new BehaviorSubject(SearchSessionState.Loading); coreStart.application.currentAppId$ = new BehaviorSubject('discover'); (coreStart.application.capabilities as any) = { @@ -65,6 +87,12 @@ test('should be disabled when permissions are off', async () => { storeSearchSession: false, }, }; + sessionService.getSearchSessionIndicatorUiConfig.mockImplementation(() => ({ + isDisabled: () => ({ + disabled: true, + reasonText: 'reason', + }), + })); const SearchSessionIndicator = createConnectedSearchSessionIndicator({ sessionService: { ...sessionService, state$ }, application: coreStart.application, @@ -80,12 +108,7 @@ test('should be disabled when permissions are off', async () => { test('should be disabled during auto-refresh', async () => { const state$ = new BehaviorSubject(SearchSessionState.Loading); - coreStart.application.currentAppId$ = new BehaviorSubject('discover'); - (coreStart.application.capabilities as any) = { - discover: { - storeSearchSession: true, - }, - }; + const SearchSessionIndicator = createConnectedSearchSessionIndicator({ sessionService: { ...sessionService, state$ }, application: coreStart.application, diff --git a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx index 5c8c01064bff43..59c1bb4a223b1e 100644 --- a/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx +++ b/x-pack/plugins/data_enhanced/public/search/ui/connected_search_session_indicator/connected_search_session_indicator.tsx @@ -29,35 +29,14 @@ export const createConnectedSearchSessionIndicator = ({ .getRefreshIntervalUpdate$() .pipe(map(isAutoRefreshEnabled), distinctUntilChanged()); - const getCapabilitiesByAppId = ( - capabilities: ApplicationStart['capabilities'], - appId?: string - ) => { - switch (appId) { - case 'dashboards': - return capabilities.dashboard; - case 'discover': - return capabilities.discover; - default: - return undefined; - } - }; - return () => { const state = useObservable(sessionService.state$.pipe(debounceTime(500))); const autoRefreshEnabled = useObservable(isAutoRefreshEnabled$, isAutoRefreshEnabled()); - const appId = useObservable(application.currentAppId$, undefined); + const isDisabledByApp = sessionService.getSearchSessionIndicatorUiConfig().isDisabled(); let disabled = false; let disabledReasonText: string = ''; - if (getCapabilitiesByAppId(application.capabilities, appId)?.storeSearchSession !== true) { - disabled = true; - disabledReasonText = i18n.translate('xpack.data.searchSessionIndicator.noCapability', { - defaultMessage: "You don't have permissions to send to background.", - }); - } - if (autoRefreshEnabled) { disabled = true; disabledReasonText = i18n.translate( @@ -68,6 +47,12 @@ export const createConnectedSearchSessionIndicator = ({ ); } + if (isDisabledByApp.disabled) { + disabled = true; + disabledReasonText = isDisabledByApp.reasonText; + } + + if (!sessionService.isSessionStorageReady()) return null; if (!state) return null; return ( diff --git a/x-pack/test/send_search_to_background_integration/config.ts b/x-pack/test/send_search_to_background_integration/config.ts index bad818bb696644..c788cc38477e6b 100644 --- a/x-pack/test/send_search_to_background_integration/config.ts +++ b/x-pack/test/send_search_to_background_integration/config.ts @@ -24,6 +24,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { resolve(__dirname, './tests/apps/dashboard/async_search'), resolve(__dirname, './tests/apps/discover'), resolve(__dirname, './tests/apps/management/search_sessions'), + resolve(__dirname, './tests/apps/lens'), ], kbnTestServer: { diff --git a/x-pack/test/send_search_to_background_integration/services/index.ts b/x-pack/test/send_search_to_background_integration/services/index.ts index 35eed5a218b422..b177ac3a01cb02 100644 --- a/x-pack/test/send_search_to_background_integration/services/index.ts +++ b/x-pack/test/send_search_to_background_integration/services/index.ts @@ -5,9 +5,9 @@ */ import { services as functionalServices } from '../../functional/services'; -import { SendToBackgroundProvider } from './send_to_background'; +import { SearchSessionsProvider } from './search_sessions'; export const services = { ...functionalServices, - searchSessions: SendToBackgroundProvider, + searchSessions: SearchSessionsProvider, }; diff --git a/x-pack/test/send_search_to_background_integration/services/send_to_background.ts b/x-pack/test/send_search_to_background_integration/services/search_sessions.ts similarity index 81% rename from x-pack/test/send_search_to_background_integration/services/send_to_background.ts rename to x-pack/test/send_search_to_background_integration/services/search_sessions.ts index 8c3261c2074aee..7041de6462243a 100644 --- a/x-pack/test/send_search_to_background_integration/services/send_to_background.ts +++ b/x-pack/test/send_search_to_background_integration/services/search_sessions.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import expect from '@kbn/expect'; import { SavedObjectsFindResponse } from 'src/core/server'; import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; import { FtrProviderContext } from '../ftr_provider_context'; @@ -20,7 +21,7 @@ type SessionStateType = | 'restored' | 'canceled'; -export function SendToBackgroundProvider({ getService }: FtrProviderContext) { +export function SearchSessionsProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const log = getService('log'); const retry = getService('retry'); @@ -36,6 +37,17 @@ export function SendToBackgroundProvider({ getService }: FtrProviderContext) { return testSubjects.exists(SEARCH_SESSION_INDICATOR_TEST_SUBJ); } + public async missingOrFail(): Promise { + return testSubjects.missingOrFail(SEARCH_SESSION_INDICATOR_TEST_SUBJ); + } + + public async disabledOrFail() { + await this.exists(); + await expect(await (await (await this.find()).findByTagName('button')).isEnabled()).to.be( + false + ); + } + public async expectState(state: SessionStateType) { return retry.waitFor(`searchSessions indicator to get into state = ${state}`, async () => { const currentState = await ( @@ -93,12 +105,12 @@ export function SendToBackgroundProvider({ getService }: FtrProviderContext) { } /* - * This cleanup function should be used by tests that create new background sesions. - * Tests should not end with new background sessions remaining in storage since that interferes with functional tests that check the _find API. - * Alternatively, a test can navigate to `Managment > Search Sessions` and use the UI to delete any created tests. + * This cleanup function should be used by tests that create new search sessions. + * Tests should not end with new search sessions remaining in storage since that interferes with functional tests that check the _find API. + * Alternatively, a test can navigate to `Management > Search Sessions` and use the UI to delete any created tests. */ public async deleteAllSearchSessions() { - log.debug('Deleting created background sessions'); + log.debug('Deleting created searcg sessions'); // ignores 409 errs and keeps retrying await retry.tryForTime(10000, async () => { const { body } = await supertest @@ -109,10 +121,10 @@ export function SendToBackgroundProvider({ getService }: FtrProviderContext) { .expect(200); const { saved_objects: savedObjects } = body as SavedObjectsFindResponse; - log.debug(`Found created background sessions: ${savedObjects.map(({ id }) => id)}`); + log.debug(`Found created search sessions: ${savedObjects.map(({ id }) => id)}`); await Promise.all( savedObjects.map(async (so) => { - log.debug(`Deleting background session: ${so.id}`); + log.debug(`Deleting search session: ${so.id}`); await supertest .delete(`/internal/session/${so.id}`) .set(`kbn-xsrf`, `anything`) diff --git a/x-pack/test/send_search_to_background_integration/tests/apps/dashboard/async_search/sessions_in_space.ts b/x-pack/test/send_search_to_background_integration/tests/apps/dashboard/async_search/sessions_in_space.ts index f590e441386427..6aea4368a2f3fa 100644 --- a/x-pack/test/send_search_to_background_integration/tests/apps/dashboard/async_search/sessions_in_space.ts +++ b/x-pack/test/send_search_to_background_integration/tests/apps/dashboard/async_search/sessions_in_space.ts @@ -23,7 +23,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const searchSessions = getService('searchSessions'); describe('dashboard in space', () => { - describe('Send to background in space', () => { + describe('Storing search sessions in space', () => { before(async () => { await esArchiver.load('dashboard/session_in_space'); @@ -92,5 +92,60 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.missingOrFail('embeddableErrorLabel'); }); }); + + describe('Disabled storing search sessions', () => { + before(async () => { + await esArchiver.load('dashboard/session_in_space'); + + await security.role.create('data_analyst', { + elasticsearch: { + indices: [{ names: ['logstash-*'], privileges: ['all'] }], + }, + kibana: [ + { + feature: { + dashboard: ['minimal_read'], + }, + spaces: ['another-space'], + }, + ], + }); + + await security.user.create('analyst', { + password: 'analyst-password', + roles: ['data_analyst'], + full_name: 'test user', + }); + + await PageObjects.security.forceLogout(); + + await PageObjects.security.login('analyst', 'analyst-password', { + expectSpaceSelector: false, + }); + }); + + after(async () => { + await security.role.delete('data_analyst'); + await security.user.delete('analyst'); + + await esArchiver.unload('dashboard/session_in_space'); + await PageObjects.security.forceLogout(); + }); + + it("Doesn't allow to store a session", async () => { + await PageObjects.common.navigateToApp('dashboard', { basePath: 's/another-space' }); + await PageObjects.dashboard.loadSavedDashboard('A Dashboard in another space'); + + await PageObjects.timePicker.setAbsoluteRange( + 'Sep 1, 2015 @ 00:00:00.000', + 'Oct 1, 2015 @ 00:00:00.000' + ); + + await PageObjects.dashboard.waitForRenderComplete(); + + await searchSessions.expectState('completed'); + await searchSessions.disabledOrFail(); + }); + }); }); } diff --git a/x-pack/test/send_search_to_background_integration/tests/apps/discover/sessions_in_space.ts b/x-pack/test/send_search_to_background_integration/tests/apps/discover/sessions_in_space.ts index 6384afb1795936..733b2edd4cd06f 100644 --- a/x-pack/test/send_search_to_background_integration/tests/apps/discover/sessions_in_space.ts +++ b/x-pack/test/send_search_to_background_integration/tests/apps/discover/sessions_in_space.ts @@ -23,7 +23,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const searchSessions = getService('searchSessions'); describe('discover in space', () => { - describe('Send to background in space', () => { + describe('Storing search sessions in space', () => { before(async () => { await esArchiver.load('dashboard/session_in_space'); @@ -93,7 +93,62 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Check that session is restored await searchSessions.expectState('restored'); - await testSubjects.missingOrFail('embeddableErrorLabel'); + await testSubjects.missingOrFail('discoverNoResultsError'); // expect error because of fake searchSessionId + }); + }); + describe('Disabled storing search sessions in space', () => { + before(async () => { + await esArchiver.load('dashboard/session_in_space'); + + await security.role.create('data_analyst', { + elasticsearch: { + indices: [{ names: ['logstash-*'], privileges: ['all'] }], + }, + kibana: [ + { + feature: { + discover: ['read'], + }, + spaces: ['another-space'], + }, + ], + }); + + await security.user.create('analyst', { + password: 'analyst-password', + roles: ['data_analyst'], + full_name: 'test user', + }); + + await PageObjects.security.forceLogout(); + + await PageObjects.security.login('analyst', 'analyst-password', { + expectSpaceSelector: false, + }); + }); + + after(async () => { + await security.role.delete('data_analyst'); + await security.user.delete('analyst'); + + await esArchiver.unload('dashboard/session_in_space'); + await PageObjects.security.forceLogout(); + }); + + it("Doesn't allow to store a session", async () => { + await PageObjects.common.navigateToApp('discover', { basePath: 's/another-space' }); + + await PageObjects.discover.selectIndexPattern('logstash-*'); + + await PageObjects.timePicker.setAbsoluteRange( + 'Sep 1, 2015 @ 00:00:00.000', + 'Oct 1, 2015 @ 00:00:00.000' + ); + + await PageObjects.discover.waitForDocTableLoadingComplete(); + + await searchSessions.expectState('completed'); + await searchSessions.disabledOrFail(); }); }); }); diff --git a/x-pack/test/send_search_to_background_integration/tests/apps/lens/index.ts b/x-pack/test/send_search_to_background_integration/tests/apps/lens/index.ts new file mode 100644 index 00000000000000..e84cede4bc87d0 --- /dev/null +++ b/x-pack/test/send_search_to_background_integration/tests/apps/lens/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile, getService }: FtrProviderContext) { + const kibanaServer = getService('kibanaServer'); + const esArchiver = getService('esArchiver'); + + describe('lens search sessions', function () { + this.tags('ciGroup3'); + + before(async () => { + await esArchiver.loadIfNeeded('logstash_functional'); + await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' }); + }); + + loadTestFile(require.resolve('./search_sessions.ts')); + }); +} diff --git a/x-pack/test/send_search_to_background_integration/tests/apps/lens/search_sessions.ts b/x-pack/test/send_search_to_background_integration/tests/apps/lens/search_sessions.ts new file mode 100644 index 00000000000000..6bd79f0f988831 --- /dev/null +++ b/x-pack/test/send_search_to_background_integration/tests/apps/lens/search_sessions.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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const searchSession = getService('searchSessions'); + const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'timePicker', 'header']); + const listingTable = getService('listingTable'); + + describe('lens search sessions', () => { + before(async () => { + await esArchiver.loadIfNeeded('logstash_functional'); + await esArchiver.loadIfNeeded('lens/basic'); + }); + after(async () => { + await esArchiver.unload('lens/basic'); + }); + + it("doesn't shows search sessions indicator UI", async () => { + await PageObjects.visualize.gotoVisualizationLandingPage(); + await listingTable.searchForItemWithName('lnsXYvis'); + await PageObjects.lens.clickVisualizeListItemTitle('lnsXYvis'); + await PageObjects.lens.goToTimeRange(); + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await PageObjects.lens.isShowingNoResults()).to.be(false); + + await searchSession.missingOrFail(); + }); + }); +} From c8afae8a5120850565ae3fa7f9db460a3f7be653 Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Wed, 27 Jan 2021 12:13:15 +0100 Subject: [PATCH 19/58] Enable v2 so migrations, disable in FTR tests (#89297) * Enable v2 so migrations, disable in FTR tests * Disable v2 migrations for ui_settings integration tests * Disable v2 migrations for reporting without serucity api integration test --- src/core/server/saved_objects/saved_objects_config.ts | 2 +- src/core/server/ui_settings/integration_tests/lib/servers.ts | 3 +++ test/common/config.js | 2 ++ .../reporting_without_security.config.ts | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/server/saved_objects/saved_objects_config.ts b/src/core/server/saved_objects/saved_objects_config.ts index 82db64daf2bd3e..0885a52078f5cb 100644 --- a/src/core/server/saved_objects/saved_objects_config.ts +++ b/src/core/server/saved_objects/saved_objects_config.ts @@ -18,7 +18,7 @@ export const savedObjectsMigrationConfig = { pollInterval: schema.number({ defaultValue: 1500 }), skip: schema.boolean({ defaultValue: false }), // TODO migrationsV2: remove/deprecate once we release migrations v2 - enableV2: schema.boolean({ defaultValue: false }), + enableV2: schema.boolean({ defaultValue: true }), }), }; diff --git a/src/core/server/ui_settings/integration_tests/lib/servers.ts b/src/core/server/ui_settings/integration_tests/lib/servers.ts index f181272030ae1d..b5198b19007d05 100644 --- a/src/core/server/ui_settings/integration_tests/lib/servers.ts +++ b/src/core/server/ui_settings/integration_tests/lib/servers.ts @@ -37,6 +37,9 @@ export async function startServers() { adjustTimeout: (t) => jest.setTimeout(t), settings: { kbn: { + migrations: { + enableV2: false, + }, uiSettings: { overrides: { foo: 'bar', diff --git a/test/common/config.js b/test/common/config.js index 8a42e6c87b214d..b6d12444b7017d 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -61,6 +61,8 @@ export default function () { ...(!!process.env.CODE_COVERAGE ? [`--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'coverage')}`] : []), + // Disable v2 migrations in tests for now + '--migrations.enableV2=false', ], }, services, diff --git a/x-pack/test/reporting_api_integration/reporting_without_security.config.ts b/x-pack/test/reporting_api_integration/reporting_without_security.config.ts index 4a95a15169b590..11182bbcdb3b09 100644 --- a/x-pack/test/reporting_api_integration/reporting_without_security.config.ts +++ b/x-pack/test/reporting_api_integration/reporting_without_security.config.ts @@ -32,6 +32,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { kbnTestServer: { ...apiConfig.get('kbnTestServer'), serverArgs: [ + `--migrations.enableV2=false`, `--elasticsearch.hosts=${formatUrl(esTestConfig.getUrlParts())}`, `--logging.json=false`, `--server.maxPayloadBytes=1679958`, From 9e6897505447d7a5911b568eb334e658bd95df78 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Wed, 27 Jan 2021 12:35:38 +0100 Subject: [PATCH 20/58] [APM] Upgrade ES client (#86594) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../plugins/apm/public/hooks/use_fetcher.tsx | 32 ++++---- .../scripts/upload-telemetry-data/index.ts | 12 +-- .../collect_data_telemetry/index.ts | 18 +++-- .../apm/server/lib/apm_telemetry/index.ts | 22 +++--- ...with_debug.ts => call_async_with_debug.ts} | 58 +++++++------- .../cancel_es_request_on_abort.ts | 27 +++++++ .../create_apm_event_client/index.test.ts | 77 +++++++++++++++++++ .../create_apm_event_client/index.ts | 45 +++++++---- .../create_internal_es_client/index.ts | 77 ++++++++++++------- .../server/lib/helpers/setup_request.test.ts | 56 +++++++------- .../apm/server/lib/helpers/setup_request.ts | 2 +- .../annotations/get_stored_annotations.ts | 17 ++-- .../server/lib/services/annotations/index.ts | 8 +- .../create_agent_config_index.ts | 8 +- .../custom_link/create_custom_link_index.ts | 8 +- x-pack/plugins/apm/server/plugin.ts | 6 +- .../apm/server/routes/create_api/index.ts | 7 +- x-pack/plugins/apm/server/routes/services.ts | 2 +- x-pack/plugins/observability/server/index.ts | 2 + .../lib/annotations/bootstrap_annotations.ts | 2 +- .../annotations/create_annotations_client.ts | 70 ++++++++++------- .../annotations/register_annotation_apis.ts | 4 +- .../server/utils/create_or_update_index.ts | 28 +++---- .../server/utils/unwrap_es_response.ts | 13 ++++ x-pack/typings/elasticsearch/index.d.ts | 5 +- 25 files changed, 396 insertions(+), 210 deletions(-) rename x-pack/plugins/apm/server/lib/helpers/create_es_client/{call_client_with_debug.ts => call_async_with_debug.ts} (51%) create mode 100644 x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts create mode 100644 x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts create mode 100644 x-pack/plugins/observability/server/utils/unwrap_es_response.ts diff --git a/x-pack/plugins/apm/public/hooks/use_fetcher.tsx b/x-pack/plugins/apm/public/hooks/use_fetcher.tsx index 8174f06e06b8b8..2b58f30a9ec649 100644 --- a/x-pack/plugins/apm/public/hooks/use_fetcher.tsx +++ b/x-pack/plugins/apm/public/hooks/use_fetcher.tsx @@ -24,6 +24,21 @@ export interface FetcherResult { error?: IHttpFetchError; } +function getDetailsFromErrorResponse(error: IHttpFetchError) { + const message = error.body?.message ?? error.response?.statusText; + return ( + <> + {message} ({error.response?.status}) +
+ {i18n.translate('xpack.apm.fetcher.error.url', { + defaultMessage: `URL`, + })} +
+ {error.response?.url} + + ); +} + // fetcher functions can return undefined OR a promise. Previously we had a more simple type // but it led to issues when using object destructuring with default values type InferResponseType = Exclude extends Promise< @@ -82,25 +97,14 @@ export function useFetcher( if (!didCancel) { const errorDetails = - 'response' in err ? ( - <> - {err.response?.statusText} ({err.response?.status}) -
- {i18n.translate('xpack.apm.fetcher.error.url', { - defaultMessage: `URL`, - })} -
- {err.response?.url} - - ) : ( - err.message - ); + 'response' in err ? getDetailsFromErrorResponse(err) : err.message; if (showToastOnError) { - notifications.toasts.addWarning({ + notifications.toasts.addDanger({ title: i18n.translate('xpack.apm.fetcher.error.title', { defaultMessage: `Error while fetching resource`, }), + text: toMountPoint(
diff --git a/x-pack/plugins/apm/scripts/upload-telemetry-data/index.ts b/x-pack/plugins/apm/scripts/upload-telemetry-data/index.ts index 8c64c37d9b7f74..e3221c17f3f2a0 100644 --- a/x-pack/plugins/apm/scripts/upload-telemetry-data/index.ts +++ b/x-pack/plugins/apm/scripts/upload-telemetry-data/index.ts @@ -17,6 +17,8 @@ import { argv } from 'yargs'; import { Logger } from 'kibana/server'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { CollectTelemetryParams } from '../../server/lib/apm_telemetry/collect_data_telemetry'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { unwrapEsResponse } from '../../../observability/server/utils/unwrap_es_response'; import { downloadTelemetryTemplate } from '../shared/download-telemetry-template'; import { mergeApmTelemetryMapping } from '../../common/apm_telemetry'; import { generateSampleDocuments } from './generate-sample-documents'; @@ -80,18 +82,18 @@ async function uploadData() { apmAgentConfigurationIndex: '.apm-agent-configuration', }, search: (body) => { - return client.search(body as any).then((res) => res.body as any); + return unwrapEsResponse(client.search(body)); }, indicesStats: (body) => { - return client.indices.stats(body as any).then((res) => res.body); + return unwrapEsResponse(client.indices.stats(body)); }, transportRequest: ((params) => { - return client.transport - .request({ + return unwrapEsResponse( + client.transport.request({ method: params.method, path: params.path, }) - .then((res) => res.body); + ); }) as CollectTelemetryParams['transportRequest'], }, }); diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts index 730645c609cb60..90aad48fe20b95 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import { merge } from 'lodash'; -import { Logger, LegacyCallAPIOptions } from 'kibana/server'; -import { IndicesStatsParams, Client } from 'elasticsearch'; +import { Logger } from 'kibana/server'; +import { RequestParams } from '@elastic/elasticsearch'; import { ESSearchRequest, ESSearchResponse, @@ -20,9 +20,17 @@ type TelemetryTaskExecutor = (params: { params: TSearchRequest ): Promise>; indicesStats( - params: IndicesStatsParams, - options?: LegacyCallAPIOptions - ): ReturnType; + params: RequestParams.IndicesStats + // promise returned by client has an abort property + // so we cannot use its ReturnType + ): Promise<{ + _all?: { + total?: { store?: { size_in_bytes?: number }; docs?: { count?: number } }; + }; + _shards?: { + total?: number; + }; + }>; transportRequest: (params: { path: string; method: 'get'; diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts index 6d91e64be034de..98abff08dab5e3 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts @@ -11,6 +11,7 @@ import { Logger, SavedObjectsErrorHelpers, } from '../../../../../../src/core/server'; +import { unwrapEsResponse } from '../../../../observability/server'; import { APMConfig } from '../..'; import { TaskManagerSetupContract, @@ -65,27 +66,22 @@ export async function createApmTelemetry({ const collectAndStore = async () => { const config = await config$.pipe(take(1)).toPromise(); const [{ elasticsearch }] = await core.getStartServices(); - const esClient = elasticsearch.legacy.client; + const esClient = elasticsearch.client; const indices = await getApmIndices({ config, savedObjectsClient, }); - const search = esClient.callAsInternalUser.bind( - esClient, - 'search' - ) as CollectTelemetryParams['search']; + const search: CollectTelemetryParams['search'] = (params) => + unwrapEsResponse(esClient.asInternalUser.search(params)); - const indicesStats = esClient.callAsInternalUser.bind( - esClient, - 'indices.stats' - ) as CollectTelemetryParams['indicesStats']; + const indicesStats: CollectTelemetryParams['indicesStats'] = (params) => + unwrapEsResponse(esClient.asInternalUser.indices.stats(params)); - const transportRequest = esClient.callAsInternalUser.bind( - esClient, - 'transport.request' - ) as CollectTelemetryParams['transportRequest']; + const transportRequest: CollectTelemetryParams['transportRequest'] = ( + params + ) => unwrapEsResponse(esClient.asInternalUser.transport.request(params)); const dataTelemetry = await collectDataTelemetry({ search, diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/call_client_with_debug.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts similarity index 51% rename from x-pack/plugins/apm/server/lib/helpers/create_es_client/call_client_with_debug.ts rename to x-pack/plugins/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts index 9f7aaafbefb8ce..9d612d82d99bb7 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/call_client_with_debug.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts @@ -7,34 +7,31 @@ /* eslint-disable no-console */ import chalk from 'chalk'; -import { - LegacyAPICaller, - KibanaRequest, -} from '../../../../../../../src/core/server'; +import { KibanaRequest } from '../../../../../../../src/core/server'; function formatObj(obj: Record) { return JSON.stringify(obj, null, 2); } -export async function callClientWithDebug({ - apiCaller, - operationName, - params, +export async function callAsyncWithDebug({ + cb, + getDebugMessage, debug, - request, }: { - apiCaller: LegacyAPICaller; - operationName: string; - params: Record; + cb: () => Promise; + getDebugMessage: () => { body: string; title: string }; debug: boolean; - request: KibanaRequest; }) { + if (!debug) { + return cb(); + } + const startTime = process.hrtime(); let res: any; let esError = null; try { - res = await apiCaller(operationName, params); + res = await cb(); } catch (e) { // catch error and throw after outputting debug info esError = e; @@ -44,23 +41,14 @@ export async function callClientWithDebug({ const highlightColor = esError ? 'bgRed' : 'inverse'; const diff = process.hrtime(startTime); const duration = `${Math.round(diff[0] * 1000 + diff[1] / 1e6)}ms`; - const routeInfo = `${request.route.method.toUpperCase()} ${ - request.route.path - }`; + + const { title, body } = getDebugMessage(); console.log( - chalk.bold[highlightColor](`=== Debug: ${routeInfo} (${duration}) ===`) + chalk.bold[highlightColor](`=== Debug: ${title} (${duration}) ===`) ); - if (operationName === 'search') { - console.log(`GET ${params.index}/_${operationName}`); - console.log(formatObj(params.body)); - } else { - console.log(chalk.bold('ES operation:'), operationName); - - console.log(chalk.bold('ES query:')); - console.log(formatObj(params)); - } + console.log(body); console.log(`\n`); } @@ -70,3 +58,19 @@ export async function callClientWithDebug({ return res; } + +export const getDebugBody = ( + params: Record, + operationName: string +) => { + if (operationName === 'search') { + return `GET ${params.index}/_search\n${formatObj(params.body)}`; + } + + return `${chalk.bold('ES operation:')} ${operationName}\n${chalk.bold( + 'ES query:' + )}\n${formatObj(params)}`; +}; + +export const getDebugTitle = (request: KibanaRequest) => + `${request.route.method.toUpperCase()} ${request.route.path}`; diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts new file mode 100644 index 00000000000000..e9b61a27f4380a --- /dev/null +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { KibanaRequest } from 'src/core/server'; + +export function cancelEsRequestOnAbort>( + promise: T, + request: KibanaRequest +) { + const subscription = request.events.aborted$.subscribe(() => { + promise.abort(); + }); + + // using .catch() here means unsubscribe will be called + // after it has thrown an error, so we use .then(onSuccess, onFailure) + // syntax + promise.then( + () => subscription.unsubscribe(), + () => subscription.unsubscribe() + ); + + return promise; +} diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts new file mode 100644 index 00000000000000..f58e04061254d5 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts @@ -0,0 +1,77 @@ +/* + * 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 { contextServiceMock } from 'src/core/server/mocks'; +import { createHttpServer } from 'src/core/server/test_utils'; +import supertest from 'supertest'; +import { createApmEventClient } from '.'; + +describe('createApmEventClient', () => { + let server: ReturnType; + + beforeEach(() => { + server = createHttpServer(); + }); + + afterEach(async () => { + await server.stop(); + }); + it('cancels a search when a request is aborted', async () => { + const { server: innerServer, createRouter } = await server.setup({ + context: contextServiceMock.createSetupContract(), + }); + const router = createRouter('/'); + + const abort = jest.fn(); + router.get( + { path: '/', validate: false }, + async (context, request, res) => { + const eventClient = createApmEventClient({ + esClient: { + search: () => { + return Object.assign( + new Promise((resolve) => setTimeout(resolve, 3000)), + { abort } + ); + }, + } as any, + debug: false, + request, + indices: {} as any, + options: { + includeFrozen: false, + }, + }); + + await eventClient.search({ + apm: { + events: [], + }, + }); + + return res.ok({ body: 'ok' }); + } + ); + + await server.start(); + + const incomingRequest = supertest(innerServer.listener) + .get('/') + // end required to send request + .end(); + + await new Promise((resolve) => { + setTimeout(() => { + incomingRequest.abort(); + setTimeout(() => { + resolve(undefined); + }, 0); + }, 50); + }); + + expect(abort).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts index b7c38068eb93e6..b2e25994d6fe68 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -5,10 +5,11 @@ */ import { ValuesType } from 'utility-types'; +import { unwrapEsResponse } from '../../../../../../observability/server'; import { APMError } from '../../../../../typings/es_schemas/ui/apm_error'; import { + ElasticsearchClient, KibanaRequest, - LegacyScopedClusterClient, } from '../../../../../../../../src/core/server'; import { ProcessorEvent } from '../../../../../common/processor_event'; import { @@ -17,11 +18,16 @@ import { } from '../../../../../../../typings/elasticsearch'; import { ApmIndicesConfig } from '../../../settings/apm_indices/get_apm_indices'; import { addFilterToExcludeLegacyData } from './add_filter_to_exclude_legacy_data'; -import { callClientWithDebug } from '../call_client_with_debug'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; import { Span } from '../../../../../typings/es_schemas/ui/span'; import { Metric } from '../../../../../typings/es_schemas/ui/metric'; import { unpackProcessorEvents } from './unpack_processor_events'; +import { + callAsyncWithDebug, + getDebugTitle, + getDebugBody, +} from '../call_async_with_debug'; +import { cancelEsRequestOnAbort } from '../cancel_es_request_on_abort'; export type APMEventESSearchRequest = Omit & { apm: { @@ -59,10 +65,7 @@ export function createApmEventClient({ indices, options: { includeFrozen } = { includeFrozen: false }, }: { - esClient: Pick< - LegacyScopedClusterClient, - 'callAsInternalUser' | 'callAsCurrentUser' - >; + esClient: ElasticsearchClient; debug: boolean; request: KibanaRequest; indices: ApmIndicesConfig; @@ -71,9 +74,9 @@ export function createApmEventClient({ }; }) { return { - search( + async search( params: TParams, - { includeLegacyData } = { includeLegacyData: false } + { includeLegacyData = false } = {} ): Promise> { const withProcessorEventFilter = unpackProcessorEvents(params, indices); @@ -81,15 +84,25 @@ export function createApmEventClient({ ? addFilterToExcludeLegacyData(withProcessorEventFilter) : withProcessorEventFilter; - return callClientWithDebug({ - apiCaller: esClient.callAsCurrentUser, - operationName: 'search', - params: { - ...withPossibleLegacyDataFilter, - ignore_throttled: !includeFrozen, - ignore_unavailable: true, + const searchParams = { + ...withPossibleLegacyDataFilter, + ignore_throttled: !includeFrozen, + ignore_unavailable: true, + }; + + return callAsyncWithDebug({ + cb: () => { + const searchPromise = cancelEsRequestOnAbort( + esClient.search(searchParams), + request + ); + + return unwrapEsResponse(searchPromise); }, - request, + getDebugMessage: () => ({ + body: getDebugBody(searchParams, 'search'), + title: getDebugTitle(request), + }), debug, }); }, diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts index 8e74a7992e9ea7..69f596520d2164 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts @@ -3,23 +3,23 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -import { - IndexDocumentParams, - IndicesCreateParams, - DeleteDocumentResponse, - DeleteDocumentParams, -} from 'elasticsearch'; import { KibanaRequest } from 'src/core/server'; +import { RequestParams } from '@elastic/elasticsearch'; +import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { unwrapEsResponse } from '../../../../../../observability/server'; import { APMRequestHandlerContext } from '../../../../routes/typings'; import { ESSearchResponse, ESSearchRequest, } from '../../../../../../../typings/elasticsearch'; -import { callClientWithDebug } from '../call_client_with_debug'; +import { + callAsyncWithDebug, + getDebugBody, + getDebugTitle, +} from '../call_async_with_debug'; +import { cancelEsRequestOnAbort } from '../cancel_es_request_on_abort'; -// `type` was deprecated in 7.0 -export type APMIndexDocumentParams = Omit, 'type'>; +export type APMIndexDocumentParams = RequestParams.Index; export type APMInternalClient = ReturnType; @@ -30,17 +30,26 @@ export function createInternalESClient({ context: APMRequestHandlerContext; request: KibanaRequest; }) { - const { callAsInternalUser } = context.core.elasticsearch.legacy.client; + const { asInternalUser } = context.core.elasticsearch.client; - const callEs = (operationName: string, params: Record) => { - return callClientWithDebug({ - apiCaller: callAsInternalUser, - operationName, - params, - request, + function callEs({ + cb, + operationName, + params, + }: { + operationName: string; + cb: () => TransportRequestPromise; + params: Record; + }) { + return callAsyncWithDebug({ + cb: () => unwrapEsResponse(cancelEsRequestOnAbort(cb(), request)), + getDebugMessage: () => ({ + title: getDebugTitle(request), + body: getDebugBody(params, operationName), + }), debug: context.params.query._debug, }); - }; + } return { search: async < @@ -49,18 +58,32 @@ export function createInternalESClient({ >( params: TSearchRequest ): Promise> => { - return callEs('search', params); + return callEs({ + operationName: 'search', + cb: () => asInternalUser.search(params), + params, + }); }, - index: (params: APMIndexDocumentParams) => { - return callEs('index', params); + index: (params: APMIndexDocumentParams) => { + return callEs({ + operationName: 'index', + cb: () => asInternalUser.index(params), + params, + }); }, - delete: ( - params: Omit - ): Promise => { - return callEs('delete', params); + delete: (params: RequestParams.Delete): Promise<{ result: string }> => { + return callEs({ + operationName: 'delete', + cb: () => asInternalUser.delete(params), + params, + }); }, - indicesCreate: (params: IndicesCreateParams) => { - return callEs('indices.create', params); + indicesCreate: (params: RequestParams.IndicesCreate) => { + return callEs({ + operationName: 'indices.create', + cb: () => asInternalUser.indices.create(params), + params, + }); }, }; } diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts index f2d291cd053bb2..f00941d6e68007 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts @@ -31,6 +31,15 @@ jest.mock('../index_pattern/get_dynamic_index_pattern', () => ({ })); function getMockRequest() { + const esClientMock = { + asCurrentUser: { + search: jest.fn().mockResolvedValue({ body: {} }), + }, + asInternalUser: { + search: jest.fn().mockResolvedValue({ body: {} }), + }, + }; + const mockContext = ({ config: new Proxy( {}, @@ -45,12 +54,7 @@ function getMockRequest() { }, core: { elasticsearch: { - legacy: { - client: { - callAsCurrentUser: jest.fn(), - callAsInternalUser: jest.fn(), - }, - }, + client: esClientMock, }, uiSettings: { client: { @@ -69,12 +73,7 @@ function getMockRequest() { } as unknown) as APMRequestHandlerContext & { core: { elasticsearch: { - legacy: { - client: { - callAsCurrentUser: jest.Mock; - callAsInternalUser: jest.Mock; - }; - }; + client: typeof esClientMock; }; uiSettings: { client: { @@ -91,6 +90,11 @@ function getMockRequest() { const mockRequest = ({ url: '', + events: { + aborted$: { + subscribe: jest.fn(), + }, + }, } as unknown) as KibanaRequest; return { mockContext, mockRequest }; @@ -106,8 +110,8 @@ describe('setupRequest', () => { body: { foo: 'bar' }, }); expect( - mockContext.core.elasticsearch.legacy.client.callAsCurrentUser - ).toHaveBeenCalledWith('search', { + mockContext.core.elasticsearch.client.asCurrentUser.search + ).toHaveBeenCalledWith({ index: ['apm-*'], body: { foo: 'bar', @@ -133,8 +137,8 @@ describe('setupRequest', () => { body: { foo: 'bar' }, } as any); expect( - mockContext.core.elasticsearch.legacy.client.callAsInternalUser - ).toHaveBeenCalledWith('search', { + mockContext.core.elasticsearch.client.asInternalUser.search + ).toHaveBeenCalledWith({ index: ['apm-*'], body: { foo: 'bar', @@ -154,8 +158,8 @@ describe('setupRequest', () => { body: { query: { bool: { filter: [{ term: 'someTerm' }] } } }, }); const params = - mockContext.core.elasticsearch.legacy.client.callAsCurrentUser.mock - .calls[0][1]; + mockContext.core.elasticsearch.client.asCurrentUser.search.mock + .calls[0][0]; expect(params.body).toEqual({ query: { bool: { @@ -184,8 +188,8 @@ describe('setupRequest', () => { } ); const params = - mockContext.core.elasticsearch.legacy.client.callAsCurrentUser.mock - .calls[0][1]; + mockContext.core.elasticsearch.client.asCurrentUser.search.mock + .calls[0][0]; expect(params.body).toEqual({ query: { bool: { @@ -214,8 +218,8 @@ describe('without a bool filter', () => { }, }); const params = - mockContext.core.elasticsearch.legacy.client.callAsCurrentUser.mock - .calls[0][1]; + mockContext.core.elasticsearch.client.asCurrentUser.search.mock + .calls[0][0]; expect(params.body).toEqual({ query: { bool: { @@ -245,8 +249,8 @@ describe('with includeFrozen=false', () => { }); const params = - mockContext.core.elasticsearch.legacy.client.callAsCurrentUser.mock - .calls[0][1]; + mockContext.core.elasticsearch.client.asCurrentUser.search.mock + .calls[0][0]; expect(params.ignore_throttled).toBe(true); }); }); @@ -265,8 +269,8 @@ describe('with includeFrozen=true', () => { }); const params = - mockContext.core.elasticsearch.legacy.client.callAsCurrentUser.mock - .calls[0][1]; + mockContext.core.elasticsearch.client.asCurrentUser.search.mock + .calls[0][0]; expect(params.ignore_throttled).toBe(false); }); }); diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts index 47529de1042a11..947eb68e100933 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts @@ -86,7 +86,7 @@ export async function setupRequest( const coreSetupRequest = { indices, apmEventClient: createApmEventClient({ - esClient: context.core.elasticsearch.legacy.client, + esClient: context.core.elasticsearch.client.asCurrentUser, debug: context.params.query._debug, request, indices, diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts index 3903298415aed5..55395f3a4ca4e3 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LegacyAPICaller, Logger } from 'kibana/server'; +import { ElasticsearchClient, Logger } from 'kibana/server'; +import { unwrapEsResponse } from '../../../../../observability/server'; import { rangeFilter } from '../../../../common/utils/range_filter'; import { ESSearchResponse } from '../../../../../../typings/elasticsearch'; import { Annotation as ESAnnotation } from '../../../../../observability/common/annotations'; @@ -18,14 +19,14 @@ export async function getStoredAnnotations({ setup, serviceName, environment, - apiCaller, + client, annotationsClient, logger, }: { setup: Setup & SetupTimeRange; serviceName: string; environment?: string; - apiCaller: LegacyAPICaller; + client: ElasticsearchClient; annotationsClient: ScopedAnnotationsClient; logger: Logger; }): Promise { @@ -50,10 +51,12 @@ export async function getStoredAnnotations({ const response: ESSearchResponse< ESAnnotation, { body: typeof body } - > = (await apiCaller('search', { - index: annotationsClient.index, - body, - })) as any; + > = await unwrapEsResponse( + client.search({ + index: annotationsClient.index, + body, + }) + ); return response.hits.hits.map((hit) => { return { diff --git a/x-pack/plugins/apm/server/lib/services/annotations/index.ts b/x-pack/plugins/apm/server/lib/services/annotations/index.ts index 9516ed37772970..304485822be28e 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/index.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/index.ts @@ -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 { LegacyAPICaller, Logger } from 'kibana/server'; +import { ElasticsearchClient, Logger } from 'kibana/server'; import { ScopedAnnotationsClient } from '../../../../../observability/server'; import { getDerivedServiceAnnotations } from './get_derived_service_annotations'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; @@ -15,7 +15,7 @@ export async function getServiceAnnotations({ serviceName, environment, annotationsClient, - apiCaller, + client, logger, }: { serviceName: string; @@ -23,7 +23,7 @@ export async function getServiceAnnotations({ setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; annotationsClient?: ScopedAnnotationsClient; - apiCaller: LegacyAPICaller; + client: ElasticsearchClient; logger: Logger; }) { // start fetching derived annotations (based on transactions), but don't wait on it @@ -41,7 +41,7 @@ export async function getServiceAnnotations({ serviceName, environment, annotationsClient, - apiCaller, + client, logger, }) : []; diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts index 83117db1167b5d..190c99d0002d87 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ILegacyClusterClient, Logger } from 'src/core/server'; +import { ElasticsearchClient, Logger } from 'src/core/server'; import { createOrUpdateIndex, MappingsDefinition, @@ -13,18 +13,18 @@ import { APMConfig } from '../../..'; import { getApmIndicesConfig } from '../apm_indices/get_apm_indices'; export async function createApmAgentConfigurationIndex({ - esClient, + client, config, logger, }: { - esClient: ILegacyClusterClient; + client: ElasticsearchClient; config: APMConfig; logger: Logger; }) { const index = getApmIndicesConfig(config).apmAgentConfigurationIndex; return createOrUpdateIndex({ index, - apiCaller: esClient.callAsInternalUser, + client, logger, mappings, }); diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts index 2bfe0d620e4e8e..aa9e7411d10141 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ILegacyClusterClient, Logger } from 'src/core/server'; +import { ElasticsearchClient, Logger } from 'src/core/server'; import { createOrUpdateIndex, MappingsDefinition, @@ -13,18 +13,18 @@ import { APMConfig } from '../../..'; import { getApmIndicesConfig } from '../apm_indices/get_apm_indices'; export const createApmCustomLinkIndex = async ({ - esClient, + client, config, logger, }: { - esClient: ILegacyClusterClient; + client: ElasticsearchClient; config: APMConfig; logger: Logger; }) => { const index = getApmIndicesConfig(config).apmCustomLinkIndex; return createOrUpdateIndex({ index, - apiCaller: esClient.callAsInternalUser, + client, logger, mappings, }); diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index 09b75137e12dfb..3e01523aa8e31c 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -173,7 +173,7 @@ export class APMPlugin implements Plugin { context.core.uiSettings.client.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN), ]); - const esClient = context.core.elasticsearch.legacy.client; + const esClient = context.core.elasticsearch.client.asCurrentUser; return createApmEventClient({ debug: debug ?? false, @@ -195,13 +195,13 @@ export class APMPlugin implements Plugin { // create agent configuration index without blocking start lifecycle createApmAgentConfigurationIndex({ - esClient: core.elasticsearch.legacy.client, + client: core.elasticsearch.client.asInternalUser, config: this.currentConfig, logger: this.logger, }); // create custom action index without blocking start lifecycle createApmCustomLinkIndex({ - esClient: core.elasticsearch.legacy.client, + client: core.elasticsearch.client.asInternalUser, config: this.currentConfig, logger: this.logger, }); diff --git a/x-pack/plugins/apm/server/routes/create_api/index.ts b/x-pack/plugins/apm/server/routes/create_api/index.ts index cfb31670bd5212..721badf7fc025b 100644 --- a/x-pack/plugins/apm/server/routes/create_api/index.ts +++ b/x-pack/plugins/apm/server/routes/create_api/index.ts @@ -147,7 +147,7 @@ function convertBoomToKibanaResponse( error: Boom.Boom, response: KibanaResponseFactory ) { - const opts = { body: error.message }; + const opts = { body: { message: error.message } }; switch (error.output.statusCode) { case 404: return response.notFound(opts); @@ -159,9 +159,6 @@ function convertBoomToKibanaResponse( return response.forbidden(opts); default: - return response.custom({ - statusCode: error.output.statusCode, - ...opts, - }); + throw error; } } diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index bfc2ebf062ac31..ef74437f5f0e7f 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -194,7 +194,7 @@ export const serviceAnnotationsRoute = createRoute({ serviceName, environment, annotationsClient, - apiCaller: context.core.elasticsearch.legacy.client.callAsCurrentUser, + client: context.core.elasticsearch.client.asCurrentUser, logger: context.logger, }); }, diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts index 78550b781b4119..e88541f69d6cfe 100644 --- a/x-pack/plugins/observability/server/index.ts +++ b/x-pack/plugins/observability/server/index.ts @@ -9,6 +9,7 @@ import { PluginInitializerContext } from 'src/core/server'; import { ObservabilityPlugin, ObservabilityPluginSetup } from './plugin'; import { createOrUpdateIndex, MappingsDefinition } from './utils/create_or_update_index'; import { ScopedAnnotationsClient } from './lib/annotations/bootstrap_annotations'; +import { unwrapEsResponse } from './utils/unwrap_es_response'; export const config = { schema: schema.object({ @@ -30,4 +31,5 @@ export { MappingsDefinition, ObservabilityPluginSetup, ScopedAnnotationsClient, + unwrapEsResponse, }; diff --git a/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts b/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts index 6fcd780d5af296..90084611d7efcc 100644 --- a/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts +++ b/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts @@ -38,7 +38,7 @@ export async function bootstrapAnnotations({ index, core, context }: Params) { ) => { return createAnnotationsClient({ index, - apiCaller: requestContext.core.elasticsearch.legacy.client.callAsCurrentUser, + esClient: requestContext.core.elasticsearch.client.asCurrentUser, logger, license: requestContext.licensing?.license, }); diff --git a/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts index 41f45683d244c5..76890cbd587e98 100644 --- a/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts +++ b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LegacyAPICaller, Logger } from 'kibana/server'; +import { ElasticsearchClient, Logger } from 'kibana/server'; import * as t from 'io-ts'; -import { Client } from 'elasticsearch'; import Boom from '@hapi/boom'; import { ILicense } from '../../../../licensing/server'; import { @@ -15,9 +14,9 @@ import { Annotation, getAnnotationByIdRt, } from '../../../common/annotations'; -import { PromiseReturnType } from '../../../typings/common'; import { createOrUpdateIndex } from '../../utils/create_or_update_index'; import { mappings } from './mappings'; +import { unwrapEsResponse } from '../../utils/unwrap_es_response'; type CreateParams = t.TypeOf; type DeleteParams = t.TypeOf; @@ -38,19 +37,25 @@ interface IndexDocumentResponse { result: string; } +interface GetResponse { + _id: string; + _index: string; + _source: Annotation; +} + export function createAnnotationsClient(params: { index: string; - apiCaller: LegacyAPICaller; + esClient: ElasticsearchClient; logger: Logger; license?: ILicense; }) { - const { index, apiCaller, logger, license } = params; + const { index, esClient, logger, license } = params; const initIndex = () => createOrUpdateIndex({ index, mappings, - apiCaller, + client: esClient, logger, }); @@ -71,9 +76,11 @@ export function createAnnotationsClient(params: { async ( createParams: CreateParams ): Promise<{ _id: string; _index: string; _source: Annotation }> => { - const indexExists = await apiCaller('indices.exists', { - index, - }); + const indexExists = await unwrapEsResponse( + esClient.indices.exists({ + index, + }) + ); if (!indexExists) { await initIndex(); @@ -86,35 +93,42 @@ export function createAnnotationsClient(params: { }, }; - const response = (await apiCaller('index', { - index, - body: annotation, - refresh: 'wait_for', - })) as IndexDocumentResponse; + const body = await unwrapEsResponse( + esClient.index({ + index, + body: annotation, + refresh: 'wait_for', + }) + ); - return apiCaller('get', { - index, - id: response._id, - }); + return ( + await esClient.get({ + index, + id: body._id, + }) + ).body; } ), getById: ensureGoldLicense(async (getByIdParams: GetByIdParams) => { const { id } = getByIdParams; - return apiCaller('get', { - id, - index, - }); + return unwrapEsResponse( + esClient.get({ + id, + index, + }) + ); }), delete: ensureGoldLicense(async (deleteParams: DeleteParams) => { const { id } = deleteParams; - const response = (await apiCaller('delete', { - index, - id, - refresh: 'wait_for', - })) as PromiseReturnType; - return response; + return unwrapEsResponse( + esClient.delete({ + index, + id, + refresh: 'wait_for', + }) + ); }), }; } diff --git a/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts b/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts index 8f0b53b5a3df28..6ae80880d22b59 100644 --- a/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts +++ b/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts @@ -55,11 +55,11 @@ export function registerAnnotationAPIs({ }); } - const apiCaller = context.core.elasticsearch.legacy.client.callAsCurrentUser; + const esClient = context.core.elasticsearch.client.asCurrentUser; const client = createAnnotationsClient({ index, - apiCaller, + esClient, logger, license: context.licensing?.license, }); diff --git a/x-pack/plugins/observability/server/utils/create_or_update_index.ts b/x-pack/plugins/observability/server/utils/create_or_update_index.ts index 1898331451262c..248488b4a5ebec 100644 --- a/x-pack/plugins/observability/server/utils/create_or_update_index.ts +++ b/x-pack/plugins/observability/server/utils/create_or_update_index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import pRetry from 'p-retry'; -import { Logger, LegacyAPICaller } from 'src/core/server'; +import { Logger, ElasticsearchClient } from 'src/core/server'; export interface MappingsObject { type: string; @@ -24,12 +24,12 @@ export interface MappingsDefinition { export async function createOrUpdateIndex({ index, mappings, - apiCaller, + client, logger, }: { index: string; mappings: MappingsDefinition; - apiCaller: LegacyAPICaller; + client: ElasticsearchClient; logger: Logger; }) { try { @@ -43,21 +43,21 @@ export async function createOrUpdateIndex({ */ await pRetry( async () => { - const indexExists = await apiCaller('indices.exists', { index }); + const indexExists = (await client.indices.exists({ index })).body; const result = indexExists ? await updateExistingIndex({ index, - apiCaller, + client, mappings, }) : await createNewIndex({ index, - apiCaller, + client, mappings, }); - if (!result.acknowledged) { - const resultError = result && result.error && JSON.stringify(result.error); + if (!result.body.acknowledged) { + const resultError = result && result.body.error && JSON.stringify(result.body.error); throw new Error(resultError); } }, @@ -75,14 +75,14 @@ export async function createOrUpdateIndex({ function createNewIndex({ index, - apiCaller, + client, mappings, }: { index: string; - apiCaller: LegacyAPICaller; + client: ElasticsearchClient; mappings: MappingsDefinition; }) { - return apiCaller('indices.create', { + return client.indices.create<{ acknowledged: boolean; error: any }>({ index, body: { // auto_expand_replicas: Allows cluster to not have replicas for this index @@ -94,14 +94,14 @@ function createNewIndex({ function updateExistingIndex({ index, - apiCaller, + client, mappings, }: { index: string; - apiCaller: LegacyAPICaller; + client: ElasticsearchClient; mappings: MappingsDefinition; }) { - return apiCaller('indices.putMapping', { + return client.indices.putMapping<{ acknowledged: boolean; error: any }>({ index, body: mappings, }); diff --git a/x-pack/plugins/observability/server/utils/unwrap_es_response.ts b/x-pack/plugins/observability/server/utils/unwrap_es_response.ts new file mode 100644 index 00000000000000..418ceeb64cc879 --- /dev/null +++ b/x-pack/plugins/observability/server/utils/unwrap_es_response.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 { PromiseValueType } from '../../../apm/typings/common'; + +export function unwrapEsResponse>( + responsePromise: T +): Promise['body']> { + return responsePromise.then((res) => res.body); +} diff --git a/x-pack/typings/elasticsearch/index.d.ts b/x-pack/typings/elasticsearch/index.d.ts index ff20ce39d64464..049e1e52c66d98 100644 --- a/x-pack/typings/elasticsearch/index.d.ts +++ b/x-pack/typings/elasticsearch/index.d.ts @@ -5,6 +5,7 @@ */ import { ValuesType } from 'utility-types'; import { Explanation, SearchParams, SearchResponse } from 'elasticsearch'; +import { RequestParams } from '@elastic/elasticsearch'; import { AggregationResponseMap, AggregationInputMap, SortOptions } from './aggregations'; export { AggregationInputMap, @@ -72,9 +73,7 @@ export interface ESSearchBody { _source?: ESSourceOptions; } -export type ESSearchRequest = Omit & { - body?: ESSearchBody; -}; +export type ESSearchRequest = RequestParams.Search; export interface ESSearchOptions { restTotalHitsAsInt: boolean; From ab1af57f0564e64907ac88f1a7a6cde4262b94a7 Mon Sep 17 00:00:00 2001 From: Silvia Mitter Date: Wed, 27 Jan 2021 13:34:11 +0100 Subject: [PATCH 21/58] update apm index pattern (#89395) --- src/plugins/apm_oss/server/tutorial/index_pattern.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/apm_oss/server/tutorial/index_pattern.json b/src/plugins/apm_oss/server/tutorial/index_pattern.json index 6eb040f2758af8..93a2393b70fa43 100644 --- a/src/plugins/apm_oss/server/tutorial/index_pattern.json +++ b/src/plugins/apm_oss/server/tutorial/index_pattern.json @@ -1,7 +1,7 @@ { "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.cgroup.memory.mem.limit.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.usage.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.build.original\",\"scripted\":false,\"searchable\":true},{\"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},{\"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},{\"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},{\"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},{\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.subdomain\",\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true},{\"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},{\"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\":\"client.user.roles\",\"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.account.name\",\"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.project.id\",\"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\":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},{\"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},{\"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},{\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.subdomain\",\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true},{\"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},{\"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\":\"destination.user.roles\",\"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.architecture\",\"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.imphash\",\"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},{\"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},{\"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},{\"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},{\"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},{\"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\":false,\"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.reason\",\"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},{\"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},{\"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.architecture\",\"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.imphash\",\"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},{\"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},{\"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\":\"file.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"file.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.version_number\",\"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},{\"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},{\"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},{\"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},{\"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},{\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true},{\"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},{\"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\":\"host.user.roles\",\"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},{\"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.mime_type\",\"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},{\"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},{\"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.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"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.file.path\",\"scripted\":false,\"searchable\":true},{\"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},{\"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\":false,\"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},{\"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},{\"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},{\"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},{\"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},{\"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},{\"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.architecture\",\"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.imphash\",\"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},{\"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},{\"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},{\"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},{\"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},{\"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},{\"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},{\"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.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.original_file_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.product\",\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true},{\"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},{\"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.architecture\",\"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.imphash\",\"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},{\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true},{\"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},{\"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},{\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true},{\"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.hosts\",\"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},{\"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},{\"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},{\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.subdomain\",\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true},{\"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},{\"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\":\"server.user.roles\",\"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},{\"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},{\"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},{\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.subdomain\",\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true},{\"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},{\"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\":\"source.user.roles\",\"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\":\"threat.technique.subtechnique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.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},{\"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},{\"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.client.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.client.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.version_number\",\"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},{\"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},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.server.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.version_number\",\"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\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"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\":\"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},{\"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},{\"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},{\"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},{\"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},{\"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.subdomain\",\"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.changes.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.changes.roles\",\"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.effective.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.effective.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true},{\"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},{\"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.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.email\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.full_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.target.roles\",\"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},{\"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},{\"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},{\"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\":\"x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.version_number\",\"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.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.node.hostname\",\"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.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\":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\":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\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"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\":\"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\":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\":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.experience.longtask.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.sum\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.max\",\"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\"}]", + "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.build.original\",\"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.subdomain\",\"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\":\"client.user.roles\",\"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.account.name\",\"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.project.id\",\"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\":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.subdomain\",\"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\":\"destination.user.roles\",\"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.architecture\",\"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.imphash\",\"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\":false,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"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\":false,\"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.reason\",\"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.architecture\",\"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.imphash\",\"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\":\"file.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"file.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.version_number\",\"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\":\"host.user.roles\",\"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.mime_type\",\"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.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"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.file.path\",\"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\":false,\"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.architecture\",\"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.imphash\",\"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.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.product\",\"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.architecture\",\"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.imphash\",\"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.hosts\",\"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.subdomain\",\"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\":\"server.user.roles\",\"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.subdomain\",\"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\":\"source.user.roles\",\"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\":\"threat.technique.subtechnique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.subtechnique.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.client.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.client.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.version_number\",\"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.server.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.server.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.version_number\",\"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\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"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\":\"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.subdomain\",\"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.roles\",\"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\":\"x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.version_number\",\"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.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.node.hostname\",\"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.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\":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\":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\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"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\":\"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\":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\":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.experience.longtask.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.sum\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.max\",\"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" }, From b09e010b16970239a61dc18363d3bc9c0e6db146 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 27 Jan 2021 13:43:55 +0100 Subject: [PATCH 22/58] [Lens] Clean up usage collector (#89109) --- x-pack/plugins/lens/server/usage/collectors.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/lens/server/usage/collectors.ts b/x-pack/plugins/lens/server/usage/collectors.ts index c32fc0371ed8a6..71a699aadb8656 100644 --- a/x-pack/plugins/lens/server/usage/collectors.ts +++ b/x-pack/plugins/lens/server/usage/collectors.ts @@ -16,11 +16,6 @@ export function registerLensUsageCollector( usageCollection: UsageCollectionSetup, taskManager: Promise ) { - let isCollectorReady = false; - taskManager.then(() => { - // mark lensUsageCollector as ready to collect when the TaskManager is ready - isCollectorReady = true; - }); const lensUsageCollector = usageCollection.makeUsageCollector({ type: 'lens', async fetch() { @@ -55,7 +50,10 @@ export function registerLensUsageCollector( }; } }, - isReady: () => isCollectorReady, + isReady: async () => { + await taskManager; + return true; + }, schema: lensUsageSchema, }); From ba1e795b3f4341547d3acc4cf9df79646e2b412d Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Wed, 27 Jan 2021 14:23:47 +0100 Subject: [PATCH 23/58] [Lens] Fix indexpattern checks for missing references (#88840) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../dimension_panel/reference_editor.test.tsx | 76 +++++++++++++++- .../dimension_panel/reference_editor.tsx | 42 ++++++--- .../indexpattern_datasource/indexpattern.tsx | 11 ++- .../public/indexpattern_datasource/mocks.ts | 78 +++++++++++++++- .../operations/definitions/index.ts | 4 +- .../operations/layer_helpers.test.ts | 89 +++++++++++++------ .../operations/layer_helpers.ts | 30 ++++--- .../public/indexpattern_datasource/utils.ts | 26 +++++- 8 files changed, 294 insertions(+), 62 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx index 0891dd27fcf172..ed1b6956409228 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx @@ -13,7 +13,7 @@ import type { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'k import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import type { DataPublicPluginStart } from 'src/plugins/data/public'; import { OperationMetadata } from '../../types'; -import { createMockedIndexPattern } from '../mocks'; +import { createMockedIndexPattern, createMockedIndexPatternWithoutType } from '../mocks'; import { ReferenceEditor, ReferenceEditorProps } from './reference_editor'; import { insertOrReplaceColumn } from '../operations'; import { FieldSelect } from './field_select'; @@ -260,6 +260,48 @@ describe('reference editor', () => { ); }); + it("should show the sub-function as invalid if there's no field compatible with it", () => { + // This may happen for saved objects after changing the type of a field + wrapper = mount( + true, + }} + /> + ); + + const subFunctionSelect = wrapper + .find('[data-test-subj="indexPattern-reference-function"]') + .first(); + + expect(subFunctionSelect.prop('isInvalid')).toEqual(true); + expect(subFunctionSelect.prop('selectedOptions')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + 'data-test-subj': 'lns-indexPatternDimension-avg incompatible', + label: 'Average', + value: 'avg', + }), + ]) + ); + }); + it('should hide the function selector when using a field-only selection style', () => { wrapper = mount( { expect(fieldSelect.prop('markAllFieldsCompatible')).toEqual(true); }); + it('should show the FieldSelect as invalid if the selected field is missing', () => { + wrapper = mount( + true, + }} + /> + ); + + const fieldSelect = wrapper.find(FieldSelect); + expect(fieldSelect.prop('fieldIsInvalid')).toEqual(true); + expect(fieldSelect.prop('selectedField')).toEqual('missing'); + expect(fieldSelect.prop('selectedOperationType')).toEqual('avg'); + expect(fieldSelect.prop('incompleteOperation')).toBeUndefined(); + expect(fieldSelect.prop('markAllFieldsCompatible')).toEqual(false); + }); + it('should show the ParamEditor for functions that offer one', () => { wrapper = mount( value === incompleteInfo.operationType)!] + const selectedOption = incompleteOperation + ? [functionOptions.find(({ value }) => value === incompleteOperation)!] : column ? [functionOptions.find(({ value }) => value === column.operationType)!] : []; // If the operationType is incomplete, the user needs to select a field- so // the function is marked as valid. - const showOperationInvalid = !column && !Boolean(incompleteInfo?.operationType); + const showOperationInvalid = !column && !Boolean(incompleteOperation); // The field is invalid if the operation has been updated without a field, // or if we are in a field-only mode but empty state - const showFieldInvalid = - Boolean(incompleteInfo?.operationType) || (selectionStyle === 'field' && !column); + const showFieldInvalid = Boolean(incompleteOperation) || (selectionStyle === 'field' && !column); + // Check if the field still exists to protect from changes + const showFieldMissingInvalid = !currentIndexPattern.getFieldByName( + incompleteField ?? (column as FieldBasedIndexPatternColumn)?.sourceField + ); + + // what about a field changing type and becoming invalid? + // Let's say this change makes the indexpattern without any number field but the operation was set to a numeric operation. + // At this point the ComboBox will crash. + // Therefore check if the selectedOption is in functionOptions and in case fill it in as disabled option + const showSelectionFunctionInvalid = Boolean(selectedOption.length && selectedOption[0] == null); + if (showSelectionFunctionInvalid) { + const selectedOperationType = incompleteOperation || column.operationType; + const brokenFunctionOption = { + label: operationPanels[selectedOperationType].displayName, + value: selectedOperationType, + className: 'lnsIndexPatternDimensionEditor__operation', + 'data-test-subj': `lns-indexPatternDimension-${selectedOperationType} incompatible`, + }; + functionOptions.push(brokenFunctionOption); + selectedOption[0] = brokenFunctionOption; + } return (
@@ -216,7 +236,7 @@ export function ReferenceEditor(props: ReferenceEditorProps) { defaultMessage: 'Choose a sub-function', })} fullWidth - isInvalid={showOperationInvalid} + isInvalid={showOperationInvalid || showSelectionFunctionInvalid} > { @@ -258,11 +278,11 @@ export function ReferenceEditor(props: ReferenceEditorProps) { defaultMessage: 'Select a field', })} fullWidth - isInvalid={showFieldInvalid} + isInvalid={showFieldInvalid || showFieldMissingInvalid} labelAppend={labelAppend} > - (getErrorMessages(layer) ?? []).map((message) => ({ - shortMessage: '', // Not displayed currently - longMessage: message, - })) + (getErrorMessages(layer, state.indexPatterns[layer.indexPatternId]) ?? []).map( + (message) => ({ + shortMessage: '', // Not displayed currently + longMessage: message, + }) + ) ); // Single layer case, no need to explain more diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts b/x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts index d0cbcee61db6f6..4aea9e8ac67a96 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts @@ -6,7 +6,83 @@ import { DragContextState } from '../drag_drop'; import { getFieldByNameFactory } from './pure_helpers'; -import type { IndexPattern } from './types'; +import type { IndexPattern, IndexPatternField } from './types'; + +export const createMockedIndexPatternWithoutType = ( + typeToFilter: IndexPatternField['type'] +): IndexPattern => { + const fields = [ + { + name: 'timestamp', + displayName: 'timestampLabel', + type: 'date', + aggregatable: true, + searchable: true, + }, + { + name: 'start_date', + displayName: 'start_date', + type: 'date', + aggregatable: true, + searchable: true, + }, + { + name: 'bytes', + displayName: 'bytes', + type: 'number', + aggregatable: true, + searchable: true, + }, + { + name: 'memory', + displayName: 'memory', + type: 'number', + aggregatable: true, + searchable: true, + }, + { + name: 'source', + displayName: 'source', + type: 'string', + aggregatable: true, + searchable: true, + esTypes: ['keyword'], + }, + { + name: 'unsupported', + displayName: 'unsupported', + type: 'geo', + aggregatable: true, + searchable: true, + }, + { + name: 'dest', + displayName: 'dest', + type: 'string', + aggregatable: true, + searchable: true, + esTypes: ['keyword'], + }, + { + name: 'scripted', + displayName: 'Scripted', + type: 'string', + searchable: true, + aggregatable: true, + scripted: true, + lang: 'painless', + script: '1234', + }, + ].filter(({ type }) => type !== typeToFilter); + return { + id: '1', + title: 'my-fake-index-pattern', + timeFieldName: 'timestamp', + hasRestrictions: false, + fields, + getFieldByName: getFieldByNameFactory(fields), + }; +}; export const createMockedIndexPattern = (): IndexPattern => { const fields = [ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts index 7dbc7d3b986a57..1cdaff53c5458e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts @@ -197,7 +197,7 @@ interface BaseOperationDefinitionProps { getErrorMessage?: ( layer: IndexPatternLayer, columnId: string, - indexPattern?: IndexPattern + indexPattern: IndexPattern ) => string[] | undefined; /* @@ -301,7 +301,7 @@ interface FieldBasedOperationDefinition { getErrorMessage: ( layer: IndexPatternLayer, columnId: string, - indexPattern?: IndexPattern + indexPattern: IndexPattern ) => string[] | undefined; } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts index c0e71dc1509e7e..94cf13a5c50a4e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts @@ -2147,14 +2147,17 @@ describe('state_helpers', () => { it('should collect errors from metric-type operation definitions', () => { const mock = jest.fn().mockReturnValue(['error 1']); operationDefinitionMap.avg.getErrorMessage = mock; - const errors = getErrorMessages({ - indexPatternId: '1', - columnOrder: [], - columns: { - // @ts-expect-error invalid column - col1: { operationType: 'avg' }, + const errors = getErrorMessages( + { + indexPatternId: '1', + columnOrder: [], + columns: { + // @ts-expect-error invalid column + col1: { operationType: 'avg' }, + }, }, - }); + indexPattern + ); expect(mock).toHaveBeenCalled(); expect(errors).toHaveLength(1); }); @@ -2162,15 +2165,18 @@ describe('state_helpers', () => { it('should collect errors from reference-type operation definitions', () => { const mock = jest.fn().mockReturnValue(['error 1']); operationDefinitionMap.testReference.getErrorMessage = mock; - const errors = getErrorMessages({ - indexPatternId: '1', - columnOrder: [], - columns: { - col1: - // @ts-expect-error not statically analyzed - { operationType: 'testReference', references: [] }, + const errors = getErrorMessages( + { + indexPatternId: '1', + columnOrder: [], + columns: { + col1: + // @ts-expect-error not statically analyzed + { operationType: 'testReference', references: [] }, + }, }, - }); + indexPattern + ); expect(mock).toHaveBeenCalled(); expect(errors).toHaveLength(1); }); @@ -2184,24 +2190,55 @@ describe('state_helpers', () => { getErrorMessage: incompleteRef, }; - const errors = getErrorMessages({ - indexPatternId: '1', - columnOrder: [], - columns: { - col1: + const errors = getErrorMessages( + { + indexPatternId: '1', + columnOrder: [], + columns: { + col1: + // @ts-expect-error not statically analyzed + { operationType: 'testReference', references: [] }, + }, + incompleteColumns: { // @ts-expect-error not statically analyzed - { operationType: 'testReference', references: [] }, - }, - incompleteColumns: { - // @ts-expect-error not statically analyzed - col1: { operationType: 'testIncompleteReference' }, + col1: { operationType: 'testIncompleteReference' }, + }, }, - }); + indexPattern + ); expect(savedRef).not.toHaveBeenCalled(); expect(incompleteRef).toHaveBeenCalled(); expect(errors).toBeUndefined(); delete operationDefinitionMap.testIncompleteReference; }); + + it('should forward the indexpattern when available', () => { + const mock = jest.fn(); + operationDefinitionMap.testReference.getErrorMessage = mock; + getErrorMessages( + { + indexPatternId: '1', + columnOrder: [], + columns: { + col1: + // @ts-expect-error not statically analyzed + { operationType: 'testReference', references: [] }, + }, + }, + indexPattern + ); + expect(mock).toHaveBeenCalledWith( + { + indexPatternId: '1', + columnOrder: [], + columns: { + col1: { operationType: 'testReference', references: [] }, + }, + }, + 'col1', + indexPattern + ); + }); }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts index d8244f3902a6e6..10618cc7545562 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts @@ -864,18 +864,24 @@ export function updateLayerIndexPattern( * - All column references are valid * - All prerequisites are met */ -export function getErrorMessages(layer: IndexPatternLayer): string[] | undefined { - const errors: string[] = []; - Object.entries(layer.columns).forEach(([columnId, column]) => { - // If we're transitioning to another operation, check for "new" incompleteColumns rather - // than "old" saved operation on the layer - const columnFinalRef = - layer.incompleteColumns?.[columnId]?.operationType || column.operationType; - const def = operationDefinitionMap[columnFinalRef]; - if (def.getErrorMessage) { - errors.push(...(def.getErrorMessage(layer, columnId) ?? [])); - } - }); +export function getErrorMessages( + layer: IndexPatternLayer, + indexPattern: IndexPattern +): string[] | undefined { + const errors: string[] = Object.entries(layer.columns) + .flatMap(([columnId, column]) => { + // If we're transitioning to another operation, check for "new" incompleteColumns rather + // than "old" saved operation on the layer + const columnFinalRef = + layer.incompleteColumns?.[columnId]?.operationType || column.operationType; + const def = operationDefinitionMap[columnFinalRef]; + + if (def.getErrorMessage) { + return def.getErrorMessage(layer, columnId, indexPattern); + } + }) + // remove the undefined values + .filter((v: string | undefined): v is string => v != null); return errors.length ? errors : undefined; } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/utils.ts b/x-pack/plugins/lens/public/indexpattern_datasource/utils.ts index 57cc4abeb723a2..b5a4905a297383 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/utils.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/utils.ts @@ -7,9 +7,10 @@ import { DataType } from '../types'; import { IndexPattern, IndexPatternLayer } from './types'; import { DraggedField } from './indexpattern'; -import { +import type { BaseIndexPatternColumn, FieldBasedIndexPatternColumn, + ReferenceBasedIndexPatternColumn, } from './operations/definitions/column_types'; import { operationDefinitionMap, IndexPatternColumn } from './operations'; @@ -53,12 +54,29 @@ export function isColumnInvalid( if (!column) return; const operationDefinition = column.operationType && operationDefinitionMap[column.operationType]; - return !!( - operationDefinition.getErrorMessage && - operationDefinition.getErrorMessage(layer, columnId, indexPattern) + // check also references for errors + const referencesHaveErrors = + true && + 'references' in column && + Boolean(getReferencesErrors(layer, column, indexPattern).filter(Boolean).length); + + return ( + !!operationDefinition.getErrorMessage?.(layer, columnId, indexPattern) || referencesHaveErrors ); } +function getReferencesErrors( + layer: IndexPatternLayer, + column: ReferenceBasedIndexPatternColumn, + indexPattern: IndexPattern +) { + return column.references?.map((referenceId: string) => { + const referencedOperation = layer.columns[referenceId]?.operationType; + const referencedDefinition = operationDefinitionMap[referencedOperation]; + return referencedDefinition?.getErrorMessage?.(layer, referenceId, indexPattern); + }); +} + export function fieldIsInvalid(column: IndexPatternColumn | undefined, indexPattern: IndexPattern) { if (!column || !hasField(column)) { return false; From 6425c5d6ae343551e953c31b4d9e4ed0b231353a Mon Sep 17 00:00:00 2001 From: Thom Heymann <190132+thomheymann@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:07:20 +0000 Subject: [PATCH 24/58] Fixed regex bug in Safari (#89399) * Fixed regex bug in Safari * Added extra unit test --- x-pack/plugins/security/common/constants.ts | 2 +- .../management/users/edit_user/create_user_page.test.tsx | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security/common/constants.ts b/x-pack/plugins/security/common/constants.ts index c235c296bcbaea..372f539d812fd6 100644 --- a/x-pack/plugins/security/common/constants.ts +++ b/x-pack/plugins/security/common/constants.ts @@ -29,7 +29,7 @@ export const NEXT_URL_QUERY_STRING_PARAMETER = 'next'; * - Must contain only letters, numbers, spaces, punctuation and printable symbols. * - Must not contain leading or trailing spaces. */ -export const NAME_REGEX = /^(?! )[a-zA-Z0-9 !"#$%&'()*+,\-./\\:;<=>?@\[\]^_`{|}~]+(??@\[\]^_`{|}~]*[a-zA-Z0-9!"#$%&'()*+,\-./\\:;<=>?@\[\]^_`{|}~]$/; /** * Maximum length of usernames and role names. diff --git a/x-pack/plugins/security/public/management/users/edit_user/create_user_page.test.tsx b/x-pack/plugins/security/public/management/users/edit_user/create_user_page.test.tsx index e7e3e1164ae14f..99c67201b2b56d 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/create_user_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/create_user_page.test.tsx @@ -88,6 +88,12 @@ describe('CreateUserPage', () => { await findAllByText(/Username must not contain leading or trailing spaces/i); + fireEvent.change(await findByLabelText('Username'), { + target: { value: 'username_with_trailing_space ' }, + }); + + await findAllByText(/Username must not contain leading or trailing spaces/i); + fireEvent.change(await findByLabelText('Username'), { target: { value: '€' }, }); From cadcbf88452165a8edf7f8c5328dc74cd200d287 Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Wed, 27 Jan 2021 08:52:44 -0600 Subject: [PATCH 25/58] [Enterprise Search] Add links to doc links service (#89260) * [Enterprise Search] Add links to doc links service * Remove extra slash * Add types * Update API docs and API review --- .../kibana-plugin-core-public.doclinksstart.links.md | 5 +++++ .../public/kibana-plugin-core-public.doclinksstart.md | 2 +- src/core/public/doc_links/doc_links_service.ts | 10 ++++++++++ src/core/public/public.api.md | 5 +++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index ff2a8a2b5f75fe..79c603165cae46 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -30,6 +30,11 @@ readonly links: { readonly metricbeat: { readonly base: string; }; + readonly enterpriseSearch: { + readonly base: string; + readonly appSearchBase: string; + readonly workplaceSearchBase: string; + }; readonly heartbeat: { readonly base: string; }; diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index 8404326f773e6f..f4bce8b51ebb1a 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -17,5 +17,5 @@ export interface DocLinksStart | --- | --- | --- | | [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | | [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: string;
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
executeWatchActionModes: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
putComponentTemplateMetadata: string;
putWatch: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
} | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: string;
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
executeWatchActionModes: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
putComponentTemplateMetadata: string;
putWatch: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
} | | diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index b82254e5a14166..c732fc7823b628 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -46,6 +46,11 @@ export class DocLinksService { auditbeat: { base: `${ELASTIC_WEBSITE_URL}guide/en/beats/auditbeat/${DOC_LINK_VERSION}`, }, + enterpriseSearch: { + base: `${ELASTIC_WEBSITE_URL}guide/en/enterprise-search/${DOC_LINK_VERSION}`, + appSearchBase: `${ELASTIC_WEBSITE_URL}guide/en/app-search/${DOC_LINK_VERSION}`, + workplaceSearchBase: `${ELASTIC_WEBSITE_URL}guide/en/workplace-search/${DOC_LINK_VERSION}`, + }, metricbeat: { base: `${ELASTIC_WEBSITE_URL}guide/en/beats/metricbeat/${DOC_LINK_VERSION}`, }, @@ -260,6 +265,11 @@ export interface DocLinksStart { readonly metricbeat: { readonly base: string; }; + readonly enterpriseSearch: { + readonly base: string; + readonly appSearchBase: string; + readonly workplaceSearchBase: string; + }; readonly heartbeat: { readonly base: string; }; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 52fc8fbf339100..d72b2aa5afd1e7 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -483,6 +483,11 @@ export interface DocLinksStart { readonly metricbeat: { readonly base: string; }; + readonly enterpriseSearch: { + readonly base: string; + readonly appSearchBase: string; + readonly workplaceSearchBase: string; + }; readonly heartbeat: { readonly base: string; }; From d1b88afd3b0c15a65158f39992d2ff7d8e129e75 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Wed, 27 Jan 2021 17:01:02 +0200 Subject: [PATCH 26/58] Increase the time needed to locate the save viz toast (#89301) --- test/functional/page_objects/common_page.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts index 1149f1b1007886..ed817b8b55e809 100644 --- a/test/functional/page_objects/common_page.ts +++ b/test/functional/page_objects/common_page.ts @@ -376,7 +376,7 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo } async closeToast() { - const toast = await find.byCssSelector('.euiToast', 2 * defaultFindTimeout); + const toast = await find.byCssSelector('.euiToast', 6 * defaultFindTimeout); await toast.moveMouseTo(); const title = await (await find.byCssSelector('.euiToastHeader__title')).getVisibleText(); From 0abf45fcf1673a714c2b4fa894cf58fb9b24e265 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Wed, 27 Jan 2021 17:03:44 +0200 Subject: [PATCH 27/58] [Vega Docs] Add experimental flag on the vega maps title (#89402) * [Vega Docs] Add experimental flag on the vega maps title * Add the experimental warning on the initial paragraph of vega maps to be more visible --- docs/user/dashboard/vega-reference.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user/dashboard/vega-reference.asciidoc b/docs/user/dashboard/vega-reference.asciidoc index 99c5e62697cfd0..4a0598cc569cdc 100644 --- a/docs/user/dashboard/vega-reference.asciidoc +++ b/docs/user/dashboard/vega-reference.asciidoc @@ -237,7 +237,7 @@ format: {property: "features"} [[vega-with-a-map]] ==== Vega with a Map -To enable *Maps*, the graph must specify `type=map` in the host configuration: +experimental[] To enable *Maps*, the graph must specify `type=map` in the host configuration: [source,yaml] ---- @@ -335,7 +335,7 @@ Use the contextual *Inspect* tool to gain insights into different elements. [float] [[inspect-elasticsearch-requests]] -======= Inspect {es} requests +====== Inspect {es} requests *Vega* uses the {ref}/search-search.html[{es} search API] to get documents and aggregation results from {es}. To troubleshoot these requests, click *Inspect*, which shows the most recent requests. From da8d6b939a9a4780292cdc6cd243752e597b0846 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 27 Jan 2021 08:18:54 -0700 Subject: [PATCH 28/58] Migrate maps_legacy, maps_oss, region_map, and tile_map plugions to TS projects (#89351) --- src/plugins/maps_legacy/public/index.ts | 3 --- .../maps_legacy/public/map/color_util.d.ts | 11 ++++++++ .../public/map/kibana_map_layer.d.ts | 25 +++++++++++++++++++ .../maps_legacy/public/tooltip_provider.d.ts | 9 +++++++ src/plugins/maps_legacy/tsconfig.json | 14 +++++++++++ src/plugins/maps_oss/tsconfig.json | 14 +++++++++++ src/plugins/region_map/tsconfig.json | 15 +++++++++++ src/plugins/tile_map/tsconfig.json | 15 +++++++++++ tsconfig.json | 8 ++++++ tsconfig.refs.json | 4 +++ 10 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 src/plugins/maps_legacy/public/map/color_util.d.ts create mode 100644 src/plugins/maps_legacy/public/map/kibana_map_layer.d.ts create mode 100644 src/plugins/maps_legacy/public/tooltip_provider.d.ts create mode 100644 src/plugins/maps_legacy/tsconfig.json create mode 100644 src/plugins/maps_oss/tsconfig.json create mode 100644 src/plugins/region_map/tsconfig.json create mode 100644 src/plugins/tile_map/tsconfig.json diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts index 95550fab1ba179..9268f14995f446 100644 --- a/src/plugins/maps_legacy/public/index.ts +++ b/src/plugins/maps_legacy/public/index.ts @@ -8,9 +8,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { MapsLegacyPlugin } from './plugin'; -// @ts-ignore import * as colorUtil from './map/color_util'; -// @ts-ignore import { KibanaMapLayer } from './map/kibana_map_layer'; import { VectorLayer, @@ -19,7 +17,6 @@ import { TmsLayer, IServiceSettings, } from './map/service_settings_types'; -// @ts-ignore import { mapTooltipProvider } from './tooltip_provider'; import './map/index.scss'; diff --git a/src/plugins/maps_legacy/public/map/color_util.d.ts b/src/plugins/maps_legacy/public/map/color_util.d.ts new file mode 100644 index 00000000000000..9ec6b3c1fb0077 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/color_util.d.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +export function getLegendColors(colorRamp: unknown, numLegendColors?: number): string[]; + +export function getColor(colorRamp: unknown, i: number): string; diff --git a/src/plugins/maps_legacy/public/map/kibana_map_layer.d.ts b/src/plugins/maps_legacy/public/map/kibana_map_layer.d.ts new file mode 100644 index 00000000000000..222cb6b215f9ab --- /dev/null +++ b/src/plugins/maps_legacy/public/map/kibana_map_layer.d.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +export class KibanaMapLayer { + constructor(); + + getBounds(): Promise; + + addToLeafletMap(leafletMap: unknown): void; + + removeFromLeafletMap(leafletMap: unknown): void; + + appendLegendContents(): void; + + updateExtent(): void; + + movePointer(): void; + + getAttributions(): unknown; +} diff --git a/src/plugins/maps_legacy/public/tooltip_provider.d.ts b/src/plugins/maps_legacy/public/tooltip_provider.d.ts new file mode 100644 index 00000000000000..4082a6ef83c4da --- /dev/null +++ b/src/plugins/maps_legacy/public/tooltip_provider.d.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +export function mapTooltipProvider(element: unknown, formatter: unknown): () => unknown; diff --git a/src/plugins/maps_legacy/tsconfig.json b/src/plugins/maps_legacy/tsconfig.json new file mode 100644 index 00000000000000..e7ea06706b64f7 --- /dev/null +++ b/src/plugins/maps_legacy/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*", "server/**/*", "config.ts"], + "references": [ + { "path": "../vis_default_editor/tsconfig.json" }, + ] +} diff --git a/src/plugins/maps_oss/tsconfig.json b/src/plugins/maps_oss/tsconfig.json new file mode 100644 index 00000000000000..03c30c3c49fd36 --- /dev/null +++ b/src/plugins/maps_oss/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*", "server/**/*", "config.ts"], + "references": [ + { "path": "../visualizations/tsconfig.json" }, + ] +} diff --git a/src/plugins/region_map/tsconfig.json b/src/plugins/region_map/tsconfig.json new file mode 100644 index 00000000000000..40f76ece2a6ffb --- /dev/null +++ b/src/plugins/region_map/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["public/**/*", "server/**/*"], + "references": [ + { "path": "../maps_legacy/tsconfig.json" }, + { "path": "../vis_default_editor/tsconfig.json" }, + ] +} diff --git a/src/plugins/tile_map/tsconfig.json b/src/plugins/tile_map/tsconfig.json new file mode 100644 index 00000000000000..40f76ece2a6ffb --- /dev/null +++ b/src/plugins/tile_map/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["public/**/*", "server/**/*"], + "references": [ + { "path": "../maps_legacy/tsconfig.json" }, + { "path": "../vis_default_editor/tsconfig.json" }, + ] +} diff --git a/tsconfig.json b/tsconfig.json index e7856aa0c87470..334a3febfddda4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,8 +27,11 @@ "src/plugins/kibana_usage_collection/**/*", "src/plugins/kibana_utils/**/*", "src/plugins/management/**/*", + "src/plugins/maps_legacy/**/*", + "src/plugins/maps_oss/**/*", "src/plugins/navigation/**/*", "src/plugins/newsfeed/**/*", + "src/plugins/region_map/**/*", "src/plugins/saved_objects/**/*", "src/plugins/saved_objects_management/**/*", "src/plugins/saved_objects_tagging_oss/**/*", @@ -37,6 +40,7 @@ "src/plugins/spaces_oss/**/*", "src/plugins/telemetry/**/*", "src/plugins/telemetry_collection_manager/**/*", + "src/plugins/tile_map/**/*", "src/plugins/timelion/**/*", "src/plugins/ui_actions/**/*", "src/plugins/url_forwarding/**/*", @@ -81,8 +85,11 @@ { "path": "./src/plugins/kibana_usage_collection/tsconfig.json" }, { "path": "./src/plugins/kibana_utils/tsconfig.json" }, { "path": "./src/plugins/management/tsconfig.json" }, + { "path": "./src/plugins/maps_legacy/tsconfig.json" }, + { "path": "./src/plugins/maps_oss/tsconfig.json" }, { "path": "./src/plugins/navigation/tsconfig.json" }, { "path": "./src/plugins/newsfeed/tsconfig.json" }, + { "path": "./src/plugins/region_map/tsconfig.json" }, { "path": "./src/plugins/saved_objects/tsconfig.json" }, { "path": "./src/plugins/saved_objects_management/tsconfig.json" }, { "path": "./src/plugins/saved_objects_tagging_oss/tsconfig.json" }, @@ -91,6 +98,7 @@ { "path": "./src/plugins/spaces_oss/tsconfig.json" }, { "path": "./src/plugins/telemetry/tsconfig.json" }, { "path": "./src/plugins/telemetry_collection_manager/tsconfig.json" }, + { "path": "./src/plugins/tile_map/tsconfig.json" }, { "path": "./src/plugins/timelion/tsconfig.json" }, { "path": "./src/plugins/ui_actions/tsconfig.json" }, { "path": "./src/plugins/url_forwarding/tsconfig.json" }, diff --git a/tsconfig.refs.json b/tsconfig.refs.json index 5edfd4231a6d59..a8eecd278160c9 100644 --- a/tsconfig.refs.json +++ b/tsconfig.refs.json @@ -23,8 +23,11 @@ { "path": "./src/plugins/kibana_usage_collection/tsconfig.json" }, { "path": "./src/plugins/kibana_utils/tsconfig.json" }, { "path": "./src/plugins/management/tsconfig.json" }, + { "path": "./src/plugins/maps_legacy/tsconfig.json" }, + { "path": "./src/plugins/maps_oss/tsconfig.json" }, { "path": "./src/plugins/navigation/tsconfig.json" }, { "path": "./src/plugins/newsfeed/tsconfig.json" }, + { "path": "./src/plugins/region_map/tsconfig.json" }, { "path": "./src/plugins/saved_objects/tsconfig.json" }, { "path": "./src/plugins/saved_objects_management/tsconfig.json" }, { "path": "./src/plugins/saved_objects_tagging_oss/tsconfig.json" }, @@ -34,6 +37,7 @@ { "path": "./src/plugins/spaces_oss/tsconfig.json" }, { "path": "./src/plugins/telemetry/tsconfig.json" }, { "path": "./src/plugins/telemetry_collection_manager/tsconfig.json" }, + { "path": "./src/plugins/tile_map/tsconfig.json" }, { "path": "./src/plugins/timelion/tsconfig.json" }, { "path": "./src/plugins/ui_actions/tsconfig.json" }, { "path": "./src/plugins/url_forwarding/tsconfig.json" }, From 007e7e4506a9256c62446a8035ae22160e69f203 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 27 Jan 2021 10:22:36 -0500 Subject: [PATCH 29/58] [Upgrade Assistant] Migrate server to new es-js client (#89207) --- .../plugins/upgrade_assistant/common/types.ts | 19 +- .../components/tabs/checkup/constants.tsx | 3 +- .../components/tabs/checkup/controls.tsx | 3 +- .../checkup/deprecations/grouped.test.tsx | 4 +- .../tabs/checkup/deprecations/grouped.tsx | 4 +- .../tabs/checkup/deprecations/health.tsx | 3 +- .../tabs/checkup/deprecations/list.tsx | 4 +- .../tabs/checkup/filter_bar.test.tsx | 3 +- .../components/tabs/checkup/filter_bar.tsx | 3 +- .../lib/es_deprecation_logging_apis.test.ts | 14 +- .../server/lib/es_deprecation_logging_apis.ts | 12 +- .../server/lib/es_indices_state_check.ts | 13 +- .../server/lib/es_migration_apis.test.ts | 111 +++-- .../server/lib/es_migration_apis.ts | 24 +- .../server/lib/es_version_precheck.test.ts | 94 ++-- .../server/lib/es_version_precheck.ts | 22 +- .../lib/reindexing/reindex_actions.test.ts | 33 +- .../server/lib/reindexing/reindex_actions.ts | 13 +- .../lib/reindexing/reindex_service.test.ts | 418 ++++++++++-------- .../server/lib/reindexing/reindex_service.ts | 107 ++--- .../server/lib/reindexing/worker.ts | 13 +- .../lib/telemetry/usage_collector.test.ts | 20 +- .../server/lib/telemetry/usage_collector.ts | 17 +- .../server/routes/__mocks__/routes.mock.ts | 4 +- .../server/routes/cluster_checkup.test.ts | 2 +- .../server/routes/cluster_checkup.ts | 12 +- .../server/routes/deprecation_logging.test.ts | 24 +- .../server/routes/deprecation_logging.ts | 8 +- .../routes/reindex_indices/reindex_handler.ts | 6 +- .../routes/reindex_indices/reindex_indices.ts | 37 +- .../upgrade_assistant/upgrade_assistant.ts | 2 +- .../upgrade_assistant_integration/config.js | 2 - .../services/index.js | 7 - .../services/legacy_es.js | 18 - .../upgrade_assistant/reindexing.js | 22 +- 35 files changed, 570 insertions(+), 531 deletions(-) delete mode 100644 x-pack/test/upgrade_assistant_integration/services/index.js delete mode 100644 x-pack/test/upgrade_assistant_integration/services/legacy_es.js diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 2a94b39ca6c66b..9625ca89b11d0b 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -5,8 +5,6 @@ */ import { SavedObject, SavedObjectAttributes } from 'src/core/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationInfo } from '../../../../src/core/server/elasticsearch/legacy/api_types'; export enum ReindexStep { // Enum values are spaced out by 10 to give us room to insert steps in between. @@ -165,6 +163,23 @@ export interface UpgradeAssistantTelemetrySavedObjectAttributes { [key: string]: any; } +export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; +export interface DeprecationInfo { + level: MIGRATION_DEPRECATION_LEVEL; + message: string; + url: string; + details?: string; +} + +export interface IndexSettingsDeprecationInfo { + [indexName: string]: DeprecationInfo[]; +} +export interface DeprecationAPIResponse { + cluster_settings: DeprecationInfo[]; + ml_settings: DeprecationInfo[]; + node_settings: DeprecationInfo[]; + index_settings: IndexSettingsDeprecationInfo; +} export interface EnrichedDeprecationInfo extends DeprecationInfo { index?: string; node?: string; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/constants.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/constants.tsx index 66c802097055b6..8637099b77c9b4 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/constants.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/constants.tsx @@ -6,8 +6,7 @@ import { IconColor } from '@elastic/eui'; import { invert } from 'lodash'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationInfo } from '../../../../../../../../src/core/server/elasticsearch/legacy/api_types'; +import { DeprecationInfo } from '../../../../../common/types'; export const LEVEL_MAP: { [level: string]: number } = { warning: 0, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/controls.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/controls.tsx index d75a25a95d67f4..c75db7e2f96e14 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/controls.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/controls.tsx @@ -8,8 +8,7 @@ import React, { FunctionComponent, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButton, EuiFieldSearch, EuiFlexGroup, EuiFlexItem, EuiCallOut } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationInfo } from '../../../../../../../../src/core/server/elasticsearch/legacy/api_types'; +import { DeprecationInfo } from '../../../../../common/types'; import { GroupByOption, LevelFilterOption, LoadingState } from '../../types'; import { FilterBar } from './filter_bar'; import { GroupByBar } from './group_by_bar'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.test.tsx index 6bdb5df0362245..727d959f49a71a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.test.tsx @@ -9,9 +9,7 @@ import React from 'react'; import { mountWithIntl, shallowWithIntl } from '@kbn/test/jest'; import { EuiBadge, EuiPagination } from '@elastic/eui'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationInfo } from '../../../../../../../../../src/core/server/elasticsearch/legacy/api_types'; -import { EnrichedDeprecationInfo } from '../../../../../../common/types'; +import { DeprecationInfo, EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GroupByOption, LevelFilterOption } from '../../../types'; import { DeprecationAccordion, filterDeps, GroupedDeprecations } from './grouped'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.tsx index de1a5a996d75f3..20ffbae143672b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.tsx @@ -18,9 +18,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationInfo } from '../../../../../../../../../src/core/server/elasticsearch/legacy/api_types'; -import { EnrichedDeprecationInfo } from '../../../../../../common/types'; +import { DeprecationInfo, EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GroupByOption, LevelFilterOption } from '../../../types'; import { DeprecationCountSummary } from './count_summary'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/health.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/health.tsx index 3ce40d0c4fdf0b..c866c1e1f68470 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/health.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/health.tsx @@ -10,8 +10,7 @@ import React, { FunctionComponent } from 'react'; import { EuiBadge, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationInfo } from '../../../../../../../../../src/core/server/elasticsearch/legacy/api_types'; +import { DeprecationInfo } from '../../../../../../common/types'; import { COLOR_MAP, LEVEL_MAP, REVERSE_LEVEL_MAP } from '../constants'; const LocalizedLevels: { [level: string]: string } = { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.tsx index 038f05aace4c3b..afc443b8c3b7d9 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.tsx @@ -6,9 +6,7 @@ import React, { FunctionComponent } from 'react'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationInfo } from '../../../../../../../../../src/core/server/elasticsearch/legacy/api_types'; -import { EnrichedDeprecationInfo } from '../../../../../../common/types'; +import { DeprecationInfo, EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GroupByOption } from '../../../types'; import { COLOR_MAP, LEVEL_MAP } from '../constants'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.test.tsx index 053ef21d6b3092..231b15fc52d72b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.test.tsx @@ -6,9 +6,8 @@ import { mount, shallow } from 'enzyme'; import React from 'react'; +import { DeprecationInfo } from '../../../../../common/types'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationInfo } from '../../../../../../../../src/core/server/elasticsearch/legacy/api_types'; import { LevelFilterOption } from '../../types'; import { FilterBar } from './filter_bar'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.tsx index 6939c547fee571..abcd02d5a5ce41 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.tsx @@ -10,8 +10,7 @@ import React from 'react'; import { EuiFilterButton, EuiFilterGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationInfo } from '../../../../../../../../src/core/server/elasticsearch/legacy/api_types'; +import { DeprecationInfo } from '../../../../../common/types'; import { LevelFilterOption } from '../../types'; const LocalizedOptions: { [option: string]: string } = { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts index b0dec299b2b12c..dee05c97f11af4 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts @@ -12,10 +12,10 @@ import { describe('getDeprecationLoggingStatus', () => { it('calls cluster.getSettings', async () => { - const dataClient = elasticsearchServiceMock.createLegacyScopedClusterClient(); + const dataClient = elasticsearchServiceMock.createScopedClusterClient(); await getDeprecationLoggingStatus(dataClient); - expect(dataClient.callAsCurrentUser).toHaveBeenCalledWith('cluster.getSettings', { - includeDefaults: true, + expect(dataClient.asCurrentUser.cluster.getSettings).toHaveBeenCalledWith({ + include_defaults: true, }); }); }); @@ -23,9 +23,9 @@ describe('getDeprecationLoggingStatus', () => { describe('setDeprecationLogging', () => { describe('isEnabled = true', () => { it('calls cluster.putSettings with logger.deprecation = WARN', async () => { - const dataClient = elasticsearchServiceMock.createLegacyScopedClusterClient(); + const dataClient = elasticsearchServiceMock.createScopedClusterClient(); await setDeprecationLogging(dataClient, true); - expect(dataClient.callAsCurrentUser).toHaveBeenCalledWith('cluster.putSettings', { + expect(dataClient.asCurrentUser.cluster.putSettings).toHaveBeenCalledWith({ body: { transient: { 'logger.deprecation': 'WARN' } }, }); }); @@ -33,9 +33,9 @@ describe('setDeprecationLogging', () => { describe('isEnabled = false', () => { it('calls cluster.putSettings with logger.deprecation = ERROR', async () => { - const dataClient = elasticsearchServiceMock.createLegacyScopedClusterClient(); + const dataClient = elasticsearchServiceMock.createScopedClusterClient(); await setDeprecationLogging(dataClient, false); - expect(dataClient.callAsCurrentUser).toHaveBeenCalledWith('cluster.putSettings', { + expect(dataClient.asCurrentUser.cluster.putSettings).toHaveBeenCalledWith({ body: { transient: { 'logger.deprecation': 'ERROR' } }, }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts index 348eebb97e384b..c545d12ac1b823 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts @@ -4,17 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ import { get } from 'lodash'; -import { ILegacyScopedClusterClient } from 'src/core/server'; +import { IScopedClusterClient } from 'src/core/server'; interface DeprecationLoggingStatus { isEnabled: boolean; } export async function getDeprecationLoggingStatus( - dataClient: ILegacyScopedClusterClient + dataClient: IScopedClusterClient ): Promise { - const response = await dataClient.callAsCurrentUser('cluster.getSettings', { - includeDefaults: true, + const { body: response } = await dataClient.asCurrentUser.cluster.getSettings({ + include_defaults: true, }); return { @@ -23,10 +23,10 @@ export async function getDeprecationLoggingStatus( } export async function setDeprecationLogging( - dataClient: ILegacyScopedClusterClient, + dataClient: IScopedClusterClient, isEnabled: boolean ): Promise { - const response = await dataClient.callAsCurrentUser('cluster.putSettings', { + const { body: response } = await dataClient.asCurrentUser.cluster.putSettings({ body: { transient: { 'logger.deprecation': isEnabled ? 'WARN' : 'ERROR', diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_indices_state_check.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_indices_state_check.ts index bce48b152700f0..739499e2235b55 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_indices_state_check.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_indices_state_check.ts @@ -4,22 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LegacyAPICaller } from 'kibana/server'; +import { ElasticsearchClient } from 'kibana/server'; import { getIndexState } from '../../common/get_index_state'; import { ResolveIndexResponseFromES } from '../../common/types'; type StatusCheckResult = Record; export const esIndicesStateCheck = async ( - callAsUser: LegacyAPICaller, + asCurrentUser: ElasticsearchClient, indices: string[] ): Promise => { - const response: ResolveIndexResponseFromES = await callAsUser('transport.request', { - method: 'GET', - path: `/_resolve/index/*`, - query: { - expand_wildcards: 'all', - }, + const { body: response } = await asCurrentUser.indices.resolveIndex({ + name: '*', + expand_wildcards: 'all', }); const result: StatusCheckResult = {}; diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts index 312a7275382b87..6e8a729b4d3bb7 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts @@ -5,95 +5,94 @@ */ import _ from 'lodash'; +import { RequestEvent } from '@elastic/elasticsearch/lib/Transport'; import { elasticsearchServiceMock } from 'src/core/server/mocks'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationAPIResponse } from '../../../../../src/core/server/elasticsearch/legacy/api_types'; +import { DeprecationAPIResponse } from '../../common/types'; import { getUpgradeAssistantStatus } from './es_migration_apis'; import fakeDeprecations from './__fixtures__/fake_deprecations.json'; const fakeIndexNames = Object.keys(fakeDeprecations.index_settings); +const asApiResponse = (body: T): RequestEvent => + ({ + body, + } as RequestEvent); + describe('getUpgradeAssistantStatus', () => { const resolvedIndices = { indices: fakeIndexNames.map((f) => ({ name: f, attributes: ['open'] })), }; - let deprecationsResponse: DeprecationAPIResponse; - - const dataClient = elasticsearchServiceMock.createLegacyScopedClusterClient(); - (dataClient.callAsCurrentUser as jest.Mock).mockImplementation(async (api, { path }) => { - if (path === '/_migration/deprecations') { - return deprecationsResponse; - } else if (path === '/_resolve/index/*') { - return resolvedIndices; - } else if (api === 'indices.getMapping') { - return {}; - } else { - throw new Error(`Unexpected API call: ${path}`); - } - }); + // @ts-expect-error mock data is too loosely typed + const deprecationsResponse: DeprecationAPIResponse = _.cloneDeep(fakeDeprecations); - beforeEach(() => { - // @ts-expect-error mock data is too loosely typed - deprecationsResponse = _.cloneDeep(fakeDeprecations); - }); + const esClient = elasticsearchServiceMock.createScopedClusterClient(); + + esClient.asCurrentUser.migration.deprecations.mockResolvedValue( + asApiResponse(deprecationsResponse) + ); + + esClient.asCurrentUser.indices.resolveIndex.mockResolvedValue(asApiResponse(resolvedIndices)); it('calls /_migration/deprecations', async () => { - await getUpgradeAssistantStatus(dataClient, false); - expect(dataClient.callAsCurrentUser).toHaveBeenCalledWith('transport.request', { - path: '/_migration/deprecations', - method: 'GET', - }); + await getUpgradeAssistantStatus(esClient, false); + expect(esClient.asCurrentUser.migration.deprecations).toHaveBeenCalled(); }); it('returns the correct shape of data', async () => { - const resp = await getUpgradeAssistantStatus(dataClient, false); + const resp = await getUpgradeAssistantStatus(esClient, false); expect(resp).toMatchSnapshot(); }); it('returns readyForUpgrade === false when critical issues found', async () => { - deprecationsResponse = { - cluster_settings: [{ level: 'critical', message: 'Do count me', url: 'https://...' }], - node_settings: [], - ml_settings: [], - index_settings: {}, - }; - - await expect(getUpgradeAssistantStatus(dataClient, false)).resolves.toHaveProperty( + esClient.asCurrentUser.migration.deprecations.mockResolvedValue( + asApiResponse({ + cluster_settings: [{ level: 'critical', message: 'Do count me', url: 'https://...' }], + node_settings: [], + ml_settings: [], + index_settings: {}, + }) + ); + + await expect(getUpgradeAssistantStatus(esClient, false)).resolves.toHaveProperty( 'readyForUpgrade', false ); }); it('returns readyForUpgrade === true when no critical issues found', async () => { - deprecationsResponse = { - cluster_settings: [{ level: 'warning', message: 'Do not count me', url: 'https://...' }], - node_settings: [], - ml_settings: [], - index_settings: {}, - }; - - await expect(getUpgradeAssistantStatus(dataClient, false)).resolves.toHaveProperty( + esClient.asCurrentUser.migration.deprecations.mockResolvedValue( + asApiResponse({ + cluster_settings: [{ level: 'warning', message: 'Do not count me', url: 'https://...' }], + node_settings: [], + ml_settings: [], + index_settings: {}, + }) + ); + + await expect(getUpgradeAssistantStatus(esClient, false)).resolves.toHaveProperty( 'readyForUpgrade', true ); }); it('filters out security realm deprecation on Cloud', async () => { - deprecationsResponse = { - cluster_settings: [ - { - level: 'critical', - message: 'Security realm settings structure changed', - url: 'https://...', - }, - ], - node_settings: [], - ml_settings: [], - index_settings: {}, - }; - - const result = await getUpgradeAssistantStatus(dataClient, true); + esClient.asCurrentUser.migration.deprecations.mockResolvedValue( + asApiResponse({ + cluster_settings: [ + { + level: 'critical', + message: 'Security realm settings structure changed', + url: 'https://...', + }, + ], + node_settings: [], + ml_settings: [], + index_settings: {}, + }) + ); + + const result = await getUpgradeAssistantStatus(esClient, true); expect(result).toHaveProperty('readyForUpgrade', true); expect(result).toHaveProperty('cluster', []); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts index 9f55b9d0497356..22b9956fc957a4 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts @@ -4,21 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ILegacyScopedClusterClient } from 'src/core/server'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { DeprecationAPIResponse } from '../../../../../src/core/server/elasticsearch/legacy/api_types'; -import { EnrichedDeprecationInfo, UpgradeAssistantStatus } from '../../common/types'; +import { IScopedClusterClient } from 'src/core/server'; +import { + DeprecationAPIResponse, + EnrichedDeprecationInfo, + UpgradeAssistantStatus, +} from '../../common/types'; import { esIndicesStateCheck } from './es_indices_state_check'; export async function getUpgradeAssistantStatus( - dataClient: ILegacyScopedClusterClient, + dataClient: IScopedClusterClient, isCloudEnabled: boolean ): Promise { - const deprecations = await dataClient.callAsCurrentUser('transport.request', { - path: '/_migration/deprecations', - method: 'GET', - }); + const { + body: deprecations, + } = await dataClient.asCurrentUser.migration.deprecations(); const cluster = getClusterDeprecations(deprecations, isCloudEnabled); const indices = getCombinedIndexInfos(deprecations); @@ -28,10 +29,7 @@ export async function getUpgradeAssistantStatus( // If we have found deprecation information for index/indices check whether the index is // open or closed. if (indexNames.length) { - const indexStates = await esIndicesStateCheck( - dataClient.callAsCurrentUser.bind(dataClient), - indexNames - ); + const indexStates = await esIndicesStateCheck(dataClient.asCurrentUser, indexNames); indices.forEach((indexData) => { indexData.blockerForReindexing = diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts index 78f159ed988674..2310f993ce27d2 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts @@ -5,7 +5,7 @@ */ import { SemVer } from 'semver'; -import { ILegacyScopedClusterClient, kibanaResponseFactory } from 'src/core/server'; +import { IScopedClusterClient, kibanaResponseFactory } from 'src/core/server'; import { xpackMocks } from '../../../../mocks'; import { CURRENT_VERSION } from '../../common/version'; import { @@ -17,14 +17,20 @@ import { describe('getAllNodeVersions', () => { it('returns a list of unique node versions', async () => { const adminClient = ({ - callAsInternalUser: jest.fn().mockResolvedValue({ + asInternalUser: { nodes: { - node1: { version: '7.0.0' }, - node2: { version: '7.0.0' }, - node3: { version: '6.0.0' }, + info: jest.fn().mockResolvedValue({ + body: { + nodes: { + node1: { version: '7.0.0' }, + node2: { version: '7.0.0' }, + node3: { version: '6.0.0' }, + }, + }, + }), }, - }), - } as unknown) as ILegacyScopedClusterClient; + }, + } as unknown) as IScopedClusterClient; await expect(getAllNodeVersions(adminClient)).resolves.toEqual([ new SemVer('6.0.0'), @@ -73,12 +79,18 @@ describe('verifyAllMatchKibanaVersion', () => { describe('EsVersionPrecheck', () => { it('returns a 403 when callCluster fails with a 403', async () => { - const fakeCall = jest.fn().mockRejectedValue({ status: 403 }); + const fakeCall = jest.fn().mockRejectedValue({ statusCode: 403 }); const ctx = xpackMocks.createRequestHandlerContext(); - ctx.core.elasticsearch.legacy.client = { - callAsCurrentUser: jest.fn(), - callAsInternalUser: fakeCall, + ctx.core.elasticsearch.client = { + asInternalUser: { + ...ctx.core.elasticsearch.client.asInternalUser, + nodes: { + ...ctx.core.elasticsearch.client.asInternalUser.nodes, + info: fakeCall, + }, + }, + asCurrentUser: ctx.core.elasticsearch.client.asCurrentUser, }; const result = await esVersionCheck(ctx, kibanaResponseFactory); @@ -87,14 +99,22 @@ describe('EsVersionPrecheck', () => { it('returns a 426 message w/ allNodesUpgraded = false when nodes are not on same version', async () => { const ctx = xpackMocks.createRequestHandlerContext(); - ctx.core.elasticsearch.legacy.client = { - callAsCurrentUser: jest.fn(), - callAsInternalUser: jest.fn().mockResolvedValue({ + ctx.core.elasticsearch.client = { + asInternalUser: { + ...ctx.core.elasticsearch.client.asInternalUser, nodes: { - node1: { version: CURRENT_VERSION.raw }, - node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + ...ctx.core.elasticsearch.client.asInternalUser.nodes, + info: jest.fn().mockResolvedValue({ + body: { + nodes: { + node1: { version: CURRENT_VERSION.raw }, + node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + }, + }, + }), }, - }), + }, + asCurrentUser: ctx.core.elasticsearch.client.asCurrentUser, }; const result = await esVersionCheck(ctx, kibanaResponseFactory); @@ -104,14 +124,22 @@ describe('EsVersionPrecheck', () => { it('returns a 426 message w/ allNodesUpgraded = true when nodes are on next version', async () => { const ctx = xpackMocks.createRequestHandlerContext(); - ctx.core.elasticsearch.legacy.client = { - callAsCurrentUser: jest.fn(), - callAsInternalUser: jest.fn().mockResolvedValue({ + ctx.core.elasticsearch.client = { + asInternalUser: { + ...ctx.core.elasticsearch.client.asInternalUser, nodes: { - node1: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, - node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + ...ctx.core.elasticsearch.client.asInternalUser.nodes, + info: jest.fn().mockResolvedValue({ + body: { + nodes: { + node1: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + node2: { version: new SemVer(CURRENT_VERSION.raw).inc('major').raw }, + }, + }, + }), }, - }), + }, + asCurrentUser: ctx.core.elasticsearch.client.asCurrentUser, }; const result = await esVersionCheck(ctx, kibanaResponseFactory); @@ -121,14 +149,22 @@ describe('EsVersionPrecheck', () => { it('returns undefined when nodes are on same version', async () => { const ctx = xpackMocks.createRequestHandlerContext(); - ctx.core.elasticsearch.legacy.client = { - callAsCurrentUser: jest.fn(), - callAsInternalUser: jest.fn().mockResolvedValue({ + ctx.core.elasticsearch.client = { + asInternalUser: { + ...ctx.core.elasticsearch.client.asInternalUser, nodes: { - node1: { version: CURRENT_VERSION.raw }, - node2: { version: CURRENT_VERSION.raw }, + ...ctx.core.elasticsearch.client.asInternalUser.nodes, + info: jest.fn().mockResolvedValue({ + body: { + nodes: { + node1: { version: CURRENT_VERSION.raw }, + node2: { version: CURRENT_VERSION.raw }, + }, + }, + }), }, - }), + }, + asCurrentUser: ctx.core.elasticsearch.client.asCurrentUser, }; await expect(esVersionCheck(ctx, kibanaResponseFactory)).resolves.toBe(undefined); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts index 2b49d4c286f610..be6c4f5ff02308 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts @@ -7,7 +7,7 @@ import { uniq } from 'lodash'; import { SemVer } from 'semver'; import { - ILegacyScopedClusterClient, + IScopedClusterClient, KibanaRequest, KibanaResponseFactory, RequestHandler, @@ -15,14 +15,22 @@ import { } from 'src/core/server'; import { CURRENT_VERSION } from '../../common/version'; +interface Nodes { + nodes: { + [nodeId: string]: { version: string }; + }; +} + /** * Returns an array of all the unique Elasticsearch Node Versions in the Elasticsearch cluster. */ -export const getAllNodeVersions = async (adminClient: ILegacyScopedClusterClient) => { +export const getAllNodeVersions = async (adminClient: IScopedClusterClient) => { // Get the version information for all nodes in the cluster. - const { nodes } = (await adminClient.callAsInternalUser('nodes.info', { - filterPath: 'nodes.*.version', - })) as { nodes: { [nodeId: string]: { version: string } } }; + const response = await adminClient.asInternalUser.nodes.info({ + filter_path: 'nodes.*.version', + }); + + const nodes = response.body.nodes; const versionStrings = Object.values(nodes).map(({ version }) => version); @@ -62,13 +70,13 @@ export const esVersionCheck = async ( ctx: RequestHandlerContext, response: KibanaResponseFactory ) => { - const { client } = ctx.core.elasticsearch.legacy; + const { client } = ctx.core.elasticsearch; let allNodeVersions: SemVer[]; try { allNodeVersions = await getAllNodeVersions(client); } catch (e) { - if (e.status === 403) { + if (e.statusCode === 403) { return response.forbidden({ body: e.message }); } diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts index 525c3781be7495..d059c03bcecb11 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts @@ -3,7 +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 { SavedObjectsErrorHelpers } from '../../../../../../src/core/server'; +import { RequestEvent } from '@elastic/elasticsearch/lib/Transport'; +import { SavedObjectsErrorHelpers } from 'src/core/server'; +import { elasticsearchServiceMock } from 'src/core/server/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ScopedClusterClientMock } from 'src/core/server/elasticsearch/client/mocks'; import moment from 'moment'; import { @@ -18,7 +22,7 @@ import { LOCK_WINDOW, ReindexActions, reindexActionsFactory } from './reindex_ac describe('ReindexActions', () => { let client: jest.Mocked; - let callCluster: jest.Mock; + let clusterClient: ScopedClusterClientMock; let actions: ReindexActions; const unimplemented = (name: string) => () => @@ -38,8 +42,8 @@ describe('ReindexActions', () => { Promise.resolve({ id, attributes } as ReindexSavedObject) ) as any, }; - callCluster = jest.fn(); - actions = reindexActionsFactory(client, callCluster); + clusterClient = elasticsearchServiceMock.createScopedClusterClient(); + actions = reindexActionsFactory(client, clusterClient.asCurrentUser); }); describe('createReindexOp', () => { @@ -281,13 +285,20 @@ describe('ReindexActions', () => { }); describe('getFlatSettings', () => { + const asApiResponse = (body: T): RequestEvent => + ({ + body, + } as RequestEvent); + it('returns flat settings', async () => { - callCluster.mockResolvedValueOnce({ - myIndex: { - settings: { 'index.mySetting': '1' }, - mappings: {}, - }, - }); + clusterClient.asCurrentUser.indices.getSettings.mockResolvedValueOnce( + asApiResponse({ + myIndex: { + settings: { 'index.mySetting': '1' }, + mappings: {}, + }, + }) + ); await expect(actions.getFlatSettings('myIndex')).resolves.toEqual({ settings: { 'index.mySetting': '1' }, mappings: {}, @@ -295,7 +306,7 @@ describe('ReindexActions', () => { }); it('returns null if index does not exist', async () => { - callCluster.mockResolvedValueOnce({}); + clusterClient.asCurrentUser.indices.getSettings.mockResolvedValueOnce(asApiResponse({})); await expect(actions.getFlatSettings('myIndex')).resolves.toBeNull(); }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts index 6d8afee1ff9504..611ab3c92b72b0 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts @@ -9,7 +9,7 @@ import moment from 'moment'; import { SavedObjectsFindResponse, SavedObjectsClientContract, - LegacyAPICaller, + ElasticsearchClient, } from 'src/core/server'; import { IndexGroup, @@ -116,7 +116,7 @@ export interface ReindexActions { export const reindexActionsFactory = ( client: SavedObjectsClientContract, - callAsUser: LegacyAPICaller + esClient: ElasticsearchClient ): ReindexActions => { // ----- Internal functions const isLocked = (reindexOp: ReindexSavedObject) => { @@ -236,9 +236,12 @@ export const reindexActionsFactory = ( }, async getFlatSettings(indexName: string) { - const flatSettings = (await callAsUser('transport.request', { - path: `/${encodeURIComponent(indexName)}?flat_settings=true`, - })) as { [indexName: string]: FlatSettings }; + const { body: flatSettings } = await esClient.indices.getSettings<{ + [indexName: string]: FlatSettings; + }>({ + index: indexName, + flat_settings: true, + }); if (!flatSettings[indexName]) { return null; diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts index dea9974791a881..8a7033c1594da3 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts @@ -5,8 +5,11 @@ */ jest.mock('../es_indices_state_check', () => ({ esIndicesStateCheck: jest.fn() })); import { BehaviorSubject } from 'rxjs'; +import { RequestEvent } from '@elastic/elasticsearch/lib/Transport'; import { Logger } from 'src/core/server'; -import { loggingSystemMock } from 'src/core/server/mocks'; +import { elasticsearchServiceMock, loggingSystemMock } from 'src/core/server/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ScopedClusterClientMock } from 'src/core/server/elasticsearch/client/mocks'; import { IndexGroup, @@ -28,9 +31,14 @@ import { reindexServiceFactory, } from './reindex_service'; +const asApiResponse = (body: T): RequestEvent => + ({ + body, + } as RequestEvent); + describe('reindexService', () => { let actions: jest.Mocked; - let callCluster: jest.Mock; + let clusterClient: ScopedClusterClientMock; let log: Logger; let service: ReindexService; let licensingPluginSetup: LicensingPluginSetup; @@ -59,7 +67,7 @@ describe('reindexService', () => { decrementIndexGroupReindexes: jest.fn(unimplemented('decrementIndexGroupReindexes')), runWhileIndexGroupLocked: jest.fn(async (group: string, f: any) => f({ attributes: {} })), }; - callCluster = jest.fn(); + clusterClient = elasticsearchServiceMock.createScopedClusterClient(); log = loggingSystemMock.create().get(); licensingPluginSetup = licensingMock.createSetup(); licensingPluginSetup.license$ = new BehaviorSubject( @@ -68,7 +76,12 @@ describe('reindexService', () => { }) ); - service = reindexServiceFactory(callCluster as any, actions, log, licensingPluginSetup); + service = reindexServiceFactory( + clusterClient.asCurrentUser, + actions, + log, + licensingPluginSetup + ); }); describe('hasRequiredPrivileges', () => { @@ -83,13 +96,13 @@ describe('reindexService', () => { }); it('calls security API with basic requirements', async () => { - callCluster.mockResolvedValueOnce({ has_all_requested: true }); + clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( + asApiResponse({ has_all_requested: true }) + ); const hasRequired = await service.hasRequiredPrivileges('anIndex'); expect(hasRequired).toBe(true); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_security/user/_has_privileges', - method: 'POST', + expect(clusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({ body: { cluster: ['manage'], index: [ @@ -108,12 +121,12 @@ describe('reindexService', () => { }); it('includes manage_ml for ML indices', async () => { - callCluster.mockResolvedValueOnce({ has_all_requested: true }); + clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( + asApiResponse({ has_all_requested: true }) + ); await service.hasRequiredPrivileges('.ml-anomalies'); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_security/user/_has_privileges', - method: 'POST', + expect(clusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({ body: { cluster: ['manage', 'manage_ml'], index: [ @@ -132,15 +145,15 @@ describe('reindexService', () => { }); it('includes checking for permissions on the baseName which could be an alias', async () => { - callCluster.mockResolvedValueOnce({ has_all_requested: true }); + clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( + asApiResponse({ has_all_requested: true }) + ); const hasRequired = await service.hasRequiredPrivileges( `reindexed-v${PREV_MAJOR_VERSION}-anIndex` ); expect(hasRequired).toBe(true); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_security/user/_has_privileges', - method: 'POST', + expect(clusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({ body: { cluster: ['manage'], index: [ @@ -163,12 +176,14 @@ describe('reindexService', () => { }); it('includes manage_watcher for watcher indices', async () => { - callCluster.mockResolvedValueOnce({ has_all_requested: true }); + clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( + asApiResponse({ + has_all_requested: true, + }) + ); await service.hasRequiredPrivileges('.watches'); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_security/user/_has_privileges', - method: 'POST', + expect(clusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({ body: { cluster: ['manage', 'manage_watcher'], index: [ @@ -212,7 +227,7 @@ describe('reindexService', () => { describe('createReindexOperation', () => { it('creates new reindex operation', async () => { - callCluster.mockResolvedValueOnce(true); // indices.exist + clusterClient.asCurrentUser.indices.exists.mockResolvedValueOnce(asApiResponse(true)); actions.findReindexOperations.mockResolvedValueOnce({ total: 0 }); actions.createReindexOp.mockResolvedValueOnce(); @@ -222,13 +237,13 @@ describe('reindexService', () => { }); it('fails if index does not exist', async () => { - callCluster.mockResolvedValueOnce(false); // indices.exist + clusterClient.asCurrentUser.indices.exists.mockResolvedValueOnce(asApiResponse(false)); await expect(service.createReindexOperation('myIndex')).rejects.toThrow(); expect(actions.createReindexOp).not.toHaveBeenCalled(); }); it('deletes existing operation if it failed', async () => { - callCluster.mockResolvedValueOnce(true); // indices.exist + clusterClient.asCurrentUser.indices.exists.mockResolvedValueOnce(asApiResponse(true)); actions.findReindexOperations.mockResolvedValueOnce({ saved_objects: [{ id: 1, attributes: { status: ReindexStatus.failed } }], total: 1, @@ -244,7 +259,7 @@ describe('reindexService', () => { }); it('deletes existing operation if it was cancelled', async () => { - callCluster.mockResolvedValueOnce(true); // indices.exist + clusterClient.asCurrentUser.indices.exists.mockResolvedValueOnce(asApiResponse(true)); actions.findReindexOperations.mockResolvedValueOnce({ saved_objects: [{ id: 1, attributes: { status: ReindexStatus.cancelled } }], total: 1, @@ -260,7 +275,7 @@ describe('reindexService', () => { }); it('fails if existing operation did not fail', async () => { - callCluster.mockResolvedValueOnce(true); // indices.exist + clusterClient.asCurrentUser.indices.exists.mockResolvedValueOnce(asApiResponse(true)); actions.findReindexOperations.mockResolvedValueOnce({ saved_objects: [{ id: 1, attributes: { status: ReindexStatus.inProgress } }], total: 1, @@ -418,10 +433,11 @@ describe('reindexService', () => { reindexTaskId: '999333', }, } as any); - callCluster.mockResolvedValueOnce(true); + + clusterClient.asCurrentUser.tasks.cancel.mockResolvedValueOnce(asApiResponse(true)); await service.cancelReindexing('myIndex'); - expect(callCluster).toHaveBeenCalledWith('tasks.cancel', { taskId: '999333' }); + expect(clusterClient.asCurrentUser.tasks.cancel).toHaveBeenCalledWith({ task_id: '999333' }); findSpy.mockRestore(); }); @@ -433,7 +449,11 @@ describe('reindexService', () => { const findSpy = jest.spyOn(service, 'findReindexOperation').mockResolvedValueOnce(reindexOp); await expect(service.cancelReindexing('myIndex')).rejects.toThrow(); - expect(callCluster).not.toHaveBeenCalledWith('tasks.cancel', { taskId: '999333' }); + expect(clusterClient.asCurrentUser.tasks.cancel).not.toHaveBeenCalledWith( + asApiResponse({ + taskId: '999333', + }) + ); findSpy.mockRestore(); }); @@ -450,7 +470,11 @@ describe('reindexService', () => { const findSpy = jest.spyOn(service, 'findReindexOperation').mockResolvedValueOnce(reindexOp); await expect(service.cancelReindexing('myIndex')).rejects.toThrow(); - expect(callCluster).not.toHaveBeenCalledWith('tasks.cancel', { taskId: '999333' }); + expect(clusterClient.asCurrentUser.tasks.cancel).not.toHaveBeenCalledWith( + asApiResponse({ + taskId: '999333', + }) + ); findSpy.mockRestore(); }); @@ -525,7 +549,7 @@ describe('reindexService', () => { ); expect(actions.incrementIndexGroupReindexes).not.toHaveBeenCalled(); expect(actions.runWhileIndexGroupLocked).not.toHaveBeenCalled(); - expect(callCluster).not.toHaveBeenCalled(); + expect(clusterClient.asCurrentUser.nodes.info).not.toHaveBeenCalled(); }); it('supports an already migrated ML index', async () => { @@ -533,11 +557,12 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f() ); - callCluster - // Mock call to /_nodes for version check - .mockResolvedValueOnce({ nodes: { nodeX: { version: '6.7.0-alpha' } } }) - // Mock call to /_ml/set_upgrade_mode?enabled=true - .mockResolvedValueOnce({ acknowledged: true }); + clusterClient.asCurrentUser.nodes.info.mockResolvedValueOnce( + asApiResponse({ nodes: { nodeX: { version: '6.7.0-alpha' } } }) + ); + clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); const mlReindexedOp = { id: '2', @@ -550,9 +575,8 @@ describe('reindexService', () => { ); expect(actions.incrementIndexGroupReindexes).toHaveBeenCalled(); expect(actions.runWhileIndexGroupLocked).toHaveBeenCalled(); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=true', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ + enabled: true, }); }); @@ -561,11 +585,13 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f() ); - callCluster - // Mock call to /_nodes for version check - .mockResolvedValueOnce({ nodes: { nodeX: { version: '6.7.0-alpha' } } }) - // Mock call to /_ml/set_upgrade_mode?enabled=true - .mockResolvedValueOnce({ acknowledged: true }); + + clusterClient.asCurrentUser.nodes.info.mockResolvedValueOnce( + asApiResponse({ nodes: { nodeX: { version: '6.7.0-alpha' } } }) + ); + clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); const updatedOp = await service.processNextStep(mlReindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual( @@ -573,9 +599,8 @@ describe('reindexService', () => { ); expect(actions.incrementIndexGroupReindexes).toHaveBeenCalled(); expect(actions.runWhileIndexGroupLocked).toHaveBeenCalled(); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=true', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ + enabled: true, }); }); @@ -587,9 +612,8 @@ describe('reindexService', () => { expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=true', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ + enabled: true, }); }); @@ -602,9 +626,8 @@ describe('reindexService', () => { expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=true', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ + enabled: true, }); }); @@ -613,11 +636,12 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f() ); - callCluster - // Mock call to /_nodes for version check - .mockResolvedValueOnce({ nodes: { nodeX: { version: '6.7.0' } } }) - // Mock call to /_ml/set_upgrade_mode?enabled=true - .mockResolvedValueOnce({ acknowledged: false }); + clusterClient.asCurrentUser.nodes.info.mockResolvedValueOnce( + asApiResponse({ nodes: { nodeX: { version: '6.7.0' } } }) + ); + clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( + asApiResponse({ acknowledged: false }) + ); const updatedOp = await service.processNextStep(mlReindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); @@ -626,9 +650,8 @@ describe('reindexService', () => { updatedOp.attributes.errorMessage!.includes('Could not stop ML jobs') ).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=true', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ + enabled: true, }); }); @@ -637,9 +660,9 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f() ); - callCluster - // Mock call to /_nodes for version check - .mockResolvedValueOnce({ nodes: { nodeX: { version: '6.6.0' } } }); + clusterClient.asCurrentUser.nodes.info.mockResolvedValueOnce( + asApiResponse({ nodes: { nodeX: { version: '6.6.0' } } }) + ); const updatedOp = await service.processNextStep(mlReindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); @@ -649,9 +672,8 @@ describe('reindexService', () => { ).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); // Should not have called ML endpoint at all - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=true', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ + enabled: true, }); }); }); @@ -669,7 +691,7 @@ describe('reindexService', () => { ); expect(actions.incrementIndexGroupReindexes).not.toHaveBeenCalled(); expect(actions.runWhileIndexGroupLocked).not.toHaveBeenCalled(); - expect(callCluster).not.toHaveBeenCalled(); + expect(clusterClient.asCurrentUser.watcher.stop).not.toHaveBeenCalled(); }); it('increments ML reindexes and calls watcher stop endpoint', async () => { @@ -677,9 +699,9 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (type: string, f: any) => f() ); - callCluster - // Mock call to /_watcher/_stop - .mockResolvedValueOnce({ acknowledged: true }); + clusterClient.asCurrentUser.watcher.stop.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); const updatedOp = await service.processNextStep(watcherReindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual( @@ -687,10 +709,7 @@ describe('reindexService', () => { ); expect(actions.incrementIndexGroupReindexes).toHaveBeenCalledWith(IndexGroup.watcher); expect(actions.runWhileIndexGroupLocked).toHaveBeenCalled(); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_watcher/_stop', - method: 'POST', - }); + expect(clusterClient.asCurrentUser.watcher.stop).toHaveBeenCalled(); }); it('fails if watcher reindexes cannot be incremented', async () => { @@ -701,9 +720,8 @@ describe('reindexService', () => { expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_watcher/_stop', - method: 'POST', + expect(clusterClient.asCurrentUser.watcher.stop).not.toHaveBeenCalledWith({ + enabled: true, }); }); @@ -716,10 +734,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_watcher/_stop', - method: 'POST', - }); + expect(clusterClient.asCurrentUser.watcher.stop).not.toHaveBeenCalled(); }); it('fails if watcher endpoint fails', async () => { @@ -727,9 +742,9 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (type: string, f: any) => f() ); - callCluster - // Mock call to /_watcher/_stop - .mockResolvedValueOnce({ acknowledged: false }); + clusterClient.asCurrentUser.watcher.stop.mockResolvedValueOnce( + asApiResponse({ acknowledged: false }) + ); const updatedOp = await service.processNextStep(watcherReindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); @@ -738,10 +753,7 @@ describe('reindexService', () => { updatedOp.attributes.errorMessage!.includes('Could not stop Watcher') ).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_watcher/_stop', - method: 'POST', - }); + expect(clusterClient.asCurrentUser.watcher.stop).toHaveBeenCalled(); }); }); }); @@ -756,17 +768,21 @@ describe('reindexService', () => { } as ReindexSavedObject; it('blocks writes and updates lastCompletedStep', async () => { - callCluster.mockResolvedValueOnce({ acknowledged: true }); + clusterClient.asCurrentUser.indices.putSettings.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.readonly); - expect(callCluster).toHaveBeenCalledWith('indices.putSettings', { + expect(clusterClient.asCurrentUser.indices.putSettings).toHaveBeenCalledWith({ index: 'myIndex', body: { 'index.blocks.write': true }, }); }); it('fails if setting updates are not acknowledged', async () => { - callCluster.mockResolvedValueOnce({ acknowledged: false }); + clusterClient.asCurrentUser.indices.putSettings.mockResolvedValueOnce( + asApiResponse({ acknowledged: false }) + ); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual( ReindexStep.indexGroupServicesStopped @@ -777,7 +793,7 @@ describe('reindexService', () => { }); it('fails if setting updates fail', async () => { - callCluster.mockRejectedValueOnce(new Error('blah!')); + clusterClient.asCurrentUser.indices.putSettings.mockRejectedValueOnce(new Error('blah!')); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual( ReindexStep.indexGroupServicesStopped @@ -797,11 +813,12 @@ describe('reindexService', () => { // The more intricate details of how the settings are chosen are test separately. it('creates new index with settings and mappings and updates lastCompletedStep', async () => { actions.getFlatSettings.mockResolvedValueOnce(settingsMappings); - callCluster.mockResolvedValueOnce({ acknowledged: true }); // indices.create - + clusterClient.asCurrentUser.indices.create.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.newIndexCreated); - expect(callCluster).toHaveBeenCalledWith('indices.create', { + expect(clusterClient.asCurrentUser.indices.create).toHaveBeenCalledWith({ index: 'myIndex-reindex-0', body: { // index.blocks.write should be removed from the settings for the new index. @@ -812,9 +829,13 @@ describe('reindexService', () => { }); it('fails if create index is not acknowledged', async () => { - callCluster - .mockResolvedValueOnce({ myIndex: settingsMappings }) - .mockResolvedValueOnce({ acknowledged: false }); + clusterClient.asCurrentUser.indices.getSettings.mockResolvedValueOnce( + asApiResponse({ myIndex: settingsMappings }) + ); + + clusterClient.asCurrentUser.indices.create.mockResolvedValueOnce( + asApiResponse({ acknowledged: false }) + ); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.readonly); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); @@ -823,10 +844,16 @@ describe('reindexService', () => { }); it('fails if create index fails', async () => { - callCluster - .mockResolvedValueOnce({ myIndex: settingsMappings }) - .mockRejectedValueOnce(new Error(`blah!`)) - .mockResolvedValueOnce({ acknowledged: true }); + clusterClient.asCurrentUser.indices.getSettings.mockResolvedValueOnce( + asApiResponse({ myIndex: settingsMappings }) + ); + + clusterClient.asCurrentUser.indices.create.mockRejectedValueOnce(new Error(`blah!`)); + + clusterClient.asCurrentUser.indices.putSettings.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); + const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.readonly); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); @@ -834,7 +861,7 @@ describe('reindexService', () => { expect(log.error).toHaveBeenCalledWith(expect.any(String)); // Original index should have been set back to allow reads. - expect(callCluster).toHaveBeenCalledWith('indices.putSettings', { + expect(clusterClient.asCurrentUser.indices.putSettings).toHaveBeenCalledWith({ index: 'myIndex', body: { 'index.blocks.write': false }, }); @@ -858,14 +885,14 @@ describe('reindexService', () => { }); it('starts reindex, saves taskId, and updates lastCompletedStep', async () => { - callCluster.mockResolvedValueOnce({ task: 'xyz' }); // reindex + clusterClient.asCurrentUser.reindex.mockResolvedValueOnce(asApiResponse({ task: 'xyz' })); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexStarted); expect(updatedOp.attributes.reindexTaskId).toEqual('xyz'); expect(updatedOp.attributes.reindexTaskPercComplete).toEqual(0); - expect(callCluster).toHaveBeenLastCalledWith('reindex', { + expect(clusterClient.asCurrentUser.reindex).toHaveBeenLastCalledWith({ refresh: true, - waitForCompletion: false, + wait_for_completion: false, body: { source: { index: 'myIndex' }, dest: { index: 'myIndex-reindex-0' }, @@ -874,7 +901,7 @@ describe('reindexService', () => { }); it('fails if starting reindex fails', async () => { - callCluster.mockRejectedValueOnce(new Error('blah!')).mockResolvedValueOnce({}); + clusterClient.asCurrentUser.reindex.mockRejectedValueOnce(new Error('blah!')); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.newIndexCreated); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); @@ -895,10 +922,13 @@ describe('reindexService', () => { describe('reindex task is not complete', () => { it('updates reindexTaskPercComplete', async () => { - callCluster.mockResolvedValueOnce({ - completed: false, - task: { status: { created: 10, total: 100 } }, - }); + clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( + asApiResponse({ + completed: false, + task: { status: { created: 10, total: 100 } }, + }) + ); + const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexStarted); expect(updatedOp.attributes.reindexTaskPercComplete).toEqual(0.1); // 10 / 100 = 0.1 @@ -907,30 +937,47 @@ describe('reindexService', () => { describe('reindex task is complete', () => { it('deletes task, updates reindexTaskPercComplete, updates lastCompletedStep', async () => { - callCluster - .mockResolvedValueOnce({ + clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( + asApiResponse({ completed: true, task: { status: { created: 100, total: 100 } }, }) - .mockResolvedValueOnce({ count: 100 }) - .mockResolvedValueOnce({ result: 'deleted' }); + ); + + clusterClient.asCurrentUser.count.mockResolvedValueOnce( + asApiResponse({ + count: 100, + }) + ); + + clusterClient.asCurrentUser.delete.mockResolvedValueOnce( + asApiResponse({ + result: 'deleted', + }) + ); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexCompleted); expect(updatedOp.attributes.reindexTaskPercComplete).toEqual(1); - expect(callCluster).toHaveBeenCalledWith('delete', { + expect(clusterClient.asCurrentUser.delete).toHaveBeenCalledWith({ index: '.tasks', id: 'xyz', }); }); it('fails if docs created is less than count in source index', async () => { - callCluster - .mockResolvedValueOnce({ + clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( + asApiResponse({ completed: true, task: { status: { created: 95, total: 95 } }, }) - .mockReturnValueOnce({ count: 100 }); + ); + + clusterClient.asCurrentUser.count.mockResolvedValueOnce( + asApiResponse({ + count: 100, + }) + ); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexStarted); @@ -941,18 +988,22 @@ describe('reindexService', () => { }); describe('reindex task is cancelled', () => { - it('deletes tsk, updates status to cancelled', async () => { - callCluster - .mockResolvedValueOnce({ + it('deletes task, updates status to cancelled', async () => { + clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( + asApiResponse({ completed: true, task: { status: { created: 100, total: 100, canceled: 'by user request' } }, }) - .mockResolvedValue({ result: 'deleted' }); + ); + + clusterClient.asCurrentUser.delete.mockResolvedValue( + asApiResponse({ result: 'deleted' }) + ); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexStarted); expect(updatedOp.attributes.status).toEqual(ReindexStatus.cancelled); - expect(callCluster).toHaveBeenCalledWith('delete', { + expect(clusterClient.asCurrentUser.delete).toHaveBeenLastCalledWith({ index: '.tasks', id: 'xyz', }); @@ -971,12 +1022,16 @@ describe('reindexService', () => { } as ReindexSavedObject; it('switches aliases, sets as complete, and updates lastCompletedStep', async () => { - callCluster - .mockResolvedValueOnce({ myIndex: { aliases: {} } }) - .mockResolvedValueOnce({ acknowledged: true }); + clusterClient.asCurrentUser.indices.getAlias.mockResolvedValue( + asApiResponse({ myIndex: { aliases: {} } }) + ); + + clusterClient.asCurrentUser.indices.updateAliases.mockResolvedValue( + asApiResponse({ acknowledged: true }) + ); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); - expect(callCluster).toHaveBeenCalledWith('indices.updateAliases', { + expect(clusterClient.asCurrentUser.indices.updateAliases).toHaveBeenCalledWith({ body: { actions: [ { add: { index: 'myIndex-reindex-0', alias: 'myIndex' } }, @@ -987,8 +1042,8 @@ describe('reindexService', () => { }); it('moves existing aliases over to new index', async () => { - callCluster - .mockResolvedValueOnce({ + clusterClient.asCurrentUser.indices.getAlias.mockResolvedValue( + asApiResponse({ myIndex: { aliases: { myAlias: {}, @@ -996,10 +1051,15 @@ describe('reindexService', () => { }, }, }) - .mockResolvedValueOnce({ acknowledged: true }); + ); + + clusterClient.asCurrentUser.indices.updateAliases.mockResolvedValue( + asApiResponse({ acknowledged: true }) + ); + const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); - expect(callCluster).toHaveBeenCalledWith('indices.updateAliases', { + expect(clusterClient.asCurrentUser.indices.updateAliases).toHaveBeenCalledWith({ body: { actions: [ { add: { index: 'myIndex-reindex-0', alias: 'myIndex' } }, @@ -1018,7 +1078,9 @@ describe('reindexService', () => { }); it('fails if switching aliases is not acknowledged', async () => { - callCluster.mockResolvedValueOnce({ acknowledged: false }); + clusterClient.asCurrentUser.indices.updateAliases.mockResolvedValue( + asApiResponse({ acknowledged: false }) + ); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexCompleted); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); @@ -1027,7 +1089,7 @@ describe('reindexService', () => { }); it('fails if switching aliases fails', async () => { - callCluster.mockRejectedValueOnce(new Error('blah!')); + clusterClient.asCurrentUser.indices.updateAliases.mockRejectedValueOnce(new Error('blah!')); const updatedOp = await service.processNextStep(reindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexCompleted); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); @@ -1053,7 +1115,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual( ReindexStep.indexGroupServicesStarted ); - expect(callCluster).not.toHaveBeenCalled(); + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalled(); }); it('decrements ML reindexes and calls ML start endpoint if no remaining ML jobs', async () => { @@ -1061,17 +1123,17 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f({ attributes: { runningReindexCount: 0 } }) ); - // Mock call to /_ml/set_upgrade_mode?enabled=false - callCluster.mockResolvedValueOnce({ acknowledged: true }); + clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); const updatedOp = await service.processNextStep(mlReindexOp); expect(actions.decrementIndexGroupReindexes).toHaveBeenCalledWith(IndexGroup.ml); expect(updatedOp.attributes.lastCompletedStep).toEqual( ReindexStep.indexGroupServicesStarted ); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=false', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ + enabled: false, }); }); @@ -1080,16 +1142,16 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f({ attributes: { runningReindexCount: 2 } }) ); - // Mock call to /_ml/set_upgrade_mode?enabled=false - callCluster.mockResolvedValueOnce({ acknowledged: true }); + clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); const updatedOp = await service.processNextStep(mlReindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual( ReindexStep.indexGroupServicesStarted ); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=false', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ + enabled: false, }); }); @@ -1102,9 +1164,8 @@ describe('reindexService', () => { expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=false', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ + enabled: false, }); }); @@ -1118,9 +1179,8 @@ describe('reindexService', () => { expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=false', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ + enabled: false, }); }); @@ -1129,9 +1189,9 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f({ attributes: { runningReindexCount: 0 } }) ); - // Mock call to /_ml/set_upgrade_mode?enabled=true - callCluster.mockResolvedValueOnce({ acknowledged: false }); - + clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( + asApiResponse({ acknowledged: false }) + ); const updatedOp = await service.processNextStep(mlReindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); @@ -1139,9 +1199,8 @@ describe('reindexService', () => { updatedOp.attributes.errorMessage!.includes('Could not resume ML jobs') ).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=false', - method: 'POST', + expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ + enabled: false, }); }); }); @@ -1157,7 +1216,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual( ReindexStep.indexGroupServicesStarted ); - expect(callCluster).not.toHaveBeenCalled(); + expect(clusterClient.asCurrentUser.watcher.start).not.toHaveBeenCalled(); }); it('decrements watcher reindexes and calls wathcer start endpoint if no remaining watcher reindexes', async () => { @@ -1165,36 +1224,31 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f({ attributes: { runningReindexCount: 0 } }) ); - // Mock call to /_watcher/_start - callCluster.mockResolvedValueOnce({ acknowledged: true }); + clusterClient.asCurrentUser.watcher.start.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); const updatedOp = await service.processNextStep(watcherReindexOp); expect(actions.decrementIndexGroupReindexes).toHaveBeenCalledWith(IndexGroup.watcher); expect(updatedOp.attributes.lastCompletedStep).toEqual( ReindexStep.indexGroupServicesStarted ); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_watcher/_start', - method: 'POST', - }); + expect(clusterClient.asCurrentUser.watcher.start).toHaveBeenCalled(); }); - it('does not call wathcer start endpoint if there are remaining wathcer reindexes', async () => { + it('does not call watcher start endpoint if there are remaining watcher reindexes', async () => { actions.decrementIndexGroupReindexes.mockResolvedValue(); actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f({ attributes: { runningReindexCount: 2 } }) ); - // Mock call to /_watcher/_start - callCluster.mockResolvedValueOnce({ acknowledged: true }); - + clusterClient.asCurrentUser.watcher.start.mockResolvedValueOnce( + asApiResponse({ acknowledged: true }) + ); const updatedOp = await service.processNextStep(watcherReindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual( ReindexStep.indexGroupServicesStarted ); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_watcher/_start', - method: 'POST', - }); + expect(clusterClient.asCurrentUser.watcher.start).not.toHaveBeenCalledWith(); }); it('fails if watcher reindexes cannot be decremented', async () => { @@ -1206,10 +1260,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_watcher/_start', - method: 'POST', - }); + expect(clusterClient.asCurrentUser.watcher.start).not.toHaveBeenCalledWith(); }); it('fails if watcher doc cannot be locked', async () => { @@ -1222,10 +1273,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).not.toHaveBeenCalledWith('transport.request', { - path: '/_watcher/_start', - method: 'POST', - }); + expect(clusterClient.asCurrentUser.watcher.start).not.toHaveBeenCalledWith(); }); it('fails if watcher endpoint fails', async () => { @@ -1233,9 +1281,10 @@ describe('reindexService', () => { actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => f({ attributes: { runningReindexCount: 0 } }) ); - // Mock call to /_watcher/_start - callCluster.mockResolvedValueOnce({ acknowledged: false }); + clusterClient.asCurrentUser.watcher.start.mockResolvedValueOnce( + asApiResponse({ acknowledged: false }) + ); const updatedOp = await service.processNextStep(watcherReindexOp); expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); @@ -1243,10 +1292,7 @@ describe('reindexService', () => { updatedOp.attributes.errorMessage!.includes('Could not start Watcher') ).toBeTruthy(); expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_watcher/_start', - method: 'POST', - }); + expect(clusterClient.asCurrentUser.watcher.start).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts index e784f42867d572..f59dc66f406128 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts @@ -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 { LegacyAPICaller, Logger } from 'src/core/server'; +import { ElasticsearchClient, Logger } from 'src/core/server'; import { first } from 'rxjs/operators'; import { LicensingPluginSetup } from '../../../../licensing/server'; @@ -127,7 +127,7 @@ export interface ReindexService { } export const reindexServiceFactory = ( - callAsUser: LegacyAPICaller, + esClient: ElasticsearchClient, actions: ReindexActions, log: Logger, licensing: LicensingPluginSetup @@ -144,12 +144,11 @@ export const reindexServiceFactory = ( await actions.runWhileIndexGroupLocked(IndexGroup.ml, async (mlDoc) => { await validateNodesMinimumVersion(6, 7); - const res = await callAsUser('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=true', - method: 'POST', + const { body } = await esClient.ml.setUpgradeMode({ + enabled: true, }); - if (!res.acknowledged) { + if (!body.acknowledged) { throw new Error(`Could not stop ML jobs`); } @@ -164,12 +163,11 @@ export const reindexServiceFactory = ( await actions.decrementIndexGroupReindexes(IndexGroup.ml); await actions.runWhileIndexGroupLocked(IndexGroup.ml, async (mlDoc) => { if (mlDoc.attributes.runningReindexCount === 0) { - const res = await callAsUser('transport.request', { - path: '/_ml/set_upgrade_mode?enabled=false', - method: 'POST', + const { body } = await esClient.ml.setUpgradeMode({ + enabled: false, }); - if (!res.acknowledged) { + if (!body.acknowledged) { throw new Error(`Could not resume ML jobs`); } } @@ -184,12 +182,9 @@ export const reindexServiceFactory = ( const stopWatcher = async () => { await actions.incrementIndexGroupReindexes(IndexGroup.watcher); await actions.runWhileIndexGroupLocked(IndexGroup.watcher, async (watcherDoc) => { - const { acknowledged } = await callAsUser('transport.request', { - path: '/_watcher/_stop', - method: 'POST', - }); + const { body } = await esClient.watcher.stop(); - if (!acknowledged) { + if (!body.acknowledged) { throw new Error('Could not stop Watcher'); } @@ -204,12 +199,9 @@ export const reindexServiceFactory = ( await actions.decrementIndexGroupReindexes(IndexGroup.watcher); await actions.runWhileIndexGroupLocked(IndexGroup.watcher, async (watcherDoc) => { if (watcherDoc.attributes.runningReindexCount === 0) { - const { acknowledged } = await callAsUser('transport.request', { - path: '/_watcher/_start', - method: 'POST', - }); + const { body } = await esClient.watcher.start(); - if (!acknowledged) { + if (!body.acknowledged) { throw new Error('Could not start Watcher'); } } @@ -221,14 +213,16 @@ export const reindexServiceFactory = ( const cleanupChanges = async (reindexOp: ReindexSavedObject) => { // Cancel reindex task if it was started but not completed if (reindexOp.attributes.lastCompletedStep === ReindexStep.reindexStarted) { - await callAsUser('tasks.cancel', { - taskId: reindexOp.attributes.reindexTaskId, - }).catch((e) => undefined); // Ignore any exceptions trying to cancel (it may have already completed). + await esClient.tasks + .cancel({ + task_id: reindexOp.attributes.reindexTaskId ?? undefined, + }) + .catch((e) => undefined); // Ignore any exceptions trying to cancel (it may have already completed). } // Set index back to writable if we ever got past this point. if (reindexOp.attributes.lastCompletedStep >= ReindexStep.readonly) { - await callAsUser('indices.putSettings', { + await esClient.indices.putSettings({ index: reindexOp.attributes.indexName, body: { 'index.blocks.write': false }, }); @@ -238,7 +232,9 @@ export const reindexServiceFactory = ( reindexOp.attributes.lastCompletedStep >= ReindexStep.newIndexCreated && reindexOp.attributes.lastCompletedStep < ReindexStep.aliasCreated ) { - await callAsUser('indices.delete', { index: reindexOp.attributes.newIndexName }); + await esClient.indices.delete({ + index: reindexOp.attributes.newIndexName, + }); } // Resume consumers if we ever got past this point. @@ -252,10 +248,7 @@ export const reindexServiceFactory = ( // ------ Functions used to process the state machine const validateNodesMinimumVersion = async (minMajor: number, minMinor: number) => { - const nodesResponse = await callAsUser('transport.request', { - path: '/_nodes', - method: 'GET', - }); + const { body: nodesResponse } = await esClient.nodes.info(); const outDatedNodes = Object.values(nodesResponse.nodes).filter((node: any) => { const matches = node.version.match(VERSION_REGEX); @@ -293,7 +286,7 @@ export const reindexServiceFactory = ( */ const setReadonly = async (reindexOp: ReindexSavedObject) => { const { indexName } = reindexOp.attributes; - const putReadonly = await callAsUser('indices.putSettings', { + const { body: putReadonly } = await esClient.indices.putSettings({ index: indexName, body: { 'index.blocks.write': true }, }); @@ -319,7 +312,7 @@ export const reindexServiceFactory = ( const { settings, mappings } = transformFlatSettings(flatSettings); - const createIndex = await callAsUser('indices.create', { + const { body: createIndex } = await esClient.indices.create({ index: newIndexName, body: { settings, @@ -345,25 +338,25 @@ export const reindexServiceFactory = ( // Where possible, derive reindex options at the last moment before reindexing // to prevent them from becoming stale as they wait in the queue. - const indicesState = await esIndicesStateCheck(callAsUser, [indexName]); + const indicesState = await esIndicesStateCheck(esClient, [indexName]); const shouldOpenAndClose = indicesState[indexName] === 'closed'; if (shouldOpenAndClose) { log.debug(`Detected closed index ${indexName}, opening...`); - await callAsUser('indices.open', { index: indexName }); + await esClient.indices.open({ index: indexName }); } - const startReindex = (await callAsUser('reindex', { + const { body: startReindexResponse } = await esClient.reindex({ refresh: true, - waitForCompletion: false, + wait_for_completion: false, body: { source: { index: indexName }, dest: { index: reindexOp.attributes.newIndexName }, }, - })) as any; + }); return actions.updateReindexOp(reindexOp, { lastCompletedStep: ReindexStep.reindexStarted, - reindexTaskId: startReindex.task, + reindexTaskId: startReindexResponse.task, reindexTaskPercComplete: 0, reindexOptions: { ...(reindexOptions ?? {}), @@ -379,12 +372,12 @@ export const reindexServiceFactory = ( * @param reindexOp */ const updateReindexStatus = async (reindexOp: ReindexSavedObject) => { - const taskId = reindexOp.attributes.reindexTaskId; + const taskId = reindexOp.attributes.reindexTaskId!; // Check reindexing task progress - const taskResponse = await callAsUser('tasks.get', { - taskId, - waitForCompletion: false, + const { body: taskResponse } = await esClient.tasks.get({ + task_id: taskId, + wait_for_completion: false, }); if (!taskResponse.completed) { @@ -403,7 +396,7 @@ export const reindexServiceFactory = ( reindexOp = await cleanupChanges(reindexOp); } else { // Check that it reindexed all documents - const { count } = await callAsUser('count', { index: reindexOp.attributes.indexName }); + const { body: count } = await esClient.count({ index: reindexOp.attributes.indexName }); if (taskResponse.task.status.created < count) { // Include the entire task result in the error message. This should be guaranteed @@ -419,7 +412,7 @@ export const reindexServiceFactory = ( } // Delete the task from ES .tasks index - const deleteTaskResp = await callAsUser('delete', { + const { body: deleteTaskResp } = await esClient.delete({ index: '.tasks', id: taskId, }); @@ -438,22 +431,22 @@ export const reindexServiceFactory = ( const switchAlias = async (reindexOp: ReindexSavedObject) => { const { indexName, newIndexName, reindexOptions } = reindexOp.attributes; - const existingAliases = ( - await callAsUser('indices.getAlias', { - index: indexName, - }) - )[indexName].aliases; + const { body: response } = await esClient.indices.getAlias({ + index: indexName, + }); + + const existingAliases = response[indexName].aliases; - const extraAlises = Object.keys(existingAliases).map((aliasName) => ({ + const extraAliases = Object.keys(existingAliases).map((aliasName) => ({ add: { index: newIndexName, alias: aliasName, ...existingAliases[aliasName] }, })); - const aliasResponse = await callAsUser('indices.updateAliases', { + const { body: aliasResponse } = await esClient.indices.updateAliases({ body: { actions: [ { add: { index: newIndexName, alias: indexName } }, { remove_index: { index: indexName } }, - ...extraAlises, + ...extraAliases, ], }, }); @@ -463,7 +456,7 @@ export const reindexServiceFactory = ( } if (reindexOptions?.openAndClose === true) { - await callAsUser('indices.close', { index: indexName }); + await esClient.indices.close({ index: indexName }); } return actions.updateReindexOp(reindexOp, { @@ -540,9 +533,7 @@ export const reindexServiceFactory = ( body.cluster = [...body.cluster, 'manage_watcher']; } - const resp = await callAsUser('transport.request', { - path: '/_security/user/_has_privileges', - method: 'POST', + const { body: resp } = await esClient.security.hasPrivileges({ body, }); @@ -567,7 +558,7 @@ export const reindexServiceFactory = ( }, async createReindexOperation(indexName: string, opts?: { enqueue: boolean }) { - const indexExists = await callAsUser('indices.exists', { index: indexName }); + const { body: indexExists } = await esClient.indices.exists({ index: indexName }); if (!indexExists) { throw error.indexNotFound(`Index ${indexName} does not exist in this cluster.`); } @@ -752,8 +743,8 @@ export const reindexServiceFactory = ( ); } - const resp = await callAsUser('tasks.cancel', { - taskId: reindexOp.attributes.reindexTaskId, + const { body: resp } = await esClient.tasks.cancel({ + task_id: reindexOp.attributes.reindexTaskId!, }); if (resp.node_failures && resp.node_failures.length > 0) { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts index 756ce17b601998..1a30f98296c3a2 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts @@ -3,12 +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 { - ILegacyClusterClient, - Logger, - SavedObjectsClientContract, - FakeRequest, -} from 'src/core/server'; +import { IClusterClient, Logger, SavedObjectsClientContract, FakeRequest } from 'src/core/server'; import moment from 'moment'; import { ReindexSavedObject, ReindexStatus } from '../../../common/types'; import { Credential, CredentialStore } from './credential_store'; @@ -53,7 +48,7 @@ export class ReindexWorker { constructor( private client: SavedObjectsClientContract, private credentialStore: CredentialStore, - private clusterClient: ILegacyClusterClient, + private clusterClient: IClusterClient, log: Logger, private licensing: LicensingPluginSetup ) { @@ -62,7 +57,7 @@ export class ReindexWorker { throw new Error(`More than one ReindexWorker cannot be created.`); } - const callAsInternalUser = this.clusterClient.callAsInternalUser.bind(this.clusterClient); + const callAsInternalUser = this.clusterClient.asInternalUser; this.reindexService = reindexServiceFactory( callAsInternalUser, @@ -151,7 +146,7 @@ export class ReindexWorker { private getCredentialScopedReindexService = (credential: Credential) => { const fakeRequest: FakeRequest = { headers: credential }; const scopedClusterClient = this.clusterClient.asScoped(fakeRequest); - const callAsCurrentUser = scopedClusterClient.callAsCurrentUser.bind(scopedClusterClient); + const callAsCurrentUser = scopedClusterClient.asCurrentUser; const actions = reindexActionsFactory(this.client, callAsCurrentUser); return reindexServiceFactory(callAsCurrentUser, actions, this.log, this.licensing); }; diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts index e14056439ca6b2..9b5223d07bfbfe 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts @@ -5,7 +5,7 @@ */ import { elasticsearchServiceMock } from 'src/core/server/mocks'; import { registerUpgradeAssistantUsageCollector } from './usage_collector'; -import { ILegacyClusterClient } from 'src/core/server'; +import { IClusterClient } from 'src/core/server'; /** * Since these route callbacks are so thin, these serve simply as integration tests @@ -18,15 +18,17 @@ describe('Upgrade Assistant Usage Collector', () => { let dependencies: any; let callClusterStub: any; let usageCollection: any; - let clusterClient: ILegacyClusterClient; + let clusterClient: IClusterClient; beforeEach(() => { - clusterClient = elasticsearchServiceMock.createLegacyClusterClient(); - (clusterClient.callAsInternalUser as jest.Mock).mockResolvedValue({ - persistent: {}, - transient: { - logger: { - deprecation: 'WARN', + clusterClient = elasticsearchServiceMock.createClusterClient(); + (clusterClient.asInternalUser.cluster.getSettings as jest.Mock).mockResolvedValue({ + body: { + persistent: {}, + transient: { + logger: { + deprecation: 'WARN', + }, }, }, }); @@ -59,7 +61,7 @@ describe('Upgrade Assistant Usage Collector', () => { }), }, elasticsearch: { - legacy: { client: clusterClient }, + client: clusterClient, }, }; }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts index 276e639678fd8e..1eafefb4238c20 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts @@ -6,7 +6,7 @@ import { get } from 'lodash'; import { - LegacyAPICaller, + ElasticsearchClient, ElasticsearchServiceStart, ISavedObjectsRepository, SavedObjectsServiceStart, @@ -38,12 +38,10 @@ async function getSavedObjectAttributesFromRepo( } } -async function getDeprecationLoggingStatusValue( - callAsCurrentUser: LegacyAPICaller -): Promise { +async function getDeprecationLoggingStatusValue(esClient: ElasticsearchClient): Promise { try { - const loggerDeprecationCallResult = await callAsCurrentUser('cluster.getSettings', { - includeDefaults: true, + const { body: loggerDeprecationCallResult } = await esClient.cluster.getSettings({ + include_defaults: true, }); return isDeprecationLoggingEnabled(loggerDeprecationCallResult); @@ -53,7 +51,7 @@ async function getDeprecationLoggingStatusValue( } export async function fetchUpgradeAssistantMetrics( - { legacy: { client: esClient } }: ElasticsearchServiceStart, + { client: esClient }: ElasticsearchServiceStart, savedObjects: SavedObjectsServiceStart ): Promise { const savedObjectsRepository = savedObjects.createInternalRepository(); @@ -62,8 +60,9 @@ export async function fetchUpgradeAssistantMetrics( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID ); - const callAsInternalUser = esClient.callAsInternalUser.bind(esClient); - const deprecationLoggingStatusValue = await getDeprecationLoggingStatusValue(callAsInternalUser); + const deprecationLoggingStatusValue = await getDeprecationLoggingStatusValue( + esClient.asInternalUser + ); const getTelemetrySavedObject = ( upgradeAssistantTelemetrySavedObjectAttrs: UpgradeAssistantTelemetrySavedObjectAttributes | null diff --git a/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/routes.mock.ts b/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/routes.mock.ts index 2df770c3ce45c0..43fe8af18c392a 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/routes.mock.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/routes.mock.ts @@ -12,9 +12,7 @@ import { export const routeHandlerContextMock = ({ core: { elasticsearch: { - legacy: { - client: elasticsearchServiceMock.createLegacyScopedClusterClient(), - }, + client: elasticsearchServiceMock.createScopedClusterClient(), }, savedObjects: { client: savedObjectsClientMock.create() }, }, diff --git a/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts index 16f8001f8e1de4..630ee9157dc902 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts @@ -80,7 +80,7 @@ describe('cluster checkup API', () => { it('returns an 403 error if it throws forbidden', async () => { const e: any = new Error(`you can't go here!`); - e.status = 403; + e.statusCode = 403; MigrationApis.getUpgradeAssistantStatus.mockRejectedValue(e); const resp = await routeDependencies.router.getHandler({ diff --git a/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.ts b/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.ts index ff673adaf1642f..6eb0378b21baa7 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.ts @@ -23,9 +23,7 @@ export function registerClusterCheckupRoutes({ cloud, router, licensing, log }: { core: { savedObjects: { client: savedObjectsClient }, - elasticsearch: { - legacy: { client }, - }, + elasticsearch: { client }, }, }, request, @@ -34,10 +32,10 @@ export function registerClusterCheckupRoutes({ cloud, router, licensing, log }: try { const status = await getUpgradeAssistantStatus(client, isCloudEnabled); - const callAsCurrentUser = client.callAsCurrentUser.bind(client); - const reindexActions = reindexActionsFactory(savedObjectsClient, callAsCurrentUser); + const asCurrentUser = client.asCurrentUser; + const reindexActions = reindexActionsFactory(savedObjectsClient, asCurrentUser); const reindexService = reindexServiceFactory( - callAsCurrentUser, + asCurrentUser, reindexActions, log, licensing @@ -52,7 +50,7 @@ export function registerClusterCheckupRoutes({ cloud, router, licensing, log }: body: status, }); } catch (e) { - if (e.status === 403) { + if (e.statusCode === 403) { return response.forbidden(e.message); } diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts index b8021eeef75e60..f76a86704e2c4e 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts @@ -37,9 +37,9 @@ describe('deprecation logging API', () => { describe('GET /api/upgrade_assistant/deprecation_logging', () => { it('returns isEnabled', async () => { - (routeHandlerContextMock.core.elasticsearch.legacy.client - .callAsCurrentUser as jest.Mock).mockResolvedValue({ - default: { logger: { deprecation: 'WARN' } }, + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster + .getSettings as jest.Mock).mockResolvedValue({ + body: { default: { logger: { deprecation: 'WARN' } } }, }); const resp = await routeDependencies.router.getHandler({ method: 'get', @@ -51,8 +51,8 @@ describe('deprecation logging API', () => { }); it('returns an error if it throws', async () => { - (routeHandlerContextMock.core.elasticsearch.legacy.client - .callAsCurrentUser as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster + .getSettings as jest.Mock).mockRejectedValue(new Error(`scary error!`)); const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/deprecation_logging', @@ -64,21 +64,21 @@ describe('deprecation logging API', () => { describe('PUT /api/upgrade_assistant/deprecation_logging', () => { it('returns isEnabled', async () => { - (routeHandlerContextMock.core.elasticsearch.legacy.client - .callAsCurrentUser as jest.Mock).mockResolvedValue({ - default: { logger: { deprecation: 'ERROR' } }, + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster + .putSettings as jest.Mock).mockResolvedValue({ + body: { default: { logger: { deprecation: 'ERROR' } } }, }); const resp = await routeDependencies.router.getHandler({ - method: 'get', + method: 'put', pathPattern: '/api/upgrade_assistant/deprecation_logging', - })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); + })(routeHandlerContextMock, { body: { isEnabled: true } }, kibanaResponseFactory); expect(resp.payload).toEqual({ isEnabled: false }); }); it('returns an error if it throws', async () => { - (routeHandlerContextMock.core.elasticsearch.legacy.client - .callAsCurrentUser as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster + .putSettings as jest.Mock).mockRejectedValue(new Error(`scary error!`)); const resp = await routeDependencies.router.getHandler({ method: 'put', pathPattern: '/api/upgrade_assistant/deprecation_logging', diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts index 38f244a4e11547..4bdb1364b071a6 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts @@ -23,9 +23,7 @@ export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) async ( { core: { - elasticsearch: { - legacy: { client }, - }, + elasticsearch: { client }, }, }, request, @@ -54,9 +52,7 @@ export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) async ( { core: { - elasticsearch: { - legacy: { client }, - }, + elasticsearch: { client }, }, }, request, diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts index fffde339c59e57..e33398fdcc93bb 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; -import { ILegacyScopedClusterClient, Logger, SavedObjectsClientContract } from 'kibana/server'; +import { IScopedClusterClient, Logger, SavedObjectsClientContract } from 'kibana/server'; import { LicensingPluginSetup } from '../../../../licensing/server'; @@ -17,7 +17,7 @@ import { error } from '../../lib/reindexing/error'; interface ReindexHandlerArgs { savedObjects: SavedObjectsClientContract; - dataClient: ILegacyScopedClusterClient; + dataClient: IScopedClusterClient; indexName: string; log: Logger; licensing: LicensingPluginSetup; @@ -38,7 +38,7 @@ export const reindexHandler = async ({ savedObjects, reindexOptions, }: ReindexHandlerArgs): Promise => { - const callAsCurrentUser = dataClient.callAsCurrentUser.bind(dataClient); + const callAsCurrentUser = dataClient.asCurrentUser; const reindexActions = reindexActionsFactory(savedObjects, callAsCurrentUser); const reindexService = reindexServiceFactory(callAsCurrentUser, reindexActions, log, licensing); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts index c745def5e89363..52157f39743e88 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts @@ -51,7 +51,7 @@ export function createReindexWorker({ savedObjects, licensing, }: CreateReindexWorker) { - const esClient = elasticsearchService.legacy.client; + const esClient = elasticsearchService.client; return new ReindexWorker(savedObjects, credentialStore, esClient, logger, licensing); } @@ -100,9 +100,7 @@ export function registerReindexIndicesRoutes( { core: { savedObjects: { client: savedObjectsClient }, - elasticsearch: { - legacy: { client: esClient }, - }, + elasticsearch: { client: esClient }, }, }, request, @@ -142,9 +140,7 @@ export function registerReindexIndicesRoutes( async ( { core: { - elasticsearch: { - legacy: { client: esClient }, - }, + elasticsearch: { client: esClient }, savedObjects, }, }, @@ -152,7 +148,7 @@ export function registerReindexIndicesRoutes( response ) => { const { client } = savedObjects; - const callAsCurrentUser = esClient.callAsCurrentUser.bind(esClient); + const callAsCurrentUser = esClient.asCurrentUser; const reindexActions = reindexActionsFactory(client, callAsCurrentUser); try { const inProgressOps = await reindexActions.findAllByStatus(ReindexStatus.inProgress); @@ -184,9 +180,7 @@ export function registerReindexIndicesRoutes( { core: { savedObjects: { client: savedObjectsClient }, - elasticsearch: { - legacy: { client: esClient }, - }, + elasticsearch: { client: esClient }, }, }, request, @@ -245,9 +239,7 @@ export function registerReindexIndicesRoutes( { core: { savedObjects, - elasticsearch: { - legacy: { client: esClient }, - }, + elasticsearch: { client: esClient }, }, }, request, @@ -255,14 +247,9 @@ export function registerReindexIndicesRoutes( ) => { const { client } = savedObjects; const { indexName } = request.params; - const callAsCurrentUser = esClient.callAsCurrentUser.bind(esClient); - const reindexActions = reindexActionsFactory(client, callAsCurrentUser); - const reindexService = reindexServiceFactory( - callAsCurrentUser, - reindexActions, - log, - licensing - ); + const asCurrentUser = esClient.asCurrentUser; + const reindexActions = reindexActionsFactory(client, asCurrentUser); + const reindexService = reindexServiceFactory(asCurrentUser, reindexActions, log, licensing); try { const hasRequiredPrivileges = await reindexService.hasRequiredPrivileges(indexName); @@ -303,9 +290,7 @@ export function registerReindexIndicesRoutes( { core: { savedObjects, - elasticsearch: { - legacy: { client: esClient }, - }, + elasticsearch: { client: esClient }, }, }, request, @@ -313,7 +298,7 @@ export function registerReindexIndicesRoutes( ) => { const { indexName } = request.params; const { client } = savedObjects; - const callAsCurrentUser = esClient.callAsCurrentUser.bind(esClient); + const callAsCurrentUser = esClient.asCurrentUser; const reindexActions = reindexActionsFactory(client, callAsCurrentUser); const reindexService = reindexServiceFactory( callAsCurrentUser, diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts index daeb71ef123826..bdfbff61bc5db8 100644 --- a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts @@ -10,7 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { reindexOperationWithLargeErrorMessage } from './reindex_operation_with_large_error_message'; export default function ({ getService }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); describe('Reindex operation saved object', function () { const dotKibanaIndex = '.kibana'; diff --git a/x-pack/test/upgrade_assistant_integration/config.js b/x-pack/test/upgrade_assistant_integration/config.js index d11b39ff74e355..5409d8a4705029 100644 --- a/x-pack/test/upgrade_assistant_integration/config.js +++ b/x-pack/test/upgrade_assistant_integration/config.js @@ -5,7 +5,6 @@ */ import path from 'path'; -import { LegacyEsProvider } from './services'; export default async function ({ readConfigFile }) { // Read the Kibana API integration tests config file so that we can utilize its services. @@ -25,7 +24,6 @@ export default async function ({ readConfigFile }) { services: { ...kibanaCommonConfig.get('services'), supertest: kibanaAPITestsConfig.get('services.supertest'), - legacyEs: LegacyEsProvider, }, esArchiver: xPackFunctionalTestsConfig.get('esArchiver'), junit: { diff --git a/x-pack/test/upgrade_assistant_integration/services/index.js b/x-pack/test/upgrade_assistant_integration/services/index.js deleted file mode 100644 index 83424ad1eb50c9..00000000000000 --- a/x-pack/test/upgrade_assistant_integration/services/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { LegacyEsProvider } from './legacy_es'; diff --git a/x-pack/test/upgrade_assistant_integration/services/legacy_es.js b/x-pack/test/upgrade_assistant_integration/services/legacy_es.js deleted file mode 100644 index 78bfd63ded3c92..00000000000000 --- a/x-pack/test/upgrade_assistant_integration/services/legacy_es.js +++ /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 { format as formatUrl } from 'url'; - -import * as legacyElasticsearch from 'elasticsearch'; - -export function LegacyEsProvider({ getService }) { - const config = getService('config'); - - return new legacyElasticsearch.Client({ - host: formatUrl(config.get('servers.elasticsearch')), - requestTimeout: config.get('timeouts.esRequestTimeout'), - }); -} diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js index 10074f68bb59ea..f57d2184d4b8db 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js @@ -13,7 +13,7 @@ import { getIndexState } from '../../../plugins/upgrade_assistant/common/get_ind export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const es = getService('legacyEs'); + const es = getService('es'); // Utility function that keeps polling API until reindex operation has completed or failed. const waitForReindexToComplete = async (indexName) => { @@ -65,14 +65,14 @@ export default function ({ getService }) { expect(lastState.status).to.equal(ReindexStatus.completed); const { newIndexName } = lastState; - const indexSummary = await es.indices.get({ index: 'dummydata' }); + const { body: indexSummary } = await es.indices.get({ index: 'dummydata' }); // The new index was created expect(indexSummary[newIndexName]).to.be.an('object'); // The original index name is aliased to the new one expect(indexSummary[newIndexName].aliases.dummydata).to.be.an('object'); // The number of documents in the new index matches what we expect - expect((await es.count({ index: lastState.newIndexName })).count).to.be(3); + expect((await es.count({ index: lastState.newIndexName })).body.count).to.be(3); // Cleanup newly created index await es.indices.delete({ @@ -95,9 +95,9 @@ export default function ({ getService }) { ], }, }); - expect((await es.count({ index: 'myAlias' })).count).to.be(3); - expect((await es.count({ index: 'wildcardAlias' })).count).to.be(3); - expect((await es.count({ index: 'myHttpsAlias' })).count).to.be(2); + expect((await es.count({ index: 'myAlias' })).body.count).to.be(3); + expect((await es.count({ index: 'wildcardAlias' })).body.count).to.be(3); + expect((await es.count({ index: 'myHttpsAlias' })).body.count).to.be(2); // Reindex await supertest @@ -107,10 +107,10 @@ export default function ({ getService }) { const lastState = await waitForReindexToComplete('dummydata'); // The regular aliases should still return 3 docs - expect((await es.count({ index: 'myAlias' })).count).to.be(3); - expect((await es.count({ index: 'wildcardAlias' })).count).to.be(3); + expect((await es.count({ index: 'myAlias' })).body.count).to.be(3); + expect((await es.count({ index: 'wildcardAlias' })).body.count).to.be(3); // The filtered alias should still return 2 docs - expect((await es.count({ index: 'myHttpsAlias' })).count).to.be(2); + expect((await es.count({ index: 'myHttpsAlias' })).body.count).to.be(2); // Cleanup newly created index await es.indices.delete({ @@ -204,8 +204,8 @@ export default function ({ getService }) { await assertQueueState(undefined, 0); // Check that the closed index is still closed after reindexing - const resolvedIndices = await es.transport.request({ - path: `_resolve/index/${nameOfIndexThatShouldBeClosed}`, + const { body: resolvedIndices } = await es.indices.resolveIndex({ + name: nameOfIndexThatShouldBeClosed, }); const test1ReindexedState = getIndexState(nameOfIndexThatShouldBeClosed, resolvedIndices); From 46ac4ed7a2827b2dd689d30a68c54e29b726ee0c Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Wed, 27 Jan 2021 07:36:10 -0800 Subject: [PATCH 30/58] [CI] Combines Jest test jobs (#85850) Signed-off-by: Tyler Smalley --- .ci/es-snapshots/Jenkinsfile_verify_es | 1 - .ci/jobs.yml | 1 - .ci/teamcity/default/jest.sh | 10 ++------ .ci/teamcity/oss/jest.sh | 7 ++++-- .ci/teamcity/tests/jest.sh | 10 ++++++++ .teamcity/src/Extensions.kt | 15 ++++++------ .teamcity/src/builds/test/AllTests.kt | 2 +- .teamcity/src/builds/test/Jest.kt | 2 +- .teamcity/src/builds/test/XPackJest.kt | 19 --------------- .teamcity/src/projects/Kibana.kt | 1 - jest.config.integration.js | 5 +++- jest.config.js | 10 +++++++- jest.config.oss.js | 19 --------------- packages/kbn-test/jest-preset.js | 2 +- .../shell_scripts/extract_archives.sh | 2 +- test/scripts/jenkins_unit.sh | 17 +++----------- test/scripts/jenkins_xpack.sh | 23 ------------------- test/scripts/test/jest_integration.sh | 2 +- test/scripts/test/jest_unit.sh | 2 +- test/scripts/test/xpack_jest_unit.sh | 6 ----- vars/kibanaCoverage.groovy | 7 ------ vars/kibanaPipeline.groovy | 15 ++++++------ vars/tasks.groovy | 1 - x-pack/jest.config.js | 11 --------- 24 files changed, 55 insertions(+), 135 deletions(-) create mode 100755 .ci/teamcity/tests/jest.sh delete mode 100644 .teamcity/src/builds/test/XPackJest.kt delete mode 100644 jest.config.oss.js delete mode 100755 test/scripts/jenkins_xpack.sh delete mode 100755 test/scripts/test/xpack_jest_unit.sh delete mode 100644 x-pack/jest.config.js diff --git a/.ci/es-snapshots/Jenkinsfile_verify_es b/.ci/es-snapshots/Jenkinsfile_verify_es index 11a39faa9aed01..b40cd91a45c572 100644 --- a/.ci/es-snapshots/Jenkinsfile_verify_es +++ b/.ci/es-snapshots/Jenkinsfile_verify_es @@ -29,7 +29,6 @@ kibanaPipeline(timeoutMinutes: 150) { withEnv(["ES_SNAPSHOT_MANIFEST=${SNAPSHOT_MANIFEST}"]) { parallel([ 'kibana-intake-agent': workers.intake('kibana-intake', './test/scripts/jenkins_unit.sh'), - 'x-pack-intake-agent': workers.intake('x-pack-intake', './test/scripts/jenkins_xpack.sh'), 'kibana-oss-agent': workers.functional('kibana-oss-tests', { kibanaPipeline.buildOss() }, [ 'oss-ciGroup1': kibanaPipeline.ossCiGroupProcess(1), 'oss-ciGroup2': kibanaPipeline.ossCiGroupProcess(2), diff --git a/.ci/jobs.yml b/.ci/jobs.yml index b05e834f5a459e..6aa93d4a1056a6 100644 --- a/.ci/jobs.yml +++ b/.ci/jobs.yml @@ -2,7 +2,6 @@ JOB: - kibana-intake - - x-pack-intake - kibana-firefoxSmoke - kibana-ciGroup1 - kibana-ciGroup2 diff --git a/.ci/teamcity/default/jest.sh b/.ci/teamcity/default/jest.sh index b900d1b6d6b4e6..dac1cc8986a1cd 100755 --- a/.ci/teamcity/default/jest.sh +++ b/.ci/teamcity/default/jest.sh @@ -1,10 +1,4 @@ #!/bin/bash -set -euo pipefail - -source "$(dirname "${0}")/../util.sh" - -export JOB=kibana-default-jest - -checks-reporter-with-killswitch "Jest Unit Tests" \ - node scripts/jest x-pack --ci --verbose --maxWorkers=5 +# This file is temporary and can be removed once #85850 has been +# merged and the changes included in open PR's (~3 days after merging) diff --git a/.ci/teamcity/oss/jest.sh b/.ci/teamcity/oss/jest.sh index 0dee07d00d2bea..b323a88ef06bc8 100755 --- a/.ci/teamcity/oss/jest.sh +++ b/.ci/teamcity/oss/jest.sh @@ -1,10 +1,13 @@ #!/bin/bash +# This file is temporary and can be removed once #85850 has been +# merged and the changes included in open PR's (~3 days after merging) + set -euo pipefail source "$(dirname "${0}")/../util.sh" export JOB=kibana-oss-jest -checks-reporter-with-killswitch "OSS Jest Unit Tests" \ - node scripts/jest --config jest.config.oss.js --ci --verbose --maxWorkers=5 +checks-reporter-with-killswitch "Jest Unit Tests" \ + node scripts/jest --ci --verbose diff --git a/.ci/teamcity/tests/jest.sh b/.ci/teamcity/tests/jest.sh new file mode 100755 index 00000000000000..c8b9b075e0e61d --- /dev/null +++ b/.ci/teamcity/tests/jest.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -euo pipefail + +source "$(dirname "${0}")/../util.sh" + +export JOB=kibana-jest + +checks-reporter-with-killswitch "Jest Unit Tests" \ + node scripts/jest --ci --verbose --coverage diff --git a/.teamcity/src/Extensions.kt b/.teamcity/src/Extensions.kt index 0a8abf4a149cf5..ce99c9c49e1983 100644 --- a/.teamcity/src/Extensions.kt +++ b/.teamcity/src/Extensions.kt @@ -20,20 +20,21 @@ fun BuildType.kibanaAgent(size: Int) { } val testArtifactRules = """ + target/junit/**/* target/kibana-* - target/test-metrics/* + target/kibana-coverage/**/* target/kibana-security-solution/**/*.png - target/junit/**/* + target/test-metrics/* target/test-suites-ci-plan.json - test/**/screenshots/session/*.png - test/**/screenshots/failure/*.png test/**/screenshots/diff/*.png + test/**/screenshots/failure/*.png + test/**/screenshots/session/*.png test/functional/failure_debug/html/*.html - x-pack/test/**/screenshots/session/*.png - x-pack/test/**/screenshots/failure/*.png x-pack/test/**/screenshots/diff/*.png - x-pack/test/functional/failure_debug/html/*.html + x-pack/test/**/screenshots/failure/*.png + x-pack/test/**/screenshots/session/*.png x-pack/test/functional/apps/reporting/reports/session/*.pdf + x-pack/test/functional/failure_debug/html/*.html """.trimIndent() fun BuildType.addTestSettings() { diff --git a/.teamcity/src/builds/test/AllTests.kt b/.teamcity/src/builds/test/AllTests.kt index 9506d98cbe50ee..a49d5f2b07f4c8 100644 --- a/.teamcity/src/builds/test/AllTests.kt +++ b/.teamcity/src/builds/test/AllTests.kt @@ -9,5 +9,5 @@ object AllTests : BuildType({ description = "All Non-Functional Tests" type = Type.COMPOSITE - dependsOn(QuickTests, Jest, XPackJest, JestIntegration, OssApiServerIntegration) + dependsOn(QuickTests, Jest, JestIntegration, OssApiServerIntegration) }) diff --git a/.teamcity/src/builds/test/Jest.kt b/.teamcity/src/builds/test/Jest.kt index c33c9c2678ca49..c9d170b5e5c3d2 100644 --- a/.teamcity/src/builds/test/Jest.kt +++ b/.teamcity/src/builds/test/Jest.kt @@ -12,7 +12,7 @@ object Jest : BuildType({ kibanaAgent(8) steps { - runbld("Jest Unit", "./.ci/teamcity/oss/jest.sh") + runbld("Jest Unit", "./.ci/teamcity/tests/jest.sh") } addTestSettings() diff --git a/.teamcity/src/builds/test/XPackJest.kt b/.teamcity/src/builds/test/XPackJest.kt deleted file mode 100644 index 8246b60823ff9b..00000000000000 --- a/.teamcity/src/builds/test/XPackJest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package builds.test - -import addTestSettings -import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType -import kibanaAgent -import runbld - -object XPackJest : BuildType({ - name = "X-Pack Jest Unit" - description = "Executes X-Pack Jest Unit Tests" - - kibanaAgent(16) - - steps { - runbld("X-Pack Jest Unit", "./.ci/teamcity/default/jest.sh") - } - - addTestSettings() -}) diff --git a/.teamcity/src/projects/Kibana.kt b/.teamcity/src/projects/Kibana.kt index 5cddcf18e067ff..c84b65027dee6c 100644 --- a/.teamcity/src/projects/Kibana.kt +++ b/.teamcity/src/projects/Kibana.kt @@ -77,7 +77,6 @@ fun Kibana(config: KibanaConfiguration = KibanaConfiguration()) : Project { name = "Jest" buildType(Jest) - buildType(XPackJest) buildType(JestIntegration) } diff --git a/jest.config.integration.js b/jest.config.integration.js index 2064abb7e36a15..99728c5471dfb7 100644 --- a/jest.config.integration.js +++ b/jest.config.integration.js @@ -17,6 +17,7 @@ module.exports = { testPathIgnorePatterns: preset.testPathIgnorePatterns.filter( (pattern) => !pattern.includes('integration_tests') ), + setupFilesAfterEnv: ['/packages/kbn-test/target/jest/setup/after_env.integration.js'], reporters: [ 'default', [ @@ -24,5 +25,7 @@ module.exports = { { reportName: 'Jest Integration Tests' }, ], ], - setupFilesAfterEnv: ['/packages/kbn-test/target/jest/setup/after_env.integration.js'], + coverageReporters: !!process.env.CI + ? [['json', { file: 'jest-integration.json' }]] + : ['html', 'text'], }; diff --git a/jest.config.js b/jest.config.js index f1833772c82a1c..9ac5e57254e5a4 100644 --- a/jest.config.js +++ b/jest.config.js @@ -7,6 +7,14 @@ */ module.exports = { + preset: '@kbn/test', rootDir: '.', - projects: [...require('./jest.config.oss').projects, ...require('./x-pack/jest.config').projects], + projects: [ + '/packages/*/jest.config.js', + '/src/*/jest.config.js', + '/src/legacy/*/jest.config.js', + '/src/plugins/*/jest.config.js', + '/test/*/jest.config.js', + '/x-pack/plugins/*/jest.config.js', + ], }; diff --git a/jest.config.oss.js b/jest.config.oss.js deleted file mode 100644 index 1b478aa85bdbaf..00000000000000 --- a/jest.config.oss.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '.', - projects: [ - '/packages/*/jest.config.js', - '/src/*/jest.config.js', - '/src/legacy/*/jest.config.js', - '/src/plugins/*/jest.config.js', - '/test/*/jest.config.js', - ], -}; diff --git a/packages/kbn-test/jest-preset.js b/packages/kbn-test/jest-preset.js index ed88944ed862d7..ebedb314f9594d 100644 --- a/packages/kbn-test/jest-preset.js +++ b/packages/kbn-test/jest-preset.js @@ -19,7 +19,7 @@ module.exports = { coveragePathIgnorePatterns: ['/node_modules/', '.*\\.d\\.ts'], // A list of reporter names that Jest uses when writing coverage reports - coverageReporters: !!process.env.CODE_COVERAGE ? ['json'] : ['html', 'text'], + coverageReporters: !!process.env.CI ? [['json', { file: 'jest.json' }]] : ['html', 'text'], // An array of file extensions your modules use moduleFileExtensions: ['js', 'mjs', 'json', 'ts', 'tsx', 'node'], diff --git a/src/dev/code_coverage/shell_scripts/extract_archives.sh b/src/dev/code_coverage/shell_scripts/extract_archives.sh index 376467f9f2e555..14b35f8786d02a 100644 --- a/src/dev/code_coverage/shell_scripts/extract_archives.sh +++ b/src/dev/code_coverage/shell_scripts/extract_archives.sh @@ -6,7 +6,7 @@ EXTRACT_DIR=/tmp/extracted_coverage mkdir -p $EXTRACT_DIR echo "### Extracting downloaded artifacts" -for x in kibana-intake x-pack-intake kibana-oss-tests kibana-xpack-tests; do +for x in kibana-intake kibana-oss-tests kibana-xpack-tests; do tar -xzf $DOWNLOAD_DIR/coverage/${x}/kibana-coverage.tar.gz -C $EXTRACT_DIR || echo "### Error 'tarring': ${x}" done diff --git a/test/scripts/jenkins_unit.sh b/test/scripts/jenkins_unit.sh index 6e28f9c3ef56ab..9e387f97a016e8 100755 --- a/test/scripts/jenkins_unit.sh +++ b/test/scripts/jenkins_unit.sh @@ -2,12 +2,6 @@ source test/scripts/jenkins_test_setup.sh -rename_coverage_file() { - test -f target/kibana-coverage/jest/coverage-final.json \ - && mv target/kibana-coverage/jest/coverage-final.json \ - target/kibana-coverage/jest/$1-coverage-final.json -} - if [[ -z "$CODE_COVERAGE" ]] ; then # Lint ./test/scripts/lint/eslint.sh @@ -34,13 +28,8 @@ if [[ -z "$CODE_COVERAGE" ]] ; then ./test/scripts/checks/test_hardening.sh else echo " -> Running jest tests with coverage" - node scripts/jest --ci --verbose --coverage --config jest.config.oss.js || true; - rename_coverage_file "oss" - echo "" - echo "" + node scripts/jest --ci --verbose --maxWorkers=6 --coverage || true; + echo " -> Running jest integration tests with coverage" - node --max-old-space-size=8192 scripts/jest_integration --ci --verbose --coverage || true; - rename_coverage_file "oss-integration" - echo "" - echo "" + node scripts/jest_integration --ci --verbose --coverage || true; fi diff --git a/test/scripts/jenkins_xpack.sh b/test/scripts/jenkins_xpack.sh deleted file mode 100755 index 66fb5ae5370bc7..00000000000000 --- a/test/scripts/jenkins_xpack.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -source test/scripts/jenkins_test_setup.sh - -if [[ -z "$CODE_COVERAGE" ]] ; then - echo " -> Running jest tests" - - ./test/scripts/test/xpack_jest_unit.sh -else - echo " -> Build runtime for canvas" - # build runtime for canvas - echo "NODE_ENV=$NODE_ENV" - node ./x-pack/plugins/canvas/scripts/shareable_runtime - echo " -> Running jest tests with coverage" - cd x-pack - node --max-old-space-size=6144 scripts/jest --ci --verbose --maxWorkers=5 --coverage --config jest.config.js || true; - # rename file in order to be unique one - test -f ../target/kibana-coverage/jest/coverage-final.json \ - && mv ../target/kibana-coverage/jest/coverage-final.json \ - ../target/kibana-coverage/jest/xpack-coverage-final.json - echo "" - echo "" -fi diff --git a/test/scripts/test/jest_integration.sh b/test/scripts/test/jest_integration.sh index 78ed804f884305..c48d9032466a36 100755 --- a/test/scripts/test/jest_integration.sh +++ b/test/scripts/test/jest_integration.sh @@ -3,4 +3,4 @@ source src/dev/ci_setup/setup_env.sh checks-reporter-with-killswitch "Jest Integration Tests" \ - node scripts/jest_integration --ci --verbose + node scripts/jest_integration --ci --verbose --coverage diff --git a/test/scripts/test/jest_unit.sh b/test/scripts/test/jest_unit.sh index 88c0fe528b88c8..14d7268c6f36de 100755 --- a/test/scripts/test/jest_unit.sh +++ b/test/scripts/test/jest_unit.sh @@ -3,4 +3,4 @@ source src/dev/ci_setup/setup_env.sh checks-reporter-with-killswitch "Jest Unit Tests" \ - node scripts/jest --config jest.config.oss.js --ci --verbose --maxWorkers=5 + node scripts/jest --ci --verbose --maxWorkers=10 --coverage diff --git a/test/scripts/test/xpack_jest_unit.sh b/test/scripts/test/xpack_jest_unit.sh deleted file mode 100755 index 33b1c8a2b51833..00000000000000 --- a/test/scripts/test/xpack_jest_unit.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -source src/dev/ci_setup/setup_env.sh - -checks-reporter-with-killswitch "X-Pack Jest" \ - node scripts/jest x-pack --ci --verbose --maxWorkers=5 diff --git a/vars/kibanaCoverage.groovy b/vars/kibanaCoverage.groovy index 609d8f78aeb969..e393f3a5d2150f 100644 --- a/vars/kibanaCoverage.groovy +++ b/vars/kibanaCoverage.groovy @@ -197,13 +197,6 @@ def ingest(jobName, buildNumber, buildUrl, timestamp, previousSha, teamAssignmen def runTests() { parallel([ 'kibana-intake-agent': workers.intake('kibana-intake', './test/scripts/jenkins_unit.sh'), - 'x-pack-intake-agent': { - withEnv([ - 'NODE_ENV=test' // Needed for jest tests only - ]) { - workers.intake('x-pack-intake', './test/scripts/jenkins_xpack.sh')() - } - }, 'kibana-oss-agent' : workers.functional( 'kibana-oss-tests', { kibanaPipeline.buildOss() }, diff --git a/vars/kibanaPipeline.groovy b/vars/kibanaPipeline.groovy index 93cb7a719bbe8c..e49692568cec8a 100644 --- a/vars/kibanaPipeline.groovy +++ b/vars/kibanaPipeline.groovy @@ -179,20 +179,21 @@ def uploadCoverageArtifacts(prefix, pattern) { def withGcsArtifactUpload(workerName, closure) { def uploadPrefix = "kibana-ci-artifacts/jobs/${env.JOB_NAME}/${BUILD_NUMBER}/${workerName}" def ARTIFACT_PATTERNS = [ + 'target/junit/**/*', 'target/kibana-*', - 'target/test-metrics/*', + 'target/kibana-coverage/**/*', 'target/kibana-security-solution/**/*.png', - 'target/junit/**/*', + 'target/test-metrics/*', 'target/test-suites-ci-plan.json', - 'test/**/screenshots/session/*.png', - 'test/**/screenshots/failure/*.png', 'test/**/screenshots/diff/*.png', + 'test/**/screenshots/failure/*.png', + 'test/**/screenshots/session/*.png', 'test/functional/failure_debug/html/*.html', - 'x-pack/test/**/screenshots/session/*.png', - 'x-pack/test/**/screenshots/failure/*.png', 'x-pack/test/**/screenshots/diff/*.png', - 'x-pack/test/functional/failure_debug/html/*.html', + 'x-pack/test/**/screenshots/failure/*.png', + 'x-pack/test/**/screenshots/session/*.png', 'x-pack/test/functional/apps/reporting/reports/session/*.pdf', + 'x-pack/test/functional/failure_debug/html/*.html', ] withEnv([ diff --git a/vars/tasks.groovy b/vars/tasks.groovy index 3493a95f0bdce5..74ad1267e93551 100644 --- a/vars/tasks.groovy +++ b/vars/tasks.groovy @@ -35,7 +35,6 @@ def test() { kibanaPipeline.scriptTask('Jest Unit Tests', 'test/scripts/test/jest_unit.sh'), kibanaPipeline.scriptTask('API Integration Tests', 'test/scripts/test/api_integration.sh'), - kibanaPipeline.scriptTask('X-Pack Jest Unit Tests', 'test/scripts/test/xpack_jest_unit.sh'), ]) } diff --git a/x-pack/jest.config.js b/x-pack/jest.config.js deleted file mode 100644 index 8158987213cd27..00000000000000 --- a/x-pack/jest.config.js +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '..', - projects: ['/x-pack/plugins/*/jest.config.js'], -}; From 82902e89189a0e74a94e206dc574033806675dae Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 27 Jan 2021 17:57:53 +0200 Subject: [PATCH 31/58] [Telemetry] Settings Collector: redact sensitive reported values (#88675) --- ...ana-plugin-core-public.uisettingsparams.md | 1 + ...-core-public.uisettingsparams.sensitive.md | 13 ++ ...re-server.iuisettingsclient.issensitive.md | 13 ++ ...na-plugin-core-server.iuisettingsclient.md | 1 + ...ana-plugin-core-server.uisettingsparams.md | 1 + ...-core-server.uisettingsparams.sensitive.md | 13 ++ .../src/tools/serializer.ts | 21 ++- src/core/public/public.api.md | 1 + src/core/server/server.api.md | 2 + .../ui_settings/settings/notifications.ts | 1 + src/core/server/ui_settings/types.ts | 4 + .../ui_settings/ui_settings_client.test.ts | 32 ++++ .../server/ui_settings/ui_settings_client.ts | 6 +- .../ui_settings/ui_settings_service.mock.ts | 1 + src/core/types/ui_settings.ts | 5 + src/plugins/kibana_usage_collection/README.md | 2 +- .../common/constants.ts | 4 + .../server/collectors/management/README.md | 51 +++++++ .../__snapshots__/index.test.ts.snap | 7 - .../collectors/management/index.test.ts | 61 -------- .../server/collectors/management/schema.ts | 51 +++++-- .../telemetry_management_collector.test.ts | 140 ++++++++++++++++++ .../telemetry_management_collector.ts | 19 +-- .../server/collectors/management/types.ts | 117 +++++++++++++++ src/plugins/telemetry/schema/oss_plugins.json | 83 ++++++++--- .../server/collector/collector.ts | 27 +++- .../vis_type_timelion/server/plugin.ts | 1 + .../dashboard_mode/server/ui_settings.ts | 1 + x-pack/plugins/reporting/server/plugin.ts | 1 + .../security_solution/server/ui_settings.ts | 4 + x-pack/test/usage_collection/config.ts | 5 +- .../stack_management_usage_test/kibana.json | 9 ++ .../public/index.ts | 11 ++ .../public/plugin.ts | 17 +++ .../public/types.ts | 14 ++ .../stack_management_usage_test/tsconfig.json | 12 ++ .../stack_management_usage/index.ts | 60 ++++++++ 37 files changed, 694 insertions(+), 118 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-core-public.uisettingsparams.sensitive.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.issensitive.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.uisettingsparams.sensitive.md create mode 100644 src/plugins/kibana_usage_collection/server/collectors/management/README.md delete mode 100644 src/plugins/kibana_usage_collection/server/collectors/management/__snapshots__/index.test.ts.snap delete mode 100644 src/plugins/kibana_usage_collection/server/collectors/management/index.test.ts create mode 100644 src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.test.ts create mode 100644 src/plugins/kibana_usage_collection/server/collectors/management/types.ts create mode 100644 x-pack/test/usage_collection/plugins/stack_management_usage_test/kibana.json create mode 100644 x-pack/test/usage_collection/plugins/stack_management_usage_test/public/index.ts create mode 100644 x-pack/test/usage_collection/plugins/stack_management_usage_test/public/plugin.ts create mode 100644 x-pack/test/usage_collection/plugins/stack_management_usage_test/public/types.ts create mode 100644 x-pack/test/usage_collection/plugins/stack_management_usage_test/tsconfig.json create mode 100644 x-pack/test/usage_collection/test_suites/stack_management_usage/index.ts diff --git a/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.md b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.md index 2cc149e2e2a79f..0b7e6467667cb2 100644 --- a/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.md +++ b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.md @@ -26,6 +26,7 @@ export interface UiSettingsParams | [readonly](./kibana-plugin-core-public.uisettingsparams.readonly.md) | boolean | a flag indicating that value cannot be changed | | [requiresPageReload](./kibana-plugin-core-public.uisettingsparams.requirespagereload.md) | boolean | a flag indicating whether new value applying requires page reloading | | [schema](./kibana-plugin-core-public.uisettingsparams.schema.md) | Type<T> | | +| [sensitive](./kibana-plugin-core-public.uisettingsparams.sensitive.md) | boolean | a flag indicating that value might contain user sensitive data. used by telemetry to mask the value of the setting when sent. | | [type](./kibana-plugin-core-public.uisettingsparams.type.md) | UiSettingsType | defines a type of UI element [UiSettingsType](./kibana-plugin-core-public.uisettingstype.md) | | [validation](./kibana-plugin-core-public.uisettingsparams.validation.md) | ImageValidation | StringValidation | | | [value](./kibana-plugin-core-public.uisettingsparams.value.md) | T | default value to fall back to if a user doesn't provide any | diff --git a/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.sensitive.md b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.sensitive.md new file mode 100644 index 00000000000000..e12f3c5649f17e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.sensitive.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) > [sensitive](./kibana-plugin-core-public.uisettingsparams.sensitive.md) + +## UiSettingsParams.sensitive property + +a flag indicating that value might contain user sensitive data. used by telemetry to mask the value of the setting when sent. + +Signature: + +```typescript +sensitive?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.issensitive.md b/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.issensitive.md new file mode 100644 index 00000000000000..a6f263e0b0f555 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.issensitive.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IUiSettingsClient](./kibana-plugin-core-server.iuisettingsclient.md) > [isSensitive](./kibana-plugin-core-server.iuisettingsclient.issensitive.md) + +## IUiSettingsClient.isSensitive property + +Shows whether the uiSetting is a sensitive value. Used by telemetry to not send sensitive values. + +Signature: + +```typescript +isSensitive: (key: string) => boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md b/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md index af99b5e5bb215e..dd4a69c13a2d92 100644 --- a/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md +++ b/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md @@ -21,6 +21,7 @@ export interface IUiSettingsClient | [getRegistered](./kibana-plugin-core-server.iuisettingsclient.getregistered.md) | () => Readonly<Record<string, PublicUiSettingsParams>> | Returns registered uiSettings values [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) | | [getUserProvided](./kibana-plugin-core-server.iuisettingsclient.getuserprovided.md) | <T = any>() => Promise<Record<string, UserProvidedValues<T>>> | Retrieves a set of all uiSettings values set by the user. | | [isOverridden](./kibana-plugin-core-server.iuisettingsclient.isoverridden.md) | (key: string) => boolean | Shows whether the uiSettings value set by the user. | +| [isSensitive](./kibana-plugin-core-server.iuisettingsclient.issensitive.md) | (key: string) => boolean | Shows whether the uiSetting is a sensitive value. Used by telemetry to not send sensitive values. | | [remove](./kibana-plugin-core-server.iuisettingsclient.remove.md) | (key: string) => Promise<void> | Removes uiSettings value by key. | | [removeMany](./kibana-plugin-core-server.iuisettingsclient.removemany.md) | (keys: string[]) => Promise<void> | Removes multiple uiSettings values by keys. | | [set](./kibana-plugin-core-server.iuisettingsclient.set.md) | (key: string, value: any) => Promise<void> | Writes uiSettings value and marks it as set by the user. | diff --git a/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.md b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.md index 4dfde5200e7e9f..d35afc4a149d19 100644 --- a/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.md +++ b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.md @@ -26,6 +26,7 @@ export interface UiSettingsParams | [readonly](./kibana-plugin-core-server.uisettingsparams.readonly.md) | boolean | a flag indicating that value cannot be changed | | [requiresPageReload](./kibana-plugin-core-server.uisettingsparams.requirespagereload.md) | boolean | a flag indicating whether new value applying requires page reloading | | [schema](./kibana-plugin-core-server.uisettingsparams.schema.md) | Type<T> | | +| [sensitive](./kibana-plugin-core-server.uisettingsparams.sensitive.md) | boolean | a flag indicating that value might contain user sensitive data. used by telemetry to mask the value of the setting when sent. | | [type](./kibana-plugin-core-server.uisettingsparams.type.md) | UiSettingsType | defines a type of UI element [UiSettingsType](./kibana-plugin-core-server.uisettingstype.md) | | [validation](./kibana-plugin-core-server.uisettingsparams.validation.md) | ImageValidation | StringValidation | | | [value](./kibana-plugin-core-server.uisettingsparams.value.md) | T | default value to fall back to if a user doesn't provide any | diff --git a/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.sensitive.md b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.sensitive.md new file mode 100644 index 00000000000000..f2c7de19dde1ad --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.sensitive.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) > [sensitive](./kibana-plugin-core-server.uisettingsparams.sensitive.md) + +## UiSettingsParams.sensitive property + +a flag indicating that value might contain user sensitive data. used by telemetry to mask the value of the setting when sent. + +Signature: + +```typescript +sensitive?: boolean; +``` diff --git a/packages/kbn-telemetry-tools/src/tools/serializer.ts b/packages/kbn-telemetry-tools/src/tools/serializer.ts index a941fa2a9d01f1..bad40b53884075 100644 --- a/packages/kbn-telemetry-tools/src/tools/serializer.ts +++ b/packages/kbn-telemetry-tools/src/tools/serializer.ts @@ -19,7 +19,7 @@ export enum TelemetryKinds { Date = 10001, } -interface DescriptorValue { +export interface DescriptorValue { kind: ts.SyntaxKind | TelemetryKinds; type: keyof typeof ts.SyntaxKind | keyof typeof TelemetryKinds; } @@ -42,6 +42,13 @@ export function isObjectDescriptor(value: any) { return false; } +export function descriptorToObject(descriptor: Descriptor | DescriptorValue) { + return Object.entries(descriptor).reduce((acc, [key, value]) => { + acc[key] = value.kind ? kindToDescriptorName(value.kind) : descriptorToObject(value); + return acc; + }, {} as Record); +} + export function kindToDescriptorName(kind: number) { switch (kind) { case ts.SyntaxKind.StringKeyword: @@ -158,6 +165,16 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor | if (symbolName === 'Date') { return { kind: TelemetryKinds.Date, type: 'Date' }; } + + // Support Array + if (symbolName === 'Array') { + if (node.typeArguments?.length !== 1) { + throw Error('Array type only supports 1 type parameter Array'); + } + const typeArgument = node.typeArguments[0]; + return { items: getDescriptor(typeArgument, program) }; + } + // Support `Record` if (symbolName === 'Record') { const descriptor = getDescriptor(node.typeArguments![1], program); @@ -243,7 +260,7 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor | case ts.SyntaxKind.UnionType: case ts.SyntaxKind.AnyKeyword: default: - throw new Error(`Unknown type ${ts.SyntaxKind[node.kind]}; ${node.getText()}`); + throw new Error(`Unknown type ${ts.SyntaxKind[node.kind]}`); } } diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index d72b2aa5afd1e7..0097127924a5cd 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -1507,6 +1507,7 @@ export interface UiSettingsParams { requiresPageReload?: boolean; // (undocumented) schema: Type; + sensitive?: boolean; type?: UiSettingsType; // (undocumented) validation?: ImageValidation | StringValidation; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 0b058011267eb3..fc90284ffe5b26 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -1195,6 +1195,7 @@ export interface IUiSettingsClient { getRegistered: () => Readonly>; getUserProvided: () => Promise>>; isOverridden: (key: string) => boolean; + isSensitive: (key: string) => boolean; remove: (key: string) => Promise; removeMany: (keys: string[]) => Promise; set: (key: string, value: any) => Promise; @@ -3100,6 +3101,7 @@ export interface UiSettingsParams { requiresPageReload?: boolean; // (undocumented) schema: Type; + sensitive?: boolean; type?: UiSettingsType; // (undocumented) validation?: ImageValidation | StringValidation; diff --git a/src/core/server/ui_settings/settings/notifications.ts b/src/core/server/ui_settings/settings/notifications.ts index a60732ecb807a8..cedd52289a68cb 100644 --- a/src/core/server/ui_settings/settings/notifications.ts +++ b/src/core/server/ui_settings/settings/notifications.ts @@ -35,6 +35,7 @@ export const getNotificationsSettings = (): Record => }, }), category: ['notifications'], + sensitive: true, schema: schema.string(), }, 'notifications:lifetime:banner': { diff --git a/src/core/server/ui_settings/types.ts b/src/core/server/ui_settings/types.ts index eb2d8b00dc488e..73f46e4db3b2cc 100644 --- a/src/core/server/ui_settings/types.ts +++ b/src/core/server/ui_settings/types.ts @@ -65,6 +65,10 @@ export interface IUiSettingsClient { * Shows whether the uiSettings value set by the user. */ isOverridden: (key: string) => boolean; + /** + * Shows whether the uiSetting is a sensitive value. Used by telemetry to not send sensitive values. + */ + isSensitive: (key: string) => boolean; } /** @internal */ diff --git a/src/core/server/ui_settings/ui_settings_client.test.ts b/src/core/server/ui_settings/ui_settings_client.test.ts index 7fa5a85e5154e0..26c4d9e8e6dd94 100644 --- a/src/core/server/ui_settings/ui_settings_client.test.ts +++ b/src/core/server/ui_settings/ui_settings_client.test.ts @@ -644,6 +644,38 @@ describe('ui settings', () => { }); }); + describe('#isSensitive()', () => { + it('returns false if sensitive config is not set', () => { + const defaults = { + foo: { + schema: schema.string(), + value: '1', + }, + }; + + const { uiSettings } = setup({ defaults }); + expect(uiSettings.isSensitive('foo')).toBe(false); + }); + + it('returns false if key is not in the settings', () => { + const { uiSettings } = setup(); + expect(uiSettings.isSensitive('baz')).toBe(false); + }); + + it('returns true if overrides defined and key is overridden', () => { + const defaults = { + foo: { + schema: schema.string(), + sensitive: true, + value: '1', + }, + }; + + const { uiSettings } = setup({ defaults }); + expect(uiSettings.isSensitive('foo')).toBe(true); + }); + }); + describe('#isOverridden()', () => { it('returns false if no overrides defined', () => { const { uiSettings } = setup(); diff --git a/src/core/server/ui_settings/ui_settings_client.ts b/src/core/server/ui_settings/ui_settings_client.ts index 2ba8caaba5170c..b8a46a2f994aa8 100644 --- a/src/core/server/ui_settings/ui_settings_client.ts +++ b/src/core/server/ui_settings/ui_settings_client.ts @@ -52,7 +52,6 @@ export class UiSettingsClient implements IUiSettingsClient { constructor(options: UiSettingsServiceOptions) { const { type, id, buildNum, savedObjectsClient, log, defaults = {}, overrides = {} } = options; - this.type = type; this.id = id; this.buildNum = buildNum; @@ -132,6 +131,11 @@ export class UiSettingsClient implements IUiSettingsClient { return this.overrides.hasOwnProperty(key); } + isSensitive(key: string): boolean { + const definition = this.defaults[key]; + return !!definition?.sensitive; + } + private assertUpdateAllowed(key: string) { if (this.isOverridden(key)) { throw new CannotOverrideError(`Unable to update "${key}" because it is overridden`); 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 a03412e37f5517..771b9d243656a3 100644 --- a/src/core/server/ui_settings/ui_settings_service.mock.ts +++ b/src/core/server/ui_settings/ui_settings_service.mock.ts @@ -25,6 +25,7 @@ const createClientMock = () => { remove: jest.fn(), removeMany: jest.fn(), isOverridden: jest.fn(), + isSensitive: jest.fn(), }; mocked.get.mockResolvedValue(false); mocked.getAll.mockResolvedValue({}); diff --git a/src/core/types/ui_settings.ts b/src/core/types/ui_settings.ts index 24dfbbeea67262..92e8f6ef2f41e7 100644 --- a/src/core/types/ui_settings.ts +++ b/src/core/types/ui_settings.ts @@ -56,6 +56,11 @@ export interface UiSettingsParams { requiresPageReload?: boolean; /** a flag indicating that value cannot be changed */ readonly?: boolean; + /** + * a flag indicating that value might contain user sensitive data. + * used by telemetry to mask the value of the setting when sent. + */ + sensitive?: boolean; /** defines a type of UI element {@link UiSettingsType} */ type?: UiSettingsType; /** optional deprecation information. Used to generate a deprecation warning. */ diff --git a/src/plugins/kibana_usage_collection/README.md b/src/plugins/kibana_usage_collection/README.md index 69711d30cdc746..85d362cf0a9b1e 100644 --- a/src/plugins/kibana_usage_collection/README.md +++ b/src/plugins/kibana_usage_collection/README.md @@ -6,6 +6,6 @@ This plugin registers the basic usage collectors from Kibana: - UI Metrics - Ops stats - Number of Saved Objects per type -- Non-default UI Settings +- [User-changed UI Settings](./server/collectors/management/README.md) - CSP configuration - Core Metrics diff --git a/src/plugins/kibana_usage_collection/common/constants.ts b/src/plugins/kibana_usage_collection/common/constants.ts index 4505c59e0f6307..052367765a6ec4 100644 --- a/src/plugins/kibana_usage_collection/common/constants.ts +++ b/src/plugins/kibana_usage_collection/common/constants.ts @@ -13,3 +13,7 @@ export const PLUGIN_NAME = 'kibana_usage_collection'; * The type name used to publish Kibana usage stats in the formatted as bulk. */ export const KIBANA_STATS_TYPE = 'kibana_stats'; +/** + * Redacted keyword; used as a value for sensitive ui settings + */ +export const REDACTED_KEYWORD = '[REDACTED]'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/README.md b/src/plugins/kibana_usage_collection/server/collectors/management/README.md new file mode 100644 index 00000000000000..b539136d57b89c --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/management/README.md @@ -0,0 +1,51 @@ +# User-changed UI Settings - Management Collector + +The Usage Collector `stack_management` reports user changed settings. +All user changed UI Settings are automatically collected. + +After adding a new setting you will be required to do the following steps: + +1. Update the [schema](./schema.ts) to include the setting name and schema type. +``` +export const stackManagementSchema: MakeSchemaFrom = { + 'MY_UI_SETTING': { type: 'keyword' }, +} +``` + +2. Update the [UsageStats interface](./types.ts) with the setting name and typescript type. +``` +export interface UsageStats { + 'MY_UI_SETTING': string; +} +``` +3. Run the telemetry checker with `--fix` flag to automatically fix the mappings + +``` +node scripts/telemetry_check --fix +``` + +If you forget any of the steps our telemetry tools and tests will help you through the process! + +## Sensitive fields + +If the configured UI setting might contain user sensitive information simply add the property `sensitive: true` to the ui setting registration config. + +``` +uiSettings.register({ + [NEWS_FEED_URL_SETTING]: { + name: i18n.translate('xpack.securitySolution.uiSettings.newsFeedUrl', { + defaultMessage: 'News feed URL', + }), + value: NEWS_FEED_URL_SETTING_DEFAULT, + sensitive: true, + description: i18n.translate('xpack.securitySolution.uiSettings.newsFeedUrlDescription', { + defaultMessage: '

News feed content will be retrieved from this URL

', + }), + category: [APP_ID], + requiresPageReload: true, + schema: schema.string(), + }, +}), +``` + +The value of any UI setting marked as `sensitive` will be reported as a keyword `[REDACTED]` instead of the actual value. This hides the actual sensitive information while giving us some intelligence over which fields the users are interactive with the most. diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/__snapshots__/index.test.ts.snap b/src/plugins/kibana_usage_collection/server/collectors/management/__snapshots__/index.test.ts.snap deleted file mode 100644 index def230dea8d705..00000000000000 --- a/src/plugins/kibana_usage_collection/server/collectors/management/__snapshots__/index.test.ts.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`telemetry_application_usage_collector fetch() 1`] = ` -Object { - "my-key": "my-value", -} -`; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/index.test.ts b/src/plugins/kibana_usage_collection/server/collectors/management/index.test.ts deleted file mode 100644 index 38baf02d6fe1b1..00000000000000 --- a/src/plugins/kibana_usage_collection/server/collectors/management/index.test.ts +++ /dev/null @@ -1,61 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { loggingSystemMock, uiSettingsServiceMock } from '../../../../../core/server/mocks'; -import { - Collector, - createUsageCollectionSetupMock, - createCollectorFetchContextMock, -} from '../../../../usage_collection/server/usage_collection.mock'; - -import { registerManagementUsageCollector } from './'; - -const logger = loggingSystemMock.createLogger(); - -describe('telemetry_application_usage_collector', () => { - let collector: Collector; - - const usageCollectionMock = createUsageCollectionSetupMock(); - usageCollectionMock.makeUsageCollector.mockImplementation((config) => { - collector = new Collector(logger, config); - return createUsageCollectionSetupMock().makeUsageCollector(config); - }); - - const uiSettingsClient = uiSettingsServiceMock.createClient(); - const getUiSettingsClient = jest.fn(() => uiSettingsClient); - const mockedFetchContext = createCollectorFetchContextMock(); - - beforeAll(() => { - registerManagementUsageCollector(usageCollectionMock, getUiSettingsClient); - }); - - test('registered collector is set', () => { - expect(collector).not.toBeUndefined(); - }); - - test('isReady() => false if no client', () => { - getUiSettingsClient.mockImplementationOnce(() => undefined as any); - expect(collector.isReady()).toBe(false); - }); - - test('isReady() => true', () => { - expect(collector.isReady()).toBe(true); - }); - - test('fetch()', async () => { - uiSettingsClient.getUserProvided.mockImplementationOnce(async () => ({ - 'my-key': { userValue: 'my-value' }, - })); - await expect(collector.fetch(mockedFetchContext)).resolves.toMatchSnapshot(); - }); - - test('fetch() should not fail if invoked when not ready', async () => { - getUiSettingsClient.mockImplementationOnce(() => undefined as any); - await expect(collector.fetch(mockedFetchContext)).resolves.toBe(undefined); - }); -}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index 28eeb461f7a86c..b644f282c1f36c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -7,18 +7,25 @@ */ import { MakeSchemaFrom } from 'src/plugins/usage_collection/server'; -import { UsageStats } from './telemetry_management_collector'; +import { UsageStats } from './types'; -// Retrieved by changing all the current settings in Kibana (we'll need to revisit it in the future). -// I would suggest we use flattened type for the mappings of this collector. export const stackManagementSchema: MakeSchemaFrom = { + // sensitive + 'timelion:quandl.key': { type: 'keyword' }, + 'securitySolution:defaultIndex': { type: 'keyword' }, + 'securitySolution:newsFeedUrl': { type: 'keyword' }, + 'xpackReporting:customPdfLogo': { type: 'keyword' }, + 'notifications:banner': { type: 'keyword' }, + 'timelion:graphite.url': { type: 'keyword' }, + 'xpackDashboardMode:roles': { type: 'keyword' }, + 'securitySolution:ipReputationLinks': { type: 'keyword' }, + // non-sensitive 'visualize:enableLabs': { type: 'boolean' }, 'visualization:heatmap:maxBuckets': { type: 'long' }, 'visualization:colorMapping': { type: 'text' }, 'visualization:regionmap:showWarnings': { type: 'boolean' }, 'visualization:dimmingOpacity': { type: 'float' }, 'visualization:tileMap:maxPrecision': { type: 'long' }, - 'securitySolution:ipReputationLinks': { type: 'text' }, 'csv:separator': { type: 'keyword' }, 'visualization:tileMap:WMSdefaults': { type: 'text' }, 'timelion:target_buckets': { type: 'long' }, @@ -27,14 +34,11 @@ export const stackManagementSchema: MakeSchemaFrom = { 'timelion:min_interval': { type: 'keyword' }, 'timelion:default_rows': { type: 'long' }, 'timelion:default_columns': { type: 'long' }, - 'timelion:quandl.key': { type: 'keyword' }, 'timelion:es.default_index': { type: 'keyword' }, 'timelion:showTutorial': { type: 'boolean' }, 'securitySolution:timeDefaults': { type: 'keyword' }, 'securitySolution:defaultAnomalyScore': { type: 'long' }, - 'securitySolution:defaultIndex': { type: 'keyword' }, // it's an array 'securitySolution:refreshIntervalDefaults': { type: 'keyword' }, - 'securitySolution:newsFeedUrl': { type: 'keyword' }, 'securitySolution:enableNewsFeed': { type: 'boolean' }, 'search:includeFrozen': { type: 'boolean' }, 'courier:maxConcurrentShardRequests': { type: 'long' }, @@ -43,21 +47,29 @@ export const stackManagementSchema: MakeSchemaFrom = { 'courier:customRequestPreference': { type: 'keyword' }, 'courier:ignoreFilterIfFieldNotInIndex': { type: 'boolean' }, 'rollups:enableIndexPatterns': { type: 'boolean' }, - 'xpackReporting:customPdfLogo': { type: 'text' }, 'notifications:lifetime:warning': { type: 'long' }, 'notifications:lifetime:banner': { type: 'long' }, 'notifications:lifetime:info': { type: 'long' }, - 'notifications:banner': { type: 'text' }, 'notifications:lifetime:error': { type: 'long' }, 'doc_table:highlight': { type: 'boolean' }, 'discover:searchOnPageLoad': { type: 'boolean' }, // eslint-disable-next-line @typescript-eslint/naming-convention 'doc_table:hideTimeColumn': { type: 'boolean' }, 'discover:sampleSize': { type: 'long' }, - defaultColumns: { type: 'keyword' }, // it's an array + defaultColumns: { + type: 'array', + items: { + type: 'keyword', + }, + }, 'context:defaultSize': { type: 'long' }, 'discover:aggs:terms:size': { type: 'long' }, - 'context:tieBreakerFields': { type: 'keyword' }, // it's an array + 'context:tieBreakerFields': { + type: 'array', + items: { + type: 'keyword', + }, + }, 'discover:sort:defaultOrder': { type: 'keyword' }, 'context:step': { type: 'long' }, 'accessibility:disableAnimations': { type: 'boolean' }, @@ -79,7 +91,12 @@ export const stackManagementSchema: MakeSchemaFrom = { 'query:queryString:options': { type: 'keyword' }, 'metrics:max_buckets': { type: 'long' }, 'query:allowLeadingWildcards': { type: 'boolean' }, - metaFields: { type: 'keyword' }, // it's an array + metaFields: { + type: 'array', + items: { + type: 'keyword', + }, + }, 'indexPattern:placeholder': { type: 'keyword' }, 'histogram:barTarget': { type: 'long' }, 'histogram:maxBars': { type: 'long' }, @@ -101,4 +118,14 @@ export const stackManagementSchema: MakeSchemaFrom = { 'csv:quoteValues': { type: 'boolean' }, 'dateFormat:dow': { type: 'keyword' }, dateFormat: { type: 'keyword' }, + 'autocomplete:useTimeRange': { type: 'boolean' }, + 'search:timeout': { type: 'long' }, + 'visualization:visualize:legacyChartsLibrary': { type: 'boolean' }, + 'doc_table:legacy': { type: 'boolean' }, + 'discover:modifyColumnsOnSwitch': { type: 'boolean' }, + 'discover:searchFieldsFromSource': { type: 'boolean' }, + 'securitySolution:rulesTableRefresh': { type: 'text' }, + 'apm:enableSignificantTerms': { type: 'boolean' }, + 'apm:enableServiceOverview': { type: 'boolean' }, + 'apm:enableCorrelations': { type: 'boolean' }, }; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.test.ts b/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.test.ts new file mode 100644 index 00000000000000..4bcd98f894e2a1 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.test.ts @@ -0,0 +1,140 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import { loggingSystemMock, uiSettingsServiceMock } from '../../../../../core/server/mocks'; +import { + Collector, + createUsageCollectionSetupMock, + createCollectorFetchContextMock, +} from '../../../../usage_collection/server/usage_collection.mock'; + +import { + registerManagementUsageCollector, + createCollectorFetch, +} from './telemetry_management_collector'; + +const logger = loggingSystemMock.createLogger(); + +describe('telemetry_application_usage_collector', () => { + let collector: Collector; + + const usageCollectionMock = createUsageCollectionSetupMock(); + usageCollectionMock.makeUsageCollector.mockImplementation((config) => { + collector = new Collector(logger, config); + return createUsageCollectionSetupMock().makeUsageCollector(config); + }); + + const uiSettingsClient = uiSettingsServiceMock.createClient(); + const getUiSettingsClient = jest.fn(() => uiSettingsClient); + const mockedFetchContext = createCollectorFetchContextMock(); + + beforeAll(() => { + registerManagementUsageCollector(usageCollectionMock, getUiSettingsClient); + }); + + test('registered collector is set', () => { + expect(collector).not.toBeUndefined(); + }); + + test('isReady() => false if no client', () => { + getUiSettingsClient.mockImplementationOnce(() => undefined as any); + expect(collector.isReady()).toBe(false); + }); + + test('isReady() => true', () => { + expect(collector.isReady()).toBe(true); + }); + + test('fetch()', async () => { + uiSettingsClient.getUserProvided.mockImplementationOnce(async () => ({ + 'visualization:colorMapping': { userValue: 'red' }, + })); + await expect(collector.fetch(mockedFetchContext)).resolves.toEqual({ + 'visualization:colorMapping': 'red', + }); + }); + + test('fetch() should not fail if invoked when not ready', async () => { + getUiSettingsClient.mockImplementationOnce(() => undefined as any); + await expect(collector.fetch(mockedFetchContext)).resolves.toBe(undefined); + }); +}); + +describe('createCollectorFetch', () => { + const mockUserSettings = { + item1: { userValue: 'test' }, + item2: { userValue: 123 }, + item3: { userValue: false }, + }; + + const mockIsSensitive = (key: string) => { + switch (key) { + case 'item1': + case 'item2': + return false; + case 'item3': + return true; + default: + throw new Error(`Unexpected ui setting: ${key}`); + } + }; + + it('returns #fetchUsageStats function', () => { + const getUiSettingsClient = jest.fn(() => undefined); + const fetchFunction = createCollectorFetch(getUiSettingsClient); + expect(typeof fetchFunction).toBe('function'); + }); + + describe('#fetchUsageStats', () => { + it('returns undefined if no uiSettingsClient returned from getUiSettingsClient', async () => { + const getUiSettingsClient = jest.fn(() => undefined); + const fetchFunction = createCollectorFetch(getUiSettingsClient); + const result = await fetchFunction(); + expect(result).toBe(undefined); + expect(getUiSettingsClient).toBeCalledTimes(1); + }); + + it('returns all user changed settings', async () => { + const uiSettingsClient = uiSettingsServiceMock.createClient(); + const getUiSettingsClient = jest.fn(() => uiSettingsClient); + uiSettingsClient.getUserProvided.mockResolvedValue(mockUserSettings); + uiSettingsClient.isSensitive.mockImplementation(mockIsSensitive); + const fetchFunction = createCollectorFetch(getUiSettingsClient); + const result = await fetchFunction(); + expect(typeof result).toBe('object'); + expect(Object.keys(result!)).toEqual(Object.keys(mockUserSettings)); + }); + + it('returns the actual values of non-sensitive settings', async () => { + const uiSettingsClient = uiSettingsServiceMock.createClient(); + const getUiSettingsClient = jest.fn(() => uiSettingsClient); + uiSettingsClient.getUserProvided.mockResolvedValue(mockUserSettings); + uiSettingsClient.isSensitive.mockImplementation(mockIsSensitive); + const fetchFunction = createCollectorFetch(getUiSettingsClient); + const result = await fetchFunction(); + expect(typeof result).toBe('object'); + expect(result!).toMatchObject({ + item1: 'test', + item2: 123, + }); + }); + + it('returns [REDACTED] as a value for sensitive settings', async () => { + const uiSettingsClient = uiSettingsServiceMock.createClient(); + const getUiSettingsClient = jest.fn(() => uiSettingsClient); + uiSettingsClient.getUserProvided.mockResolvedValue(mockUserSettings); + uiSettingsClient.isSensitive.mockImplementation(mockIsSensitive); + const fetchFunction = createCollectorFetch(getUiSettingsClient); + const result = await fetchFunction(); + expect(typeof result).toBe('object'); + expect(result!).toMatchObject({ + item3: '[REDACTED]', + }); + }); + }); +}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts index c45f3d6139d95c..651fbbd5a897a1 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts @@ -9,12 +9,8 @@ import { IUiSettingsClient } from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { stackManagementSchema } from './schema'; - -export interface UsageStats extends Record { - // We don't support `type` yet. Only interfaces. So I added at least 1 known key to the generic - // Record extension to avoid eslint reverting it back to a `type` - 'visualize:enableLabs': boolean; -} +import { UsageStats } from './types'; +import { REDACTED_KEYWORD } from '../../../common/constants'; export function createCollectorFetch(getUiSettingsClient: () => IUiSettingsClient | undefined) { return async function fetchUsageStats(): Promise { @@ -23,11 +19,12 @@ export function createCollectorFetch(getUiSettingsClient: () => IUiSettingsClien return; } - const user = await uiSettingsClient.getUserProvided(); - const modifiedEntries = Object.keys(user) - .filter((key: string) => key !== 'buildNum') - .reduce((obj: any, key: string) => { - obj[key] = user[key].userValue; + const userProvided = await uiSettingsClient.getUserProvided(); + const modifiedEntries = Object.entries(userProvided) + .filter(([key]) => key !== 'buildNum') + .reduce((obj: any, [key, { userValue }]) => { + const sensitive = uiSettingsClient.isSensitive(key); + obj[key] = sensitive ? REDACTED_KEYWORD : userValue; return obj; }, {}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts new file mode 100644 index 00000000000000..417841ee895697 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -0,0 +1,117 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +export interface UsageStats { + /** + * sensitive settings + */ + 'timelion:quandl.key': string; + 'securitySolution:defaultIndex': string; + 'securitySolution:newsFeedUrl': string; + 'xpackReporting:customPdfLogo': string; + 'notifications:banner': string; + 'timelion:graphite.url': string; + 'xpackDashboardMode:roles': string; + 'securitySolution:ipReputationLinks': string; + /** + * non-sensitive settings + */ + 'autocomplete:useTimeRange': boolean; + 'search:timeout': number; + 'visualization:visualize:legacyChartsLibrary': boolean; + 'doc_table:legacy': boolean; + 'discover:modifyColumnsOnSwitch': boolean; + 'discover:searchFieldsFromSource': boolean; + 'securitySolution:rulesTableRefresh': string; + 'apm:enableSignificantTerms': boolean; + 'apm:enableServiceOverview': boolean; + 'apm:enableCorrelations': boolean; + 'visualize:enableLabs': boolean; + 'visualization:heatmap:maxBuckets': number; + 'visualization:colorMapping': string; + 'visualization:regionmap:showWarnings': boolean; + 'visualization:dimmingOpacity': number; + 'visualization:tileMap:maxPrecision': number; + 'csv:separator': string; + 'visualization:tileMap:WMSdefaults': string; + 'timelion:target_buckets': number; + 'timelion:max_buckets': number; + 'timelion:es.timefield': string; + 'timelion:min_interval': string; + 'timelion:default_rows': number; + 'timelion:default_columns': number; + 'timelion:es.default_index': string; + 'timelion:showTutorial': boolean; + 'securitySolution:timeDefaults': string; + 'securitySolution:defaultAnomalyScore': number; + 'securitySolution:refreshIntervalDefaults': string; + 'securitySolution:enableNewsFeed': boolean; + 'search:includeFrozen': boolean; + 'courier:maxConcurrentShardRequests': number; + 'courier:batchSearches': boolean; + 'courier:setRequestPreference': string; + 'courier:customRequestPreference': string; + 'courier:ignoreFilterIfFieldNotInIndex': boolean; + 'rollups:enableIndexPatterns': boolean; + 'notifications:lifetime:warning': number; + 'notifications:lifetime:banner': number; + 'notifications:lifetime:info': number; + 'notifications:lifetime:error': number; + 'doc_table:highlight': boolean; + 'discover:searchOnPageLoad': boolean; + // eslint-disable-next-line @typescript-eslint/naming-convention + 'doc_table:hideTimeColumn': boolean; + 'discover:sampleSize': number; + defaultColumns: string[]; + 'context:defaultSize': number; + 'discover:aggs:terms:size': number; + 'context:tieBreakerFields': string[]; + 'discover:sort:defaultOrder': string; + 'context:step': number; + 'accessibility:disableAnimations': boolean; + 'ml:fileDataVisualizerMaxFileSize': string; + 'ml:anomalyDetection:results:enableTimeDefaults': boolean; + 'ml:anomalyDetection:results:timeDefaults': string; + 'truncate:maxHeight': number; + 'timepicker:timeDefaults': string; + 'timepicker:refreshIntervalDefaults': string; + 'timepicker:quickRanges': string; + 'theme:version': string; + 'theme:darkMode': boolean; + 'state:storeInSessionStorage': boolean; + 'savedObjects:perPage': number; + 'search:queryLanguage': string; + 'shortDots:enable': boolean; + 'sort:options': string; + 'savedObjects:listingLimit': number; + 'query:queryString:options': string; + 'metrics:max_buckets': number; + 'query:allowLeadingWildcards': boolean; + metaFields: string[]; + 'indexPattern:placeholder': string; + 'histogram:barTarget': number; + 'histogram:maxBars': number; + 'format:number:defaultLocale': string; + 'format:percent:defaultPattern': string; + 'format:number:defaultPattern': string; + 'history:limit': number; + 'format:defaultTypeMap': string; + 'format:currency:defaultPattern': string; + defaultIndex: string; + 'format:bytes:defaultPattern': string; + 'filters:pinnedByDefault': boolean; + 'filterEditor:suggestValues': boolean; + 'fields:popularLimit': number; + dateNanosFormat: string; + defaultRoute: string; + 'dateFormat:tz': string; + 'dateFormat:scaled': string; + 'csv:quoteValues': boolean; + 'dateFormat:dow': string; + dateFormat: string; +} diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 7bac6a809eca3d..950fdf9405b754 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -4076,6 +4076,27 @@ }, "stack_management": { "properties": { + "timelion:quandl.key": { + "type": "keyword" + }, + "securitySolution:defaultIndex": { + "type": "keyword" + }, + "securitySolution:newsFeedUrl": { + "type": "keyword" + }, + "xpackReporting:customPdfLogo": { + "type": "keyword" + }, + "notifications:banner": { + "type": "keyword" + }, + "timelion:graphite.url": { + "type": "keyword" + }, + "xpackDashboardMode:roles": { + "type": "keyword" + }, "visualize:enableLabs": { "type": "boolean" }, @@ -4095,7 +4116,7 @@ "type": "long" }, "securitySolution:ipReputationLinks": { - "type": "text" + "type": "keyword" }, "csv:separator": { "type": "keyword" @@ -4121,9 +4142,6 @@ "timelion:default_columns": { "type": "long" }, - "timelion:quandl.key": { - "type": "keyword" - }, "timelion:es.default_index": { "type": "keyword" }, @@ -4136,15 +4154,9 @@ "securitySolution:defaultAnomalyScore": { "type": "long" }, - "securitySolution:defaultIndex": { - "type": "keyword" - }, "securitySolution:refreshIntervalDefaults": { "type": "keyword" }, - "securitySolution:newsFeedUrl": { - "type": "keyword" - }, "securitySolution:enableNewsFeed": { "type": "boolean" }, @@ -4169,9 +4181,6 @@ "rollups:enableIndexPatterns": { "type": "boolean" }, - "xpackReporting:customPdfLogo": { - "type": "text" - }, "notifications:lifetime:warning": { "type": "long" }, @@ -4181,9 +4190,6 @@ "notifications:lifetime:info": { "type": "long" }, - "notifications:banner": { - "type": "text" - }, "notifications:lifetime:error": { "type": "long" }, @@ -4200,7 +4206,10 @@ "type": "long" }, "defaultColumns": { - "type": "keyword" + "type": "array", + "items": { + "type": "keyword" + } }, "context:defaultSize": { "type": "long" @@ -4209,7 +4218,10 @@ "type": "long" }, "context:tieBreakerFields": { - "type": "keyword" + "type": "array", + "items": { + "type": "keyword" + } }, "discover:sort:defaultOrder": { "type": "keyword" @@ -4275,7 +4287,10 @@ "type": "boolean" }, "metaFields": { - "type": "keyword" + "type": "array", + "items": { + "type": "keyword" + } }, "indexPattern:placeholder": { "type": "keyword" @@ -4339,6 +4354,36 @@ }, "dateFormat": { "type": "keyword" + }, + "autocomplete:useTimeRange": { + "type": "boolean" + }, + "search:timeout": { + "type": "long" + }, + "visualization:visualize:legacyChartsLibrary": { + "type": "boolean" + }, + "doc_table:legacy": { + "type": "boolean" + }, + "discover:modifyColumnsOnSwitch": { + "type": "boolean" + }, + "discover:searchFieldsFromSource": { + "type": "boolean" + }, + "securitySolution:rulesTableRefresh": { + "type": "text" + }, + "apm:enableSignificantTerms": { + "type": "boolean" + }, + "apm:enableServiceOverview": { + "type": "boolean" + }, + "apm:enableCorrelations": { + "type": "boolean" } } }, diff --git a/src/plugins/usage_collection/server/collector/collector.ts b/src/plugins/usage_collection/server/collector/collector.ts index ccc17ea1c5967d..8e8a74902d4790 100644 --- a/src/plugins/usage_collection/server/collector/collector.ts +++ b/src/plugins/usage_collection/server/collector/collector.ts @@ -14,17 +14,38 @@ import { KibanaRequest, } from 'src/core/server'; -export type AllowedSchemaNumberTypes = 'long' | 'integer' | 'short' | 'byte' | 'double' | 'float'; +export type AllowedSchemaNumberTypes = + | 'long' + | 'integer' + | 'short' + | 'byte' + | 'double' + | 'float' + | 'date'; +export type AllowedSchemaStringTypes = 'keyword' | 'text' | 'date'; +export type AllowedSchemaBooleanTypes = 'boolean'; -export type AllowedSchemaTypes = AllowedSchemaNumberTypes | 'keyword' | 'text' | 'boolean' | 'date'; +export type AllowedSchemaTypes = + | AllowedSchemaNumberTypes + | AllowedSchemaStringTypes + | AllowedSchemaBooleanTypes; export interface SchemaField { type: string; } +export type PossibleSchemaTypes = U extends string + ? AllowedSchemaStringTypes + : U extends number + ? AllowedSchemaNumberTypes + : U extends boolean + ? AllowedSchemaBooleanTypes + : // allow any schema type from the union if typescript is unable to resolve the exact U type + AllowedSchemaTypes; + export type RecursiveMakeSchemaFrom = U extends object ? MakeSchemaFrom - : { type: AllowedSchemaTypes }; + : { type: PossibleSchemaTypes }; // Using Required to enforce all optional keys in the object export type MakeSchemaFrom = { diff --git a/src/plugins/vis_type_timelion/server/plugin.ts b/src/plugins/vis_type_timelion/server/plugin.ts index f999c1dfc773a9..fca557efc01e34 100644 --- a/src/plugins/vis_type_timelion/server/plugin.ts +++ b/src/plugins/vis_type_timelion/server/plugin.ts @@ -173,6 +173,7 @@ export class Plugin { defaultMessage: '{experimentalLabel} Your API key from www.quandl.com', values: { experimentalLabel: `[${experimentalLabel}]` }, }), + sensitive: true, category: ['timelion'], schema: schema.string(), }, diff --git a/x-pack/plugins/dashboard_mode/server/ui_settings.ts b/x-pack/plugins/dashboard_mode/server/ui_settings.ts index f692ec8a33fc91..59de82cf7b3ab8 100644 --- a/x-pack/plugins/dashboard_mode/server/ui_settings.ts +++ b/x-pack/plugins/dashboard_mode/server/ui_settings.ts @@ -22,6 +22,7 @@ export function getUiSettings(): Record> { }), value: [DASHBOARD_ONLY_USER_ROLE], category: ['dashboard'], + sensitive: true, deprecation: { message: i18n.translate('xpack.dashboardMode.uiSettings.dashboardsOnlyRolesDeprecation', { defaultMessage: 'This setting is deprecated and will be removed in Kibana 8.0.', diff --git a/x-pack/plugins/reporting/server/plugin.ts b/x-pack/plugins/reporting/server/plugin.ts index 05556f050e213d..35101dbaab2465 100644 --- a/x-pack/plugins/reporting/server/plugin.ts +++ b/x-pack/plugins/reporting/server/plugin.ts @@ -52,6 +52,7 @@ export class ReportingPlugin description: i18n.translate('xpack.reporting.pdfFooterImageDescription', { defaultMessage: `Custom image to use in the PDF's footer`, }), + sensitive: true, type: 'image', schema: schema.nullable(schema.byteSize({ max: '200kb' })), category: [PLUGIN_ID], diff --git a/x-pack/plugins/security_solution/server/ui_settings.ts b/x-pack/plugins/security_solution/server/ui_settings.ts index 548f718e1bc80d..0d679cdefb92cf 100644 --- a/x-pack/plugins/security_solution/server/ui_settings.ts +++ b/x-pack/plugins/security_solution/server/ui_settings.ts @@ -78,6 +78,8 @@ export const initUiSettings = (uiSettings: CoreSetup['uiSettings']) => { name: i18n.translate('xpack.securitySolution.uiSettings.defaultIndexLabel', { defaultMessage: 'Elasticsearch indices', }), + sensitive: true, + value: DEFAULT_INDEX_PATTERN, description: i18n.translate('xpack.securitySolution.uiSettings.defaultIndexDescription', { defaultMessage: @@ -147,6 +149,7 @@ export const initUiSettings = (uiSettings: CoreSetup['uiSettings']) => { defaultMessage: 'News feed URL', }), value: NEWS_FEED_URL_SETTING_DEFAULT, + sensitive: true, description: i18n.translate('xpack.securitySolution.uiSettings.newsFeedUrlDescription', { defaultMessage: '

News feed content will be retrieved from this URL

', }), @@ -167,6 +170,7 @@ export const initUiSettings = (uiSettings: CoreSetup['uiSettings']) => { 'Array of URL templates to build the list of reputation URLs to be displayed on the IP Details page.', } ), + sensitive: true, category: [APP_ID], requiresPageReload: true, schema: schema.arrayOf( diff --git a/x-pack/test/usage_collection/config.ts b/x-pack/test/usage_collection/config.ts index 27b12a1ff298c1..d31ecc444d00d8 100644 --- a/x-pack/test/usage_collection/config.ts +++ b/x-pack/test/usage_collection/config.ts @@ -24,7 +24,10 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { return { ...xpackFunctionalConfig.getAll(), // list paths to the files that contain your plugins tests - testFiles: [resolve(__dirname, './test_suites/application_usage')], + testFiles: [ + resolve(__dirname, './test_suites/application_usage'), + resolve(__dirname, './test_suites/stack_management_usage'), + ], services, pageObjects, diff --git a/x-pack/test/usage_collection/plugins/stack_management_usage_test/kibana.json b/x-pack/test/usage_collection/plugins/stack_management_usage_test/kibana.json new file mode 100644 index 00000000000000..b586de3fa4d793 --- /dev/null +++ b/x-pack/test/usage_collection/plugins/stack_management_usage_test/kibana.json @@ -0,0 +1,9 @@ +{ + "id": "StackManagementUsageTest", + "version": "1.0.0", + "kibanaVersion": "kibana", + "configPath": ["xpack", "StackManagementUsageTest"], + "requiredPlugins": [], + "server": false, + "ui": true +} diff --git a/x-pack/test/usage_collection/plugins/stack_management_usage_test/public/index.ts b/x-pack/test/usage_collection/plugins/stack_management_usage_test/public/index.ts new file mode 100644 index 00000000000000..82aae6988052a7 --- /dev/null +++ b/x-pack/test/usage_collection/plugins/stack_management_usage_test/public/index.ts @@ -0,0 +1,11 @@ +/* + * 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 { StackManagementUsageTest } from './plugin'; + +export function plugin() { + return new StackManagementUsageTest(); +} diff --git a/x-pack/test/usage_collection/plugins/stack_management_usage_test/public/plugin.ts b/x-pack/test/usage_collection/plugins/stack_management_usage_test/public/plugin.ts new file mode 100644 index 00000000000000..3cd10a1d4c178c --- /dev/null +++ b/x-pack/test/usage_collection/plugins/stack_management_usage_test/public/plugin.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Plugin, CoreSetup, CoreStart } from 'kibana/public'; +import './types'; + +export class StackManagementUsageTest implements Plugin { + public setup(core: CoreSetup) {} + + public start(core: CoreStart) { + const allUiSettings = core.uiSettings.getAll(); + window.__registeredUiSettings__ = allUiSettings; + } +} diff --git a/x-pack/test/usage_collection/plugins/stack_management_usage_test/public/types.ts b/x-pack/test/usage_collection/plugins/stack_management_usage_test/public/types.ts new file mode 100644 index 00000000000000..c49ec89d94b9fb --- /dev/null +++ b/x-pack/test/usage_collection/plugins/stack_management_usage_test/public/types.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IUiSettingsClient } from 'src/core/public'; +export {}; // Hack to declare this file as a module so TS allows us to extend the Global Window interface + +declare global { + interface Window { + __registeredUiSettings__: ReturnType; + } +} diff --git a/x-pack/test/usage_collection/plugins/stack_management_usage_test/tsconfig.json b/x-pack/test/usage_collection/plugins/stack_management_usage_test/tsconfig.json new file mode 100644 index 00000000000000..f1bf94a38de8fd --- /dev/null +++ b/x-pack/test/usage_collection/plugins/stack_management_usage_test/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "public/**/*.ts", + "public/**/*.tsx", + ], + "exclude": [] +} diff --git a/x-pack/test/usage_collection/test_suites/stack_management_usage/index.ts b/x-pack/test/usage_collection/test_suites/stack_management_usage/index.ts new file mode 100644 index 00000000000000..b8f0cf522605e3 --- /dev/null +++ b/x-pack/test/usage_collection/test_suites/stack_management_usage/index.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { stackManagementSchema } from '../../../../../src/plugins/kibana_usage_collection/server/collectors/management/schema'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + describe('Stack Management', function () { + this.tags('ciGroup1'); + const { common } = getPageObjects(['common']); + const browser = getService('browser'); + + let registeredSettings: Record; + + before(async () => { + await common.navigateToApp('home'); // Navigate to Home to make sure all the appIds are loaded + registeredSettings = await browser.execute(() => window.__registeredUiSettings__); + }); + + it('registers all UI Settings in the UsageStats interface', () => { + const unreportedUISettings = Object.keys(registeredSettings) + .filter((key) => key !== 'buildNum') + .filter((key) => typeof _.get(stackManagementSchema, key) === 'undefined'); + + if (unreportedUISettings.length) { + throw new Error( + `Detected the following unregistered UI Settings in the stack management collector: + ${JSON.stringify(unreportedUISettings, null)} + Update the management collector schema and its UsageStats interface. + Refer to src/plugins/kibana_usage_collection/server/collectors/management/README.md for additional information. + ` + ); + } + }); + + it('registers all sensitive UI settings as keyword type', async () => { + const sensitiveSettings = Object.entries(registeredSettings) + .filter(([, config]) => config.sensitive) + .map(([key]) => key); + + const nonBooleanSensitiveProps = sensitiveSettings + .map((key) => ({ key, ..._.get(stackManagementSchema, key) })) + .filter((keyDescriptor) => keyDescriptor.type !== 'keyword'); + + if (nonBooleanSensitiveProps.length) { + throw new Error( + `Detected the following sensitive UI Settings in the stack management collector not having a 'keyword' type: + ${JSON.stringify(nonBooleanSensitiveProps, null)} + Update each setting in the management collector schema with ({ type: 'keyword' }). + Refer to src/plugins/kibana_usage_collection/server/collectors/management/README.md for additional information. + ` + ); + } + }); + }); +} From 289ca57bb5f90183857d3c78d79673687a659db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ester=20Mart=C3=AD=20Vilaseca?= Date: Wed, 27 Jan 2021 17:27:34 +0100 Subject: [PATCH 32/58] [Metrics UI] Fix Host Overview boxes in Host Detail page (#89299) * change from type:gauge to type:top_n in inventory models * Add test for hostSystemOverview metric * fix lint errors Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../host/metrics/tsvb/host_docker_overview.ts | 2 +- .../host/metrics/tsvb/host_k8s_overview.ts | 2 +- .../host/metrics/tsvb/host_system_overview.ts | 2 +- .../shared/metrics/tsvb/aws_overview.ts | 2 +- .../apis/metrics_ui/metrics.ts | 25 +++++++++++++++++++ 5 files changed, 29 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_docker_overview.ts b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_docker_overview.ts index d7026d7648d371..b8cf094d7bd4c0 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_docker_overview.ts +++ b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_docker_overview.ts @@ -15,7 +15,7 @@ export const hostDockerOverview: TSVBMetricModelCreator = ( index_pattern: indexPattern, interval, time_field: timeField, - type: 'gauge', + type: 'top_n', series: [ { id: 'total', diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_k8s_overview.ts b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_k8s_overview.ts index 86d615231f070a..1488fe5504c0b3 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_k8s_overview.ts +++ b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_k8s_overview.ts @@ -16,7 +16,7 @@ export const hostK8sOverview: TSVBMetricModelCreator = ( index_pattern: indexPattern, interval, time_field: timeField, - type: 'gauge', + type: 'top_n', series: [ { id: 'cpucap', diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_system_overview.ts b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_system_overview.ts index 953c14ab2a9ce9..cbd76dd8e9637a 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_system_overview.ts +++ b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_system_overview.ts @@ -16,7 +16,7 @@ export const hostSystemOverview: TSVBMetricModelCreator = ( index_pattern: indexPattern, interval, time_field: timeField, - type: 'gauge', + type: 'top_n', series: [ { id: 'cpu', diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/aws_overview.ts b/x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/aws_overview.ts index 5ba61d1f92517e..28e1b7860aab43 100644 --- a/x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/aws_overview.ts +++ b/x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/aws_overview.ts @@ -14,7 +14,7 @@ export const awsOverview: TSVBMetricModelCreator = (timeField, indexPattern): TS id_type: 'cloud', interval: '>=5m', time_field: timeField, - type: 'gauge', + type: 'top_n', series: [ { id: 'cpu-util', diff --git a/x-pack/test/api_integration/apis/metrics_ui/metrics.ts b/x-pack/test/api_integration/apis/metrics_ui/metrics.ts index 23b0a96ecd401f..b9cbc58bbd6f76 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/metrics.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/metrics.ts @@ -93,5 +93,30 @@ export default function ({ getService }: FtrProviderContext) { expect(resp.metrics.length).to.equal(2); }); }); + + it('should return multiple values for hostSystemOverview metric', () => { + const data = fetchNodeDetails({ + sourceId: 'default', + metrics: ['hostSystemOverview'], + timerange: { + to: max, + from: min, + interval: '>=1m', + }, + nodeId: 'demo-stack-mysql-01', + nodeType: 'host' as InfraNodeType, + }); + return data.then((resp) => { + if (!resp) { + return; + } + + const hostSystemOverviewMetric = resp.metrics.find( + (metric) => metric.id === 'hostSystemOverview' + ); + + expect(hostSystemOverviewMetric?.series.length).to.be.greaterThan(1); + }); + }); }); } From 7de33830d6a65166528adb51627d92ecdc2c153b Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Wed, 27 Jan 2021 16:57:05 +0000 Subject: [PATCH 33/58] [Discover] Grouping multifields in a doc table (#88560) * [Discover] Grouping multifields in a doc table * Fixing scss selector * Remove unnecessary comment Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/doc_viewer/doc_viewer.scss | 8 + .../components/table/table.test.tsx | 193 +++++++++++++++--- .../application/components/table/table.tsx | 107 ++++++++-- .../components/table/table_row.tsx | 25 ++- 4 files changed, 280 insertions(+), 53 deletions(-) diff --git a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss index 5bae3d64a6b695..95a50b54b53648 100644 --- a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss +++ b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss @@ -19,6 +19,14 @@ padding-top: $euiSizeS; } + .kbnDocViewer__multifield_row:hover td { + background-color: transparent; + } + + .kbnDocViewer__multifield_title { + font-family: $euiFontFamily; + } + .dscFieldName { color: $euiColorDarkShade; } diff --git a/src/plugins/discover/public/application/components/table/table.test.tsx b/src/plugins/discover/public/application/components/table/table.test.tsx index 1ffc0e5af95acd..ac074cf229c77b 100644 --- a/src/plugins/discover/public/application/components/table/table.test.tsx +++ b/src/plugins/discover/public/application/components/table/table.test.tsx @@ -167,30 +167,6 @@ describe('DocViewTable at Discover', () => { }); }); -describe('DocViewTable at Discover Doc', () => { - const hit = { - _index: 'logstash-2014.09.09', - _score: 1, - _type: 'doc', - _id: 'id123', - _source: { - extension: 'html', - not_mapped: 'yes', - }, - }; - // here no action buttons are rendered - const props = { - hit, - indexPattern, - }; - const component = mount(); - const foundLength = findTestSubject(component, 'addInclusiveFilterButton').length; - - it(`renders no action buttons`, () => { - expect(foundLength).toBe(0); - }); -}); - describe('DocViewTable at Discover Context', () => { // here no toggleColumnButtons are rendered const hit = { @@ -243,3 +219,172 @@ describe('DocViewTable at Discover Context', () => { expect(component.html() !== html).toBeTruthy(); }); }); + +describe('DocViewTable at Discover Doc', () => { + const hit = { + _index: 'logstash-2014.09.09', + _score: 1, + _type: 'doc', + _id: 'id123', + _source: { + extension: 'html', + not_mapped: 'yes', + }, + }; + // here no action buttons are rendered + const props = { + hit, + indexPattern, + }; + const component = mount(); + const foundLength = findTestSubject(component, 'addInclusiveFilterButton').length; + + it(`renders no action buttons`, () => { + expect(foundLength).toBe(0); + }); +}); + +describe('DocViewTable at Discover Doc with Fields API', () => { + const indexPatterneCommerce = ({ + fields: { + getAll: () => [ + { + name: '_index', + type: 'string', + scripted: false, + filterable: true, + }, + { + name: 'category', + type: 'string', + scripted: false, + filterable: true, + }, + { + name: 'category.keyword', + displayName: 'category.keyword', + type: 'string', + scripted: false, + filterable: true, + spec: { + subType: { + multi: { + parent: 'category', + }, + }, + }, + }, + { + name: 'customer_first_name', + type: 'string', + scripted: false, + filterable: true, + }, + { + name: 'customer_first_name.keyword', + displayName: 'customer_first_name.keyword', + type: 'string', + scripted: false, + filterable: false, + spec: { + subType: { + multi: { + parent: 'customer_first_name', + }, + }, + }, + }, + { + name: 'customer_first_name.nickname', + displayName: 'customer_first_name.nickname', + type: 'string', + scripted: false, + filterable: false, + spec: { + subType: { + multi: { + parent: 'customer_first_name', + }, + }, + }, + }, + ], + }, + metaFields: ['_index', '_type', '_score', '_id'], + flattenHit: jest.fn((hit) => { + const result = {} as Record; + Object.keys(hit).forEach((key) => { + if (key !== 'fields') { + result[key] = hit[key]; + } else { + Object.keys(hit.fields).forEach((field) => { + result[field] = hit.fields[field]; + }); + } + }); + return result; + }), + formatHit: jest.fn((hit) => { + const result = {} as Record; + Object.keys(hit).forEach((key) => { + if (key !== 'fields') { + result[key] = hit[key]; + } else { + Object.keys(hit.fields).forEach((field) => { + result[field] = hit.fields[field]; + }); + } + }); + return result; + }), + } as unknown) as IndexPattern; + + indexPatterneCommerce.fields.getByName = (name: string) => { + return indexPatterneCommerce.fields.getAll().find((field) => field.name === name); + }; + + const fieldsHit = { + _index: 'logstash-2014.09.09', + _type: 'doc', + _id: 'id123', + _score: null, + fields: { + category: "Women's Clothing", + 'category.keyword': "Women's Clothing", + customer_first_name: 'Betty', + 'customer_first_name.keyword': 'Betty', + 'customer_first_name.nickname': 'Betsy', + }, + }; + const props = { + hit: fieldsHit, + columns: ['Document'], + indexPattern: indexPatterneCommerce, + filter: jest.fn(), + onAddColumn: jest.fn(), + onRemoveColumn: jest.fn(), + }; + // @ts-ignore + const component = mount(); + it('renders multifield rows', () => { + const categoryMultifieldRow = findTestSubject( + component, + 'tableDocViewRow-multifieldsTitle-category' + ); + expect(categoryMultifieldRow.length).toBe(1); + const categoryKeywordRow = findTestSubject(component, 'tableDocViewRow-category.keyword'); + expect(categoryKeywordRow.length).toBe(1); + + const customerNameMultiFieldRow = findTestSubject( + component, + 'tableDocViewRow-multifieldsTitle-customer_first_name' + ); + expect(customerNameMultiFieldRow.length).toBe(1); + expect(findTestSubject(component, 'tableDocViewRow-customer_first_name.keyword').length).toBe( + 1 + ); + expect(findTestSubject(component, 'tableDocViewRow-customer_first_name.nickname').length).toBe( + 1 + ); + }); +}); diff --git a/src/plugins/discover/public/application/components/table/table.tsx b/src/plugins/discover/public/application/components/table/table.tsx index 090df8baba409e..7528828a06f972 100644 --- a/src/plugins/discover/public/application/components/table/table.tsx +++ b/src/plugins/discover/public/application/components/table/table.tsx @@ -5,8 +5,8 @@ * compliance with, at your election, the Elastic License or the Server Side * Public License, v 1. */ - -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; import { DocViewTableRow } from './table_row'; import { trimAngularSpan } from './table_helper'; import { isNestedFieldParent } from '../../helpers/nested_fields'; @@ -23,6 +23,36 @@ export function DocViewTable({ onRemoveColumn, }: DocViewRenderProps) { const [fieldRowOpen, setFieldRowOpen] = useState({} as Record); + const [multiFields, setMultiFields] = useState({} as Record); + const [fieldsWithParents, setFieldsWithParents] = useState([] as string[]); + + useEffect(() => { + if (!indexPattern) { + return; + } + const mapping = indexPattern.fields.getByName; + const flattened = indexPattern.flattenHit(hit); + const map: Record = {}; + const arr: string[] = []; + + Object.keys(flattened).forEach((key) => { + const field = mapping(key); + + if (field && field.spec?.subType?.multi?.parent) { + const parent = field.spec.subType.multi.parent; + if (!map[parent]) { + map[parent] = [] as string[]; + } + const value = map[parent]; + value.push(key); + map[parent] = value; + arr.push(key); + } + }); + setMultiFields(map); + setFieldsWithParents(arr); + }, [indexPattern, hit]); + if (!indexPattern) { return null; } @@ -34,11 +64,13 @@ export function DocViewTable({ fieldRowOpen[field] = !fieldRowOpen[field]; setFieldRowOpen({ ...fieldRowOpen }); } - return ( {Object.keys(flattened) + .filter((field) => { + return !fieldsWithParents.includes(field); + }) .sort((fieldA, fieldB) => { const mappingA = mapping(fieldA); const mappingB = mapping(fieldB); @@ -67,23 +99,60 @@ export function DocViewTable({ const fieldType = isNestedFieldParent(field, indexPattern) ? 'nested' : indexPattern.fields.getByName(field)?.type; - return ( - toggleValueCollapse(field)} - onToggleColumn={toggleColumn} - value={value} - valueRaw={valueRaw} - /> + + toggleValueCollapse(field)} + onToggleColumn={toggleColumn} + value={value} + valueRaw={valueRaw} + /> + {multiFields[field] ? ( + + + + + ) : null} + {multiFields[field] + ? multiFields[field].map((multiField) => { + return ( + toggleValueCollapse(field)} + onToggleColumn={toggleColumn} + value={value} + valueRaw={valueRaw} + /> + ); + }) + : null} + ); })} diff --git a/src/plugins/discover/public/application/components/table/table_row.tsx b/src/plugins/discover/public/application/components/table/table_row.tsx index 61f9fa50091c18..2b91a757e9bc23 100644 --- a/src/plugins/discover/public/application/components/table/table_row.tsx +++ b/src/plugins/discover/public/application/components/table/table_row.tsx @@ -18,7 +18,7 @@ import { DocViewTableRowIconUnderscore } from './table_row_icon_underscore'; import { FieldName } from '../field_name/field_name'; export interface Props { - field: string; + field?: string; fieldMapping?: FieldMapping; fieldType: string; displayUnderscoreWarning: boolean; @@ -51,25 +51,30 @@ export function DocViewTableRow({ kbnDocViewer__value: true, 'truncate-by-height': isCollapsible && isCollapsed, }); - + const key = field ? field : fieldMapping?.displayName; return ( - +
  + + {i18n.translate('discover.fieldChooser.discoverField.multiFields', { + defaultMessage: 'Multi fields', + })} + +
- + {field ? ( + + ) : ( +   + )} {isCollapsible && ( )} {displayUnderscoreWarning && } + {field ? null :
{key}: 
}
Date: Wed, 27 Jan 2021 17:58:42 +0100 Subject: [PATCH 34/58] [Discover] Merge discover.tsx and discover_legacy.tsx (#88465) --- .../public/application/angular/discover.js | 5 +- .../application/angular/discover_legacy.html | 4 +- .../doc_table/create_doc_table_react.tsx | 33 +- .../components/create_discover_directive.ts | 5 +- .../create_discover_legacy_directive.ts | 45 -- ...over_legacy.test.tsx => discover.test.tsx} | 16 +- .../application/components/discover.tsx | 125 +++-- .../discover_grid/discover_grid.tsx | 8 +- .../discover_grid/discover_grid_columns.tsx | 7 +- .../components/discover_legacy.tsx | 517 ------------------ .../public/application/components/types.ts | 179 ++++++ .../application/helpers/columns.test.ts | 46 ++ .../public/application/helpers/columns.ts | 22 + .../discover/public/get_inner_angular.ts | 2 - test/functional/apps/discover/_data_grid.ts | 4 +- .../apps/discover/_data_grid_field_data.ts | 2 +- 16 files changed, 387 insertions(+), 633 deletions(-) delete mode 100644 src/plugins/discover/public/application/components/create_discover_legacy_directive.ts rename src/plugins/discover/public/application/components/{discover_legacy.test.tsx => discover.test.tsx} (89%) delete mode 100644 src/plugins/discover/public/application/components/discover_legacy.tsx create mode 100644 src/plugins/discover/public/application/components/types.ts create mode 100644 src/plugins/discover/public/application/helpers/columns.test.ts create mode 100644 src/plugins/discover/public/application/helpers/columns.ts diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js index 5c26680c7cc458..41c80a717ce75c 100644 --- a/src/plugins/discover/public/application/angular/discover.js +++ b/src/plugins/discover/public/application/angular/discover.js @@ -24,7 +24,6 @@ import { import { getSortArray } from './doc_table'; import * as columnActions from './doc_table/actions/columns'; import indexTemplateLegacy from './discover_legacy.html'; -import indexTemplateGrid from './discover_datagrid.html'; import { addHelpMenuToAppChrome } from '../components/help_menu/help_menu_util'; import { discoverResponseHandler } from './response_handler'; import { @@ -116,9 +115,7 @@ app.config(($routeProvider) => { }; const discoverRoute = { ...defaults, - template: getServices().uiSettings.get('doc_table:legacy', true) - ? indexTemplateLegacy - : indexTemplateGrid, + template: indexTemplateLegacy, reloadOnSearch: false, resolve: { savedObjects: function ($route, Promise) { diff --git a/src/plugins/discover/public/application/angular/discover_legacy.html b/src/plugins/discover/public/application/angular/discover_legacy.html index 9383980fd9fd6f..76e5c568ffde6a 100644 --- a/src/plugins/discover/public/application/angular/discover_legacy.html +++ b/src/plugins/discover/public/application/angular/discover_legacy.html @@ -1,5 +1,5 @@ - - + diff --git a/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx b/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx index 06b6e504832e4e..cbd93feb835a0d 100644 --- a/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx +++ b/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx @@ -9,8 +9,11 @@ import angular, { auto, ICompileService, IScope } from 'angular'; import { render } from 'react-dom'; import React, { useRef, useEffect } from 'react'; +import { EuiButtonEmpty } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; import { getServices, IIndexPattern } from '../../../kibana_services'; import { IndexPatternField } from '../../../../../data/common/index_patterns'; + export type AngularScope = IScope; export interface AngularDirective { @@ -83,9 +86,11 @@ export interface DocTableLegacyProps { indexPattern: IIndexPattern; minimumVisibleRows: number; onAddColumn?: (column: string) => void; + onBackToTop: () => void; onSort?: (sort: string[][]) => void; onMoveColumn?: (columns: string, newIdx: number) => void; onRemoveColumn?: (column: string) => void; + sampleSize: number; sort?: string[][]; useNewFieldsApi?: boolean; } @@ -120,5 +125,31 @@ export function DocTableLegacy(renderProps: DocTableLegacyProps) { return renderFn(ref.current, renderProps); } }, [renderFn, renderProps]); - return
; + return ( +
+
+ {renderProps.rows.length === renderProps.sampleSize ? ( +
+ + + + +
+ ) : ( + + ​ + + )} +
+ ); } diff --git a/src/plugins/discover/public/application/components/create_discover_directive.ts b/src/plugins/discover/public/application/components/create_discover_directive.ts index 42b99b635a7911..10439488f4bc7b 100644 --- a/src/plugins/discover/public/application/components/create_discover_directive.ts +++ b/src/plugins/discover/public/application/components/create_discover_directive.ts @@ -17,18 +17,21 @@ export function createDiscoverDirective(reactDirective: any) { ['histogramData', { watchDepth: 'reference' }], ['hits', { watchDepth: 'reference' }], ['indexPattern', { watchDepth: 'reference' }], + ['minimumVisibleRows', { watchDepth: 'reference' }], ['onAddColumn', { watchDepth: 'reference' }], ['onAddFilter', { watchDepth: 'reference' }], ['onChangeInterval', { watchDepth: 'reference' }], + ['onMoveColumn', { watchDepth: 'reference' }], ['onRemoveColumn', { watchDepth: 'reference' }], ['onSetColumns', { watchDepth: 'reference' }], + ['onSkipBottomButtonClick', { watchDepth: 'reference' }], ['onSort', { watchDepth: 'reference' }], ['opts', { watchDepth: 'reference' }], ['resetQuery', { watchDepth: 'reference' }], ['resultState', { watchDepth: 'reference' }], ['rows', { watchDepth: 'reference' }], + ['savedSearch', { watchDepth: 'reference' }], ['searchSource', { watchDepth: 'reference' }], - ['setColumns', { watchDepth: 'reference' }], ['setIndexPattern', { watchDepth: 'reference' }], ['showSaveQuery', { watchDepth: 'reference' }], ['state', { watchDepth: 'reference' }], diff --git a/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts b/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts deleted file mode 100644 index b2b9fd38f73b14..00000000000000 --- a/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { DiscoverLegacy } from './discover_legacy'; - -export function createDiscoverLegacyDirective(reactDirective: any) { - return reactDirective(DiscoverLegacy, [ - ['fetch', { watchDepth: 'reference' }], - ['fetchCounter', { watchDepth: 'reference' }], - ['fetchError', { watchDepth: 'reference' }], - ['fieldCounts', { watchDepth: 'reference' }], - ['histogramData', { watchDepth: 'reference' }], - ['hits', { watchDepth: 'reference' }], - ['indexPattern', { watchDepth: 'reference' }], - ['minimumVisibleRows', { watchDepth: 'reference' }], - ['onAddColumn', { watchDepth: 'reference' }], - ['onAddFilter', { watchDepth: 'reference' }], - ['onChangeInterval', { watchDepth: 'reference' }], - ['onMoveColumn', { watchDepth: 'reference' }], - ['onRemoveColumn', { watchDepth: 'reference' }], - ['onSetColumns', { watchDepth: 'reference' }], - ['onSkipBottomButtonClick', { watchDepth: 'reference' }], - ['onSort', { watchDepth: 'reference' }], - ['opts', { watchDepth: 'reference' }], - ['resetQuery', { watchDepth: 'reference' }], - ['resultState', { watchDepth: 'reference' }], - ['rows', { watchDepth: 'reference' }], - ['savedSearch', { watchDepth: 'reference' }], - ['searchSource', { watchDepth: 'reference' }], - ['setIndexPattern', { watchDepth: 'reference' }], - ['showSaveQuery', { watchDepth: 'reference' }], - ['state', { watchDepth: 'reference' }], - ['timefilterUpdateHandler', { watchDepth: 'reference' }], - ['timeRange', { watchDepth: 'reference' }], - ['topNavMenu', { watchDepth: 'reference' }], - ['updateQuery', { watchDepth: 'reference' }], - ['updateSavedQueryId', { watchDepth: 'reference' }], - ['useNewFieldsApi', { watchDepth: 'reference' }], - ]); -} diff --git a/src/plugins/discover/public/application/components/discover_legacy.test.tsx b/src/plugins/discover/public/application/components/discover.test.tsx similarity index 89% rename from src/plugins/discover/public/application/components/discover_legacy.test.tsx rename to src/plugins/discover/public/application/components/discover.test.tsx index 04f294912d49ee..3088ca45f79417 100644 --- a/src/plugins/discover/public/application/components/discover_legacy.test.tsx +++ b/src/plugins/discover/public/application/components/discover.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { shallowWithIntl } from '@kbn/test/jest'; -import { DiscoverLegacy } from './discover_legacy'; +import { Discover } from './discover'; import { inspectorPluginMock } from '../../../../inspector/public/mocks'; import { esHits } from '../../__mocks__/es_hits'; import { indexPatternMock } from '../../__mocks__/index_pattern'; @@ -19,7 +19,7 @@ import { savedSearchMock } from '../../__mocks__/saved_search'; import { createSearchSourceMock } from '../../../../data/common/search/search_source/mocks'; import { dataPluginMock } from '../../../../data/public/mocks'; import { createFilterManagerMock } from '../../../../data/public/query/filter_manager/filter_manager.mock'; -import { uiSettingsMock } from '../../__mocks__/ui_settings'; +import { uiSettingsMock as mockUiSettings } from '../../__mocks__/ui_settings'; import { IndexPattern, IndexPatternAttributes } from '../../../../data/common/index_patterns'; import { SavedObject } from '../../../../../core/types'; import { navigationPluginMock } from '../../../../navigation/public/mocks'; @@ -40,6 +40,7 @@ jest.mock('../../kibana_services', () => { }, }, navigation: mockNavigation, + uiSettings: mockUiSettings, }), }; }); @@ -53,6 +54,7 @@ function getProps(indexPattern: IndexPattern) { save: true, }, }, + uiSettings: mockUiSettings, } as unknown) as DiscoverServices; return { @@ -72,7 +74,7 @@ function getProps(indexPattern: IndexPattern) { onSkipBottomButtonClick: jest.fn(), onSort: jest.fn(), opts: { - config: uiSettingsMock, + config: mockUiSettings, data: dataPluginMock.createStartContract(), fixedScroll: jest.fn(), filterManager: createFilterManagerMock(), @@ -105,15 +107,13 @@ function getProps(indexPattern: IndexPattern) { }; } -describe('Descover legacy component', () => { +describe('Discover component', () => { test('selected index pattern without time field displays no chart toggle', () => { - const component = shallowWithIntl(); + const component = shallowWithIntl(); expect(component.find('[data-test-subj="discoverChartToggle"]').length).toBe(0); }); test('selected index pattern with time field displays chart toggle', () => { - const component = shallowWithIntl( - - ); + const component = shallowWithIntl(); expect(component.find('[data-test-subj="discoverChartToggle"]').length).toBe(1); }); }); diff --git a/src/plugins/discover/public/application/components/discover.tsx b/src/plugins/discover/public/application/components/discover.tsx index 704e7a9c02e1be..5653ef4f574356 100644 --- a/src/plugins/discover/public/application/components/discover.tsx +++ b/src/plugins/discover/public/application/components/discover.tsx @@ -26,25 +26,30 @@ import classNames from 'classnames'; import { HitsCounter } from './hits_counter'; import { TimechartHeader } from './timechart_header'; import { getServices } from '../../kibana_services'; -import { DiscoverUninitialized, DiscoverHistogram } from '../angular/directives'; +import { DiscoverHistogram, DiscoverUninitialized } from '../angular/directives'; import { DiscoverNoResults } from './no_results'; import { LoadingSpinner } from './loading_spinner/loading_spinner'; +import { DocTableLegacy, DocTableLegacyProps } from '../angular/doc_table/create_doc_table_react'; +import { SkipBottomButton } from './skip_bottom_button'; import { search } from '../../../../data/public'; import { DiscoverSidebarResponsive, DiscoverSidebarResponsiveProps, } from './sidebar/discover_sidebar_responsive'; -import { DiscoverProps } from './discover_legacy'; +import { DiscoverProps } from './types'; +import { getDisplayedColumns } from '../helpers/columns'; import { SortPairArr } from '../angular/doc_table/lib/get_sort'; import { DiscoverGrid, DiscoverGridProps } from './discover_grid/discover_grid'; +import { SEARCH_FIELDS_FROM_SOURCE } from '../../../common'; -export const SidebarMemoized = React.memo((props: DiscoverSidebarResponsiveProps) => ( +const DocTableLegacyMemoized = React.memo((props: DocTableLegacyProps) => ( + +)); +const SidebarMemoized = React.memo((props: DiscoverSidebarResponsiveProps) => ( )); -export const DataGridMemoized = React.memo((props: DiscoverGridProps) => ( - -)); +const DataGridMemoized = React.memo((props: DiscoverGridProps) => ); export function Discover({ fetch, @@ -54,11 +59,14 @@ export function Discover({ histogramData, hits, indexPattern, + minimumVisibleRows, onAddColumn, onAddFilter, onChangeInterval, + onMoveColumn, onRemoveColumn, onSetColumns, + onSkipBottomButtonClick, onSort, opts, resetQuery, @@ -66,7 +74,6 @@ export function Discover({ rows, searchSource, setIndexPattern, - showSaveQuery, state, timefilterUpdateHandler, timeRange, @@ -76,6 +83,11 @@ export function Discover({ }: DiscoverProps) { const scrollableDesktop = useRef(null); const collapseIcon = useRef(null); + const isMobile = () => { + // collapse icon isn't displayed in mobile view, use it to detect which view is displayed + return collapseIcon && !collapseIcon.current; + }; + const [toggleOn, toggleChart] = useState(true); const [isSidebarClosed, setIsSidebarClosed] = useState(false); const services = getServices(); @@ -88,18 +100,8 @@ export function Discover({ ? bucketAggConfig.buckets?.getInterval() : undefined; const contentCentered = resultState === 'uninitialized'; - const showTimeCol = !config.get('doc_table:hideTimeColumn', false) && indexPattern.timeFieldName; - const columns = - state.columns && - state.columns.length > 0 && - // check if all columns where removed except the configured timeField (this can't be removed) - !(state.columns.length === 1 && state.columns[0] === indexPattern.timeFieldName) - ? state.columns - : ['_source']; - // if columns include _source this is considered as default view, so you can't remove columns - // until you add a column using Discover's sidebar - const defaultColumns = columns.includes('_source'); - + const isLegacy = services.uiSettings.get('doc_table:legacy'); + const useNewFieldsApi = !services.uiSettings.get(SEARCH_FIELDS_FROM_SOURCE); return ( @@ -114,7 +116,7 @@ export function Discover({ savedQueryId={state.savedQuery} screenTitle={savedSearch.title} showDatePicker={indexPattern.isTimeBased()} - showSaveQuery={showSaveQuery} + showSaveQuery={!!services.capabilities.discover.saveQuery} showSearchBar={true} useDefaultBehaviors={true} /> @@ -137,6 +139,7 @@ export function Discover({ setIndexPattern={setIndexPattern} isClosed={isSidebarClosed} trackUiMetric={trackUiMetric} + useNewFieldsApi={useNewFieldsApi} /> @@ -207,24 +210,28 @@ export function Discover({ /> )} - - { - toggleChart(!toggleOn); - }} - > - {toggleOn - ? i18n.translate('discover.hideChart', { - defaultMessage: 'Hide chart', - }) - : i18n.translate('discover.showChart', { - defaultMessage: 'Show chart', - })} - - + {opts.timefield && ( + + { + toggleChart(!toggleOn); + }} + data-test-subj="discoverChartToggle" + > + {toggleOn + ? i18n.translate('discover.hideChart', { + defaultMessage: 'Hide chart', + }) + : i18n.translate('discover.showChart', { + defaultMessage: 'Show chart', + })} + + + )} + {isLegacy && } {toggleOn && opts.timefield && ( @@ -238,7 +245,10 @@ export function Discover({ className="dscTimechart" > {opts.chartAggConfigs && histogramData && rows.length !== 0 && ( -
+
- {rows && rows.length && ( + {isLegacy && rows && rows.length && ( + { + if (scrollableDesktop && scrollableDesktop.current) { + scrollableDesktop.current.focus(); + } + // Only the desktop one needs to target a specific container + if (!isMobile() && scrollableDesktop.current) { + scrollableDesktop.current.scrollTo(0, 0); + } else if (window) { + window.scrollTo(0, 0); + } + }} + onFilter={onAddFilter} + onMoveColumn={onMoveColumn} + onRemoveColumn={onRemoveColumn} + onSort={onSort} + sampleSize={opts.sampleSize} + useNewFieldsApi={useNewFieldsApi} + /> + )} + {!isLegacy && rows && rows.length && (
{ export const DiscoverGrid = ({ ariaLabelledBy, columns, - defaultColumns, indexPattern, onAddColumn, onFilter, @@ -144,6 +137,7 @@ export const DiscoverGrid = ({ sort, }: DiscoverGridProps) => { const [expanded, setExpanded] = useState(undefined); + const defaultColumns = columns.includes('_source'); /** * Pagination diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx index 481d308cf88a9a..6a247ad951c9b2 100644 --- a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx @@ -48,7 +48,12 @@ export function buildEuiGridColumn( id: columnName, schema: getSchemaByKbnType(indexPatternField?.type), isSortable: indexPatternField?.sortable, - display: indexPatternField?.displayName, + display: + columnName === '_source' + ? i18n.translate('discover.grid.documentHeader', { + defaultMessage: 'Document', + }) + : indexPatternField?.displayName, actions: { showHide: defaultColumns || columnName === indexPattern.timeFieldName diff --git a/src/plugins/discover/public/application/components/discover_legacy.tsx b/src/plugins/discover/public/application/components/discover_legacy.tsx deleted file mode 100644 index 1b90b845a8fff1..00000000000000 --- a/src/plugins/discover/public/application/components/discover_legacy.tsx +++ /dev/null @@ -1,517 +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 - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import './discover.scss'; - -import React, { useState, useRef } from 'react'; -import { - EuiButtonEmpty, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiHideFor, - EuiPage, - EuiPageBody, - EuiPageContent, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; -import { IUiSettingsClient, MountPoint } from 'kibana/public'; -import classNames from 'classnames'; -import { HitsCounter } from './hits_counter'; -import { TimechartHeader } from './timechart_header'; -import { getServices, IndexPattern } from '../../kibana_services'; -import { DiscoverUninitialized, DiscoverHistogram } from '../angular/directives'; -import { DiscoverNoResults } from './no_results'; -import { LoadingSpinner } from './loading_spinner/loading_spinner'; -import { DocTableLegacy, DocTableLegacyProps } from '../angular/doc_table/create_doc_table_react'; -import { SkipBottomButton } from './skip_bottom_button'; -import { - search, - ISearchSource, - TimeRange, - Query, - IndexPatternAttributes, - DataPublicPluginStart, - AggConfigs, - FilterManager, -} from '../../../../data/public'; -import { Chart } from '../angular/helpers/point_series'; -import { AppState } from '../angular/discover_state'; -import { SavedSearch } from '../../saved_searches'; -import { SavedObject } from '../../../../../core/types'; -import { TopNavMenuData } from '../../../../navigation/public'; -import { - DiscoverSidebarResponsive, - DiscoverSidebarResponsiveProps, -} from './sidebar/discover_sidebar_responsive'; -import { DocViewFilterFn, ElasticSearchHit } from '../doc_views/doc_views_types'; - -export interface DiscoverProps { - /** - * Function to fetch documents from Elasticsearch - */ - fetch: () => void; - /** - * Counter how often data was fetched (used for testing) - */ - fetchCounter: number; - /** - * Error in case of a failing document fetch - */ - fetchError?: Error; - /** - * Statistics by fields calculated using the fetched documents - */ - fieldCounts: Record; - /** - * Histogram aggregation data - */ - histogramData?: Chart; - /** - * Number of documents found by recent fetch - */ - hits: number; - /** - * Current IndexPattern - */ - indexPattern: IndexPattern; - /** - * Value needed for legacy "infinite" loading functionality - * Determins how much records are rendered using the legacy table - * Increased when scrolling down - */ - minimumVisibleRows: number; - /** - * Function to add a column to state - */ - onAddColumn: (column: string) => void; - /** - * Function to add a filter to state - */ - onAddFilter: DocViewFilterFn; - /** - * Function to change the used time interval of the date histogram - */ - onChangeInterval: (interval: string) => void; - /** - * Function to move a given column to a given index, used in legacy table - */ - onMoveColumn: (columns: string, newIdx: number) => void; - /** - * Function to remove a given column from state - */ - onRemoveColumn: (column: string) => void; - /** - * Function to replace columns in state - */ - onSetColumns: (columns: string[]) => void; - /** - * Function to scroll down the legacy table to the bottom - */ - onSkipBottomButtonClick: () => void; - /** - * Function to change sorting of the table, triggers a fetch - */ - onSort: (sort: string[][]) => void; - opts: { - /** - * Date histogram aggregation config - */ - chartAggConfigs?: AggConfigs; - /** - * Client of uiSettings - */ - config: IUiSettingsClient; - /** - * Data plugin - */ - data: DataPublicPluginStart; - /** - * Data plugin filter manager - */ - filterManager: FilterManager; - /** - * List of available index patterns - */ - indexPatternList: Array>; - /** - * The number of documents that can be displayed in the table/grid - */ - sampleSize: number; - /** - * Current instance of SavedSearch - */ - savedSearch: SavedSearch; - /** - * Function to set the header menu - */ - setHeaderActionMenu: (menuMount: MountPoint | undefined) => void; - /** - * Timefield of the currently used index pattern - */ - timefield: string; - /** - * Function to set the current state - */ - setAppState: (state: Partial) => void; - }; - /** - * Function to reset the current query - */ - resetQuery: () => void; - /** - * Current state of the actual query, one of 'uninitialized', 'loading' ,'ready', 'none' - */ - resultState: string; - /** - * Array of document of the recent successful search request - */ - rows: ElasticSearchHit[]; - /** - * Instance of SearchSource, the high level search API - */ - searchSource: ISearchSource; - /** - * Function to change the current index pattern - */ - setIndexPattern: (id: string) => void; - /** - * Determines whether the user should be able to use the save query feature - */ - showSaveQuery: boolean; - /** - * Current app state of URL - */ - state: AppState; - /** - * Function to update the time filter - */ - timefilterUpdateHandler: (ranges: { from: number; to: number }) => void; - /** - * Currently selected time range - */ - timeRange?: { from: string; to: string }; - /** - * Menu data of top navigation (New, save ...) - */ - topNavMenu: TopNavMenuData[]; - /** - * Function to update the actual query - */ - updateQuery: (payload: { dateRange: TimeRange; query?: Query }, isUpdate?: boolean) => void; - /** - * Function to update the actual savedQuery id - */ - updateSavedQueryId: (savedQueryId?: string) => void; - useNewFieldsApi?: boolean; -} - -export const DocTableLegacyMemoized = React.memo((props: DocTableLegacyProps) => ( - -)); -export const SidebarMemoized = React.memo((props: DiscoverSidebarResponsiveProps) => ( - -)); - -export function DiscoverLegacy({ - fetch, - fetchCounter, - fieldCounts, - fetchError, - histogramData, - hits, - indexPattern, - minimumVisibleRows, - onAddColumn, - onAddFilter, - onChangeInterval, - onMoveColumn, - onRemoveColumn, - onSkipBottomButtonClick, - onSort, - opts, - resetQuery, - resultState, - rows, - searchSource, - setIndexPattern, - showSaveQuery, - state, - timefilterUpdateHandler, - timeRange, - topNavMenu, - updateQuery, - updateSavedQueryId, - useNewFieldsApi, -}: DiscoverProps) { - const scrollableDesktop = useRef(null); - const collapseIcon = useRef(null); - const isMobile = () => { - // collapse icon isn't displayed in mobile view, use it to detect which view is displayed - return collapseIcon && !collapseIcon.current; - }; - - const [toggleOn, toggleChart] = useState(true); - const [isSidebarClosed, setIsSidebarClosed] = useState(false); - const services = getServices(); - const { TopNavMenu } = services.navigation.ui; - const { trackUiMetric } = services; - const { savedSearch, indexPatternList } = opts; - const bucketAggConfig = opts.chartAggConfigs?.aggs[1]; - const bucketInterval = - bucketAggConfig && search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig) - ? bucketAggConfig.buckets?.getInterval() - : undefined; - const contentCentered = resultState === 'uninitialized'; - - const getDisplayColumns = () => { - if (!state.columns) { - return []; - } - const columns = [...state.columns]; - if (useNewFieldsApi) { - return columns.filter((column) => column !== '_source'); - } - return columns.length === 0 ? ['_source'] : columns; - }; - - return ( - - - - -

- {savedSearch.title} -

- - - - - - - setIsSidebarClosed(!isSidebarClosed)} - data-test-subj="collapseSideBarButton" - aria-controls="discover-sidebar" - aria-expanded={isSidebarClosed ? 'false' : 'true'} - aria-label="Toggle sidebar" - buttonRef={collapseIcon} - /> - - - - - {resultState === 'none' && ( - - )} - {resultState === 'uninitialized' && } - {resultState === 'loading' && } - {resultState === 'ready' && ( - - - - - 0 ? hits : 0} - showResetButton={!!(savedSearch && savedSearch.id)} - onResetQuery={resetQuery} - /> - - {toggleOn && ( - - - - )} - {opts.timefield && ( - - { - toggleChart(!toggleOn); - }} - data-test-subj="discoverChartToggle" - > - {toggleOn - ? i18n.translate('discover.hideChart', { - defaultMessage: 'Hide chart', - }) - : i18n.translate('discover.showChart', { - defaultMessage: 'Show chart', - })} - - - )} - - - - {toggleOn && opts.timefield && ( - -
- {opts.chartAggConfigs && rows.length !== 0 && histogramData && ( -
- -
- )} -
-
- )} - - -
-

- -

- {rows && rows.length && ( -
- - {rows.length === opts.sampleSize ? ( -
- - - { - if (scrollableDesktop && scrollableDesktop.current) { - scrollableDesktop.current.focus(); - } - // Only the desktop one needs to target a specific container - if (!isMobile() && scrollableDesktop.current) { - scrollableDesktop.current.scrollTo(0, 0); - } else if (window) { - window.scrollTo(0, 0); - } - }} - > - - -
- ) : ( - - ​ - - )} -
- )} -
-
-
- )} -
-
-
-
-
-
- ); -} diff --git a/src/plugins/discover/public/application/components/types.ts b/src/plugins/discover/public/application/components/types.ts new file mode 100644 index 00000000000000..fe0d40f222f237 --- /dev/null +++ b/src/plugins/discover/public/application/components/types.ts @@ -0,0 +1,179 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ +import { IUiSettingsClient, MountPoint, SavedObject } from 'kibana/public'; +import { Chart } from '../angular/helpers/point_series'; +import { IndexPattern } from '../../../../data/common/index_patterns/index_patterns'; +import { DocViewFilterFn, ElasticSearchHit } from '../doc_views/doc_views_types'; +import { AggConfigs } from '../../../../data/common/search/aggs'; + +import { + DataPublicPluginStart, + FilterManager, + IndexPatternAttributes, + ISearchSource, + Query, + TimeRange, +} from '../../../../data/public'; +import { SavedSearch } from '../../saved_searches'; +import { AppState } from '../angular/discover_state'; +import { TopNavMenuData } from '../../../../navigation/public'; + +export interface DiscoverProps { + /** + * Function to fetch documents from Elasticsearch + */ + fetch: () => void; + /** + * Counter how often data was fetched (used for testing) + */ + fetchCounter: number; + /** + * Error in case of a failing document fetch + */ + fetchError?: Error; + /** + * Statistics by fields calculated using the fetched documents + */ + fieldCounts: Record; + /** + * Histogram aggregation data + */ + histogramData?: Chart; + /** + * Number of documents found by recent fetch + */ + hits: number; + /** + * Current IndexPattern + */ + indexPattern: IndexPattern; + /** + * Value needed for legacy "infinite" loading functionality + * Determins how much records are rendered using the legacy table + * Increased when scrolling down + */ + minimumVisibleRows: number; + /** + * Function to add a column to state + */ + onAddColumn: (column: string) => void; + /** + * Function to add a filter to state + */ + onAddFilter: DocViewFilterFn; + /** + * Function to change the used time interval of the date histogram + */ + onChangeInterval: (interval: string) => void; + /** + * Function to move a given column to a given index, used in legacy table + */ + onMoveColumn: (columns: string, newIdx: number) => void; + /** + * Function to remove a given column from state + */ + onRemoveColumn: (column: string) => void; + /** + * Function to replace columns in state + */ + onSetColumns: (columns: string[]) => void; + /** + * Function to scroll down the legacy table to the bottom + */ + onSkipBottomButtonClick: () => void; + /** + * Function to change sorting of the table, triggers a fetch + */ + onSort: (sort: string[][]) => void; + opts: { + /** + * Date histogram aggregation config + */ + chartAggConfigs?: AggConfigs; + /** + * Client of uiSettings + */ + config: IUiSettingsClient; + /** + * Data plugin + */ + data: DataPublicPluginStart; + /** + * Data plugin filter manager + */ + filterManager: FilterManager; + /** + * List of available index patterns + */ + indexPatternList: Array>; + /** + * The number of documents that can be displayed in the table/grid + */ + sampleSize: number; + /** + * Current instance of SavedSearch + */ + savedSearch: SavedSearch; + /** + * Function to set the header menu + */ + setHeaderActionMenu: (menuMount: MountPoint | undefined) => void; + /** + * Timefield of the currently used index pattern + */ + timefield: string; + /** + * Function to set the current state + */ + setAppState: (state: Partial) => void; + }; + /** + * Function to reset the current query + */ + resetQuery: () => void; + /** + * Current state of the actual query, one of 'uninitialized', 'loading' ,'ready', 'none' + */ + resultState: string; + /** + * Array of document of the recent successful search request + */ + rows: ElasticSearchHit[]; + /** + * Instance of SearchSource, the high level search API + */ + searchSource: ISearchSource; + /** + * Function to change the current index pattern + */ + setIndexPattern: (id: string) => void; + /** + * Current app state of URL + */ + state: AppState; + /** + * Function to update the time filter + */ + timefilterUpdateHandler: (ranges: { from: number; to: number }) => void; + /** + * Currently selected time range + */ + timeRange?: { from: string; to: string }; + /** + * Menu data of top navigation (New, save ...) + */ + topNavMenu: TopNavMenuData[]; + /** + * Function to update the actual query + */ + updateQuery: (payload: { dateRange: TimeRange; query?: Query }, isUpdate?: boolean) => void; + /** + * Function to update the actual savedQuery id + */ + updateSavedQueryId: (savedQueryId?: string) => void; +} diff --git a/src/plugins/discover/public/application/helpers/columns.test.ts b/src/plugins/discover/public/application/helpers/columns.test.ts new file mode 100644 index 00000000000000..d455fd1f42c6d4 --- /dev/null +++ b/src/plugins/discover/public/application/helpers/columns.test.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import { getDisplayedColumns } from './columns'; +import { indexPatternWithTimefieldMock } from '../../__mocks__/index_pattern_with_timefield'; +import { indexPatternMock } from '../../__mocks__/index_pattern'; + +describe('getDisplayedColumns', () => { + test('returns default columns given a index pattern without timefield', async () => { + const result = getDisplayedColumns([], indexPatternMock); + expect(result).toMatchInlineSnapshot(` + Array [ + "_source", + ] + `); + }); + test('returns default columns given a index pattern with timefield', async () => { + const result = getDisplayedColumns([], indexPatternWithTimefieldMock); + expect(result).toMatchInlineSnapshot(` + Array [ + "_source", + ] + `); + }); + test('returns default columns when just timefield is in state', async () => { + const result = getDisplayedColumns(['timestamp'], indexPatternWithTimefieldMock); + expect(result).toMatchInlineSnapshot(` + Array [ + "_source", + ] + `); + }); + test('returns columns given by argument, no fallback ', async () => { + const result = getDisplayedColumns(['test'], indexPatternWithTimefieldMock); + expect(result).toMatchInlineSnapshot(` + Array [ + "test", + ] + `); + }); +}); diff --git a/src/plugins/discover/public/application/helpers/columns.ts b/src/plugins/discover/public/application/helpers/columns.ts new file mode 100644 index 00000000000000..d2d47c932b7bd0 --- /dev/null +++ b/src/plugins/discover/public/application/helpers/columns.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ +import { IndexPattern } from '../../../../data/common'; + +/** + * Function to provide fallback when + * 1) no columns are given + * 2) Just one column is given, which is the configured timefields + */ +export function getDisplayedColumns(stateColumns: string[] = [], indexPattern: IndexPattern) { + return stateColumns && + stateColumns.length > 0 && + // check if all columns where removed except the configured timeField (this can't be removed) + !(stateColumns.length === 1 && stateColumns[0] === indexPattern.timeFieldName) + ? stateColumns + : ['_source']; +} diff --git a/src/plugins/discover/public/get_inner_angular.ts b/src/plugins/discover/public/get_inner_angular.ts index b27426a6c06213..4eda742d967f48 100644 --- a/src/plugins/discover/public/get_inner_angular.ts +++ b/src/plugins/discover/public/get_inner_angular.ts @@ -42,7 +42,6 @@ import { } from '../../kibana_legacy/public'; import { DiscoverStartPlugins } from './plugin'; import { getScopedHistory } from './kibana_services'; -import { createDiscoverLegacyDirective } from './application/components/create_discover_legacy_directive'; import { createDiscoverDirective } from './application/components/create_discover_directive'; /** @@ -124,7 +123,6 @@ export function initializeInnerAngularModule( .config(watchMultiDecorator) .run(registerListenEventListener) .directive('renderComplete', createRenderCompleteDirective) - .directive('discoverLegacy', createDiscoverLegacyDirective) .directive('discover', createDiscoverDirective); } diff --git a/test/functional/apps/discover/_data_grid.ts b/test/functional/apps/discover/_data_grid.ts index 3bac05c5b18fc2..1329e7657ad9c1 100644 --- a/test/functional/apps/discover/_data_grid.ts +++ b/test/functional/apps/discover/_data_grid.ts @@ -38,7 +38,7 @@ export default function ({ const getTitles = async () => (await testSubjects.getVisibleText('dataGridHeader')).replace(/\s|\r?\n|\r/g, ' '); - expect(await getTitles()).to.be('Time (@timestamp) _source'); + expect(await getTitles()).to.be('Time (@timestamp) Document'); await PageObjects.discover.clickFieldListItemAdd('bytes'); expect(await getTitles()).to.be('Time (@timestamp) bytes'); @@ -50,7 +50,7 @@ export default function ({ expect(await getTitles()).to.be('Time (@timestamp) agent'); await PageObjects.discover.clickFieldListItemAdd('agent'); - expect(await getTitles()).to.be('Time (@timestamp) _source'); + expect(await getTitles()).to.be('Time (@timestamp) Document'); }); }); } diff --git a/test/functional/apps/discover/_data_grid_field_data.ts b/test/functional/apps/discover/_data_grid_field_data.ts index bdbaacc33c1bd8..3eec84ad3d7c09 100644 --- a/test/functional/apps/discover/_data_grid_field_data.ts +++ b/test/functional/apps/discover/_data_grid_field_data.ts @@ -57,7 +57,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('doc view should show Time and _source columns', async function () { - const expectedHeader = 'Time (@timestamp) _source'; + const expectedHeader = 'Time (@timestamp) Document'; const DocHeader = await dataGrid.getHeaderFields(); expect(DocHeader.join(' ')).to.be(expectedHeader); }); From d931ed61e4c989f44b1340f88848a2e4828f9727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Wed, 27 Jan 2021 17:59:44 +0100 Subject: [PATCH 35/58] [ILM] Policy phases redesign (#88671) * Phases redesign * Title and name field layout * Active highlight wip * Copy comments * Updated data allocation dropdown * Min age error message * Fixed tests * Fixed edit policy integration tests * Fixed more tests * Cleaned up test files * Use hotProperty instead of a string * Clean up in phase component * Fixed i18n files * Updated optional fields * Updated aria attributes after running axe tests * Added review suggestions * Reversed data allocation field changes * Fixed type error * Reversed on/off label and prepend input label * Deleted property consts from phases components * Removed not needed i18n consts and added i18n where missing * Fixed merge conflicts with master Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../client_integration/app/app.test.ts | 39 +- .../edit_policy/edit_policy.helpers.tsx | 46 +- .../edit_policy/edit_policy.test.ts | 38 +- .../__jest__/components/edit_policy.test.tsx | 14 +- .../public/application/constants/policy.ts | 27 +- .../active_highlight/active_highlight.scss | 16 + .../active_highlight/active_highlight.tsx | 17 + .../index.ts | 2 +- .../sections/edit_policy/components/index.ts | 1 + .../phases/cold_phase/cold_phase.tsx | 199 ++------ .../phases/delete_phase/delete_phase.tsx | 4 +- .../components/phases/hot_phase/hot_phase.tsx | 426 ++++++++---------- .../edit_policy/components/phases/index.ts | 2 + .../edit_policy/components/phases/phase.tsx | 119 +++++ .../phases/shared_fields/forcemerge_field.tsx | 58 +-- .../components/phases/shared_fields/index.ts | 8 +- ...put_field.tsx => index_priority_field.tsx} | 49 +- .../shared_fields/min_age_field/index.ts | 7 + .../min_age_field/min_age_field.tsx | 158 +++++++ .../util.ts | 0 .../min_age_input_field.tsx | 205 --------- .../phases/shared_fields/replicas_field.tsx | 59 +++ .../phases/shared_fields/shrink_field.tsx | 36 +- .../phases/warm_phase/warm_phase.tsx | 170 +------ .../sections/edit_policy/edit_policy.tsx | 362 +++++++-------- .../form/deserializer_and_serializer.test.ts | 9 - .../sections/edit_policy/form/schema.ts | 57 ++- .../edit_policy/form/serializer/serializer.ts | 28 +- .../sections/edit_policy/i18n_texts.ts | 29 +- .../lib/absolute_timing_to_relative_timing.ts | 7 +- .../application/services/ui_metric.test.ts | 10 +- .../public/application/services/ui_metric.ts | 9 +- .../public/shared_imports.ts | 1 + .../translations/translations/ja-JP.json | 33 -- .../translations/translations/zh-CN.json | 33 -- 35 files changed, 1030 insertions(+), 1248 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/active_highlight.scss create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/active_highlight.tsx rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/{phases/shared_fields/min_age_input_field => active_highlight}/index.ts (80%) create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/phase.tsx rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/{set_priority_input_field.tsx => index_priority_field.tsx} (50%) create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/index.ts create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/min_age_field.tsx rename x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/{min_age_input_field => min_age_field}/util.ts (100%) delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_input_field/min_age_input_field.tsx create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/replicas_field.tsx diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts index 1ffbae39d37050..1b49416ebbbe91 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts @@ -21,6 +21,9 @@ const PERCENT_SIGN_NAME = 'test%'; const PERCENT_SIGN_WITH_OTHER_CHARS_NAME = 'test%#'; const PERCENT_SIGN_25_SEQUENCE = 'test%25'; +const createPolicyTitle = 'Create Policy'; +const editPolicyTitle = 'Edit Policy'; + window.scrollTo = jest.fn(); jest.mock('@elastic/eui', () => { @@ -52,7 +55,7 @@ describe('', () => { await actions.clickCreatePolicyButton(); component.update(); - expect(testBed.find('policyTitle').text()).toBe(`Create an index lifecycle policy`); + expect(testBed.find('policyTitle').text()).toBe(createPolicyTitle); expect(testBed.find('policyNameField').props().value).toBe(''); }); @@ -68,7 +71,7 @@ describe('', () => { await actions.clickCreatePolicyButton(); component.update(); - expect(testBed.find('policyTitle').text()).toBe(`Create an index lifecycle policy`); + expect(testBed.find('policyTitle').text()).toBe(createPolicyTitle); expect(testBed.find('policyNameField').props().value).toBe(''); }); }); @@ -89,9 +92,7 @@ describe('', () => { await actions.clickPolicyNameLink(); component.update(); - expect(testBed.find('policyTitle').text()).toBe( - `Edit index lifecycle policy ${SPECIAL_CHARS_NAME}` - ); + expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${SPECIAL_CHARS_NAME}`); }); test('loading edit policy page url works', async () => { @@ -102,9 +103,7 @@ describe('', () => { const { component } = testBed; component.update(); - expect(testBed.find('policyTitle').text()).toBe( - `Edit index lifecycle policy ${SPECIAL_CHARS_NAME}` - ); + expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${SPECIAL_CHARS_NAME}`); }); // using double encoding to counteract react-router's v5 internal decodeURI call @@ -117,9 +116,7 @@ describe('', () => { const { component } = testBed; component.update(); - expect(testBed.find('policyTitle').text()).toBe( - `Edit index lifecycle policy ${SPECIAL_CHARS_NAME}` - ); + expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${SPECIAL_CHARS_NAME}`); }); }); @@ -136,9 +133,7 @@ describe('', () => { const { component } = testBed; component.update(); - expect(testBed.find('policyTitle').text()).toBe( - `Edit index lifecycle policy ${PERCENT_SIGN_NAME}` - ); + expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${PERCENT_SIGN_NAME}`); }); test('loading edit policy page url with double encoding works', async () => { @@ -149,9 +144,7 @@ describe('', () => { const { component } = testBed; component.update(); - expect(testBed.find('policyTitle').text()).toBe( - `Edit index lifecycle policy ${PERCENT_SIGN_NAME}` - ); + expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${PERCENT_SIGN_NAME}`); }); }); @@ -174,7 +167,7 @@ describe('', () => { component.update(); expect(testBed.find('policyTitle').text()).toBe( - `Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}` + `${editPolicyTitle} ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}` ); }); @@ -188,7 +181,7 @@ describe('', () => { // known issue https://github.com/elastic/kibana/issues/82440 expect(testBed.find('policyTitle').text()).not.toBe( - `Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}` + `${editPolicyTitle} ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}` ); }); @@ -203,7 +196,7 @@ describe('', () => { component.update(); expect(testBed.find('policyTitle').text()).toBe( - `Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}` + `${editPolicyTitle} ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}` ); }); }); @@ -225,7 +218,7 @@ describe('', () => { component.update(); expect(testBed.find('policyTitle').text()).toBe( - `Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}` + `${editPolicyTitle} ${PERCENT_SIGN_25_SEQUENCE}` ); }); @@ -239,7 +232,7 @@ describe('', () => { // known issue https://github.com/elastic/kibana/issues/82440 expect(testBed.find('policyTitle').text()).not.toBe( - `Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}` + `${editPolicyTitle} ${PERCENT_SIGN_25_SEQUENCE}` ); }); @@ -254,7 +247,7 @@ describe('', () => { component.update(); expect(testBed.find('policyTitle').text()).toBe( - `Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}` + `${editPolicyTitle} ${PERCENT_SIGN_25_SEQUENCE}` ); }); }); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx index 72a0372628a223..64b654b0302364 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx @@ -89,6 +89,13 @@ export const setup = async (arg?: { appServicesContext: Partial async (checked: boolean) => { + await act(async () => { + form.selectCheckBox(dataTestSubject, checked); + }); + component.update(); + }; + function createFormSetValueAction(dataTestSubject: string) { return async (value: V) => { await act(async () => { @@ -146,17 +153,21 @@ export const setup = async (arg?: { appServicesContext: Partial exists(toggleSelector), toggleForceMerge: createFormToggleAction(toggleSelector), setForcemergeSegmentsCount: createFormSetValueAction(`${phase}-selectedForceMergeSegments`), - setBestCompression: createFormToggleAction(`${phase}-bestCompression`), + setBestCompression: createFormCheckboxAction(`${phase}-bestCompression`), }; }; - const setIndexPriority = (phase: Phases) => - createFormSetValueAction(`${phase}-phaseIndexPriority`); + const createIndexPriorityActions = (phase: Phases) => { + const toggleSelector = `${phase}-indexPrioritySwitch`; + return { + indexPriorityExists: () => exists(toggleSelector), + toggleIndexPriority: createFormToggleAction(toggleSelector), + setIndexPriority: createFormSetValueAction(`${phase}-indexPriority`), + }; + }; const enable = (phase: Phases) => createFormToggleAction(`enablePhaseSwitch-${phase}`); - const warmPhaseOnRollover = createFormToggleAction(`warm-warmPhaseOnRollover`); - const setMinAgeValue = (phase: Phases) => createFormSetValueAction(`${phase}-selectedMinimumAge`); const setMinAgeUnits = (phase: Phases) => @@ -190,13 +201,15 @@ export const setup = async (arg?: { appServicesContext: Partial async (value: string) => { - await createFormToggleAction(`${phase}-shrinkSwitch`)(true); - await createFormSetValueAction(`${phase}-selectedPrimaryShardCount`)(value); + const createShrinkActions = (phase: Phases) => { + const toggleSelector = `${phase}-shrinkSwitch`; + return { + shrinkExists: () => exists(toggleSelector), + toggleShrink: createFormToggleAction(toggleSelector), + setShrink: createFormSetValueAction(`${phase}-primaryShardCount`), + }; }; - const shrinkExists = (phase: Phases) => () => exists(`${phase}-shrinkSwitch`); - const setFreeze = createFormToggleAction('freezeSwitch'); const freezeExists = () => exists('freezeSwitch'); @@ -250,25 +263,22 @@ export const setup = async (arg?: { appServicesContext: Partial', () => { max_size: '50gb', unknown_setting: 123, // Made up setting that should stay preserved }, - set_priority: { - priority: 100, - }, }, min_age: '0ms', }, @@ -126,8 +123,10 @@ describe('', () => { await actions.hot.toggleForceMerge(true); await actions.hot.setForcemergeSegmentsCount('123'); await actions.hot.setBestCompression(true); + await actions.hot.toggleShrink(true); await actions.hot.setShrink('2'); await actions.hot.setReadonly(true); + await actions.hot.toggleIndexPriority(true); await actions.hot.setIndexPriority('123'); await actions.savePolicy(); @@ -186,13 +185,7 @@ describe('', () => { const hotActions = policy.phases.hot.actions; const rolloverAction = hotActions.rollover; expect(rolloverAction).toBe(undefined); - expect(hotActions).toMatchInlineSnapshot(` - Object { - "set_priority": Object { - "priority": 100, - }, - } - `); + expect(hotActions).toMatchInlineSnapshot(`Object {}`); }); test('enabling searchable snapshot should hide force merge, freeze and shrink in subsequent phases', async () => { @@ -260,6 +253,7 @@ describe('', () => { "priority": 50, }, }, + "min_age": "0ms", } `); }); @@ -270,6 +264,7 @@ describe('', () => { await actions.warm.setDataAllocation('node_attrs'); await actions.warm.setSelectedNodeAttribute('test:123'); await actions.warm.setReplicas('123'); + await actions.warm.toggleShrink(true); await actions.warm.setShrink('123'); await actions.warm.toggleForceMerge(true); await actions.warm.setForcemergeSegmentsCount('123'); @@ -290,9 +285,6 @@ describe('', () => { "max_age": "30d", "max_size": "50gb", }, - "set_priority": Object { - "priority": 100, - }, }, "min_age": "0ms", }, @@ -316,24 +308,12 @@ describe('', () => { "number_of_shards": 123, }, }, + "min_age": "0ms", }, }, } `); }); - - test('setting warm phase on rollover to "false"', async () => { - const { actions } = testBed; - await actions.warm.enable(true); - await actions.warm.warmPhaseOnRollover(false); - await actions.warm.setMinAgeValue('123'); - await actions.warm.setMinAgeUnits('d'); - await actions.savePolicy(); - const latestRequest = server.requests[server.requests.length - 1]; - const warmPhaseMinAge = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm - .min_age; - expect(warmPhaseMinAge).toBe('123d'); - }); }); describe('policy with include and exclude', () => { @@ -458,9 +438,6 @@ describe('', () => { "max_age": "30d", "max_size": "50gb", }, - "set_priority": Object { - "priority": 100, - }, }, "min_age": "0ms", }, @@ -662,9 +639,6 @@ describe('', () => { "allocate": Object { "number_of_replicas": 123, }, - "set_priority": Object { - "priority": 50, - }, } `); }); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx index 6aa6c3177ca5dd..d847c3a7f97666 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx @@ -157,7 +157,7 @@ const setPhaseIndexPriority = async ( phase: string, priority: string | number ) => { - const priorityInput = findTestSubject(rendered, `${phase}-phaseIndexPriority`); + const priorityInput = findTestSubject(rendered, `${phase}-indexPriority`); await act(async () => { priorityInput.simulate('change', { target: { value: priority } }); }); @@ -324,9 +324,6 @@ describe('edit policy', () => { max_age: '30d', max_size: '50gb', }, - set_priority: { - priority: 100, - }, }, min_age: '0ms', }, @@ -451,6 +448,7 @@ describe('edit policy', () => { const rendered = mountWithIntl(component); await noRollover(rendered); await setPolicyName(rendered, 'mypolicy'); + await setPhaseIndexPriority(rendered, 'hot', '-1'); waitForFormLibValidation(rendered); expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]); @@ -512,7 +510,7 @@ describe('edit policy', () => { }); rendered.update(); await setPhaseAfter(rendered, 'warm', '1'); - const shrinkInput = findTestSubject(rendered, 'warm-selectedPrimaryShardCount'); + const shrinkInput = findTestSubject(rendered, 'warm-primaryShardCount'); await act(async () => { shrinkInput.simulate('change', { target: { value: '0' } }); }); @@ -529,7 +527,7 @@ describe('edit policy', () => { findTestSubject(rendered, 'warm-shrinkSwitch').simulate('click'); }); rendered.update(); - const shrinkInput = findTestSubject(rendered, 'warm-selectedPrimaryShardCount'); + const shrinkInput = findTestSubject(rendered, 'warm-primaryShardCount'); await act(async () => { shrinkInput.simulate('change', { target: { value: '-1' } }); }); @@ -845,7 +843,7 @@ describe('edit policy', () => { await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); - // Assert that only the custom and off options exist + // Assert that default, custom and 'none' options exist findTestSubject(rendered, 'dataTierSelect').simulate('click'); expect(findTestSubject(rendered, 'defaultDataAllocationOption').exists()).toBeTruthy(); expect(findTestSubject(rendered, 'customDataAllocationOption').exists()).toBeTruthy(); @@ -885,7 +883,7 @@ describe('edit policy', () => { await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); - // Assert that only the custom and off options exist + // Assert that default, custom and 'none' options exist findTestSubject(rendered, 'dataTierSelect').simulate('click'); expect(findTestSubject(rendered, 'defaultDataAllocationOption').exists()).toBeFalsy(); expect(findTestSubject(rendered, 'customDataAllocationOption').exists()).toBeTruthy(); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts b/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts index a892a7a031a872..6eae59ec4e6ea6 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts @@ -4,16 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - SerializedPhase, - DeletePhase, - SerializedPolicy, - RolloverAction, -} from '../../../common/types'; +import { SerializedPolicy, RolloverAction } from '../../../common/types'; -export const defaultSetPriority: string = '100'; - -export const defaultPhaseIndexPriority: string = '50'; +export const defaultIndexPriority = { + hot: '100', + warm: '50', + cold: '0', +}; export const defaultRolloverAction: RolloverAction = { max_age: '30d', @@ -30,15 +27,3 @@ export const defaultPolicy: SerializedPolicy = { }, }, }; - -export const defaultNewDeletePhase: DeletePhase = { - phaseEnabled: false, - selectedMinimumAge: '0', - selectedMinimumAgeUnits: 'd', - waitForSnapshotPolicy: '', -}; - -export const serializedPhaseInitialization: SerializedPhase = { - min_age: '0ms', - actions: {}, -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/active_highlight.scss b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/active_highlight.scss new file mode 100644 index 00000000000000..96ca0c3a610671 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/active_highlight.scss @@ -0,0 +1,16 @@ +.ilmActivePhaseHighlight { + border-left: $euiBorderWidthThin solid $euiColorLightShade; + height: 100%; + + &.hotPhase.active { + border-left-color: $euiColorVis9_behindText; + } + + &.warmPhase.active { + border-left-color: $euiColorVis5_behindText; + } + + &.coldPhase.active { + border-left-color: $euiColorVis1_behindText; + } +} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/active_highlight.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/active_highlight.tsx new file mode 100644 index 00000000000000..64db9e1ec5481b --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/active_highlight.tsx @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FunctionComponent } from 'react'; + +import './active_highlight.scss'; + +interface Props { + phase: 'hot' | 'warm' | 'cold'; + enabled: boolean; +} +export const ActiveHighlight: FunctionComponent = ({ phase, enabled }) => { + return
; +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_input_field/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/index.ts similarity index 80% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_input_field/index.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/index.ts index 0228a524f8129c..a1db0c3997edb1 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_input_field/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/active_highlight/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { MinAgeInputField } from './min_age_input_field'; +export { ActiveHighlight } from './active_highlight'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts index d22206d7ae4de1..960b632d70bd42 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts @@ -11,6 +11,7 @@ export { OptionalLabel } from './optional_label'; export { PolicyJsonFlyout } from './policy_json_flyout'; export { DescribedFormRow, ToggleFieldWithDescribedFormRow } from './described_form_row'; export { FieldLoadingError } from './field_loading_error'; +export { ActiveHighlight } from './active_highlight'; export { Timeline } from './timeline'; export * from './phases'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx index 4e1ec76c52a773..976f584ef4d3a5 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx @@ -9,28 +9,21 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; -import { EuiDescribedFormGroup, EuiTextColor, EuiAccordion } from '@elastic/eui'; +import { EuiTextColor } from '@elastic/eui'; -import { Phases } from '../../../../../../../common/types'; +import { useFormData } from '../../../../../../shared_imports'; -import { useFormData, UseField, ToggleField, NumericField } from '../../../../../../shared_imports'; - -import { useEditPolicyContext } from '../../../edit_policy_context'; import { useConfigurationIssues } from '../../../form'; -import { - LearnMoreLink, - ActiveBadge, - DescribedFormRow, - ToggleFieldWithDescribedFormRow, -} from '../../'; +import { LearnMoreLink, ToggleFieldWithDescribedFormRow } from '../../'; import { - MinAgeInputField, DataTierAllocationField, - SetPriorityInputField, SearchableSnapshotField, + IndexPriorityField, + ReplicasField, } from '../shared_fields'; +import { Phase } from '../phase'; const i18nTexts = { dataTierAllocation: { @@ -41,166 +34,64 @@ const i18nTexts = { }, }; -const coldProperty: keyof Phases = 'cold'; - const formFieldPaths = { enabled: '_meta.cold.enabled', searchableSnapshot: 'phases.cold.actions.searchable_snapshot.snapshot_repository', }; export const ColdPhase: FunctionComponent = () => { - const { policy } = useEditPolicyContext(); const { isUsingSearchableSnapshotInHotPhase } = useConfigurationIssues(); const [formData] = useFormData({ - watch: [formFieldPaths.enabled, formFieldPaths.searchableSnapshot], + watch: [formFieldPaths.searchableSnapshot], }); - const enabled = get(formData, formFieldPaths.enabled); const showReplicasField = get(formData, formFieldPaths.searchableSnapshot) == null; return ( -
- <> - {/* Section title group; containing min age */} - + + + {showReplicasField && } + + {/* Freeze section */} + {!isUsingSearchableSnapshotInHotPhase && ( + -

- -

{' '} - {enabled && } -
+

+ +

} - titleSize="s" description={ - <> -

- -

- - + + {' '} + + } fullWidth + titleSize="xs" + switchProps={{ + 'data-test-subj': 'freezeSwitch', + path: '_meta.cold.freezeEnabled', + }} > - {enabled && } - - {enabled && ( - <> - - - - { - /* Replicas section */ - showReplicasField && ( - - {i18n.translate('xpack.indexLifecycleMgmt.coldPhase.replicasTitle', { - defaultMessage: 'Replicas', - })} - - } - description={i18n.translate( - 'xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasDescription', - { - defaultMessage: - 'Set the number of replicas. Remains the same as the previous phase by default.', - } - )} - switchProps={{ - 'data-test-subj': 'cold-setReplicasSwitch', - label: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel', - { defaultMessage: 'Set replicas' } - ), - initialValue: - policy.phases.cold?.actions?.allocate?.number_of_replicas != null, - }} - fullWidth - > - - - ) - } - - {/* Freeze section */} - {!isUsingSearchableSnapshotInHotPhase && ( - - - - } - description={ - - {' '} - - - } - fullWidth - titleSize="xs" - switchProps={{ - 'data-test-subj': 'freezeSwitch', - path: '_meta.cold.freezeEnabled', - }} - > -
- - )} - {/* Data tier allocation section */} - - - - - )} - -
+
+ + )} + + {/* Data tier allocation section */} + + + + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx index 37323b97edc923..5c43bb413eb5eb 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx @@ -13,7 +13,7 @@ import { useFormData, UseField, ToggleField } from '../../../../../../shared_imp import { ActiveBadge, LearnMoreLink, OptionalLabel } from '../../index'; -import { MinAgeInputField, SnapshotPoliciesField } from '../shared_fields'; +import { MinAgeField, SnapshotPoliciesField } from '../shared_fields'; const formFieldPaths = { enabled: '_meta.delete.enabled', @@ -63,7 +63,7 @@ export const DeletePhase: FunctionComponent = () => { } fullWidth > - {enabled && } + {enabled && } {enabled ? ( { const { license } = useEditPolicyContext(); const [formData] = useFormData({ @@ -56,245 +51,210 @@ export const HotPhase: FunctionComponent = () => { const [showEmptyRolloverFieldsError, setShowEmptyRolloverFieldsError] = useState(false); return ( - <> - + -

- -

{' '} - -
+

+ {i18n.translate('xpack.indexLifecycleMgmt.hotPhase.rolloverFieldTitle', { + defaultMessage: 'Rollover', + })} +

} description={ -

- -

+ <> + +

+ {' '} + + } + docPath="ilm-rollover.html" + /> +

+
+ + path={isUsingDefaultRolloverPath}> + {(field) => ( + <> + field.setValue(e.target.checked)} + data-test-subj="useDefaultRolloverSwitch" + /> +   + + } + /> + + )} +
+ } + fullWidth > -
- - - - - {i18n.translate('xpack.indexLifecycleMgmt.hotPhase.rolloverFieldTitle', { - defaultMessage: 'Rollover', - })} - - } - description={ - <> - -

- {' '} - + path="_meta.hot.customRollover.enabled"> + {(field) => ( + <> + field.setValue(e.target.checked)} + data-test-subj="rolloverSwitch" + /> +   + } - docPath="ilm-rollover.html" /> -

-
- - path={isUsingDefaultRolloverPath}> - {(field) => ( + + )} + + {isUsingRollover && ( + <> + + {showEmptyRolloverFieldsError && ( <> - field.setValue(e.target.checked)} - data-test-subj="useDefaultRolloverSwitch" - /> -   - - } - /> + +
{i18nTexts.editPolicy.errors.rollOverConfigurationCallout.body}
+
+ )} - - - } - fullWidth - > - {isUsingDefaultRollover === false ? ( -
- path="_meta.hot.customRollover.enabled"> - {(field) => ( - <> - field.setValue(e.target.checked)} - data-test-subj="rolloverSwitch" + + + + {(field) => { + const showErrorCallout = field.errors.some( + (e) => e.code === ROLLOVER_EMPTY_VALIDATION + ); + if (showErrorCallout !== showEmptyRolloverFieldsError) { + setShowEmptyRolloverFieldsError(showErrorCallout); + } + return ( + + ); + }} + + + + -   - - } + + + + + + - - )} - - {isUsingRollover && ( - <> - - {showEmptyRolloverFieldsError && ( - <> - -
{i18nTexts.editPolicy.errors.rollOverConfigurationCallout.body}
-
- - - )} - - - - {(field) => { - const showErrorCallout = field.errors.some( - (e) => e.code === ROLLOVER_EMPTY_VALIDATION - ); - if (showErrorCallout !== showEmptyRolloverFieldsError) { - setShowEmptyRolloverFieldsError(showErrorCallout); - } - return ( - - ); - }} - - - - - - - - - - - - - - - - - - - - - - - )} -
- ) : ( -
- )} - - {isUsingRollover && ( - <> - {} - - {license.canUseSearchableSnapshot() && } - - + + + + + + + + + + + + + )} +
+ ) : ( +
)} - - - + + {isUsingRollover && ( + <> + {} + + {license.canUseSearchableSnapshot() && } + + + )} + + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/index.ts index 076c16e87e8d63..c2c7e6a7690717 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/index.ts @@ -11,3 +11,5 @@ export { WarmPhase } from './warm_phase'; export { ColdPhase } from './cold_phase'; export { DeletePhase } from './delete_phase'; + +export { Phase } from './phase'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/phase.tsx new file mode 100644 index 00000000000000..6de18f1c1d3cba --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/phase.tsx @@ -0,0 +1,119 @@ +/* + * 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, { FunctionComponent, useState } from 'react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiTitle, + EuiSpacer, + EuiText, + EuiButtonEmpty, +} from '@elastic/eui'; +import { get } from 'lodash'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { ToggleField, UseField, useFormData } from '../../../../../shared_imports'; +import { i18nTexts } from '../../i18n_texts'; + +import { ActiveHighlight } from '../active_highlight'; +import { MinAgeField } from './shared_fields'; + +interface Props { + phase: 'hot' | 'warm' | 'cold'; +} + +export const Phase: FunctionComponent = ({ children, phase }) => { + const enabledPath = `_meta.${phase}.enabled`; + const [formData] = useFormData({ + watch: [enabledPath], + }); + + // hot phase is always enabled + const enabled = get(formData, enabledPath) || phase === 'hot'; + + const [isShowingSettings, setShowingSettings] = useState(false); + return ( + + + + + + + + + + {phase !== 'hot' && ( + + + + )} + + +

{i18nTexts.editPolicy.titles[phase]}

+
+
+
+
+ {enabled && ( + + + + {phase !== 'hot' && } + + + { + setShowingSettings(!isShowingSettings); + }} + size="xs" + iconType="controlsVertical" + iconSide="left" + aria-controls={`${phase}-phaseContent`} + > + + + + + + )} +
+ + + {i18nTexts.editPolicy.descriptions[phase]} + + + {enabled && ( +
+ + {children} +
+ )} +
+
+
+ ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx index 8776dbbbc75531..8d6807c90dae8e 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx @@ -6,9 +6,8 @@ import React, { useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiSpacer, EuiTextColor } from '@elastic/eui'; -import { UseField, ToggleField, NumericField } from '../../../../../../shared_imports'; +import { UseField, CheckBoxField, NumericField } from '../../../../../../shared_imports'; import { i18nTexts } from '../../../i18n_texts'; @@ -38,50 +37,43 @@ export const ForcemergeField: React.FunctionComponent = ({ phase }) => { } description={ - + <> {' '} - + } titleSize="xs" fullWidth switchProps={{ - 'aria-label': i18nTexts.editPolicy.forceMergeEnabledFieldLabel, - 'data-test-subj': `${phase}-forceMergeSwitch`, - 'aria-controls': 'forcemergeContent', label: i18nTexts.editPolicy.forceMergeEnabledFieldLabel, + 'data-test-subj': `${phase}-forceMergeSwitch`, initialValue: initialToggleValue, }} > - -
- - -
+ + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts index 15167672265fd4..710df7e95f8fc7 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts @@ -8,9 +8,7 @@ export { DataTierAllocationField } from './data_tier_allocation_field'; export { ForcemergeField } from './forcemerge_field'; -export { SetPriorityInputField } from './set_priority_input_field'; - -export { MinAgeInputField } from './min_age_input_field'; +export { MinAgeField } from './min_age_field'; export { SnapshotPoliciesField } from './snapshot_policies_field'; @@ -19,3 +17,7 @@ export { ShrinkField } from './shrink_field'; export { SearchableSnapshotField } from './searchable_snapshot_field'; export { ReadonlyField } from './readonly_field'; + +export { ReplicasField } from './replicas_field'; + +export { IndexPriorityField } from './index_priority_field'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/set_priority_input_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index_priority_field.tsx similarity index 50% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/set_priority_input_field.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index_priority_field.tsx index 328587a379b76f..570033812c2471 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/set_priority_input_field.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index_priority_field.tsx @@ -4,23 +4,32 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FunctionComponent } from 'react'; +import React, { FunctionComponent, useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiTextColor, EuiDescribedFormGroup } from '@elastic/eui'; - -import { Phases } from '../../../../../../../common/types'; +import { i18n } from '@kbn/i18n'; +import { EuiSpacer, EuiTextColor } from '@elastic/eui'; import { UseField, NumericField } from '../../../../../../shared_imports'; - -import { LearnMoreLink } from '../..'; +import { LearnMoreLink, DescribedFormRow } from '../..'; +import { useEditPolicyContext } from '../../../edit_policy_context'; interface Props { - phase: keyof Phases & string; + phase: 'hot' | 'warm' | 'cold'; } -export const SetPriorityInputField: FunctionComponent = ({ phase }) => { +export const IndexPriorityField: FunctionComponent = ({ phase }) => { + const { policy, isNewPolicy } = useEditPolicyContext(); + + const initialToggleValue = useMemo(() => { + return ( + isNewPolicy || // enable index priority for new policies + !policy.phases[phase]?.actions || // enable index priority for new phases + policy.phases[phase]?.actions?.set_priority != null // enable index priority if it's set + ); + }, [isNewPolicy, policy.phases, phase]); + return ( - = ({ phase }) => { } titleSize="xs" fullWidth + switchProps={{ + label: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.indexPriority.indexPriorityEnabledFieldLabel', + { + defaultMessage: 'Set index priority', + } + ), + 'data-test-subj': `${phase}-indexPrioritySwitch`, + initialValue: initialToggleValue, + }} > + - + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/index.ts new file mode 100644 index 00000000000000..43ef0cf5d9b717 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/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 { MinAgeField } from './min_age_field'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/min_age_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/min_age_field.tsx new file mode 100644 index 00000000000000..8a84b7fa0e762a --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/min_age_field.tsx @@ -0,0 +1,158 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiFieldNumber, + EuiFieldNumberProps, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiSelect, + EuiText, +} from '@elastic/eui'; + +import { UseField, getFieldValidityAndErrorMessage } from '../../../../../../../shared_imports'; + +import { getUnitsAriaLabelForPhase, getTimingLabelForPhase } from './util'; + +type PhaseWithMinAgeAction = 'warm' | 'cold' | 'delete'; + +const i18nTexts = { + daysOptionLabel: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.daysOptionLabel', { + defaultMessage: 'days', + }), + + hoursOptionLabel: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.hoursOptionLabel', { + defaultMessage: 'hours', + }), + minutesOptionLabel: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.minutesOptionLabel', { + defaultMessage: 'minutes', + }), + + secondsOptionLabel: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.secondsOptionLabel', { + defaultMessage: 'seconds', + }), + millisecondsOptionLabel: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.milliSecondsOptionLabel', + { + defaultMessage: 'milliseconds', + } + ), + + microsecondsOptionLabel: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.microSecondsOptionLabel', + { + defaultMessage: 'microseconds', + } + ), + + nanosecondsOptionLabel: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.nanoSecondsOptionLabel', + { + defaultMessage: 'nanoseconds', + } + ), +}; + +interface Props { + phase: PhaseWithMinAgeAction; +} + +export const MinAgeField: FunctionComponent = ({ phase }): React.ReactElement => { + return ( + + {(field) => { + const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); + return ( + + + + + + + + + + + + + + + {(unitField) => { + const { isInvalid: isUnitFieldInvalid } = getFieldValidityAndErrorMessage( + unitField + ); + return ( + { + unitField.setValue(e.target.value); + }} + isInvalid={isUnitFieldInvalid} + append={'old'} + data-test-subj={`${phase}-selectedMinimumAgeUnits`} + aria-label={getUnitsAriaLabelForPhase(phase)} + options={[ + { + value: 'd', + text: i18nTexts.daysOptionLabel, + }, + { + value: 'h', + text: i18nTexts.hoursOptionLabel, + }, + { + value: 'm', + text: i18nTexts.minutesOptionLabel, + }, + { + value: 's', + text: i18nTexts.secondsOptionLabel, + }, + { + value: 'ms', + text: i18nTexts.millisecondsOptionLabel, + }, + { + value: 'micros', + text: i18nTexts.microsecondsOptionLabel, + }, + { + value: 'nanos', + text: i18nTexts.nanosecondsOptionLabel, + }, + ]} + /> + ); + }} + + + + + + + ); + }} + + ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_input_field/util.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/util.ts similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_input_field/util.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_field/util.ts diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_input_field/min_age_input_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_input_field/min_age_input_field.tsx deleted file mode 100644 index 59086ce572252c..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/min_age_input_field/min_age_input_field.tsx +++ /dev/null @@ -1,205 +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 React, { FunctionComponent } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; - -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; - -import { UseField, NumericField, SelectField } from '../../../../../../../shared_imports'; - -import { LearnMoreLink } from '../../../learn_more_link'; -import { useConfigurationIssues } from '../../../../form'; - -import { getUnitsAriaLabelForPhase, getTimingLabelForPhase } from './util'; - -type PhaseWithMinAgeAction = 'warm' | 'cold' | 'delete'; - -interface Props { - phase: PhaseWithMinAgeAction; -} - -export const MinAgeInputField: FunctionComponent = ({ phase }): React.ReactElement => { - const { isUsingRollover: rolloverEnabled } = useConfigurationIssues(); - - let daysOptionLabel; - let hoursOptionLabel; - let minutesOptionLabel; - let secondsOptionLabel; - let millisecondsOptionLabel; - let microsecondsOptionLabel; - let nanosecondsOptionLabel; - - if (rolloverEnabled) { - daysOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel', - { - defaultMessage: 'days from rollover', - } - ); - - hoursOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel', - { - defaultMessage: 'hours from rollover', - } - ); - minutesOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel', - { - defaultMessage: 'minutes from rollover', - } - ); - - secondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel', - { - defaultMessage: 'seconds from rollover', - } - ); - millisecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel', - { - defaultMessage: 'milliseconds from rollover', - } - ); - - microsecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel', - { - defaultMessage: 'microseconds from rollover', - } - ); - - nanosecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel', - { - defaultMessage: 'nanoseconds from rollover', - } - ); - } else { - daysOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel', - { - defaultMessage: 'days from index creation', - } - ); - - hoursOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationHoursOptionLabel', - { - defaultMessage: 'hours from index creation', - } - ); - - minutesOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationMinutesOptionLabel', - { - defaultMessage: 'minutes from index creation', - } - ); - - secondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationSecondsOptionLabel', - { - defaultMessage: 'seconds from index creation', - } - ); - - millisecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationMilliSecondsOptionLabel', - { - defaultMessage: 'milliseconds from index creation', - } - ); - - microsecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationMicroSecondsOptionLabel', - { - defaultMessage: 'microseconds from index creation', - } - ); - - nanosecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationNanoSecondsOptionLabel', - { - defaultMessage: 'nanoseconds from index creation', - } - ); - } - - return ( - - - - } - /> - ), - euiFieldProps: { - 'data-test-subj': `${phase}-selectedMinimumAge`, - min: 0, - }, - }} - /> - - - - - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/replicas_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/replicas_field.tsx new file mode 100644 index 00000000000000..6d8e019ff8a0c3 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/replicas_field.tsx @@ -0,0 +1,59 @@ +/* + * 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, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { UseField, NumericField } from '../../../../../../shared_imports'; +import { useEditPolicyContext } from '../../../edit_policy_context'; +import { DescribedFormRow } from '../../described_form_row'; + +interface Props { + phase: 'warm' | 'cold'; +} + +export const ReplicasField: FunctionComponent = ({ phase }) => { + const { policy } = useEditPolicyContext(); + const initialValue = policy.phases[phase]?.actions?.allocate?.number_of_replicas != null; + return ( + + {i18n.translate('xpack.indexLifecycleMgmt.numberOfReplicas.formRowTitle', { + defaultMessage: 'Replicas', + })} + + } + description={i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.numberOfReplicas.formRowDescription', + { + defaultMessage: + 'Set the number of replicas. Remains the same as the previous phase by default.', + } + )} + switchProps={{ + 'data-test-subj': `${phase}-setReplicasSwitch`, + label: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.numberOfReplicas.switchLabel', { + defaultMessage: 'Set replicas', + }), + initialValue, + }} + fullWidth + > + + + ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/shrink_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/shrink_field.tsx index c5fc31d9839bd9..da200e9e68d174 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/shrink_field.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/shrink_field.tsx @@ -42,32 +42,28 @@ export const ShrinkField: FunctionComponent = ({ phase }) => { } titleSize="xs" switchProps={{ - 'aria-controls': 'shrinkContent', 'data-test-subj': `${phase}-shrinkSwitch`, label: i18nTexts.editPolicy.shrinkLabel, - 'aria-label': i18nTexts.editPolicy.shrinkLabel, initialValue: Boolean(policy.phases[phase]?.actions?.shrink), }} fullWidth > -
- - - - - - -
+ + + + + + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx index 77078e94d7e98b..47255da08df72e 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx @@ -5,30 +5,21 @@ */ import React, { FunctionComponent } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { get } from 'lodash'; -import { EuiSpacer, EuiDescribedFormGroup, EuiAccordion } from '@elastic/eui'; - -import { useFormData, UseField, ToggleField, NumericField } from '../../../../../../shared_imports'; - -import { Phases } from '../../../../../../../common/types'; - -import { useEditPolicyContext } from '../../../edit_policy_context'; import { useConfigurationIssues } from '../../../form'; -import { ActiveBadge, DescribedFormRow } from '../../'; - import { - MinAgeInputField, ForcemergeField, - SetPriorityInputField, + IndexPriorityField, DataTierAllocationField, ShrinkField, ReadonlyField, + ReplicasField, } from '../shared_fields'; +import { Phase } from '../phase'; + const i18nTexts = { dataTierAllocation: { description: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.description', { @@ -37,153 +28,26 @@ const i18nTexts = { }, }; -const warmProperty: keyof Phases = 'warm'; - -const formFieldPaths = { - enabled: '_meta.warm.enabled', - warmPhaseOnRollover: '_meta.warm.warmPhaseOnRollover', -}; - export const WarmPhase: FunctionComponent = () => { - const { policy } = useEditPolicyContext(); - const { isUsingSearchableSnapshotInHotPhase, isUsingRollover } = useConfigurationIssues(); - const [formData] = useFormData({ - watch: [formFieldPaths.enabled, formFieldPaths.warmPhaseOnRollover], - }); - - const enabled = get(formData, formFieldPaths.enabled); - const warmPhaseOnRollover = get(formData, formFieldPaths.warmPhaseOnRollover); + const { isUsingSearchableSnapshotInHotPhase } = useConfigurationIssues(); return ( -
- <> - -

- -

{' '} - {enabled && } -
- } - titleSize="s" - description={ - <> -

- -

- - - } - fullWidth - > - <> - {enabled && ( - <> - {isUsingRollover && ( - - )} - {(!warmPhaseOnRollover || !isUsingRollover) && ( - <> - - - - )} - - )} - - + + - {enabled && ( - - - {i18n.translate('xpack.indexLifecycleMgmt.warmPhase.replicasTitle', { - defaultMessage: 'Replicas', - })} - - } - description={i18n.translate( - 'xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasDescription', - { - defaultMessage: - 'Set the number of replicas. Remains the same as the previous phase by default.', - } - )} - switchProps={{ - 'data-test-subj': 'warm-setReplicasSwitch', - label: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel', - { defaultMessage: 'Set replicas' } - ), - initialValue: policy.phases.warm?.actions?.allocate?.number_of_replicas != null, - }} - fullWidth - > - - + {!isUsingSearchableSnapshotInHotPhase && } - {!isUsingSearchableSnapshotInHotPhase && } + {!isUsingSearchableSnapshotInHotPhase && } - {!isUsingSearchableSnapshotInHotPhase && } + - + {/* Data tier allocation section */} + - {/* Data tier allocation section */} - - - - )} - -
+ + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx index 228a0f9fdb942d..b1cf41773de3c5 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, useEffect, useState, useMemo } from 'react'; +import React, { Fragment, useEffect, useMemo, useState } from 'react'; import { get } from 'lodash'; import { RouteComponentProps } from 'react-router-dom'; @@ -16,7 +16,6 @@ import { i18n } from '@kbn/i18n'; import { EuiButton, EuiButtonEmpty, - EuiDescribedFormGroup, EuiFlexGroup, EuiFlexItem, EuiFormRow, @@ -24,33 +23,35 @@ import { EuiPage, EuiPageBody, EuiPageContent, + EuiPageContentHeader, + EuiPageContentHeaderSection, EuiSpacer, EuiSwitch, EuiText, EuiTitle, } from '@elastic/eui'; -import { useForm, UseField, TextField, useFormData } from '../../../shared_imports'; +import { TextField, UseField, useForm, useFormData } from '../../../shared_imports'; import { toasts } from '../../services/notification'; import { savePolicy } from './save_policy'; import { - LearnMoreLink, - PolicyJsonFlyout, ColdPhase, DeletePhase, HotPhase, + PolicyJsonFlyout, WarmPhase, Timeline, } from './components'; -import { schema, deserializer, createSerializer, createPolicyNameValidations, Form } from './form'; +import { createPolicyNameValidations, createSerializer, deserializer, Form, schema } from './form'; import { useEditPolicyContext } from './edit_policy_context'; import { FormInternal } from './types'; +import { createDocLink } from '../../services/documentation'; export interface Props { history: RouteComponentProps['history']; @@ -75,7 +76,7 @@ export const EditPolicy: React.FunctionComponent = ({ history }) => { return createSerializer(isNewPolicy ? undefined : currentPolicy); }, [isNewPolicy, currentPolicy]); - const [saveAsNew, setSaveAsNew] = useState(isNewPolicy); + const [saveAsNew, setSaveAsNew] = useState(false); const originalPolicyName: string = isNewPolicy ? '' : policyName!; const { form } = useForm({ @@ -116,7 +117,7 @@ export const EditPolicy: React.FunctionComponent = ({ history }) => { ); } else { const success = await savePolicy( - { ...policy, name: saveAsNew ? currentPolicyName : originalPolicyName }, + { ...policy, name: saveAsNew || isNewPolicy ? currentPolicyName : originalPolicyName }, isNewPolicy || saveAsNew ); if (success) { @@ -132,216 +133,187 @@ export const EditPolicy: React.FunctionComponent = ({ history }) => { return ( - - -

- {isNewPolicy - ? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', { - defaultMessage: 'Create an index lifecycle policy', - }) - : i18n.translate('xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage', { - defaultMessage: 'Edit index lifecycle policy {originalPolicyName}', - values: { originalPolicyName }, - })} -

-
- -
-
- - -

- {' '} - + + + +

+ {isNewPolicy + ? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', { + defaultMessage: 'Create Policy', + }) + : i18n.translate('xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage', { + defaultMessage: 'Edit Policy {originalPolicyName}', + values: { originalPolicyName }, + })} +

+ + + + + + + + + + {isNewPolicy ? null : ( + + +

+ - } - /> -

-
- - - - {isNewPolicy ? null : ( - - -

- - - - .{' '} - -

-
- - - - { - setSaveAsNew(e.target.checked); - }} - label={ - - - - } /> - -
- )} - - {saveAsNew || isNewPolicy ? ( - - +

+
+ + + + { + setSaveAsNew(e.target.checked); + }} + label={ + -
- } - titleSize="s" - fullWidth - > - - path={policyNamePath} - config={{ - label: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameLabel', { - defaultMessage: 'Policy name', - }), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.validPolicyNameMessage', - { - defaultMessage: - 'A policy name cannot start with an underscore and cannot contain a comma or a space.', - } - ), - validations: policyNameValidations, - }} - component={TextField} - componentProps={{ - fullWidth: false, - euiFieldProps: { - 'data-test-subj': 'policyNameField', - }, - }} + } /> - - ) : null} - - + + + )} + + {saveAsNew || isNewPolicy ? ( + + path={policyNamePath} + config={{ + label: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameLabel', { + defaultMessage: 'Policy name', + }), + helpText: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.validPolicyNameMessage', + { + defaultMessage: + 'A policy name cannot start with an underscore and cannot contain a comma or a space.', + } + ), + validations: policyNameValidations, + }} + component={TextField} + componentProps={{ + fullWidth: false, + euiFieldProps: { + 'data-test-subj': 'policyNameField', + }, + }} + /> + ) : null} - + - + - + - + - + - + - + - + - + - + - - - - - - {saveAsNew ? ( - - ) : ( - - )} - - + - - - - - - - - - - - {isShowingPolicyJsonFlyout ? ( - - ) : ( + + + + {isShowingPolicyJsonFlyout ? ( + + ) : ( + + )} + + + + + + + - )} - - - - - {isShowingPolicyJsonFlyout ? ( - setIsShowingPolicyJsonFlyout(false)} - /> - ) : null} - -
+ + + + + + {saveAsNew ? ( + + ) : ( + + )} + + + + + + + {isShowingPolicyJsonFlyout ? ( + setIsShowingPolicyJsonFlyout(false)} + /> + ) : null} + diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer_and_serializer.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer_and_serializer.test.ts index b5abf51c29028a..44512c2a511ec8 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer_and_serializer.test.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer_and_serializer.test.ts @@ -260,15 +260,6 @@ describe('deserializer and serializer', () => { expect(result.phases.hot!.actions.readonly).toBeUndefined(); }); - it('removes min_age from warm when rollover is enabled', () => { - formInternal._meta.hot.customRollover.enabled = true; - formInternal._meta.warm.warmPhaseOnRollover = true; - - const result = serializer(formInternal); - - expect(result.phases.warm!.min_age).toBeUndefined(); - }); - it('adds default rollover configuration when enabled, but previously not configured', () => { delete formInternal.phases.hot!.actions.rollover; formInternal._meta.hot.isUsingDefaultRollover = true; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts index 4bdf902d27b6d1..9883c2de0685da 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts @@ -7,13 +7,13 @@ import { i18n } from '@kbn/i18n'; import { FormSchema, fieldValidators } from '../../../../shared_imports'; -import { defaultSetPriority, defaultPhaseIndexPriority } from '../../../constants'; +import { defaultIndexPriority } from '../../../constants'; import { ROLLOVER_FORM_PATHS } from '../constants'; -const rolloverFormPaths = Object.values(ROLLOVER_FORM_PATHS); - import { FormInternal } from '../types'; +const rolloverFormPaths = Object.values(ROLLOVER_FORM_PATHS); + import { ifExistsNumberGreaterThanZero, ifExistsNumberNonNegative, @@ -54,7 +54,6 @@ export const schema: FormSchema = { }, bestCompression: { label: i18nTexts.editPolicy.bestCompressionFieldLabel, - helpText: i18nTexts.editPolicy.bestCompressionFieldHelpText, }, readonlyEnabled: { defaultValue: false, @@ -69,18 +68,11 @@ export const schema: FormSchema = { { defaultMessage: 'Activate warm phase' } ), }, - warmPhaseOnRollover: { - defaultValue: true, - label: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.moveToWarmPhaseOnRolloverLabel', { - defaultMessage: 'Move to warm phase on rollover', - }), - }, minAgeUnit: { defaultValue: 'ms', }, bestCompression: { label: i18nTexts.editPolicy.bestCompressionFieldLabel, - helpText: i18nTexts.editPolicy.bestCompressionFieldHelpText, }, dataTierAllocationType: { label: i18nTexts.editPolicy.allocationTypeOptionsFieldLabel, @@ -218,9 +210,14 @@ export const schema: FormSchema = { }, set_priority: { priority: { - defaultValue: defaultSetPriority as any, - label: i18nTexts.editPolicy.setPriorityFieldLabel, - validations: [{ validator: ifExistsNumberNonNegative }], + defaultValue: defaultIndexPriority.hot as any, + label: i18nTexts.editPolicy.indexPriorityFieldLabel, + validations: [ + { + validator: emptyField(i18nTexts.editPolicy.errors.numberRequired), + }, + { validator: ifExistsNumberNonNegative }, + ], serializer: serializers.stringToNumber, }, }, @@ -239,9 +236,12 @@ export const schema: FormSchema = { allocate: { number_of_replicas: { label: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasLabel', { - defaultMessage: 'Number of replicas (optional)', + defaultMessage: 'Number of replicas', }), validations: [ + { + validator: emptyField(i18nTexts.editPolicy.errors.numberRequired), + }, { validator: ifExistsNumberNonNegative, }, @@ -289,9 +289,14 @@ export const schema: FormSchema = { }, set_priority: { priority: { - defaultValue: defaultPhaseIndexPriority as any, - label: i18nTexts.editPolicy.setPriorityFieldLabel, - validations: [{ validator: ifExistsNumberNonNegative }], + defaultValue: defaultIndexPriority.warm as any, + label: i18nTexts.editPolicy.indexPriorityFieldLabel, + validations: [ + { + validator: emptyField(i18nTexts.editPolicy.errors.numberRequired), + }, + { validator: ifExistsNumberNonNegative }, + ], serializer: serializers.stringToNumber, }, }, @@ -310,9 +315,12 @@ export const schema: FormSchema = { allocate: { number_of_replicas: { label: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasLabel', { - defaultMessage: 'Number of replicas (optional)', + defaultMessage: 'Number of replicas', }), validations: [ + { + validator: emptyField(i18nTexts.editPolicy.errors.numberRequired), + }, { validator: ifExistsNumberNonNegative, }, @@ -322,9 +330,14 @@ export const schema: FormSchema = { }, set_priority: { priority: { - defaultValue: '0' as any, - label: i18nTexts.editPolicy.setPriorityFieldLabel, - validations: [{ validator: ifExistsNumberNonNegative }], + defaultValue: defaultIndexPriority.cold as any, + label: i18nTexts.editPolicy.indexPriorityFieldLabel, + validations: [ + { + validator: emptyField(i18nTexts.editPolicy.errors.numberRequired), + }, + { validator: ifExistsNumberNonNegative }, + ], serializer: serializers.stringToNumber, }, }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts index f718073afa3522..f7cdecdc352fb0 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts @@ -20,9 +20,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( ): SerializedPolicy => { const { _meta, ...updatedPolicy } = data; - if (!updatedPolicy.phases || !updatedPolicy.phases.hot) { - updatedPolicy.phases = { hot: { actions: {} } }; - } + updatedPolicy.phases = { hot: { actions: {} }, ...updatedPolicy.phases }; return produce(originalPolicy ?? defaultPolicy, (draft) => { // Copy over all updated fields @@ -32,7 +30,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( * Important shared values for serialization */ const isUsingRollover = Boolean( - _meta.hot.isUsingDefaultRollover || _meta.hot.customRollover.enabled + _meta.hot?.isUsingDefaultRollover || _meta.hot?.customRollover.enabled ); // Next copy over all meta fields and delete any fields that have been removed @@ -53,7 +51,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( * HOT PHASE ROLLOVER */ if (isUsingRollover) { - if (_meta.hot.isUsingDefaultRollover) { + if (_meta.hot?.isUsingDefaultRollover) { hotPhaseActions.rollover = cloneDeep(defaultRolloverAction); } else { // Rollover may not exist if editing an existing policy with initially no rollover configured @@ -63,7 +61,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( // We are using user-defined, custom rollover settings. if (updatedPolicy.phases.hot!.actions.rollover?.max_age) { - hotPhaseActions.rollover.max_age = `${hotPhaseActions.rollover.max_age}${_meta.hot.customRollover.maxAgeUnit}`; + hotPhaseActions.rollover.max_age = `${hotPhaseActions.rollover.max_age}${_meta.hot?.customRollover.maxAgeUnit}`; } else { delete hotPhaseActions.rollover.max_age; } @@ -73,7 +71,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( } if (updatedPolicy.phases.hot!.actions.rollover?.max_size) { - hotPhaseActions.rollover.max_size = `${hotPhaseActions.rollover.max_size}${_meta.hot.customRollover.maxStorageSizeUnit}`; + hotPhaseActions.rollover.max_size = `${hotPhaseActions.rollover.max_size}${_meta.hot?.customRollover.maxStorageSizeUnit}`; } else { delete hotPhaseActions.rollover.max_size; } @@ -84,20 +82,20 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( */ if (!updatedPolicy.phases.hot!.actions?.forcemerge) { delete hotPhaseActions.forcemerge; - } else if (_meta.hot.bestCompression) { + } else if (_meta.hot?.bestCompression) { hotPhaseActions.forcemerge!.index_codec = 'best_compression'; } else { delete hotPhaseActions.forcemerge!.index_codec; } - if (_meta.hot.bestCompression && hotPhaseActions.forcemerge) { + if (_meta.hot?.bestCompression && hotPhaseActions.forcemerge) { hotPhaseActions.forcemerge.index_codec = 'best_compression'; } /** * HOT PHASE READ-ONLY */ - if (_meta.hot.readonlyEnabled) { + if (_meta.hot?.readonlyEnabled) { hotPhaseActions.readonly = hotPhaseActions.readonly ?? {}; } else { delete hotPhaseActions.readonly; @@ -140,17 +138,9 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( /** * WARM PHASE MIN AGE * - * If warm phase on rollover is enabled, delete min age field - * An index lifecycle switches to warm phase when rollover occurs, so you cannot specify a warm phase time - * They are mutually exclusive */ - if ( - (!isUsingRollover || !_meta.warm.warmPhaseOnRollover) && - updatedPolicy.phases.warm?.min_age - ) { + if (updatedPolicy.phases.warm?.min_age) { warmPhase.min_age = `${updatedPolicy.phases.warm!.min_age}${_meta.warm.minAgeUnit}`; - } else { - delete warmPhase.min_age; } /** diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts index f30a40fdd2bb95..71085a6d7a2b8a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts @@ -40,10 +40,10 @@ export const i18nTexts = { defaultMessage: 'Number of segments', } ), - setPriorityFieldLabel: i18n.translate( + indexPriorityFieldLabel: i18n.translate( 'xpack.indexLifecycleMgmt.editPolicy.indexPriorityLabel', { - defaultMessage: 'Index priority (optional)', + defaultMessage: 'Index priority', } ), bestCompressionFieldLabel: i18n.translate( @@ -170,5 +170,30 @@ export const i18nTexts = { } ), }, + titles: { + hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseTitle', { + defaultMessage: 'Hot phase', + }), + warm: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseTitle', { + defaultMessage: 'Warm phase', + }), + cold: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseTitle', { + defaultMessage: 'Cold phase', + }), + }, + descriptions: { + hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseDescription', { + defaultMessage: + 'This phase is required. You are actively querying and writing to your index. For faster updates, you can roll over the index when it gets too big or too old.', + }), + warm: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseDescription', { + defaultMessage: + 'You are still querying your index, but it is read-only. You can allocate shards to less performant hardware. For faster searches, you can reduce the number of shards and force merge segments.', + }), + cold: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseDescription', { + defaultMessage: + 'You are querying your index less frequently, so you can allocate shards on significantly less performant hardware. Because your queries are slower, you can reduce the number of replicas.', + }), + }, }, }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/lib/absolute_timing_to_relative_timing.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/lib/absolute_timing_to_relative_timing.ts index c77b171a56bed2..2f37608b2d7ae2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/lib/absolute_timing_to_relative_timing.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/lib/absolute_timing_to_relative_timing.ts @@ -70,9 +70,10 @@ export interface PhaseAgeInMilliseconds { const phaseOrder: Phase[] = ['hot', 'warm', 'cold', 'delete']; const getMinAge = (phase: MinAgePhase, formData: FormInternal) => ({ - min_age: formData.phases[phase]?.min_age - ? formData.phases[phase]!.min_age! + formData._meta[phase].minAgeUnit - : '0ms', + min_age: + formData.phases && formData.phases[phase]?.min_age + ? formData.phases[phase]!.min_age! + formData._meta[phase].minAgeUnit + : '0ms', }); const formDataToAbsoluteTimings = (formData: FormInternal): AbsoluteTimings => { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts index 2f1c7798e7a4d2..4b22d1c8448b52 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts @@ -9,7 +9,7 @@ import { UIM_CONFIG_WARM_PHASE, UIM_CONFIG_SET_PRIORITY, UIM_CONFIG_FREEZE_INDEX, - defaultPhaseIndexPriority, + defaultIndexPriority, } from '../constants/'; import { getUiMetricsForPhases } from './ui_metric'; @@ -22,7 +22,7 @@ describe('getUiMetricsForPhases', () => { min_age: '0ms', actions: { set_priority: { - priority: parseInt(defaultPhaseIndexPriority, 10), + priority: parseInt(defaultIndexPriority.cold, 10), }, }, }, @@ -37,7 +37,7 @@ describe('getUiMetricsForPhases', () => { min_age: '0ms', actions: { set_priority: { - priority: parseInt(defaultPhaseIndexPriority, 10), + priority: parseInt(defaultIndexPriority.warm, 10), }, }, }, @@ -52,7 +52,7 @@ describe('getUiMetricsForPhases', () => { min_age: '0ms', actions: { set_priority: { - priority: parseInt(defaultPhaseIndexPriority, 10) + 1, + priority: parseInt(defaultIndexPriority.warm, 10) + 1, }, }, }, @@ -68,7 +68,7 @@ describe('getUiMetricsForPhases', () => { actions: { freeze: {}, set_priority: { - priority: parseInt(defaultPhaseIndexPriority, 10), + priority: parseInt(defaultIndexPriority.cold, 10), }, }, }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts index bcf4b6cf1da0d2..ffdcf927a5b67e 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts @@ -19,8 +19,7 @@ import { UIM_CONFIG_FREEZE_INDEX, UIM_CONFIG_SET_PRIORITY, UIM_CONFIG_WARM_PHASE, - defaultSetPriority, - defaultPhaseIndexPriority, + defaultIndexPriority, } from '../constants'; import { Phases } from '../../../common/types'; @@ -50,17 +49,17 @@ export function getUiMetricsForPhases(phases: Phases): string[] { const isHotPhasePriorityChanged = phases.hot && phases.hot.actions.set_priority && - phases.hot.actions.set_priority.priority !== parseInt(defaultSetPriority, 10); + phases.hot.actions.set_priority.priority !== parseInt(defaultIndexPriority.hot, 10); const isWarmPhasePriorityChanged = phases.warm && phases.warm.actions.set_priority && - phases.warm.actions.set_priority.priority !== parseInt(defaultPhaseIndexPriority, 10); + phases.warm.actions.set_priority.priority !== parseInt(defaultIndexPriority.warm, 10); const isColdPhasePriorityChanged = phases.cold && phases.cold.actions.set_priority && - phases.cold.actions.set_priority.priority !== parseInt(defaultPhaseIndexPriority, 10); + phases.cold.actions.set_priority.priority !== parseInt(defaultIndexPriority.cold, 10); // If the priority is different than the default, we'll consider it a user interaction, // even if the user has set it to undefined. return ( diff --git a/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts b/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts index 4cb5d952394089..fdb25dec6f1fdb 100644 --- a/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts +++ b/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts @@ -31,6 +31,7 @@ export { SuperSelectField, ComboBoxField, TextField, + CheckBoxField, } from '../../../../src/plugins/es_ui_shared/static/forms/components'; export { attemptToURIDecode } from '../../../../src/plugins/es_ui_shared/public'; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index da9228335a3f3b..e2506cb6ca8f02 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9416,9 +9416,7 @@ "xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableTitle": "コールドティアに割り当てられているノードがありません", "xpack.indexLifecycleMgmt.coldPhase.dataTier.description": "頻度が低い読み取り専用アクセス用に最適化されたノードにデータを移動します。安価なハードウェアのコールドフェーズにデータを格納します。", "xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel": "インデックスを凍結", - "xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasDescription": "レプリカの数を設定します。デフォルトでは前のフェーズと同じです。", "xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasLabel": "レプリカ数(任意)", - "xpack.indexLifecycleMgmt.coldPhase.replicasTitle": "レプリカ", "xpack.indexLifecycleMgmt.common.dataTier.title": "データ割り当て", "xpack.indexLifecycleMgmt.confirmDelete.cancelButton": "キャンセル", "xpack.indexLifecycleMgmt.confirmDelete.deleteButton": "削除", @@ -9431,11 +9429,8 @@ "xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.title": "コールドティアを作成", "xpack.indexLifecycleMgmt.editPolicy.cold.nodeAttributesMissingDescription": "属性に基づく割り当てを使用するには、elasticsearch.yml でカスタムノード属性を定義します。", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.activateColdPhaseSwitchLabel": "コールドフェーズを有効にする", - "xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseDescriptionText": "インデックスへのクエリの頻度を減らすことで、大幅に性能が低いハードウェアにシャードを割り当てることができます。クエリが遅いため、複製の数を減らすことができます。", - "xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseLabel": "コールドフェーズ", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText": "インデックスを読み取り専用にし、メモリー消費量を最小化します。", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText": "凍結", - "xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel": "レプリカを設定", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText": "ノード属性に基づいてデータを移動します。", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input": "カスタム", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText": "コールドティアのノードにデータを移動します。", @@ -9452,13 +9447,6 @@ "xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage": "インデックスライフサイクルポリシーを作成します", "xpack.indexLifecycleMgmt.editPolicy.createSearchableSnapshotLink": "スナップショットリポジドリを作成", "xpack.indexLifecycleMgmt.editPolicy.createSnapshotRepositoryLink": "新しいスナップショットリポジドリを作成", - "xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel": "インデックスの作成からの経過日数", - "xpack.indexLifecycleMgmt.editPolicy.creationHoursOptionLabel": "インデックスの作成からの経過時間数", - "xpack.indexLifecycleMgmt.editPolicy.creationMicroSecondsOptionLabel": "インデックスの作成からの経過時間(マイクロ秒)", - "xpack.indexLifecycleMgmt.editPolicy.creationMilliSecondsOptionLabel": "インデックスの作成からの経過時間(ミリ秒)", - "xpack.indexLifecycleMgmt.editPolicy.creationMinutesOptionLabel": "インデックスの作成からの経過時間(分)", - "xpack.indexLifecycleMgmt.editPolicy.creationNanoSecondsOptionLabel": "インデックスの作成からの経過時間(ナノ秒)", - "xpack.indexLifecycleMgmt.editPolicy.creationSecondsOptionLabel": "インデックスの作成からの経過時間(秒)", "xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.allocationFieldLabel": "データティアオプション", "xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.nodeAllocationFieldLabel": "ノード属性を選択", "xpack.indexLifecycleMgmt.editPolicy.dataTierColdLabel": "コールド", @@ -9499,23 +9487,17 @@ "xpack.indexLifecycleMgmt.editPolicy.formErrorsMessage": "このページのエラーを修正してください。", "xpack.indexLifecycleMgmt.editPolicy.hidePolicyJsonButto": "リクエストを非表示", "xpack.indexLifecycleMgmt.editPolicy.hotPhase.enableRolloverTipContent": "現在のインデックスが定義された条件のいずれかを満たすときに、新しいインデックスにロールオーバーします。", - "xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseDescriptionMessage": "このフェーズは必須です。アクティブにクエリを実行しインデックスに書き込んでいます。 更新を高速化するため、大きくなりすぎたり古くなりすぎたりした際にインデックスをロールオーバーできます。", - "xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseLabel": "ホットフェーズ", "xpack.indexLifecycleMgmt.editPolicy.hotPhase.learnAboutRolloverLinkText": "詳細", "xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDefaultsTipContent": "インデックスが 30 日経過するか、50 GB に達したらロールオーバーします。", "xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDescriptionMessage": "効率的なストレージと高いパフォーマンスのための時系列データの自動ロールアウト。", "xpack.indexLifecycleMgmt.editPolicy.indexPriorityLabel": "インデックス優先度(任意)", "xpack.indexLifecycleMgmt.editPolicy.indexPriorityText": "インデックスの優先順位", - "xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexLifecycleManagementLinkText": "インデックスライフサイクルの詳細をご覧ください。", "xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexTemplatesLink": "インデックステンプレートの詳細をご覧ください", "xpack.indexLifecycleMgmt.editPolicy.learnAboutShardAllocationLink": "シャード割り当ての詳細をご覧ください", - "xpack.indexLifecycleMgmt.editPolicy.learnAboutTimingText": "タイミングの詳細をご覧ください", "xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesLoadingFailedTitle": "既存のライフサイクルポリシーを読み込めません", "xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesReloadButton": "再試行", - "xpack.indexLifecycleMgmt.editPolicy.lifecyclePolicyDescriptionText": "インデックスへのアクティブな書き込みから削除までの、インデックスライフサイクルの 4 つのフェーズを自動化するには、インデックスポリシーを使用します。", "xpack.indexLifecycleMgmt.editPolicy.loadSnapshotRepositoriesErrorBody": "このフィールドを更新し、既存のスナップショットリポジトリの名前を入力します。", "xpack.indexLifecycleMgmt.editPolicy.loadSnapshotRepositoriesErrorTitle": "スナップショットリポジトリを読み込めません", - "xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名前", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "ノード属性を使用して、シャード割り当てを制御します。{learnMoreLink}。", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "割り当て構成を修正しない", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesLoadingFailedTitle": "ノードデータを読み込めません", @@ -9542,13 +9524,6 @@ "xpack.indexLifecycleMgmt.editPolicy.readonlyDescription": "有効にすると、インデックスおよびインデックスメタデータを読み取り専用にします。無効にすると、書き込みとメタデータの変更を許可します。", "xpack.indexLifecycleMgmt.editPolicy.readonlyTitle": "読み取り専用", "xpack.indexLifecycleMgmt.editPolicy.reloadSnapshotRepositoriesLabel": "スナップショットリポジドリの再読み込み", - "xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel": "ロールオーバーからの経過日数", - "xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel": "ロールオーバーからの経過時間数", - "xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel": "ロールオーバーからの経過時間(マイクロ秒)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel": "ロールオーバーからの経過時間(ミリ秒)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel": "ロールオーバーからの経過時間数(分)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel": "ロールオーバーからの経過時間(ナノ秒)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel": "ロールオーバーからの経過時間(秒)", "xpack.indexLifecycleMgmt.editPolicy.saveAsNewButton": "新規ポリシーとして保存します", "xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage": "新規ポリシーとして保存します", "xpack.indexLifecycleMgmt.editPolicy.saveButton": "ポリシーを保存", @@ -9573,15 +9548,11 @@ "xpack.indexLifecycleMgmt.editPolicy.warm.nodeAttributesMissingDescription": "属性に基づく割り当てを使用するには、elasticsearch.yml でカスタムノード属性を定義します。", "xpack.indexLifecycleMgmt.editPolicy.warmPhase.activateWarmPhaseSwitchLabel": "ウォームフェーズを有効にする", "xpack.indexLifecycleMgmt.editPolicy.warmPhase.indexPriorityExplanationText": "ノードの再起動後にインデックスを復元する優先順位を設定します。優先順位の高いインデックスは優先順位の低いインデックスよりも先に復元されます。", - "xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel": "レプリカを設定", - "xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseDescriptionMessage": "まだインデックスにクエリを実行中ですが、読み取り専用です。性能の低いハードウェアにシャードを割り当てることができます。検索を高速化するために、シャードの数を減らしセグメントを結合することができます。", - "xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseLabel": "ウォームフェーズ", "xpack.indexLifecycleMgmt.featureCatalogueDescription": "ライフサイクルポリシーを定義し、インデックス年齢として自動的に処理を実行します。", "xpack.indexLifecycleMgmt.featureCatalogueTitle": "インデックスライフサイクルを管理", "xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel": "格納されたフィールドを圧縮", "xpack.indexLifecycleMgmt.forcemerge.enableLabel": "データを強制結合", "xpack.indexLifecycleMgmt.forceMerge.numberOfSegmentsLabel": "セグメントの数", - "xpack.indexLifecycleMgmt.hotPhase.advancedSettingsButton": "高度な設定", "xpack.indexLifecycleMgmt.hotPhase.bytesLabel": "バイト", "xpack.indexLifecycleMgmt.hotPhase.daysLabel": "日", "xpack.indexLifecycleMgmt.hotPhase.enableRolloverLabel": "ロールオーバーを有効にする", @@ -9705,7 +9676,6 @@ "xpack.indexLifecycleMgmt.shrink.indexFieldLabel": "インデックスを縮小", "xpack.indexLifecycleMgmt.shrink.numberOfPrimaryShardsLabel": "プライマリシャードの数", "xpack.indexLifecycleMgmt.templateNotFoundMessage": "テンプレート{name}が見つかりません。", - "xpack.indexLifecycleMgmt.warmPhase.advancedSettingsButton": "高度な設定", "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableBody": "ロールに基づく割り当てを使用するには、1つ以上のノードを、ウォームまたはホットティアに割り当てます。使用可能なノードがない場合、ポリシーは割り当てを完了できません。", "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableTitle": "ウォームティアに割り当てられているノードがありません", "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold": "このポリシーはコールドフェーズのデータを{tier}ティアノードに移動します。", @@ -9713,10 +9683,7 @@ "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm": "このポリシーはウォームフェーズのデータを{tier}ティアノードに移動します。", "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm.title": "ウォームティアに割り当てられているノードがありません", "xpack.indexLifecycleMgmt.warmPhase.dataTier.description": "頻度が低い読み取り専用アクセス用に最適化されたノードにデータを移動します。", - "xpack.indexLifecycleMgmt.warmPhase.moveToWarmPhaseOnRolloverLabel": "ロールオーバー時にウォームフェーズに変更", - "xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasDescription": "レプリカの数を設定します。デフォルトでは前のフェーズと同じです。", "xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasLabel": "レプリカ数(任意)", - "xpack.indexLifecycleMgmt.warmPhase.replicasTitle": "レプリカ", "xpack.infra.alerting.alertFlyout.groupBy.placeholder": "なし(グループなし)", "xpack.infra.alerting.alertFlyout.groupByLabel": "グループ分けの条件", "xpack.infra.alerting.alertsButton": "アラート", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 679edaf9e0cdd7..7b8ea35baf0ff2 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9440,9 +9440,7 @@ "xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableTitle": "没有分配到冷层的节点", "xpack.indexLifecycleMgmt.coldPhase.dataTier.description": "将数据移到针对不太频繁的只读访问优化的节点。将处于冷阶段的数据存储在成本较低的硬件上。", "xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel": "冻结索引", - "xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasDescription": "设置副本数目。默认情况下仍与上一阶段相同。", "xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasLabel": "副本分片数(可选)", - "xpack.indexLifecycleMgmt.coldPhase.replicasTitle": "副本分片", "xpack.indexLifecycleMgmt.common.dataTier.title": "数据分配", "xpack.indexLifecycleMgmt.confirmDelete.cancelButton": "取消", "xpack.indexLifecycleMgmt.confirmDelete.deleteButton": "删除", @@ -9455,11 +9453,8 @@ "xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.title": "创建冷层", "xpack.indexLifecycleMgmt.editPolicy.cold.nodeAttributesMissingDescription": "在 elasticsearch.yml 中定义定制节点属性,以使用基于属性的分配。", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.activateColdPhaseSwitchLabel": "激活冷阶段", - "xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseDescriptionText": "您查询自己索引的频率较低,因此您可以在效率较低的硬件上分配分片。因为您的查询较为缓慢,所以您可以减少副本分片数目。", - "xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseLabel": "冷阶段", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText": "使索引只读,并最大限度减小其内存占用。", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText": "冻结", - "xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel": "设置副本", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText": "根据节点属性移动数据。", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input": "定制", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText": "将数据移到冷层中的节点。", @@ -9476,13 +9471,6 @@ "xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage": "创建索引生命周期策略", "xpack.indexLifecycleMgmt.editPolicy.createSearchableSnapshotLink": "创建快照库", "xpack.indexLifecycleMgmt.editPolicy.createSnapshotRepositoryLink": "创建新的快照库", - "xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel": "天(自索引创建)", - "xpack.indexLifecycleMgmt.editPolicy.creationHoursOptionLabel": "小时(自索引创建)", - "xpack.indexLifecycleMgmt.editPolicy.creationMicroSecondsOptionLabel": "微秒(自索引创建)", - "xpack.indexLifecycleMgmt.editPolicy.creationMilliSecondsOptionLabel": "毫秒(自索引创建)", - "xpack.indexLifecycleMgmt.editPolicy.creationMinutesOptionLabel": "分钟(自索引创建)", - "xpack.indexLifecycleMgmt.editPolicy.creationNanoSecondsOptionLabel": "纳秒(自索引创建)", - "xpack.indexLifecycleMgmt.editPolicy.creationSecondsOptionLabel": "秒(自索引创建)", "xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.allocationFieldLabel": "数据层选项", "xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.nodeAllocationFieldLabel": "选择节点属性", "xpack.indexLifecycleMgmt.editPolicy.dataTierColdLabel": "冷", @@ -9523,23 +9511,17 @@ "xpack.indexLifecycleMgmt.editPolicy.formErrorsMessage": "请修复此页面上的错误。", "xpack.indexLifecycleMgmt.editPolicy.hidePolicyJsonButto": "隐藏请求", "xpack.indexLifecycleMgmt.editPolicy.hotPhase.enableRolloverTipContent": "在当前索引满足定义的条件之一时,滚动更新到新索引。", - "xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseDescriptionMessage": "此阶段为必需。您正频繁地查询并写到您的索引。 为了获取更快的更新,在索引变得过大或过旧时,您可以滚动更新索引。", - "xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseLabel": "热阶段", "xpack.indexLifecycleMgmt.editPolicy.hotPhase.learnAboutRolloverLinkText": "了解详情", "xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDefaultsTipContent": "当索引已存在 30 天或达到 50 GB 时滚动更新。", "xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDescriptionMessage": "自动滚动更新时间序列数据,以实现高效存储和更高性能。", "xpack.indexLifecycleMgmt.editPolicy.indexPriorityLabel": "索引优先级(可选)", "xpack.indexLifecycleMgmt.editPolicy.indexPriorityText": "索引优先级", - "xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexLifecycleManagementLinkText": "了解索引生命周期。", "xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexTemplatesLink": "了解索引模板", "xpack.indexLifecycleMgmt.editPolicy.learnAboutShardAllocationLink": "了解分片分配", - "xpack.indexLifecycleMgmt.editPolicy.learnAboutTimingText": "了解计时", "xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesLoadingFailedTitle": "无法加载现有生命周期策略", "xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesReloadButton": "重试", - "xpack.indexLifecycleMgmt.editPolicy.lifecyclePolicyDescriptionText": "使用索引策略自动化索引生命周期的四个阶段,从频繁地写入到索引到删除索引。", "xpack.indexLifecycleMgmt.editPolicy.loadSnapshotRepositoriesErrorBody": "刷新此字段并输入现有快照储存库的名称。", "xpack.indexLifecycleMgmt.editPolicy.loadSnapshotRepositoriesErrorTitle": "无法加载快照存储库", - "xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名称", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "使用节点属性控制分片分配。{learnMoreLink}。", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "切勿修改分配配置", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesLoadingFailedTitle": "无法加载节点数据", @@ -9566,13 +9548,6 @@ "xpack.indexLifecycleMgmt.editPolicy.readonlyDescription": "启用以使索引及索引元数据只读;禁用以允许写入和元数据更改。", "xpack.indexLifecycleMgmt.editPolicy.readonlyTitle": "只读", "xpack.indexLifecycleMgmt.editPolicy.reloadSnapshotRepositoriesLabel": "重新加载快照存储库", - "xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel": "天(自滚动更新)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel": "小时(自滚动更新)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel": "微秒(自滚动更新)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel": "毫秒(自滚动更新)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel": "分钟(自滚动更新)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel": "纳秒(自滚动更新)", - "xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel": "秒(自滚动更新)", "xpack.indexLifecycleMgmt.editPolicy.saveAsNewButton": "另存为新策略", "xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage": "另存为新策略", "xpack.indexLifecycleMgmt.editPolicy.saveButton": "保存策略", @@ -9597,15 +9572,11 @@ "xpack.indexLifecycleMgmt.editPolicy.warm.nodeAttributesMissingDescription": "在 elasticsearch.yml 中定义定制节点属性,以使用基于属性的分配。", "xpack.indexLifecycleMgmt.editPolicy.warmPhase.activateWarmPhaseSwitchLabel": "激活温阶段", "xpack.indexLifecycleMgmt.editPolicy.warmPhase.indexPriorityExplanationText": "设置在节点重新启动后恢复索引的优先级。较高优先级的索引会在较低优先级的索引之前恢复。", - "xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel": "设置副本", - "xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseDescriptionMessage": "您仍在查询自己的索引,但其为只读。您可以将分片分配给效率较低的硬件。为了获取更快的搜索,您可以减少分片数目并强制合并段。", - "xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseLabel": "温阶段", "xpack.indexLifecycleMgmt.featureCatalogueDescription": "定义生命周期策略,以随着索引老化自动执行操作。", "xpack.indexLifecycleMgmt.featureCatalogueTitle": "管理索引生命周期", "xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel": "压缩已存储字段", "xpack.indexLifecycleMgmt.forcemerge.enableLabel": "强制合并数据", "xpack.indexLifecycleMgmt.forceMerge.numberOfSegmentsLabel": "分段数目", - "xpack.indexLifecycleMgmt.hotPhase.advancedSettingsButton": "高级设置", "xpack.indexLifecycleMgmt.hotPhase.bytesLabel": "字节", "xpack.indexLifecycleMgmt.hotPhase.daysLabel": "天", "xpack.indexLifecycleMgmt.hotPhase.enableRolloverLabel": "启用滚动更新", @@ -9731,7 +9702,6 @@ "xpack.indexLifecycleMgmt.shrink.indexFieldLabel": "缩小索引", "xpack.indexLifecycleMgmt.shrink.numberOfPrimaryShardsLabel": "主分片数目", "xpack.indexLifecycleMgmt.templateNotFoundMessage": "找不到模板 {name}。", - "xpack.indexLifecycleMgmt.warmPhase.advancedSettingsButton": "高级设置", "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableBody": "至少将一个节点分配到温层或冷层,以使用基于角色的分配。如果没有可用节点,则策略无法完成分配。", "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableTitle": "没有分配到温层的节点", "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold": "此策略会改为将冷阶段的数据移到{tier}层节点。", @@ -9739,10 +9709,7 @@ "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm": "此策略会改为将温阶段的数据移到{tier}层节点。", "xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm.title": "没有分配到温层的节点", "xpack.indexLifecycleMgmt.warmPhase.dataTier.description": "将数据移到针对不太频繁的只读访问优化的节点。", - "xpack.indexLifecycleMgmt.warmPhase.moveToWarmPhaseOnRolloverLabel": "滚动更新时移到温阶段", - "xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasDescription": "设置副本数目。默认情况下仍与上一阶段相同。", "xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasLabel": "副本分片数(可选)", - "xpack.indexLifecycleMgmt.warmPhase.replicasTitle": "副本分片", "xpack.infra.alerting.alertFlyout.groupBy.placeholder": "无内容(未分组)", "xpack.infra.alerting.alertFlyout.groupByLabel": "分组依据", "xpack.infra.alerting.alertsButton": "告警", From 466334529c2fa981e83babdc6bcc01b039aee038 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Wed, 27 Jan 2021 09:00:50 -0800 Subject: [PATCH 36/58] [Alerts][Actions][Telemetry] Fix mappings for Kibana actions and alert types telemetry. (#88532) * [Alerts][Actions][Telemetry] Fix mappings for Kibana actions and alert types telemetry. * fixed count_active_by_type for actions * fixed tests * Fixed due to comments. * Fixed due to comments. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/usage/actions_telemetry.test.ts | 90 ++++++++++++++++++- .../actions/server/usage/actions_telemetry.ts | 48 +++++++++- x-pack/plugins/actions/server/usage/task.ts | 26 +++++- .../server/usage/alerts_telemetry.test.ts | 8 +- .../alerts/server/usage/alerts_telemetry.ts | 13 ++- 5 files changed, 169 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts index 1b0fe036335311..08a3fd007554ef 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts @@ -4,16 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getTotalCount } from './actions_telemetry'; +import { getInUseTotalCount, getTotalCount } from './actions_telemetry'; describe('actions telemetry', () => { - test('getTotalCount should replace action types names with . to __', async () => { + test('getTotalCount should replace first symbol . to __ for action types names', async () => { const mockEsClient = jest.fn(); mockEsClient.mockReturnValue({ aggregations: { byActionTypeId: { value: { - types: { '.index': 1, '.server-log': 1 }, + types: { '.index': 1, '.server-log': 1, 'some.type': 1, 'another.type.': 1 }, }, }, }, @@ -56,6 +56,38 @@ describe('actions telemetry', () => { updated_at: '2020-03-26T18:46:44.449Z', }, }, + { + _id: 'action:00000000-1', + _index: '.kibana_1', + _score: 0, + _source: { + action: { + actionTypeId: 'some.type', + config: {}, + name: 'test type', + secrets: {}, + }, + references: [], + type: 'action', + updated_at: '2020-03-26T18:46:44.449Z', + }, + }, + { + _id: 'action:00000000-2', + _index: '.kibana_1', + _score: 0, + _source: { + action: { + actionTypeId: 'another.type.', + config: {}, + name: 'test another type', + secrets: {}, + }, + references: [], + type: 'action', + updated_at: '2020-03-26T18:46:44.449Z', + }, + }, ], }, }); @@ -69,6 +101,58 @@ Object { "countByType": Object { "__index": 1, "__server-log": 1, + "another.type__": 1, + "some.type": 1, + }, + "countTotal": 4, +} +`); + }); + + test('getInUseTotalCount', async () => { + const mockEsClient = jest.fn(); + mockEsClient.mockReturnValue({ + aggregations: { + refs: { + actionRefIds: { + value: { + connectorIds: { '1': 'action-0', '123': 'action-0' }, + total: 2, + }, + }, + }, + hits: { + hits: [], + }, + }, + }); + const actionsBulkGet = jest.fn(); + actionsBulkGet.mockReturnValue({ + saved_objects: [ + { + id: '1', + attributes: { + actionTypeId: '.server-log', + }, + }, + { + id: '123', + attributes: { + actionTypeId: '.slack', + }, + }, + ], + }); + const telemetry = await getInUseTotalCount(mockEsClient, actionsBulkGet, 'test'); + + expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(actionsBulkGet).toHaveBeenCalledTimes(1); + + expect(telemetry).toMatchInlineSnapshot(` +Object { + "countByType": Object { + "__server-log": 1, + "__slack": 1, }, "countTotal": 2, } diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index e3ff2552fed9c2..cc49232150eeef 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -4,7 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LegacyAPICaller } from 'kibana/server'; +import { + LegacyAPICaller, + SavedObjectsBaseOptions, + SavedObjectsBulkGetObject, + SavedObjectsBulkResponse, +} from 'kibana/server'; +import { ActionResult } from '../types'; export async function getTotalCount(callCluster: LegacyAPICaller, kibanaIndex: string) { const scriptedMetric = { @@ -58,14 +64,23 @@ export async function getTotalCount(callCluster: LegacyAPICaller, kibanaIndex: s // eslint-disable-next-line @typescript-eslint/no-explicit-any (obj: any, key: string) => ({ ...obj, - [key.replace('.', '__')]: searchResult.aggregations.byActionTypeId.value.types[key], + [replaceFirstAndLastDotSymbols(key)]: searchResult.aggregations.byActionTypeId.value.types[ + key + ], }), {} ), }; } -export async function getInUseTotalCount(callCluster: LegacyAPICaller, kibanaIndex: string) { +export async function getInUseTotalCount( + callCluster: LegacyAPICaller, + actionsBulkGet: ( + objects?: SavedObjectsBulkGetObject[] | undefined, + options?: SavedObjectsBaseOptions | undefined + ) => Promise>>>, + kibanaIndex: string +): Promise<{ countTotal: number; countByType: Record }> { const scriptedMetric = { scripted_metric: { init_script: 'state.connectorIds = new HashMap(); state.total = 0;', @@ -145,7 +160,32 @@ export async function getInUseTotalCount(callCluster: LegacyAPICaller, kibanaInd }, }); - return actionResults.aggregations.refs.actionRefIds.value.total; + const bulkFilter = Object.entries( + actionResults.aggregations.refs.actionRefIds.value.connectorIds + ).map(([key]) => ({ + id: key, + type: 'action', + fields: ['id', 'actionTypeId'], + })); + const actions = await actionsBulkGet(bulkFilter); + const countByType = actions.saved_objects.reduce( + (actionTypeCount: Record, action) => { + const alertTypeId = replaceFirstAndLastDotSymbols(action.attributes.actionTypeId); + const currentCount = + actionTypeCount[alertTypeId] !== undefined ? actionTypeCount[alertTypeId] : 0; + actionTypeCount[alertTypeId] = currentCount + 1; + return actionTypeCount; + }, + {} + ); + return { countTotal: actionResults.aggregations.refs.actionRefIds.value.total, countByType }; +} + +function replaceFirstAndLastDotSymbols(strToReplace: string) { + const hasFirstSymbolDot = strToReplace.startsWith('.'); + const appliedString = hasFirstSymbolDot ? strToReplace.replace('.', '__') : strToReplace; + const hasLastSymbolDot = strToReplace.endsWith('.'); + return hasLastSymbolDot ? `${appliedString.slice(0, -1)}__` : appliedString; } // TODO: Implement executions count telemetry with eventLog, when it will write to index diff --git a/x-pack/plugins/actions/server/usage/task.ts b/x-pack/plugins/actions/server/usage/task.ts index 176ba29ef748ab..001db21ffebcc7 100644 --- a/x-pack/plugins/actions/server/usage/task.ts +++ b/x-pack/plugins/actions/server/usage/task.ts @@ -4,13 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger, CoreSetup, LegacyAPICaller } from 'kibana/server'; +import { + Logger, + CoreSetup, + LegacyAPICaller, + SavedObjectsBulkGetObject, + SavedObjectsBaseOptions, +} from 'kibana/server'; import moment from 'moment'; import { RunContext, TaskManagerSetupContract, TaskManagerStartContract, } from '../../../task_manager/server'; +import { ActionResult } from '../types'; import { getTotalCount, getInUseTotalCount } from './actions_telemetry'; export const TELEMETRY_TASK_TYPE = 'actions_telemetry'; @@ -66,19 +73,30 @@ export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex client.callAsInternalUser(...args) ); }; + const actionsBulkGet = ( + objects?: SavedObjectsBulkGetObject[], + options?: SavedObjectsBaseOptions + ) => { + return core + .getStartServices() + .then(([{ savedObjects }]) => + savedObjects.createInternalRepository(['action']).bulkGet(objects, options) + ); + }; return { async run() { return Promise.all([ getTotalCount(callCluster, kibanaIndex), - getInUseTotalCount(callCluster, kibanaIndex), + getInUseTotalCount(callCluster, actionsBulkGet, kibanaIndex), ]) - .then(([totalAggegations, countActiveTotal]) => { + .then(([totalAggegations, totalInUse]) => { return { state: { runs: (state.runs || 0) + 1, count_total: totalAggegations.countTotal, count_by_type: totalAggegations.countByType, - count_active_total: countActiveTotal, + count_active_total: totalInUse.countTotal, + count_active_by_type: totalInUse.countByType, }, runAt: getNextMidnight(), }; diff --git a/x-pack/plugins/alerts/server/usage/alerts_telemetry.test.ts b/x-pack/plugins/alerts/server/usage/alerts_telemetry.test.ts index 171f80cf11cb8c..843100194e4b67 100644 --- a/x-pack/plugins/alerts/server/usage/alerts_telemetry.test.ts +++ b/x-pack/plugins/alerts/server/usage/alerts_telemetry.test.ts @@ -7,13 +7,13 @@ import { getTotalCountInUse } from './alerts_telemetry'; describe('alerts telemetry', () => { - test('getTotalCountInUse should replace action types names with . to __', async () => { + test('getTotalCountInUse should replace first "." symbol to "__" in alert types names', async () => { const mockEsClient = jest.fn(); mockEsClient.mockReturnValue({ aggregations: { byAlertTypeId: { value: { - types: { '.index-threshold': 2 }, + types: { '.index-threshold': 2, 'logs.alert.document.count': 1, 'document.test.': 1 }, }, }, }, @@ -30,8 +30,10 @@ describe('alerts telemetry', () => { Object { "countByType": Object { "__index-threshold": 2, + "document.test__": 1, + "logs.alert.document.count": 1, }, - "countTotal": 2, + "countTotal": 4, } `); }); diff --git a/x-pack/plugins/alerts/server/usage/alerts_telemetry.ts b/x-pack/plugins/alerts/server/usage/alerts_telemetry.ts index 6edebb1decb610..72b189aa67f4b9 100644 --- a/x-pack/plugins/alerts/server/usage/alerts_telemetry.ts +++ b/x-pack/plugins/alerts/server/usage/alerts_telemetry.ts @@ -250,7 +250,7 @@ export async function getTotalCountAggregations(callCluster: LegacyAPICaller, ki // eslint-disable-next-line @typescript-eslint/no-explicit-any (obj: any, key: string) => ({ ...obj, - [key.replace('.', '__')]: results.aggregations.byAlertTypeId.value.types[key], + [replaceFirstAndLastDotSymbols(key)]: results.aggregations.byAlertTypeId.value.types[key], }), {} ), @@ -310,11 +310,20 @@ export async function getTotalCountInUse(callCluster: LegacyAPICaller, kibanaIne // eslint-disable-next-line @typescript-eslint/no-explicit-any (obj: any, key: string) => ({ ...obj, - [key.replace('.', '__')]: searchResult.aggregations.byAlertTypeId.value.types[key], + [replaceFirstAndLastDotSymbols(key)]: searchResult.aggregations.byAlertTypeId.value.types[ + key + ], }), {} ), }; } +function replaceFirstAndLastDotSymbols(strToReplace: string) { + const hasFirstSymbolDot = strToReplace.startsWith('.'); + const appliedString = hasFirstSymbolDot ? strToReplace.replace('.', '__') : strToReplace; + const hasLastSymbolDot = strToReplace.endsWith('.'); + return hasLastSymbolDot ? `${appliedString.slice(0, -1)}__` : appliedString; +} + // TODO: Implement executions count telemetry with eventLog, when it will write to index From 723dd32693addda90c73cafe041b9bf5ce4b3ea3 Mon Sep 17 00:00:00 2001 From: Kent Marten <65553677+kmartastic@users.noreply.github.com> Date: Wed, 27 Jan 2021 09:34:03 -0800 Subject: [PATCH 37/58] [maps] Update point to point docs with use cases (#89246) Co-authored-by: Kent Marten --- docs/maps/maps-aggregations.asciidoc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/maps/maps-aggregations.asciidoc b/docs/maps/maps-aggregations.asciidoc index f09d99250c22dd..3c66e187bf59cd 100644 --- a/docs/maps/maps-aggregations.asciidoc +++ b/docs/maps/maps-aggregations.asciidoc @@ -98,6 +98,13 @@ Point to point uses an {es} {ref}/search-aggregations-bucket-terms-aggregation.h Then, a nested {ref}/search-aggregations-bucket-geotilegrid-aggregation.html[GeoTile grid aggregation] groups sources for each destination into grids. A line connects each source grid centroid to each destination. +Point-to-point layers are used in several common use cases: + +* Source-destination maps for network traffic +* Origin-destination maps for flight data +* Origin-destination flows for import/export/migration +* Origin-destination for pick-up/drop-off data + image::maps/images/point_to_point.png[] [role="xpack"] From da9ad2ade4e80961c30ef4df27f4d1467a34c4ab Mon Sep 17 00:00:00 2001 From: Quynh Nguyen <43350163+qn895@users.noreply.github.com> Date: Wed, 27 Jan 2021 11:39:50 -0600 Subject: [PATCH 38/58] [ML] Add embedded map to geo_point fields for Data Visualizer (#88880) --- .../maps/public/embeddable/map_embeddable.tsx | 2 +- x-pack/plugins/ml/kibana.json | 6 +- .../plugins/ml/public/application/_index.scss | 1 + x-pack/plugins/ml/public/application/app.tsx | 3 + .../components/ml_embedded_map/_index.scss | 1 + .../ml_embedded_map/_ml_embedded_map.scss | 8 + .../components/ml_embedded_map/index.ts | 7 + .../ml_embedded_map/ml_embedded_map.tsx | 160 ++++++++++++++++++ .../contexts/kibana/kibana_context.ts | 4 + .../expanded_row/file_based_expanded_row.tsx | 2 +- .../geo_point_content/format_utils.ts | 76 +++++++++ .../geo_point_content/geo_point_content.tsx | 79 +++++++++ .../expanded_row/geo_point_content/index.ts | 7 + .../file_datavisualizer_view/_index.scss | 2 +- .../components/expanded_row/expanded_row.tsx | 28 ++- .../expanded_row/geo_point_content.tsx | 78 +++++++++ .../examples_list/examples_list.tsx | 34 ++-- .../field_data_row/top_values/top_values.tsx | 108 +++++++----- .../datavisualizer/index_based/page.tsx | 35 ++-- .../stats_table/_field_data_row.scss | 15 ++ .../datavisualizer/stats_table/_index.scss | 10 +- .../field_data_expanded_row/_index.scss | 6 + .../boolean_content.tsx | 7 +- .../field_data_expanded_row/date_content.tsx | 7 +- .../document_stats.tsx | 3 +- .../expanded_row_content.tsx | 24 +++ .../geo_point_content.tsx | 35 ---- .../field_data_expanded_row/index.ts | 2 +- .../field_data_expanded_row/ip_content.tsx | 20 +-- .../keyword_content.tsx | 19 +-- .../number_content.tsx | 26 +-- .../field_data_expanded_row/other_content.tsx | 6 +- .../field_data_expanded_row/text_content.tsx | 7 +- .../components/field_data_row/_index.scss | 3 + .../field_data_row/distinct_values.tsx | 2 +- .../field_data_row/document_stats.tsx | 2 +- .../field_data_row/number_content_preview.tsx | 7 +- .../application/util/dependency_cache.ts | 3 + x-pack/plugins/ml/public/plugin.ts | 8 +- .../models/data_visualizer/data_visualizer.ts | 21 +-- .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - .../data_visualizer/file_data_visualizer.ts | 41 +++++ .../files_to_import/geo_file.csv | 14 ++ .../data_visualizer/index_data_visualizer.ts | 79 ++++++++- .../services/ml/data_visualizer_table.ts | 51 +++++- 46 files changed, 842 insertions(+), 223 deletions(-) create mode 100644 x-pack/plugins/ml/public/application/components/ml_embedded_map/_index.scss create mode 100644 x-pack/plugins/ml/public/application/components/ml_embedded_map/_ml_embedded_map.scss create mode 100644 x-pack/plugins/ml/public/application/components/ml_embedded_map/index.ts create mode 100644 x-pack/plugins/ml/public/application/components/ml_embedded_map/ml_embedded_map.tsx create mode 100644 x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/format_utils.ts create mode 100644 x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/geo_point_content.tsx create mode 100644 x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/index.ts create mode 100644 x-pack/plugins/ml/public/application/datavisualizer/index_based/components/expanded_row/geo_point_content.tsx create mode 100644 x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/expanded_row_content.tsx delete mode 100644 x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/geo_point_content.tsx create mode 100644 x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/_index.scss create mode 100644 x-pack/test/functional/apps/ml/data_visualizer/files_to_import/geo_file.csv diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index 67981ab3aede5f..bcdc23bddd2ebd 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -68,7 +68,7 @@ import { MapEmbeddableInput, MapEmbeddableOutput, } from './types'; -export { MapEmbeddableInput }; +export { MapEmbeddableInput, MapEmbeddableOutput }; export class MapEmbeddable extends Embeddable diff --git a/x-pack/plugins/ml/kibana.json b/x-pack/plugins/ml/kibana.json index 8ec9b8ee976d42..1c47512e0b3de0 100644 --- a/x-pack/plugins/ml/kibana.json +++ b/x-pack/plugins/ml/kibana.json @@ -24,7 +24,8 @@ "security", "spaces", "management", - "licenseManagement" + "licenseManagement", + "maps" ], "server": true, "ui": true, @@ -35,7 +36,8 @@ "dashboard", "savedObjects", "home", - "spaces" + "spaces", + "maps" ], "extraPublicDirs": [ "common" diff --git a/x-pack/plugins/ml/public/application/_index.scss b/x-pack/plugins/ml/public/application/_index.scss index 7512c180970ad1..da1c226a665f6d 100644 --- a/x-pack/plugins/ml/public/application/_index.scss +++ b/x-pack/plugins/ml/public/application/_index.scss @@ -30,6 +30,7 @@ @import 'components/navigation_menu/index'; @import 'components/rule_editor/index'; // SASSTODO: This file overwrites EUI directly @import 'components/stats_bar/index'; + @import 'components/ml_embedded_map/index'; // Hacks are last so they can overwrite anything above if needed @import 'hacks'; diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index d3a055f957c3aa..68ee32e24391cf 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -77,6 +77,8 @@ const App: FC = ({ coreStart, deps, appMountParams }) => { security: deps.security, licenseManagement: deps.licenseManagement, storage: localStorage, + embeddable: deps.embeddable, + maps: deps.maps, ...coreStart, }; @@ -118,6 +120,7 @@ export const renderApp = ( http: coreStart.http, security: deps.security, urlGenerators: deps.share.urlGenerators, + maps: deps.maps, }); appMountParams.onAppLeave((actions) => actions.default()); diff --git a/x-pack/plugins/ml/public/application/components/ml_embedded_map/_index.scss b/x-pack/plugins/ml/public/application/components/ml_embedded_map/_index.scss new file mode 100644 index 00000000000000..6d0d30dae670ea --- /dev/null +++ b/x-pack/plugins/ml/public/application/components/ml_embedded_map/_index.scss @@ -0,0 +1 @@ +@import 'ml_embedded_map'; diff --git a/x-pack/plugins/ml/public/application/components/ml_embedded_map/_ml_embedded_map.scss b/x-pack/plugins/ml/public/application/components/ml_embedded_map/_ml_embedded_map.scss new file mode 100644 index 00000000000000..495fc40ddb27c1 --- /dev/null +++ b/x-pack/plugins/ml/public/application/components/ml_embedded_map/_ml_embedded_map.scss @@ -0,0 +1,8 @@ +.mlEmbeddedMapContent { + width: 100%; + height: 100%; + display: flex; + flex: 1 1 100%; + z-index: 1; + min-height: 0; // Absolute must for Firefox to scroll contents +} diff --git a/x-pack/plugins/ml/public/application/components/ml_embedded_map/index.ts b/x-pack/plugins/ml/public/application/components/ml_embedded_map/index.ts new file mode 100644 index 00000000000000..ce5dfb5171a6da --- /dev/null +++ b/x-pack/plugins/ml/public/application/components/ml_embedded_map/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 { MlEmbeddedMapComponent } from './ml_embedded_map'; diff --git a/x-pack/plugins/ml/public/application/components/ml_embedded_map/ml_embedded_map.tsx b/x-pack/plugins/ml/public/application/components/ml_embedded_map/ml_embedded_map.tsx new file mode 100644 index 00000000000000..d5fdc9d52a1028 --- /dev/null +++ b/x-pack/plugins/ml/public/application/components/ml_embedded_map/ml_embedded_map.tsx @@ -0,0 +1,160 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useEffect, useRef, useState } from 'react'; + +import { htmlIdGenerator } from '@elastic/eui'; +import { LayerDescriptor } from '../../../../../maps/common/descriptor_types'; +import { + MapEmbeddable, + MapEmbeddableInput, + MapEmbeddableOutput, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../../../maps/public/embeddable'; +import { MAP_SAVED_OBJECT_TYPE, RenderTooltipContentParams } from '../../../../../maps/public'; +import { + EmbeddableFactory, + ErrorEmbeddable, + isErrorEmbeddable, + ViewMode, +} from '../../../../../../../src/plugins/embeddable/public'; +import { useMlKibana } from '../../contexts/kibana'; + +export function MlEmbeddedMapComponent({ + layerList, + mapEmbeddableInput, + renderTooltipContent, +}: { + layerList: LayerDescriptor[]; + mapEmbeddableInput?: MapEmbeddableInput; + renderTooltipContent?: (params: RenderTooltipContentParams) => JSX.Element; +}) { + const [embeddable, setEmbeddable] = useState(); + + const embeddableRoot: React.RefObject = useRef(null); + const baseLayers = useRef(); + + const { + services: { embeddable: embeddablePlugin, maps: mapsPlugin }, + } = useMlKibana(); + + const factory: + | EmbeddableFactory + | undefined = embeddablePlugin + ? embeddablePlugin.getEmbeddableFactory(MAP_SAVED_OBJECT_TYPE) + : undefined; + + // Update the layer list with updated geo points upon refresh + useEffect(() => { + async function updateIndexPatternSearchLayer() { + if ( + embeddable && + !isErrorEmbeddable(embeddable) && + Array.isArray(layerList) && + Array.isArray(baseLayers.current) + ) { + embeddable.setLayerList([...baseLayers.current, ...layerList]); + } + } + updateIndexPatternSearchLayer(); + }, [embeddable, layerList]); + + useEffect(() => { + async function setupEmbeddable() { + if (!factory) { + // eslint-disable-next-line no-console + console.error('Map embeddable not found.'); + return; + } + const input: MapEmbeddableInput = { + id: htmlIdGenerator()(), + attributes: { title: '' }, + filters: [], + hidePanelTitles: true, + refreshConfig: { + value: 0, + pause: false, + }, + viewMode: ViewMode.VIEW, + isLayerTOCOpen: false, + hideFilterActions: true, + // Zoom Lat/Lon values are set to make sure map is in center in the panel + // It will also omit Greenland/Antarctica etc. NOTE: Can be removed when initialLocation is set + mapCenter: { + lon: 11, + lat: 20, + zoom: 1, + }, + // can use mapSettings to center map on anomalies + mapSettings: { + disableInteractive: false, + hideToolbarOverlay: false, + hideLayerControl: false, + hideViewControl: false, + // Doesn't currently work with GEO_JSON. Will uncomment when https://github.com/elastic/kibana/pull/88294 is in + // initialLocation: INITIAL_LOCATION.AUTO_FIT_TO_BOUNDS, // this will startup based on data-extent + autoFitToDataBounds: true, // this will auto-fit when there are changes to the filter and/or query + }, + }; + + const embeddableObject = await factory.create(input); + + if (embeddableObject && !isErrorEmbeddable(embeddableObject)) { + const basemapLayerDescriptor = mapsPlugin + ? await mapsPlugin.createLayerDescriptors.createBasemapLayerDescriptor() + : null; + + if (basemapLayerDescriptor) { + baseLayers.current = [basemapLayerDescriptor]; + await embeddableObject.setLayerList(baseLayers.current); + } + } + + setEmbeddable(embeddableObject); + } + + setupEmbeddable(); + // we want this effect to execute exactly once after the component mounts + }, []); + + useEffect(() => { + if (embeddable && !isErrorEmbeddable(embeddable) && mapEmbeddableInput !== undefined) { + embeddable.updateInput(mapEmbeddableInput); + } + }, [embeddable, mapEmbeddableInput]); + + useEffect(() => { + if (embeddable && !isErrorEmbeddable(embeddable) && renderTooltipContent !== undefined) { + embeddable.setRenderTooltipContent(renderTooltipContent); + } + }, [embeddable, renderTooltipContent]); + + // We can only render after embeddable has already initialized + useEffect(() => { + if (embeddableRoot.current && embeddable) { + embeddable.render(embeddableRoot.current); + } + }, [embeddable, embeddableRoot]); + + if (!embeddablePlugin) { + // eslint-disable-next-line no-console + console.error('Embeddable start plugin not found'); + return null; + } + if (!mapsPlugin) { + // eslint-disable-next-line no-console + console.error('Maps start plugin not found'); + return null; + } + + return ( +
+ ); +} diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts index 4a7550788db56d..a97fd513c9c99d 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts @@ -15,12 +15,16 @@ import { LicenseManagementUIPluginSetup } from '../../../../../license_managemen import { SharePluginStart } from '../../../../../../../src/plugins/share/public'; import { MlServicesContext } from '../../app'; import { IStorageWrapper } from '../../../../../../../src/plugins/kibana_utils/public'; +import type { EmbeddableStart } from '../../../../../../../src/plugins/embeddable/public'; +import { MapsStartApi } from '../../../../../maps/public'; interface StartPlugins { data: DataPublicPluginStart; security?: SecurityPluginSetup; licenseManagement?: LicenseManagementUIPluginSetup; share: SharePluginStart; + embeddable: EmbeddableStart; + maps?: MapsStartApi; } export type StartServices = CoreStart & StartPlugins & { diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/file_based_expanded_row.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/file_based_expanded_row.tsx index 77f31ae9c2322a..a8d8eb18776ec5 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/file_based_expanded_row.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/file_based_expanded_row.tsx @@ -8,13 +8,13 @@ import React from 'react'; import { BooleanContent, DateContent, - GeoPointContent, IpContent, KeywordContent, OtherContent, TextContent, NumberContent, } from '../../../stats_table/components/field_data_expanded_row'; +import { GeoPointContent } from './geo_point_content/geo_point_content'; import { ML_JOB_FIELD_TYPES } from '../../../../../../common/constants/field_types'; import type { FileBasedFieldVisConfig } from '../../../stats_table/types/field_vis_config'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/format_utils.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/format_utils.ts new file mode 100644 index 00000000000000..8a442e345014dc --- /dev/null +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/format_utils.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Feature, Point } from 'geojson'; +import { euiPaletteColorBlind } from '@elastic/eui'; +import { DEFAULT_GEO_REGEX } from './geo_point_content'; +import { SOURCE_TYPES } from '../../../../../../../../maps/common/constants'; + +export const convertWKTGeoToLonLat = ( + value: string | number +): { lat: number; lon: number } | undefined => { + if (typeof value === 'string') { + const trimmedValue = value.trim().replace('POINT (', '').replace(')', ''); + const regExpSerializer = DEFAULT_GEO_REGEX; + const parsed = regExpSerializer.exec(trimmedValue.trim()); + + if (parsed?.groups?.lat != null && parsed?.groups?.lon != null) { + return { + lat: parseFloat(parsed.groups.lat.trim()), + lon: parseFloat(parsed.groups.lon.trim()), + }; + } + } +}; + +export const DEFAULT_POINT_COLOR = euiPaletteColorBlind()[0]; +export const getGeoPointsLayer = ( + features: Array>, + pointColor: string = DEFAULT_POINT_COLOR +) => { + return { + id: 'geo_points', + label: 'Geo points', + sourceDescriptor: { + type: SOURCE_TYPES.GEOJSON_FILE, + __featureCollection: { + features, + type: 'FeatureCollection', + }, + }, + visible: true, + style: { + type: 'VECTOR', + properties: { + fillColor: { + type: 'STATIC', + options: { + color: pointColor, + }, + }, + lineColor: { + type: 'STATIC', + options: { + color: '#fff', + }, + }, + lineWidth: { + type: 'STATIC', + options: { + size: 2, + }, + }, + iconSize: { + type: 'STATIC', + options: { + size: 6, + }, + }, + }, + }, + type: 'VECTOR', + }; +}; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/geo_point_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/geo_point_content.tsx new file mode 100644 index 00000000000000..a498b786229bba --- /dev/null +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/geo_point_content.tsx @@ -0,0 +1,79 @@ +/* + * 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, { FC, useMemo } from 'react'; + +import { EuiFlexItem } from '@elastic/eui'; +import { Feature, Point } from 'geojson'; +import type { FieldDataRowProps } from '../../../../stats_table/types/field_data_row'; +import { DocumentStatsTable } from '../../../../stats_table/components/field_data_expanded_row/document_stats'; +import { MlEmbeddedMapComponent } from '../../../../../components/ml_embedded_map'; +import { convertWKTGeoToLonLat, getGeoPointsLayer } from './format_utils'; +import { ExpandedRowContent } from '../../../../stats_table/components/field_data_expanded_row/expanded_row_content'; +import { ExamplesList } from '../../../../index_based/components/field_data_row/examples_list'; + +export const DEFAULT_GEO_REGEX = RegExp('(?.+) (?.+)'); + +export const GeoPointContent: FC = ({ config }) => { + const formattedResults = useMemo(() => { + const { stats } = config; + + if (stats === undefined || stats.topValues === undefined) return null; + if (Array.isArray(stats.topValues)) { + const geoPointsFeatures: Array> = []; + + // reformatting the top values from POINT (-2.359207 51.37837) to (-2.359207, 51.37837) + const formattedExamples = []; + + for (let i = 0; i < stats.topValues.length; i++) { + const value = stats.topValues[i]; + const coordinates = convertWKTGeoToLonLat(value.key); + if (coordinates) { + const formattedGeoPoint = `(${coordinates.lat}, ${coordinates.lon})`; + formattedExamples.push(coordinates); + + geoPointsFeatures.push({ + type: 'Feature', + id: `ml-${config.fieldName}-${i}`, + geometry: { + type: 'Point', + coordinates: [coordinates.lat, coordinates.lon], + }, + properties: { + value: formattedGeoPoint, + count: value.doc_count, + }, + }); + } + } + + if (geoPointsFeatures.length > 0) { + return { + examples: formattedExamples, + layerList: [getGeoPointsLayer(geoPointsFeatures)], + }; + } + } + }, [config]); + return ( + + + {formattedResults && Array.isArray(formattedResults.examples) && ( + + + + )} + {formattedResults && Array.isArray(formattedResults.layerList) && ( + + + + )} + + ); +}; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/index.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/index.ts new file mode 100644 index 00000000000000..d3a50db45ec579 --- /dev/null +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/expanded_row/geo_point_content/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 { GeoPointContent } from './geo_point_content'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/_index.scss b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/_index.scss index 957ca0eec24d3d..c1191ad270e4c9 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/_index.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/_index.scss @@ -1 +1 @@ -@import 'file_datavisualizer_view' +@import 'file_datavisualizer_view'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/expanded_row/expanded_row.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/expanded_row/expanded_row.tsx index 7018f73ff6c32c..6d58efee36f364 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/expanded_row/expanded_row.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/expanded_row/expanded_row.tsx @@ -6,23 +6,31 @@ import React from 'react'; +import { ML_JOB_FIELD_TYPES } from '../../../../../../common/constants/field_types'; +import { LoadingIndicator } from '../field_data_row/loading_indicator'; +import { NotInDocsContent } from '../field_data_row/content_types'; import { FieldVisConfig } from '../../../stats_table/types'; import { BooleanContent, DateContent, - GeoPointContent, IpContent, KeywordContent, NumberContent, OtherContent, TextContent, } from '../../../stats_table/components/field_data_expanded_row'; +import { CombinedQuery, GeoPointContent } from './geo_point_content'; +import { IndexPattern } from '../../../../../../../../../src/plugins/data/common/index_patterns/index_patterns'; -import { ML_JOB_FIELD_TYPES } from '../../../../../../common/constants/field_types'; -import { LoadingIndicator } from '../field_data_row/loading_indicator'; -import { NotInDocsContent } from '../field_data_row/content_types'; - -export const IndexBasedDataVisualizerExpandedRow = ({ item }: { item: FieldVisConfig }) => { +export const IndexBasedDataVisualizerExpandedRow = ({ + item, + indexPattern, + combinedQuery, +}: { + item: FieldVisConfig; + indexPattern: IndexPattern | undefined; + combinedQuery: CombinedQuery; +}) => { const config = item; const { loading, type, existsInDocs, fieldName } = config; @@ -42,7 +50,13 @@ export const IndexBasedDataVisualizerExpandedRow = ({ item }: { item: FieldVisCo return ; case ML_JOB_FIELD_TYPES.GEO_POINT: - return ; + return ( + + ); case ML_JOB_FIELD_TYPES.IP: return ; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/expanded_row/geo_point_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/expanded_row/geo_point_content.tsx new file mode 100644 index 00000000000000..94db5d1ba686c1 --- /dev/null +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/expanded_row/geo_point_content.tsx @@ -0,0 +1,78 @@ +/* + * 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, { FC, useEffect, useState } from 'react'; + +import { EuiFlexItem } from '@elastic/eui'; +import { ExamplesList } from '../../../index_based/components/field_data_row/examples_list'; +import { FieldVisConfig } from '../../../stats_table/types'; +import { IndexPattern } from '../../../../../../../../../src/plugins/data/common/index_patterns/index_patterns'; +import { MlEmbeddedMapComponent } from '../../../../components/ml_embedded_map'; +import { ML_JOB_FIELD_TYPES } from '../../../../../../common/constants/field_types'; +import { ES_GEO_FIELD_TYPE } from '../../../../../../../maps/common/constants'; +import { LayerDescriptor } from '../../../../../../../maps/common/descriptor_types'; +import { useMlKibana } from '../../../../contexts/kibana'; +import { DocumentStatsTable } from '../../../stats_table/components/field_data_expanded_row/document_stats'; +import { ExpandedRowContent } from '../../../stats_table/components/field_data_expanded_row/expanded_row_content'; + +export interface CombinedQuery { + searchString: string | { [key: string]: any }; + searchQueryLanguage: string; +} +export const GeoPointContent: FC<{ + config: FieldVisConfig; + indexPattern: IndexPattern | undefined; + combinedQuery: CombinedQuery; +}> = ({ config, indexPattern, combinedQuery }) => { + const { stats } = config; + const [layerList, setLayerList] = useState([]); + const { + services: { maps: mapsPlugin }, + } = useMlKibana(); + + // Update the layer list with updated geo points upon refresh + useEffect(() => { + async function updateIndexPatternSearchLayer() { + if ( + indexPattern?.id !== undefined && + config !== undefined && + config.fieldName !== undefined && + config.type === ML_JOB_FIELD_TYPES.GEO_POINT + ) { + const params = { + indexPatternId: indexPattern.id, + geoFieldName: config.fieldName, + geoFieldType: config.type as ES_GEO_FIELD_TYPE.GEO_POINT, + query: { + query: combinedQuery.searchString, + language: combinedQuery.searchQueryLanguage, + }, + }; + const searchLayerDescriptor = mapsPlugin + ? await mapsPlugin.createLayerDescriptors.createESSearchSourceLayerDescriptor(params) + : null; + if (searchLayerDescriptor) { + setLayerList([...layerList, searchLayerDescriptor]); + } + } + } + updateIndexPatternSearchLayer(); + }, [indexPattern, config.fieldName, combinedQuery]); + + if (stats?.examples === undefined) return null; + return ( + + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_row/examples_list/examples_list.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_row/examples_list/examples_list.tsx index 1e8f7586258d50..a59c6e0fe41839 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_row/examples_list/examples_list.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_row/examples_list/examples_list.tsx @@ -15,25 +15,29 @@ interface Props { } export const ExamplesList: FC = ({ examples }) => { - if ( - examples === undefined || - examples === null || - !Array.isArray(examples) || - examples.length === 0 - ) { + if (examples === undefined || examples === null || !Array.isArray(examples)) { return null; } - - const examplesContent = examples.map((example, i) => { - return ( - ); - }); + } else { + examplesContent = examples.map((example, i) => { + return ( + + ); + }); + } return (
diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_row/top_values/top_values.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_row/top_values/top_values.tsx index bd83aaa1f61493..8ad48a3e60d3af 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_row/top_values/top_values.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_row/top_values/top_values.tsx @@ -19,9 +19,11 @@ import { FormattedMessage } from '@kbn/i18n/react'; import classNames from 'classnames'; import { kibanaFieldFormat } from '../../../../../formatters/kibana_field_format'; import { roundToDecimalPlace } from '../../../../../formatters/round_to_decimal_place'; +import { ExpandedRowFieldHeader } from '../../../../stats_table/components/expanded_row_field_header'; +import { FieldVisStats } from '../../../../stats_table/types'; interface Props { - stats: any; + stats: FieldVisStats | undefined; fieldFormat?: any; barColor?: 'primary' | 'secondary' | 'danger' | 'subdued' | 'accent'; compressed?: boolean; @@ -37,6 +39,7 @@ function getPercentLabel(docCount: number, topValuesSampleSize: number): string } export const TopValues: FC = ({ stats, fieldFormat, barColor, compressed }) => { + if (stats === undefined) return null; const { topValues, topValuesSampleSize, @@ -46,51 +49,64 @@ export const TopValues: FC = ({ stats, fieldFormat, barColor, compressed } = stats; const progressBarMax = isTopValuesSampled === true ? topValuesSampleSize : count; return ( -
- {Array.isArray(topValues) && - topValues.map((value: any) => ( - - + + + + +
+ {Array.isArray(topValues) && + topValues.map((value) => ( + + + + + {kibanaFieldFormat(value.key, fieldFormat)} + + + + + + + {progressBarMax !== undefined && ( + + + {getPercentLabel(value.doc_count, progressBarMax)} + + )} - > - - - {kibanaFieldFormat(value.key, fieldFormat)} - - - - - - - - - {getPercentLabel(value.doc_count, progressBarMax)} - - - - ))} - {isTopValuesSampled === true && ( - - - - - - - )} -
+
+ ))} + {isTopValuesSampled === true && ( + + + + + + + )} +
+ ); }; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/page.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/page.tsx index e5b243d5240345..8cf5e28ad3b5bd 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/page.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/page.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC, Fragment, useEffect, useMemo, useState } from 'react'; +import React, { FC, Fragment, useEffect, useMemo, useState, useCallback } from 'react'; import { merge } from 'rxjs'; import { EuiFlexGroup, @@ -112,19 +112,6 @@ export const getDefaultDataVisualizerListState = (): Required { - const item = items.find((fieldVisConfig) => fieldVisConfig.fieldName === fieldName); - if (item !== undefined) { - m[fieldName] = ; - } - return m; - }, {} as ItemIdToExpandedRowMap); -} - export const Page: FC = () => { const mlContext = useMlContext(); const restorableDefaults = getDefaultDataVisualizerListState(); @@ -678,6 +665,26 @@ export const Page: FC = () => { } return { visibleFieldsCount: _visibleFieldsCount, totalFieldsCount: _totalFieldsCount }; }, [overallStats, showEmptyFields]); + + const getItemIdToExpandedRowMap = useCallback( + function (itemIds: string[], items: FieldVisConfig[]): ItemIdToExpandedRowMap { + return itemIds.reduce((m: ItemIdToExpandedRowMap, fieldName: string) => { + const item = items.find((fieldVisConfig) => fieldVisConfig.fieldName === fieldName); + if (item !== undefined) { + m[fieldName] = ( + + ); + } + return m; + }, {} as ItemIdToExpandedRowMap); + }, + [currentIndexPattern, searchQuery] + ); + const { services: { docLinks }, } = useMlKibana(); diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/_field_data_row.scss b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/_field_data_row.scss index 2ab26f1564a1fc..1832b0f78b895f 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/_field_data_row.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/_field_data_row.scss @@ -60,6 +60,21 @@ @include euiCodeFont; } + .mlFieldDataCard__geoContent { + z-index: auto; + flex: 1; + display: flex; + flex-direction: column; + height: 100%; + position: relative; + .embPanel__content { + display: flex; + flex: 1 1 100%; + z-index: 1; + min-height: 0; // Absolute must for Firefox to scroll contents + } + } + .mlFieldDataCard__stats { padding: $euiSizeS $euiSizeS 0 $euiSizeS; text-align: center; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/_index.scss b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/_index.scss index 6e7e66db9e03a5..9e838c180713f8 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/_index.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/_index.scss @@ -1,5 +1,6 @@ -@import 'components/field_data_expanded_row/number_content'; +@import 'components/field_data_expanded_row/index'; @import 'components/field_count_stats/index'; +@import 'components/field_data_row/index'; .mlDataVisualizerFieldExpandedRow { padding-left: $euiSize * 4; @@ -37,6 +38,7 @@ } .mlDataVisualizerSummaryTable { max-width: 350px; + min-width: 250px; .euiTableRow > .euiTableRowCell { border-bottom: 0; } @@ -45,6 +47,10 @@ } } .mlDataVisualizerSummaryTableWrapper { - max-width: 350px; + max-width: 300px; + } + .mlDataVisualizerMapWrapper { + min-height: 300px; + min-width: 600px; } } diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/_index.scss b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/_index.scss index fdc591a140fea9..799beec093ccab 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/_index.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/_index.scss @@ -1 +1,7 @@ @import 'number_content'; + +.mlDataVisualizerExpandedRow { + @include euiBreakpoint('xs', 's', 'm') { + flex-direction: column; + } +} diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/boolean_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/boolean_content.tsx index a75920dd09b34e..70e98153fd55cc 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/boolean_content.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/boolean_content.tsx @@ -5,7 +5,7 @@ */ import React, { FC, ReactNode, useMemo } from 'react'; -import { EuiBasicTable, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { EuiBasicTable, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { Axis, BarSeries, Chart, Settings } from '@elastic/charts'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -16,6 +16,7 @@ import { getTFPercentage } from '../../utils'; import { roundToDecimalPlace } from '../../../../formatters/round_to_decimal_place'; import { useDataVizChartTheme } from '../../hooks'; import { DocumentStatsTable } from './document_stats'; +import { ExpandedRowContent } from './expanded_row_content'; function getPercentLabel(value: number): string { if (value === 0) { @@ -85,7 +86,7 @@ export const BooleanContent: FC = ({ config }) => { ); return ( - + @@ -138,6 +139,6 @@ export const BooleanContent: FC = ({ config }) => { /> - + ); }; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/date_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/date_content.tsx index 8d122df628381e..a6e7901df4e8ea 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/date_content.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/date_content.tsx @@ -5,7 +5,7 @@ */ import React, { FC, ReactNode } from 'react'; -import { EuiBasicTable, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiBasicTable, EuiFlexItem } from '@elastic/eui'; // @ts-ignore import { formatDate } from '@elastic/eui/lib/services/format'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -14,6 +14,7 @@ import { i18n } from '@kbn/i18n'; import type { FieldDataRowProps } from '../../types/field_data_row'; import { ExpandedRowFieldHeader } from '../expanded_row_field_header'; import { DocumentStatsTable } from './document_stats'; +import { ExpandedRowContent } from './expanded_row_content'; const TIME_FORMAT = 'MMM D YYYY, HH:mm:ss.SSS'; interface SummaryTableItem { function: string; @@ -66,7 +67,7 @@ export const DateContent: FC = ({ config }) => { ]; return ( - + {summaryTableTitle} @@ -80,6 +81,6 @@ export const DateContent: FC = ({ config }) => { tableLayout="auto" /> - + ); }; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/document_stats.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/document_stats.tsx index 177ac722166f72..fd23e9d51bf4ee 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/document_stats.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/document_stats.tsx @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n'; import { EuiBasicTable, EuiFlexItem } from '@elastic/eui'; import { ExpandedRowFieldHeader } from '../expanded_row_field_header'; import { FieldDataRowProps } from '../../types'; +import { roundToDecimalPlace } from '../../../../formatters/round_to_decimal_place'; const metaTableColumns = [ { @@ -59,7 +60,7 @@ export const DocumentStatsTable: FC = ({ config }) => { defaultMessage="percentage" /> ), - value: `${(count / sampleCount) * 100}%`, + value: `${roundToDecimalPlace((count / sampleCount) * 100)}%`, }, { function: 'distinctValues', diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/expanded_row_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/expanded_row_content.tsx new file mode 100644 index 00000000000000..6c14bd7a64a944 --- /dev/null +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/expanded_row_content.tsx @@ -0,0 +1,24 @@ +/* + * 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, { FC, ReactNode } from 'react'; +import { EuiFlexGroup } from '@elastic/eui'; + +interface Props { + children: ReactNode; + dataTestSubj: string; +} +export const ExpandedRowContent: FC = ({ children, dataTestSubj }) => { + return ( + + {children} + + ); +}; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/geo_point_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/geo_point_content.tsx deleted file mode 100644 index 993c7a94f5e06d..00000000000000 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/geo_point_content.tsx +++ /dev/null @@ -1,35 +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 React, { FC } from 'react'; - -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import type { FieldDataRowProps } from '../../types/field_data_row'; -import { ExamplesList } from '../../../index_based/components/field_data_row/examples_list'; -import { DocumentStatsTable } from './document_stats'; -import { TopValues } from '../../../index_based/components/field_data_row/top_values'; - -export const GeoPointContent: FC = ({ config }) => { - const { stats } = config; - if (stats === undefined || (stats?.examples === undefined && stats?.topValues === undefined)) - return null; - - return ( - - - {Array.isArray(stats.examples) && ( - - - - )} - {Array.isArray(stats.topValues) && ( - - - - )} - - ); -}; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/index.ts b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/index.ts index c6cd50f6bc2e9c..b9b1e181343b70 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/index.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/index.ts @@ -6,7 +6,7 @@ export { BooleanContent } from './boolean_content'; export { DateContent } from './date_content'; -export { GeoPointContent } from './geo_point_content'; +export { GeoPointContent } from '../../../file_based/components/expanded_row/geo_point_content/geo_point_content'; export { KeywordContent } from './keyword_content'; export { IpContent } from './ip_content'; export { NumberContent } from './number_content'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/ip_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/ip_content.tsx index 79492bb44a2dcb..183268d6a7ef88 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/ip_content.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/ip_content.tsx @@ -5,14 +5,10 @@ */ import React, { FC } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; - -import { FormattedMessage } from '@kbn/i18n/react'; - import type { FieldDataRowProps } from '../../types/field_data_row'; import { TopValues } from '../../../index_based/components/field_data_row/top_values'; -import { ExpandedRowFieldHeader } from '../expanded_row_field_header'; import { DocumentStatsTable } from './document_stats'; +import { ExpandedRowContent } from './expanded_row_content'; export const IpContent: FC = ({ config }) => { const { stats } = config; @@ -22,17 +18,9 @@ export const IpContent: FC = ({ config }) => { const fieldFormat = 'fieldFormat' in config ? config.fieldFormat : undefined; return ( - + - - - - - - - + + ); }; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/keyword_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/keyword_content.tsx index 634f5b55513a3a..d11ecc7d8804b0 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/keyword_content.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/keyword_content.tsx @@ -5,31 +5,20 @@ */ import React, { FC } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import type { FieldDataRowProps } from '../../types/field_data_row'; import { TopValues } from '../../../index_based/components/field_data_row/top_values'; -import { ExpandedRowFieldHeader } from '../expanded_row_field_header'; import { DocumentStatsTable } from './document_stats'; +import { ExpandedRowContent } from './expanded_row_content'; export const KeywordContent: FC = ({ config }) => { const { stats } = config; const fieldFormat = 'fieldFormat' in config ? config.fieldFormat : undefined; return ( - + - - - - - - - - + + ); }; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/number_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/number_content.tsx index d05de26d3c5d46..56811e61ad8911 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/number_content.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/number_content.tsx @@ -5,7 +5,7 @@ */ import React, { FC, ReactNode, useEffect, useState } from 'react'; -import { EuiBasicTable, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { EuiBasicTable, EuiFlexItem, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; @@ -20,6 +20,7 @@ import { import { TopValues } from '../../../index_based/components/field_data_row/top_values'; import { ExpandedRowFieldHeader } from '../expanded_row_field_header'; import { DocumentStatsTable } from './document_stats'; +import { ExpandedRowContent } from './expanded_row_content'; const METRIC_DISTRIBUTION_CHART_WIDTH = 325; const METRIC_DISTRIBUTION_CHART_HEIGHT = 200; @@ -97,7 +98,7 @@ export const NumberContent: FC = ({ config }) => { } ); return ( - + {summaryTableTitle} @@ -112,24 +113,7 @@ export const NumberContent: FC = ({ config }) => { {stats && ( - - - - - - - - - - + )} {distribution && ( @@ -164,6 +148,6 @@ export const NumberContent: FC = ({ config }) => { )} - + ); }; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/other_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/other_content.tsx index a6d7398990cd39..08884619db2d66 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/other_content.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/other_content.tsx @@ -5,18 +5,18 @@ */ import React, { FC } from 'react'; -import { EuiFlexGroup } from '@elastic/eui'; import type { FieldDataRowProps } from '../../types/field_data_row'; import { ExamplesList } from '../../../index_based/components/field_data_row/examples_list'; import { DocumentStatsTable } from './document_stats'; +import { ExpandedRowContent } from './expanded_row_content'; export const OtherContent: FC = ({ config }) => { const { stats } = config; if (stats === undefined) return null; return ( - + {Array.isArray(stats.examples) && } - + ); }; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/text_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/text_content.tsx index 55639ecc5761fa..c0a5ca18d03b57 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/text_content.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_expanded_row/text_content.tsx @@ -5,13 +5,14 @@ */ import React, { FC, Fragment } from 'react'; -import { EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { EuiCallOut, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import type { FieldDataRowProps } from '../../types/field_data_row'; import { ExamplesList } from '../../../index_based/components/field_data_row/examples_list'; +import { ExpandedRowContent } from './expanded_row_content'; export const TextContent: FC = ({ config }) => { const { stats } = config; @@ -23,7 +24,7 @@ export const TextContent: FC = ({ config }) => { const numExamples = examples.length; return ( - + {numExamples > 0 && } {numExamples === 0 && ( @@ -59,6 +60,6 @@ export const TextContent: FC = ({ config }) => { )} - + ); }; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/_index.scss b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/_index.scss new file mode 100644 index 00000000000000..27483feb573b87 --- /dev/null +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/_index.scss @@ -0,0 +1,3 @@ +.mlDataVisualizerColumnHeaderIcon { + max-width: $euiSizeM; +} diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/distinct_values.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/distinct_values.tsx index 819d5278c0d788..44c028d1ba8b5c 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/distinct_values.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/distinct_values.tsx @@ -12,7 +12,7 @@ export const DistinctValues = ({ cardinality }: { cardinality?: number }) => { if (cardinality === undefined) return null; return ( - + diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/document_stats.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/document_stats.tsx index 9c89d74fa751b5..b223fd5d98c1a0 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/document_stats.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/document_stats.tsx @@ -21,7 +21,7 @@ export const DocumentStat = ({ config }: FieldDataRowProps) => { return ( - + diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/number_content_preview.tsx b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/number_content_preview.tsx index 3a84ae644cb4ec..996fffd225f963 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/number_content_preview.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_table/components/field_data_row/number_content_preview.tsx @@ -14,6 +14,7 @@ import { } from '../metric_distribution_chart'; import { formatSingleValue } from '../../../../formatters/format_value'; import { FieldVisConfig } from '../../types'; +import { kibanaFieldFormat } from '../../../../formatters/kibana_field_format'; const METRIC_DISTRIBUTION_CHART_WIDTH = 150; const METRIC_DISTRIBUTION_CHART_HEIGHT = 80; @@ -59,14 +60,16 @@ export const IndexBasedNumberContentPreview: FC = ({ <> - {legendText.min} + + {kibanaFieldFormat(legendText.min, fieldFormat)} + - {legendText.max} + {kibanaFieldFormat(legendText.max, fieldFormat)} diff --git a/x-pack/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/plugins/ml/public/application/util/dependency_cache.ts index d7ca0203ab69e2..9aa16f521554c6 100644 --- a/x-pack/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/plugins/ml/public/application/util/dependency_cache.ts @@ -21,6 +21,7 @@ import type { import type { IndexPatternsContract, DataPublicPluginStart } from 'src/plugins/data/public'; import type { SharePluginStart } from 'src/plugins/share/public'; import type { SecurityPluginSetup } from '../../../../security/public'; +import type { MapsStartApi } from '../../../../maps/public'; export interface DependencyCache { timefilter: DataPublicPluginSetup['query']['timefilter'] | null; @@ -40,6 +41,7 @@ export interface DependencyCache { security: SecurityPluginSetup | undefined | null; i18n: I18nStart | null; urlGenerators: SharePluginStart['urlGenerators'] | null; + maps: MapsStartApi | null; } const cache: DependencyCache = { @@ -60,6 +62,7 @@ const cache: DependencyCache = { security: null, i18n: null, urlGenerators: null, + maps: null, }; export function setDependencyCache(deps: Partial) { diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index 7c32671be93c44..3ba79e0eb9187b 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -25,7 +25,7 @@ import type { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import type { DataPublicPluginStart } from 'src/plugins/data/public'; import type { HomePublicPluginSetup } from 'src/plugins/home/public'; import type { IndexPatternManagementSetup } from 'src/plugins/index_pattern_management/public'; -import type { EmbeddableSetup } from 'src/plugins/embeddable/public'; +import type { EmbeddableSetup, EmbeddableStart } from 'src/plugins/embeddable/public'; import type { SpacesPluginStart } from '../../spaces/public'; import { AppStatus, AppUpdater, DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; @@ -45,6 +45,7 @@ import { setDependencyCache } from './application/util/dependency_cache'; import { registerFeature } from './register_feature'; // Not importing from `ml_url_generator/index` here to avoid importing unnecessary code import { registerUrlGenerator } from './ml_url_generator/ml_url_generator'; +import type { MapsStartApi } from '../../maps/public'; export interface MlStartDependencies { data: DataPublicPluginStart; @@ -52,6 +53,8 @@ export interface MlStartDependencies { kibanaLegacy: KibanaLegacyStart; uiActions: UiActionsStart; spaces?: SpacesPluginStart; + embeddable: EmbeddableStart; + maps?: MapsStartApi; } export interface MlSetupDependencies { security?: SecurityPluginSetup; @@ -102,7 +105,8 @@ export class MlPlugin implements Plugin { usageCollection: pluginsSetup.usageCollection, licenseManagement: pluginsSetup.licenseManagement, home: pluginsSetup.home, - embeddable: pluginsSetup.embeddable, + embeddable: { ...pluginsSetup.embeddable, ...pluginsStart.embeddable }, + maps: pluginsStart.maps, uiActions: pluginsStart.uiActions, kibanaVersion, }, diff --git a/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts b/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts index 7b3f97b684edc6..22e75ec6947338 100644 --- a/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts +++ b/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts @@ -1189,7 +1189,8 @@ export class DataVisualizer { }); const searchBody = { - _source: field, + fields: [field], + _source: false, query: { bool: { filter: filterCriteria, @@ -1209,16 +1210,16 @@ export class DataVisualizer { if (body.hits.total.value > 0) { const hits = body.hits.hits; for (let i = 0; i < hits.length; i++) { - // Look in the _source for the field value. - // If the field is not in the _source (as will happen if the - // field is populated using copy_to in the index mapping), - // there will be no example to add. // Use lodash get() to support field names containing dots. - const example: any = get(hits[i]._source, field); - if (example !== undefined && stats.examples.indexOf(example) === -1) { - stats.examples.push(example); - if (stats.examples.length === maxExamples) { - break; + const doc: object[] | undefined = get(hits[i].fields, field); + // the results from fields query is always an array + if (Array.isArray(doc) && doc.length > 0) { + const example = doc[0]; + if (example !== undefined && stats.examples.indexOf(example) === -1) { + stats.examples.push(example); + if (stats.examples.length === maxExamples) { + break; + } } } } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e2506cb6ca8f02..d798bc9b42c95d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -13073,8 +13073,6 @@ "xpack.ml.featureRegistry.mlFeatureName": "機械学習", "xpack.ml.fieldDataCard.cardBoolean.valuesLabel": "値", "xpack.ml.fieldDataCard.cardDate.summaryTableTitle": "まとめ", - "xpack.ml.fieldDataCard.cardIp.topValuesLabel": "トップの値", - "xpack.ml.fieldDataCard.cardKeyword.topValuesLabel": "トップの値", "xpack.ml.fieldDataCard.cardText.fieldMayBePopulatedDescription": "たとえば、ドキュメントマッピングで {copyToParam} パラメーターを使ったり、{includesParam} と {excludesParam} パラメーターを使用してインデックスした後に {sourceParam} フィールドから切り取ったりして入力される場合があります。", "xpack.ml.fieldDataCard.cardText.fieldNotPresentDescription": "このフィールドはクエリが実行されたドキュメントの {sourceParam} フィールドにありませんでした。", "xpack.ml.fieldDataCard.cardText.noExamplesForFieldsTitle": "このフィールドの例が取得されませんでした", @@ -13092,7 +13090,6 @@ "xpack.ml.fieldDataCardExpandedRow.numberContent.medianLabel": "中間", "xpack.ml.fieldDataCardExpandedRow.numberContent.minLabel": "分", "xpack.ml.fieldDataCardExpandedRow.numberContent.summaryTableTitle": "まとめ", - "xpack.ml.fieldDataCardExpandedRow.numberContent.topValuesTitle": "トップの値", "xpack.ml.fieldTitleBar.documentCountLabel": "ドキュメントカウント", "xpack.ml.fieldTypeIcon.booleanTypeAriaLabel": "ブールタイプ", "xpack.ml.fieldTypeIcon.dateTypeAriaLabel": "日付タイプ", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 7b8ea35baf0ff2..c6f2965803813d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -13104,8 +13104,6 @@ "xpack.ml.featureRegistry.mlFeatureName": "Machine Learning", "xpack.ml.fieldDataCard.cardBoolean.valuesLabel": "值", "xpack.ml.fieldDataCard.cardDate.summaryTableTitle": "摘要", - "xpack.ml.fieldDataCard.cardIp.topValuesLabel": "排名最前值", - "xpack.ml.fieldDataCard.cardKeyword.topValuesLabel": "排名最前值", "xpack.ml.fieldDataCard.cardText.fieldMayBePopulatedDescription": "例如,可以使用文档映射中的 {copyToParam} 参数进行填充,也可以在索引后通过使用 {includesParam} 和 {excludesParam} 参数从 {sourceParam} 字段中修剪。", "xpack.ml.fieldDataCard.cardText.fieldNotPresentDescription": "查询的文档的 {sourceParam} 字段中不存在此字段。", "xpack.ml.fieldDataCard.cardText.noExamplesForFieldsTitle": "没有获取此字段的示例", @@ -13123,7 +13121,6 @@ "xpack.ml.fieldDataCardExpandedRow.numberContent.medianLabel": "中值", "xpack.ml.fieldDataCardExpandedRow.numberContent.minLabel": "最小值", "xpack.ml.fieldDataCardExpandedRow.numberContent.summaryTableTitle": "摘要", - "xpack.ml.fieldDataCardExpandedRow.numberContent.topValuesTitle": "排名最前值", "xpack.ml.fieldTitleBar.documentCountLabel": "文档计数", "xpack.ml.fieldTypeIcon.booleanTypeAriaLabel": "布尔类型", "xpack.ml.fieldTypeIcon.dateTypeAriaLabel": "日期类型", diff --git a/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts b/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts index 531eba54f931da..10926a831d36b0 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts @@ -112,6 +112,47 @@ export default function ({ getService }: FtrProviderContext) { fieldNameFiltersResultCount: 1, }, }, + { + suiteSuffix: 'with a file containing geo field', + filePath: path.join(__dirname, 'files_to_import', 'geo_file.csv'), + indexName: 'user-import_2', + createIndexPattern: false, + fieldTypeFilters: [ML_JOB_FIELD_TYPES.GEO_POINT], + fieldNameFilters: ['Coordinates'], + expected: { + results: { + title: 'geo_file.csv', + numberOfFields: 3, + }, + metricFields: [], + nonMetricFields: [ + { + fieldName: 'Context', + type: ML_JOB_FIELD_TYPES.UNKNOWN, + docCountFormatted: '0 (0%)', + exampleCount: 0, + }, + { + fieldName: 'Coordinates', + type: ML_JOB_FIELD_TYPES.GEO_POINT, + docCountFormatted: '13 (100%)', + exampleCount: 7, + }, + { + fieldName: 'Location', + type: ML_JOB_FIELD_TYPES.KEYWORD, + docCountFormatted: '13 (100%)', + exampleCount: 7, + }, + ], + visibleMetricFieldsCount: 0, + totalMetricFieldsCount: 0, + populatedFieldsCount: 3, + totalFieldsCount: 3, + fieldTypeFiltersResultCount: 1, + fieldNameFiltersResultCount: 1, + }, + }, ]; const testDataListNegative = [ diff --git a/x-pack/test/functional/apps/ml/data_visualizer/files_to_import/geo_file.csv b/x-pack/test/functional/apps/ml/data_visualizer/files_to_import/geo_file.csv new file mode 100644 index 00000000000000..df7417f474d836 --- /dev/null +++ b/x-pack/test/functional/apps/ml/data_visualizer/files_to_import/geo_file.csv @@ -0,0 +1,14 @@ +Coordinates,Location,Context +POINT (-2.516919 51.423683),On or near A4175, +POINT (-2.515072 51.419357),On or near Stockwood Hill, +POINT (-2.509126 51.416137),On or near St Francis Road, +POINT (-2.509384 51.40959),On or near Barnard Walk, +POINT (-2.509126 51.416137),On or near St Francis Road, +POINT (-2.516919 51.423683),On or near A4175, +POINT (-2.511571 51.414895),On or near Orchard Close, +POINT (-2.534338 51.417697),On or near Scotland Lane, +POINT (-2.509384 51.40959),On or near Barnard Walk, +POINT (-2.495055 51.422132),On or near Cross Street, +POINT (-2.509384 51.40959),On or near Barnard Walk, +POINT (-2.495055 51.422132),On or near Cross Street, +POINT (-2.509126 51.416137),On or near St Francis Road, \ No newline at end of file diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts index 0833f84960ea67..01d7ca6af4cc3d 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts @@ -24,6 +24,11 @@ interface TestData { sourceIndexOrSavedSearch: string; fieldNameFilters: string[]; fieldTypeFilters: string[]; + rowsPerPage?: 10 | 25 | 50; + sampleSizeValidations: Array<{ + size: number; + expected: { field: string; docCountFormatted: string }; + }>; expected: { totalDocCountFormatted: string; metricFields?: MetricFieldVisConfig[]; @@ -47,6 +52,10 @@ export default function ({ getService }: FtrProviderContext) { sourceIndexOrSavedSearch: 'ft_farequote', fieldNameFilters: ['airline', '@timestamp'], fieldTypeFilters: [ML_JOB_FIELD_TYPES.KEYWORD], + sampleSizeValidations: [ + { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, + ], expected: { totalDocCountFormatted: '86,274', metricFields: [ @@ -132,6 +141,10 @@ export default function ({ getService }: FtrProviderContext) { sourceIndexOrSavedSearch: 'ft_farequote_kuery', fieldNameFilters: ['@version'], fieldTypeFilters: [ML_JOB_FIELD_TYPES.DATE, ML_JOB_FIELD_TYPES.TEXT], + sampleSizeValidations: [ + { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, + ], expected: { totalDocCountFormatted: '34,415', metricFields: [ @@ -217,6 +230,10 @@ export default function ({ getService }: FtrProviderContext) { sourceIndexOrSavedSearch: 'ft_farequote_lucene', fieldNameFilters: ['@version.keyword', 'type'], fieldTypeFilters: [ML_JOB_FIELD_TYPES.NUMBER], + sampleSizeValidations: [ + { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, + ], expected: { totalDocCountFormatted: '34,416', metricFields: [ @@ -297,6 +314,41 @@ export default function ({ getService }: FtrProviderContext) { }, }; + const sampleLogTestData: TestData = { + suiteTitle: 'geo point field', + sourceIndexOrSavedSearch: 'ft_module_sample_logs', + fieldNameFilters: ['geo.coordinates'], + fieldTypeFilters: [ML_JOB_FIELD_TYPES.GEO_POINT], + rowsPerPage: 50, + expected: { + totalDocCountFormatted: '408', + metricFields: [], + // only testing the geo_point fields + nonMetricFields: [ + { + fieldName: 'geo.coordinates', + type: ML_JOB_FIELD_TYPES.GEO_POINT, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '408 (100%)', + exampleCount: 10, + }, + ], + emptyFields: [], + visibleMetricFieldsCount: 4, + totalMetricFieldsCount: 5, + populatedFieldsCount: 35, + totalFieldsCount: 36, + fieldNameFiltersResultCount: 1, + fieldTypeFiltersResultCount: 1, + }, + sampleSizeValidations: [ + { size: 1000, expected: { field: 'geo.coordinates', docCountFormatted: '408 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '408 (100%)' } }, + ], + }; + function runTests(testData: TestData) { it(`${testData.suiteTitle} loads the source data in the data visualizer`, async () => { await ml.testExecution.logTestStep( @@ -332,6 +384,10 @@ export default function ({ getService }: FtrProviderContext) { ); await ml.dataVisualizerIndexBased.assertDataVisualizerTableExist(); + if (testData.rowsPerPage) { + await ml.dataVisualizerTable.ensureNumRowsPerPage(testData.rowsPerPage); + } + await ml.dataVisualizerTable.assertSearchPanelExist(); await ml.dataVisualizerTable.assertSampleSizeInputExists(); await ml.dataVisualizerTable.assertFieldTypeInputExists(); @@ -376,8 +432,14 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep( `${testData.suiteTitle} sample size control changes non-metric fields` ); - await ml.dataVisualizerTable.setSampleSizeInputValue(1000, 'airline', '1000 (100%)'); - await ml.dataVisualizerTable.setSampleSizeInputValue(5000, '@timestamp', '5000 (100%)'); + for (const sampleSizeCase of testData.sampleSizeValidations) { + const { size, expected } = sampleSizeCase; + await ml.dataVisualizerTable.setSampleSizeInputValue( + size, + expected.field, + expected.docCountFormatted + ); + } await ml.testExecution.logTestStep('sets and resets field type filter correctly'); await ml.dataVisualizerTable.setFieldTypeFilter( @@ -411,7 +473,10 @@ export default function ({ getService }: FtrProviderContext) { this.tags(['mlqa']); before(async () => { await esArchiver.loadIfNeeded('ml/farequote'); + await esArchiver.loadIfNeeded('ml/module_sample_logs'); + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await ml.testResources.createIndexPatternIfNeeded('ft_module_sample_logs', '@timestamp'); await ml.testResources.createSavedSearchFarequoteLuceneIfNeeded(); await ml.testResources.createSavedSearchFarequoteKueryIfNeeded(); await ml.testResources.setKibanaTimeZoneToUTC(); @@ -447,5 +512,15 @@ export default function ({ getService }: FtrProviderContext) { runTests(farequoteLuceneSearchTestData); }); + + describe('with module_sample_logs ', function () { + // Run tests on full farequote index. + it(`${sampleLogTestData.suiteTitle} loads the data visualizer selector page`, async () => { + // Start navigation from the base of the ML app. + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToDataVisualizer(); + }); + runTests(sampleLogTestData); + }); }); } diff --git a/x-pack/test/functional/services/ml/data_visualizer_table.ts b/x-pack/test/functional/services/ml/data_visualizer_table.ts index ad4625ed4dcb4d..4772b3c894471b 100644 --- a/x-pack/test/functional/services/ml/data_visualizer_table.ts +++ b/x-pack/test/functional/services/ml/data_visualizer_table.ts @@ -288,6 +288,16 @@ export function MachineLearningDataVisualizerTableProvider( await this.ensureDetailsClosed(fieldName); } + public async assertExamplesList(fieldName: string, expectedExamplesCount: number) { + const examplesList = await testSubjects.find( + this.detailsSelector(fieldName, 'mlFieldDataExamplesList') + ); + const examplesListItems = await examplesList.findAllByTagName('li'); + expect(examplesListItems).to.have.length( + expectedExamplesCount, + `Expected example list item count for field '${fieldName}' to be '${expectedExamplesCount}' (got '${examplesListItems.length}')` + ); + } public async assertTextFieldContents( fieldName: string, docCountFormatted: string, @@ -297,14 +307,33 @@ export function MachineLearningDataVisualizerTableProvider( await this.assertFieldDocCount(fieldName, docCountFormatted); await this.ensureDetailsOpen(fieldName); - const examplesList = await testSubjects.find( - this.detailsSelector(fieldName, 'mlFieldDataExamplesList') - ); - const examplesListItems = await examplesList.findAllByTagName('li'); - expect(examplesListItems).to.have.length( - expectedExamplesCount, - `Expected example list item count for field '${fieldName}' to be '${expectedExamplesCount}' (got '${examplesListItems.length}')` - ); + await this.assertExamplesList(fieldName, expectedExamplesCount); + await this.ensureDetailsClosed(fieldName); + } + + public async assertGeoPointFieldContents( + fieldName: string, + docCountFormatted: string, + expectedExamplesCount: number + ) { + await this.assertRowExists(fieldName); + await this.assertFieldDocCount(fieldName, docCountFormatted); + await this.ensureDetailsOpen(fieldName); + + await this.assertExamplesList(fieldName, expectedExamplesCount); + + await testSubjects.existOrFail(this.detailsSelector(fieldName, 'mlEmbeddedMapContent')); + + await this.ensureDetailsClosed(fieldName); + } + + public async assertUnknownFieldContents(fieldName: string, docCountFormatted: string) { + await this.assertRowExists(fieldName); + await this.assertFieldDocCount(fieldName, docCountFormatted); + await this.ensureDetailsOpen(fieldName); + + await testSubjects.existOrFail(this.detailsSelector(fieldName, 'mlDVDocumentStatsContent')); + await this.ensureDetailsClosed(fieldName); } @@ -321,10 +350,14 @@ export function MachineLearningDataVisualizerTableProvider( await this.assertKeywordFieldContents(fieldName, docCountFormatted, exampleCount); } else if (fieldType === ML_JOB_FIELD_TYPES.TEXT) { await this.assertTextFieldContents(fieldName, docCountFormatted, exampleCount); + } else if (fieldType === ML_JOB_FIELD_TYPES.GEO_POINT) { + await this.assertGeoPointFieldContents(fieldName, docCountFormatted, exampleCount); + } else if (fieldType === ML_JOB_FIELD_TYPES.UNKNOWN) { + await this.assertUnknownFieldContents(fieldName, docCountFormatted); } } - public async ensureNumRowsPerPage(n: 10 | 25 | 100) { + public async ensureNumRowsPerPage(n: 10 | 25 | 50) { const paginationButton = 'mlDataVisualizerTable > tablePaginationPopoverButton'; await retry.tryForTime(10000, async () => { await testSubjects.existOrFail(paginationButton); From 42a9490e7bb967649043fe59af5048bae3842505 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Wed, 27 Jan 2021 17:58:06 +0000 Subject: [PATCH 39/58] [Logs UI] Display category in anomalies table (#88677) * Add category pattern to anomalies table --- .../results/log_entry_anomalies.ts | 86 ++----------------- .../results/log_entry_categories.ts | 54 +----------- .../results/log_entry_category_examples.ts | 2 +- .../results/log_entry_examples.ts | 12 +-- .../common/http_api/log_entries/entries.ts | 51 +---------- .../common/http_api/log_entries/highlights.ts | 3 +- .../common/http_api/shared/time_range.ts | 9 +- .../infra/common/log_analysis/index.ts | 2 + .../log_analysis/log_analysis_results.ts | 43 ++++++++++ .../log_analysis/log_entry_anomalies.ts | 59 +++++++++++++ .../log_entry_categories_analysis.ts | 42 +++++++++ .../common/log_analysis/log_entry_examples.ts | 17 ++++ .../infra/common/log_entry/log_entry.ts | 54 +++++++++++- x-pack/plugins/infra/common/time/index.ts | 1 + .../plugins/infra/common/time/time_range.ts | 14 +++ .../category_expression.tsx | 2 +- .../logging/log_text_stream/item.ts | 2 +- .../log_entry_field_column.test.tsx | 2 +- .../log_entry_field_column.tsx | 2 +- .../log_entry_message_column.test.tsx | 2 +- .../log_entry_message_column.tsx | 2 +- .../logging/log_text_stream/log_entry_row.tsx | 2 +- .../scrollable_log_text_stream_view.tsx | 2 +- .../containers/logs/log_entries/index.ts | 2 +- .../log_highlights/log_entry_highlights.tsx | 3 +- .../containers/logs/log_stream/index.ts | 3 +- .../view_log_in_context.ts | 2 +- .../containers/logs/with_stream_items.ts | 2 +- .../page_results_content.tsx | 2 +- .../analyze_dataset_in_ml_action.tsx | 2 +- .../anomaly_severity_indicator_list.tsx | 2 +- .../top_categories/category_details_row.tsx | 2 +- .../category_example_message.tsx | 4 +- .../top_categories/datasets_action_list.tsx | 4 +- .../sections/top_categories/datasets_list.tsx | 2 +- .../log_entry_count_sparkline.tsx | 4 +- .../single_metric_sparkline.tsx | 2 +- .../top_categories/top_categories_section.tsx | 4 +- .../top_categories/top_categories_table.tsx | 6 +- .../get_top_log_entry_categories.ts | 4 +- .../use_log_entry_categories_results.ts | 6 +- .../log_entry_rate/page_results_content.tsx | 2 +- .../sections/anomalies/chart.tsx | 2 +- .../sections/anomalies/expanded_row.tsx | 6 +- .../sections/anomalies/index.tsx | 2 +- .../sections/anomalies/log_entry_example.tsx | 8 +- .../sections/anomalies/table.tsx | 41 +++++---- .../service_calls/get_log_entry_anomalies.ts | 4 +- .../use_log_entry_anomalies_results.ts | 18 ++-- .../log_entry_rate/use_log_entry_examples.ts | 2 +- .../logs/stream/page_view_log_in_context.tsx | 2 +- .../infra/public/test_utils/entries.ts | 2 +- .../infra/public/utils/log_entry/log_entry.ts | 2 +- .../utils/log_entry/log_entry_highlight.ts | 2 +- .../log_entries_domain/log_entries_domain.ts | 3 +- .../lib/domains/log_entries_domain/message.ts | 2 +- .../lib/log_analysis/log_entry_anomalies.ts | 52 ++++++++--- .../log_entry_categories_analysis.ts | 8 +- .../queries/log_entry_anomalies.ts | 12 +-- .../queries/top_log_entry_categories.ts | 6 +- .../results/log_entry_anomalies.ts | 5 +- .../apis/metrics_ui/log_entries.ts | 5 +- 62 files changed, 394 insertions(+), 313 deletions(-) create mode 100644 x-pack/plugins/infra/common/log_analysis/log_entry_anomalies.ts create mode 100644 x-pack/plugins/infra/common/log_analysis/log_entry_examples.ts create mode 100644 x-pack/plugins/infra/common/time/time_range.ts rename x-pack/plugins/infra/public/{pages/logs/log_entry_categories/sections/top_categories => components/logging/log_analysis_results}/category_expression.tsx (95%) diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies.ts index 62b76a0ae475e8..614684d29ae767 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies.ts @@ -7,48 +7,17 @@ import * as rt from 'io-ts'; import { timeRangeRT, routeTimingMetadataRT } from '../../shared'; +import { + logEntryAnomalyRT, + logEntryAnomalyDatasetsRT, + anomaliesSortRT, + paginationRT, + paginationCursorRT, +} from '../../../log_analysis'; export const LOG_ANALYSIS_GET_LOG_ENTRY_ANOMALIES_PATH = '/api/infra/log_analysis/results/log_entry_anomalies'; -// [Sort field value, tiebreaker value] -const paginationCursorRT = rt.tuple([ - rt.union([rt.string, rt.number]), - rt.union([rt.string, rt.number]), -]); - -export type PaginationCursor = rt.TypeOf; - -export const anomalyTypeRT = rt.keyof({ - logRate: null, - logCategory: null, -}); - -export type AnomalyType = rt.TypeOf; - -const logEntryAnomalyCommonFieldsRT = rt.type({ - id: rt.string, - anomalyScore: rt.number, - dataset: rt.string, - typical: rt.number, - actual: rt.number, - type: anomalyTypeRT, - duration: rt.number, - startTime: rt.number, - jobId: rt.string, -}); -const logEntrylogRateAnomalyRT = logEntryAnomalyCommonFieldsRT; -const logEntrylogCategoryAnomalyRT = rt.partial({ - categoryId: rt.string, -}); -const logEntryAnomalyRT = rt.intersection([ - logEntryAnomalyCommonFieldsRT, - logEntrylogRateAnomalyRT, - logEntrylogCategoryAnomalyRT, -]); - -export type LogEntryAnomaly = rt.TypeOf; - export const getLogEntryAnomaliesSuccessReponsePayloadRT = rt.intersection([ rt.type({ data: rt.intersection([ @@ -78,43 +47,6 @@ export type GetLogEntryAnomaliesSuccessResponsePayload = rt.TypeOf< typeof getLogEntryAnomaliesSuccessReponsePayloadRT >; -const sortOptionsRT = rt.keyof({ - anomalyScore: null, - dataset: null, - startTime: null, -}); - -const sortDirectionsRT = rt.keyof({ - asc: null, - desc: null, -}); - -const paginationPreviousPageCursorRT = rt.type({ - searchBefore: paginationCursorRT, -}); - -const paginationNextPageCursorRT = rt.type({ - searchAfter: paginationCursorRT, -}); - -const paginationRT = rt.intersection([ - rt.type({ - pageSize: rt.number, - }), - rt.partial({ - cursor: rt.union([paginationPreviousPageCursorRT, paginationNextPageCursorRT]), - }), -]); - -export type Pagination = rt.TypeOf; - -const sortRT = rt.type({ - field: sortOptionsRT, - direction: sortDirectionsRT, -}); - -export type Sort = rt.TypeOf; - export const getLogEntryAnomaliesRequestPayloadRT = rt.type({ data: rt.intersection([ rt.type({ @@ -127,9 +59,9 @@ export const getLogEntryAnomaliesRequestPayloadRT = rt.type({ // Pagination properties pagination: paginationRT, // Sort properties - sort: sortRT, + sort: anomaliesSortRT, // Dataset filters - datasets: rt.array(rt.string), + datasets: logEntryAnomalyDatasetsRT, }), ]), }); diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_categories.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_categories.ts index 0554192398fc57..019ae01c1437c5 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_categories.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_categories.ts @@ -13,6 +13,8 @@ import { routeTimingMetadataRT, } from '../../shared'; +import { logEntryCategoryRT, categoriesSortRT } from '../../../log_analysis'; + export const LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORIES_PATH = '/api/infra/log_analysis/results/log_entry_categories'; @@ -30,23 +32,6 @@ export type LogEntryCategoriesHistogramParameters = rt.TypeOf< typeof logEntryCategoriesHistogramParametersRT >; -const sortOptionsRT = rt.keyof({ - maximumAnomalyScore: null, - logEntryCount: null, -}); - -const sortDirectionsRT = rt.keyof({ - asc: null, - desc: null, -}); - -const categorySortRT = rt.type({ - field: sortOptionsRT, - direction: sortDirectionsRT, -}); - -export type CategorySort = rt.TypeOf; - export const getLogEntryCategoriesRequestPayloadRT = rt.type({ data: rt.intersection([ rt.type({ @@ -59,7 +44,7 @@ export const getLogEntryCategoriesRequestPayloadRT = rt.type({ // a list of histograms to create histograms: rt.array(logEntryCategoriesHistogramParametersRT), // the criteria to the categories by - sort: categorySortRT, + sort: categoriesSortRT, }), rt.partial({ // the datasets to filter for (optional, unfiltered if not present) @@ -76,39 +61,6 @@ export type GetLogEntryCategoriesRequestPayload = rt.TypeOf< * response */ -export const logEntryCategoryHistogramBucketRT = rt.type({ - startTime: rt.number, - bucketDuration: rt.number, - logEntryCount: rt.number, -}); - -export type LogEntryCategoryHistogramBucket = rt.TypeOf; - -export const logEntryCategoryHistogramRT = rt.type({ - histogramId: rt.string, - buckets: rt.array(logEntryCategoryHistogramBucketRT), -}); - -export type LogEntryCategoryHistogram = rt.TypeOf; - -export const logEntryCategoryDatasetRT = rt.type({ - name: rt.string, - maximumAnomalyScore: rt.number, -}); - -export type LogEntryCategoryDataset = rt.TypeOf; - -export const logEntryCategoryRT = rt.type({ - categoryId: rt.number, - datasets: rt.array(logEntryCategoryDatasetRT), - histograms: rt.array(logEntryCategoryHistogramRT), - logEntryCount: rt.number, - maximumAnomalyScore: rt.number, - regularExpression: rt.string, -}); - -export type LogEntryCategory = rt.TypeOf; - export const getLogEntryCategoriesSuccessReponsePayloadRT = rt.intersection([ rt.type({ data: rt.type({ diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_examples.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_examples.ts index e9e3c6e0ca3f98..3166d40d703921 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_examples.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_examples.ts @@ -12,7 +12,7 @@ import { timeRangeRT, routeTimingMetadataRT, } from '../../shared'; -import { logEntryContextRT } from '../../log_entries'; +import { logEntryContextRT } from '../../../log_entry'; export const LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORY_EXAMPLES_PATH = '/api/infra/log_analysis/results/log_entry_category_examples'; diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_examples.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_examples.ts index 1eed29cd37560c..c061545ec09ed0 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_examples.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_examples.ts @@ -5,7 +5,7 @@ */ import * as rt from 'io-ts'; - +import { logEntryExampleRT } from '../../../log_analysis'; import { badRequestErrorRT, forbiddenErrorRT, @@ -46,16 +46,6 @@ export type GetLogEntryExamplesRequestPayload = rt.TypeOf< * response */ -const logEntryExampleRT = rt.type({ - id: rt.string, - dataset: rt.string, - message: rt.string, - timestamp: rt.number, - tiebreaker: rt.number, -}); - -export type LogEntryExample = rt.TypeOf; - export const getLogEntryExamplesSuccessReponsePayloadRT = rt.intersection([ rt.type({ data: rt.type({ diff --git a/x-pack/plugins/infra/common/http_api/log_entries/entries.ts b/x-pack/plugins/infra/common/http_api/log_entries/entries.ts index 31bc62f48791a5..b4d9a5744d5ac0 100644 --- a/x-pack/plugins/infra/common/http_api/log_entries/entries.ts +++ b/x-pack/plugins/infra/common/http_api/log_entries/entries.ts @@ -5,8 +5,7 @@ */ import * as rt from 'io-ts'; -import { logEntryCursorRT } from '../../log_entry'; -import { jsonArrayRT } from '../../typed_json'; +import { logEntryCursorRT, logEntryRT } from '../../log_entry'; import { logSourceColumnConfigurationRT } from '../log_sources'; export const LOG_ENTRIES_PATH = '/api/log_entries/entries'; @@ -52,54 +51,6 @@ export type LogEntriesAfterRequest = rt.TypeOf; export type LogEntriesCenteredRequest = rt.TypeOf; export type LogEntriesRequest = rt.TypeOf; -export const logMessageConstantPartRT = rt.type({ - constant: rt.string, -}); -export const logMessageFieldPartRT = rt.type({ - field: rt.string, - value: jsonArrayRT, - highlights: rt.array(rt.string), -}); - -export const logMessagePartRT = rt.union([logMessageConstantPartRT, logMessageFieldPartRT]); - -export const logTimestampColumnRT = rt.type({ columnId: rt.string, timestamp: rt.number }); -export const logFieldColumnRT = rt.type({ - columnId: rt.string, - field: rt.string, - value: jsonArrayRT, - highlights: rt.array(rt.string), -}); -export const logMessageColumnRT = rt.type({ - columnId: rt.string, - message: rt.array(logMessagePartRT), -}); - -export const logColumnRT = rt.union([logTimestampColumnRT, logFieldColumnRT, logMessageColumnRT]); - -export const logEntryContextRT = rt.union([ - rt.type({}), - rt.type({ 'container.id': rt.string }), - rt.type({ 'host.name': rt.string, 'log.file.path': rt.string }), -]); - -export const logEntryRT = rt.type({ - id: rt.string, - cursor: logEntryCursorRT, - columns: rt.array(logColumnRT), - context: logEntryContextRT, -}); - -export type LogMessageConstantPart = rt.TypeOf; -export type LogMessageFieldPart = rt.TypeOf; -export type LogMessagePart = rt.TypeOf; -export type LogTimestampColumn = rt.TypeOf; -export type LogFieldColumn = rt.TypeOf; -export type LogMessageColumn = rt.TypeOf; -export type LogColumn = rt.TypeOf; -export type LogEntryContext = rt.TypeOf; -export type LogEntry = rt.TypeOf; - export const logEntriesResponseRT = rt.type({ data: rt.intersection([ rt.type({ diff --git a/x-pack/plugins/infra/common/http_api/log_entries/highlights.ts b/x-pack/plugins/infra/common/http_api/log_entries/highlights.ts index 648da43134a276..96bf8beb29021f 100644 --- a/x-pack/plugins/infra/common/http_api/log_entries/highlights.ts +++ b/x-pack/plugins/infra/common/http_api/log_entries/highlights.ts @@ -5,13 +5,12 @@ */ import * as rt from 'io-ts'; -import { logEntryCursorRT } from '../../log_entry'; +import { logEntryCursorRT, logEntryRT } from '../../log_entry'; import { logEntriesBaseRequestRT, logEntriesBeforeRequestRT, logEntriesAfterRequestRT, logEntriesCenteredRequestRT, - logEntryRT, } from './entries'; export const LOG_ENTRIES_HIGHLIGHTS_PATH = '/api/log_entries/highlights'; diff --git a/x-pack/plugins/infra/common/http_api/shared/time_range.ts b/x-pack/plugins/infra/common/http_api/shared/time_range.ts index efda07423748b7..07317092cdedbc 100644 --- a/x-pack/plugins/infra/common/http_api/shared/time_range.ts +++ b/x-pack/plugins/infra/common/http_api/shared/time_range.ts @@ -4,11 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -import * as rt from 'io-ts'; - -export const timeRangeRT = rt.type({ - startTime: rt.number, - endTime: rt.number, -}); - -export type TimeRange = rt.TypeOf; +export * from '../../time/time_range'; diff --git a/x-pack/plugins/infra/common/log_analysis/index.ts b/x-pack/plugins/infra/common/log_analysis/index.ts index 0b4fa374a5da95..f055f642c8d1b6 100644 --- a/x-pack/plugins/infra/common/log_analysis/index.ts +++ b/x-pack/plugins/infra/common/log_analysis/index.ts @@ -10,3 +10,5 @@ export * from './log_analysis_results'; export * from './log_entry_rate_analysis'; export * from './log_entry_categories_analysis'; export * from './job_parameters'; +export * from './log_entry_anomalies'; +export * from './log_entry_examples'; diff --git a/x-pack/plugins/infra/common/log_analysis/log_analysis_results.ts b/x-pack/plugins/infra/common/log_analysis/log_analysis_results.ts index f4497dbba50567..897a5a4bb84dfe 100644 --- a/x-pack/plugins/infra/common/log_analysis/log_analysis_results.ts +++ b/x-pack/plugins/infra/common/log_analysis/log_analysis_results.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import * as rt from 'io-ts'; + export const ML_SEVERITY_SCORES = { warning: 3, minor: 25, @@ -55,3 +57,44 @@ export const compareDatasetsByMaximumAnomalyScore = < firstDataset: Dataset, secondDataset: Dataset ) => firstDataset.maximumAnomalyScore - secondDataset.maximumAnomalyScore; + +// Generic Sort + +const sortDirectionsRT = rt.keyof({ + asc: null, + desc: null, +}); + +export const sortRT = (fields: Fields) => + rt.type({ + field: fields, + direction: sortDirectionsRT, + }); + +// Pagination +// [Sort field value, tiebreaker value] +export const paginationCursorRT = rt.tuple([ + rt.union([rt.string, rt.number]), + rt.union([rt.string, rt.number]), +]); + +export type PaginationCursor = rt.TypeOf; + +const paginationPreviousPageCursorRT = rt.type({ + searchBefore: paginationCursorRT, +}); + +const paginationNextPageCursorRT = rt.type({ + searchAfter: paginationCursorRT, +}); + +export const paginationRT = rt.intersection([ + rt.type({ + pageSize: rt.number, + }), + rt.partial({ + cursor: rt.union([paginationPreviousPageCursorRT, paginationNextPageCursorRT]), + }), +]); + +export type Pagination = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/log_analysis/log_entry_anomalies.ts b/x-pack/plugins/infra/common/log_analysis/log_entry_anomalies.ts new file mode 100644 index 00000000000000..c426646e8e8470 --- /dev/null +++ b/x-pack/plugins/infra/common/log_analysis/log_entry_anomalies.ts @@ -0,0 +1,59 @@ +/* + * 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 rt from 'io-ts'; +import { sortRT } from './log_analysis_results'; + +export const anomalyTypeRT = rt.keyof({ + logRate: null, + logCategory: null, +}); + +export type AnomalyType = rt.TypeOf; + +export const logEntryAnomalyCommonFieldsRT = rt.type({ + id: rt.string, + anomalyScore: rt.number, + dataset: rt.string, + typical: rt.number, + actual: rt.number, + type: anomalyTypeRT, + duration: rt.number, + startTime: rt.number, + jobId: rt.string, +}); +export const logEntrylogRateAnomalyRT = logEntryAnomalyCommonFieldsRT; +export type RateAnomaly = rt.TypeOf; + +export const logEntrylogCategoryAnomalyRT = rt.intersection([ + logEntryAnomalyCommonFieldsRT, + rt.type({ + categoryId: rt.string, + categoryRegex: rt.string, + categoryTerms: rt.string, + }), +]); +export type CategoryAnomaly = rt.TypeOf; + +export const logEntryAnomalyRT = rt.union([logEntrylogRateAnomalyRT, logEntrylogCategoryAnomalyRT]); + +export type LogEntryAnomaly = rt.TypeOf; + +export const logEntryAnomalyDatasetsRT = rt.array(rt.string); +export type LogEntryAnomalyDatasets = rt.TypeOf; + +export const isCategoryAnomaly = (anomaly: LogEntryAnomaly): anomaly is CategoryAnomaly => { + return anomaly.type === 'logCategory'; +}; + +const sortOptionsRT = rt.keyof({ + anomalyScore: null, + dataset: null, + startTime: null, +}); + +export const anomaliesSortRT = sortRT(sortOptionsRT); +export type AnomaliesSort = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/log_analysis/log_entry_categories_analysis.ts b/x-pack/plugins/infra/common/log_analysis/log_entry_categories_analysis.ts index 0957126ee52e3b..4292eaeb5f98cf 100644 --- a/x-pack/plugins/infra/common/log_analysis/log_entry_categories_analysis.ts +++ b/x-pack/plugins/infra/common/log_analysis/log_entry_categories_analysis.ts @@ -5,6 +5,7 @@ */ import * as rt from 'io-ts'; +import { sortRT } from './log_analysis_results'; export const logEntryCategoriesJobTypeRT = rt.keyof({ 'log-entry-categories-count': null, @@ -15,3 +16,44 @@ export type LogEntryCategoriesJobType = rt.TypeOf; + +export const logEntryCategoryHistogramBucketRT = rt.type({ + startTime: rt.number, + bucketDuration: rt.number, + logEntryCount: rt.number, +}); + +export type LogEntryCategoryHistogramBucket = rt.TypeOf; + +export const logEntryCategoryHistogramRT = rt.type({ + histogramId: rt.string, + buckets: rt.array(logEntryCategoryHistogramBucketRT), +}); + +export type LogEntryCategoryHistogram = rt.TypeOf; + +export const logEntryCategoryRT = rt.type({ + categoryId: rt.number, + datasets: rt.array(logEntryCategoryDatasetRT), + histograms: rt.array(logEntryCategoryHistogramRT), + logEntryCount: rt.number, + maximumAnomalyScore: rt.number, + regularExpression: rt.string, +}); + +export type LogEntryCategory = rt.TypeOf; + +const sortOptionsRT = rt.keyof({ + maximumAnomalyScore: null, + logEntryCount: null, +}); + +export const categoriesSortRT = sortRT(sortOptionsRT); +export type CategoriesSort = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/log_analysis/log_entry_examples.ts b/x-pack/plugins/infra/common/log_analysis/log_entry_examples.ts new file mode 100644 index 00000000000000..78d230e35dc748 --- /dev/null +++ b/x-pack/plugins/infra/common/log_analysis/log_entry_examples.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as rt from 'io-ts'; + +export const logEntryExampleRT = rt.type({ + id: rt.string, + dataset: rt.string, + message: rt.string, + timestamp: rt.number, + tiebreaker: rt.number, +}); + +export type LogEntryExample = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/log_entry/log_entry.ts b/x-pack/plugins/infra/common/log_entry/log_entry.ts index e02acebe277113..eec1fb59f3091c 100644 --- a/x-pack/plugins/infra/common/log_entry/log_entry.ts +++ b/x-pack/plugins/infra/common/log_entry/log_entry.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ +import * as rt from 'io-ts'; import { TimeKey } from '../time'; -import { InfraLogEntry } from '../graphql/types'; - -export type LogEntry = InfraLogEntry; +import { logEntryCursorRT } from './log_entry_cursor'; +import { jsonArrayRT } from '../typed_json'; export interface LogEntryOrigin { id: string; @@ -42,3 +42,51 @@ export function isLessOrEqual(time1: LogEntryTime, time2: LogEntryTime) { export function isBetween(min: LogEntryTime, max: LogEntryTime, operand: LogEntryTime) { return isLessOrEqual(min, operand) && isLessOrEqual(operand, max); } + +export const logMessageConstantPartRT = rt.type({ + constant: rt.string, +}); +export const logMessageFieldPartRT = rt.type({ + field: rt.string, + value: jsonArrayRT, + highlights: rt.array(rt.string), +}); + +export const logMessagePartRT = rt.union([logMessageConstantPartRT, logMessageFieldPartRT]); + +export const logTimestampColumnRT = rt.type({ columnId: rt.string, timestamp: rt.number }); +export const logFieldColumnRT = rt.type({ + columnId: rt.string, + field: rt.string, + value: jsonArrayRT, + highlights: rt.array(rt.string), +}); +export const logMessageColumnRT = rt.type({ + columnId: rt.string, + message: rt.array(logMessagePartRT), +}); + +export const logColumnRT = rt.union([logTimestampColumnRT, logFieldColumnRT, logMessageColumnRT]); + +export const logEntryContextRT = rt.union([ + rt.type({}), + rt.type({ 'container.id': rt.string }), + rt.type({ 'host.name': rt.string, 'log.file.path': rt.string }), +]); + +export const logEntryRT = rt.type({ + id: rt.string, + cursor: logEntryCursorRT, + columns: rt.array(logColumnRT), + context: logEntryContextRT, +}); + +export type LogMessageConstantPart = rt.TypeOf; +export type LogMessageFieldPart = rt.TypeOf; +export type LogMessagePart = rt.TypeOf; +export type LogEntryContext = rt.TypeOf; +export type LogEntry = rt.TypeOf; +export type LogTimestampColumn = rt.TypeOf; +export type LogFieldColumn = rt.TypeOf; +export type LogMessageColumn = rt.TypeOf; +export type LogColumn = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/time/index.ts b/x-pack/plugins/infra/common/time/index.ts index f49d46fa4920f7..63bba2fa807ac9 100644 --- a/x-pack/plugins/infra/common/time/index.ts +++ b/x-pack/plugins/infra/common/time/index.ts @@ -7,3 +7,4 @@ export * from './time_unit'; export * from './time_scale'; export * from './time_key'; +export * from './time_range'; diff --git a/x-pack/plugins/infra/common/time/time_range.ts b/x-pack/plugins/infra/common/time/time_range.ts new file mode 100644 index 00000000000000..efda07423748b7 --- /dev/null +++ b/x-pack/plugins/infra/common/time/time_range.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as rt from 'io-ts'; + +export const timeRangeRT = rt.type({ + startTime: rt.number, + endTime: rt.number, +}); + +export type TimeRange = rt.TypeOf; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_expression.tsx b/x-pack/plugins/infra/public/components/logging/log_analysis_results/category_expression.tsx similarity index 95% rename from x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_expression.tsx rename to x-pack/plugins/infra/public/components/logging/log_analysis_results/category_expression.tsx index d5480977e7f9ee..9684777ac92166 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_expression.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_analysis_results/category_expression.tsx @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import React, { memo } from 'react'; -import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; +import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common'; export const RegularExpressionRepresentation: React.FunctionComponent<{ maximumSegmentCount?: number; diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/item.ts b/x-pack/plugins/infra/public/components/logging/log_text_stream/item.ts index 19e8108ee50e85..b0ff36574bedef 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/item.ts +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/item.ts @@ -7,7 +7,7 @@ import { bisector } from 'd3-array'; import { compareToTimeKey, TimeKey } from '../../../../common/time'; -import { LogEntry } from '../../../../common/http_api'; +import { LogEntry } from '../../../../common/log_entry'; export type StreamItem = LogEntryStreamItem; diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.test.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.test.tsx index 8de9e565b00be1..2b30d43f8c38da 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.test.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.test.tsx @@ -7,7 +7,7 @@ import { render } from '@testing-library/react'; import React from 'react'; import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common'; -import { LogFieldColumn } from '../../../../common/http_api'; +import { LogFieldColumn } from '../../../../common/log_entry'; import { LogEntryFieldColumn } from './log_entry_field_column'; describe('LogEntryFieldColumn', () => { diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx index 4a9b0d0906a76e..0d295b4df5566b 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { JsonValue } from '../../../../../../../src/plugins/kibana_utils/common'; import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common'; -import { LogColumn } from '../../../../common/http_api'; +import { LogColumn } from '../../../../common/log_entry'; import { isFieldColumn, isHighlightFieldColumn } from '../../../utils/log_entry'; import { FieldValue } from './field_value'; import { LogEntryColumnContent } from './log_entry_column'; diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.test.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.test.tsx index 5d36e5cd47c59b..00281c2df3133f 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.test.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.test.tsx @@ -7,7 +7,7 @@ import { render } from '@testing-library/react'; import React from 'react'; import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common'; -import { LogMessageColumn } from '../../../../common/http_api'; +import { LogMessageColumn } from '../../../../common/log_entry'; import { LogEntryMessageColumn } from './log_entry_message_column'; describe('LogEntryMessageColumn', () => { diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx index bfc160ada2e6a3..92214dee9de220 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx @@ -6,7 +6,7 @@ import React, { memo, useMemo } from 'react'; import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common'; -import { LogColumn, LogMessagePart } from '../../../../common/http_api'; +import { LogColumn, LogMessagePart } from '../../../../common/log_entry'; import { isConstantSegment, isFieldSegment, diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_row.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_row.tsx index 93c657fbdda971..1a472df2b5c906 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_row.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_row.tsx @@ -17,7 +17,7 @@ import { LogEntryFieldColumn } from './log_entry_field_column'; import { LogEntryMessageColumn } from './log_entry_message_column'; import { LogEntryTimestampColumn } from './log_entry_timestamp_column'; import { monospaceTextStyle, hoveredContentStyle, highlightedContentStyle } from './text_styles'; -import { LogEntry, LogColumn } from '../../../../common/http_api'; +import { LogEntry, LogColumn } from '../../../../common/log_entry'; import { LogEntryContextMenu } from './log_entry_context_menu'; import { LogColumnRenderConfiguration, diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx index d399e47a735624..8fb63533cf61bf 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx @@ -25,7 +25,7 @@ import { MeasurableItemView } from './measurable_item_view'; import { VerticalScrollPanel } from './vertical_scroll_panel'; import { useColumnWidths, LogEntryColumnWidths } from './log_entry_column'; import { LogDateRow } from './log_date_row'; -import { LogEntry } from '../../../../common/http_api'; +import { LogEntry } from '../../../../common/log_entry'; import { LogColumnRenderConfiguration } from '../../../utils/log_column_render_configuration'; interface ScrollableLogTextStreamViewProps { diff --git a/x-pack/plugins/infra/public/containers/logs/log_entries/index.ts b/x-pack/plugins/infra/public/containers/logs/log_entries/index.ts index bf4c5fbe0b13bf..f1b820857e3407 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_entries/index.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_entries/index.ts @@ -10,10 +10,10 @@ import { pick, throttle } from 'lodash'; import { TimeKey, timeKeyIsBetween } from '../../../../common/time'; import { LogEntriesResponse, - LogEntry, LogEntriesRequest, LogEntriesBaseRequest, } from '../../../../common/http_api'; +import { LogEntry } from '../../../../common/log_entry'; import { fetchLogEntries } from './api/fetch_log_entries'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; diff --git a/x-pack/plugins/infra/public/containers/logs/log_highlights/log_entry_highlights.tsx b/x-pack/plugins/infra/public/containers/logs/log_highlights/log_entry_highlights.tsx index b4edebe8f8207c..fb72874df54099 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_highlights/log_entry_highlights.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_highlights/log_entry_highlights.tsx @@ -9,7 +9,8 @@ import { useEffect, useMemo, useState } from 'react'; import { TimeKey } from '../../../../common/time'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; import { fetchLogEntriesHighlights } from './api/fetch_log_entries_highlights'; -import { LogEntry, LogEntriesHighlightsResponse } from '../../../../common/http_api'; +import { LogEntriesHighlightsResponse } from '../../../../common/http_api'; +import { LogEntry } from '../../../../common/log_entry'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; export const useLogEntryHighlights = ( diff --git a/x-pack/plugins/infra/public/containers/logs/log_stream/index.ts b/x-pack/plugins/infra/public/containers/logs/log_stream/index.ts index ff30e993aa3a92..da7176125dae4c 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_stream/index.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_stream/index.ts @@ -10,8 +10,7 @@ import usePrevious from 'react-use/lib/usePrevious'; import { esKuery } from '../../../../../../../src/plugins/data/public'; import { fetchLogEntries } from '../log_entries/api/fetch_log_entries'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { LogEntry } from '../../../../common/http_api'; -import { LogEntryCursor } from '../../../../common/log_entry'; +import { LogEntryCursor, LogEntry } from '../../../../common/log_entry'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { LogSourceConfigurationProperties } from '../log_source'; diff --git a/x-pack/plugins/infra/public/containers/logs/view_log_in_context/view_log_in_context.ts b/x-pack/plugins/infra/public/containers/logs/view_log_in_context/view_log_in_context.ts index 61e1ea353880a0..2888e5a2b3ac50 100644 --- a/x-pack/plugins/infra/public/containers/logs/view_log_in_context/view_log_in_context.ts +++ b/x-pack/plugins/infra/public/containers/logs/view_log_in_context/view_log_in_context.ts @@ -5,7 +5,7 @@ */ import { useState } from 'react'; import createContainer from 'constate'; -import { LogEntry } from '../../../../common/http_api'; +import { LogEntry } from '../../../../common/log_entry'; interface ViewLogInContextProps { sourceId: string; diff --git a/x-pack/plugins/infra/public/containers/logs/with_stream_items.ts b/x-pack/plugins/infra/public/containers/logs/with_stream_items.ts index 2b8986820d5a43..89b5d993fa01e7 100644 --- a/x-pack/plugins/infra/public/containers/logs/with_stream_items.ts +++ b/x-pack/plugins/infra/public/containers/logs/with_stream_items.ts @@ -11,7 +11,7 @@ import { RendererFunction } from '../../utils/typed_react'; import { LogHighlightsState } from './log_highlights/log_highlights'; import { LogEntriesState, LogEntriesStateParams, LogEntriesCallbacks } from './log_entries'; import { UniqueTimeKey } from '../../../common/time'; -import { LogEntry } from '../../../common/http_api'; +import { LogEntry } from '../../../common/log_entry'; export const WithStreamItems: React.FunctionComponent<{ children: RendererFunction< diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx index ecddd8a9aa5bee..4445b735bedc95 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx @@ -12,7 +12,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common'; import { useTrackPageview } from '../../../../../observability/public'; -import { TimeRange } from '../../../../common/http_api/shared/time_range'; +import { TimeRange } from '../../../../common/time/time_range'; import { CategoryJobNoticesSection } from '../../../components/logging/log_analysis_job_status'; import { useLogEntryCategoriesModuleContext } from '../../../containers/logs/log_analysis/modules/log_entry_categories'; import { ViewLogInContext } from '../../../containers/logs/view_log_in_context'; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx index 3e1398c804686b..8fe87c14c1a7c8 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx @@ -8,7 +8,7 @@ import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { TimeRange } from '../../../../../../common/http_api/shared'; +import { TimeRange } from '../../../../../../common/time/time_range'; import { getEntitySpecificSingleMetricViewerLink } from '../../../../../components/logging/log_analysis_results'; import { useLinkProps } from '../../../../../hooks/use_link_props'; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/anomaly_severity_indicator_list.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/anomaly_severity_indicator_list.tsx index 47bb31ab4ae3e3..20f0ee00bd5054 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/anomaly_severity_indicator_list.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/anomaly_severity_indicator_list.tsx @@ -6,7 +6,7 @@ import React from 'react'; -import { LogEntryCategoryDataset } from '../../../../../../common/http_api/log_analysis'; +import { LogEntryCategoryDataset } from '../../../../../../common/log_analysis'; import { getFriendlyNameForPartitionId } from '../../../../../../common/log_analysis'; import { AnomalySeverityIndicator } from '../../../../../components/logging/log_analysis_results/anomaly_severity_indicator'; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_details_row.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_details_row.tsx index de07f3eb020293..8b4f075b782a94 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_details_row.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_details_row.tsx @@ -7,7 +7,7 @@ import React, { useEffect } from 'react'; import { useLogEntryCategoryExamples } from '../../use_log_entry_category_examples'; import { LogEntryExampleMessages } from '../../../../../components/logging/log_entry_examples/log_entry_examples'; -import { TimeRange } from '../../../../../../common/http_api/shared'; +import { TimeRange } from '../../../../../../common/time/time_range'; import { CategoryExampleMessage } from './category_example_message'; const exampleCount = 5; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx index 84d7e198636e92..e24fdd06bc6d9b 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx @@ -9,8 +9,8 @@ import { i18n } from '@kbn/i18n'; import { encode } from 'rison-node'; import moment from 'moment'; -import { LogEntry, LogEntryContext } from '../../../../../../common/http_api'; -import { TimeRange } from '../../../../../../common/http_api/shared'; +import { LogEntry, LogEntryContext } from '../../../../../../common/log_entry'; +import { TimeRange } from '../../../../../../common/time'; import { getFriendlyNameForPartitionId, partitionField, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/datasets_action_list.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/datasets_action_list.tsx index 2321dafaead1c6..6bbc640b5b007e 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/datasets_action_list.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/datasets_action_list.tsx @@ -6,8 +6,8 @@ import React from 'react'; -import { LogEntryCategoryDataset } from '../../../../../../common/http_api/log_analysis'; -import { TimeRange } from '../../../../../../common/http_api/shared'; +import { LogEntryCategoryDataset } from '../../../../../../common/log_analysis'; +import { TimeRange } from '../../../../../../common/time'; import { getFriendlyNameForPartitionId } from '../../../../../../common/log_analysis'; import { AnalyzeCategoryDatasetInMlAction } from './analyze_dataset_in_ml_action'; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/datasets_list.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/datasets_list.tsx index 779ac3e8c3a073..78690285180d78 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/datasets_list.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/datasets_list.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; -import { LogEntryCategoryDataset } from '../../../../../../common/http_api/log_analysis'; +import { LogEntryCategoryDataset } from '../../../../../../common/log_analysis'; import { getFriendlyNameForPartitionId } from '../../../../../../common/log_analysis'; export const DatasetsList: React.FunctionComponent<{ diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/log_entry_count_sparkline.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/log_entry_count_sparkline.tsx index 42d6509802ed4f..d94dbb9d335568 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/log_entry_count_sparkline.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/log_entry_count_sparkline.tsx @@ -6,8 +6,8 @@ import React, { useMemo } from 'react'; -import { LogEntryCategoryHistogram } from '../../../../../../common/http_api/log_analysis'; -import { TimeRange } from '../../../../../../common/http_api/shared'; +import { LogEntryCategoryHistogram } from '../../../../../../common/log_analysis'; +import { TimeRange } from '../../../../../../common/time'; import { SingleMetricComparison } from './single_metric_comparison'; import { SingleMetricSparkline } from './single_metric_sparkline'; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_sparkline.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_sparkline.tsx index 5fb8e3380f23f7..c8453bdcdefbd5 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_sparkline.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_sparkline.tsx @@ -13,7 +13,7 @@ import { } from '@elastic/eui/dist/eui_charts_theme'; import { useKibanaUiSetting } from '../../../../../utils/use_kibana_ui_setting'; -import { TimeRange } from '../../../../../../common/http_api/shared'; +import { TimeRange } from '../../../../../../common/time'; interface TimeSeriesPoint { timestamp: number; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_section.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_section.tsx index c7a6c89012a3a7..f810a675a18d1a 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_section.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_section.tsx @@ -8,8 +8,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiSpacer, EuiTitle } fro import { i18n } from '@kbn/i18n'; import React from 'react'; -import { LogEntryCategory } from '../../../../../../common/http_api/log_analysis'; -import { TimeRange } from '../../../../../../common/http_api/shared'; +import { LogEntryCategory } from '../../../../../../common/log_analysis'; +import { TimeRange } from '../../../../../../common/time'; import { BetaBadge } from '../../../../../components/beta_badge'; import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper'; import { RecreateJobButton } from '../../../../../components/logging/log_analysis_setup/create_job_button'; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_table.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_table.tsx index 954b6a9ab3ed32..834c99502a5900 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_table.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_table.tsx @@ -15,12 +15,12 @@ import { LogEntryCategory, LogEntryCategoryDataset, LogEntryCategoryHistogram, -} from '../../../../../../common/http_api/log_analysis'; -import { TimeRange } from '../../../../../../common/http_api/shared'; +} from '../../../../../../common/log_analysis'; +import { TimeRange } from '../../../../../../common/time'; import { RowExpansionButton } from '../../../../../components/basic_table'; import { AnomalySeverityIndicatorList } from './anomaly_severity_indicator_list'; import { CategoryDetailsRow } from './category_details_row'; -import { RegularExpressionRepresentation } from './category_expression'; +import { RegularExpressionRepresentation } from '../../../../../components/logging/log_analysis_results/category_expression'; import { DatasetActionsList } from './datasets_action_list'; import { DatasetsList } from './datasets_list'; import { LogEntryCountSparkline } from './log_entry_count_sparkline'; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_top_log_entry_categories.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_top_log_entry_categories.ts index a0eaecf04fa4b6..b25b6cbe6f631c 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_top_log_entry_categories.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_top_log_entry_categories.ts @@ -10,8 +10,8 @@ import { getLogEntryCategoriesRequestPayloadRT, getLogEntryCategoriesSuccessReponsePayloadRT, LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORIES_PATH, - CategorySort, } from '../../../../../common/http_api/log_analysis'; +import { CategoriesSort } from '../../../../../common/log_analysis'; import { decodeOrThrow } from '../../../../../common/runtime_types'; interface RequestArgs { @@ -20,7 +20,7 @@ interface RequestArgs { endTime: number; categoryCount: number; datasets?: string[]; - sort: CategorySort; + sort: CategoriesSort; } export const callGetTopLogEntryCategoriesAPI = async ( diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results.ts index a64b73dea25e66..e3fba926109554 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_results.ts @@ -9,8 +9,8 @@ import { useMemo, useState } from 'react'; import { GetLogEntryCategoriesSuccessResponsePayload, GetLogEntryCategoryDatasetsSuccessResponsePayload, - CategorySort, } from '../../../../common/http_api/log_analysis'; +import { CategoriesSort } from '../../../../common/log_analysis'; import { useTrackedPromise, CanceledPromiseError } from '../../../utils/use_tracked_promise'; import { callGetTopLogEntryCategoriesAPI } from './service_calls/get_top_log_entry_categories'; import { callGetLogEntryCategoryDatasetsAPI } from './service_calls/get_log_entry_category_datasets'; @@ -19,8 +19,8 @@ import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; type TopLogEntryCategories = GetLogEntryCategoriesSuccessResponsePayload['data']['categories']; type LogEntryCategoryDatasets = GetLogEntryCategoryDatasetsSuccessResponsePayload['data']['datasets']; -export type SortOptions = CategorySort; -export type ChangeSortOptions = (sortOptions: CategorySort) => void; +export type SortOptions = CategoriesSort; +export type ChangeSortOptions = (sortOptions: CategoriesSort) => void; export const useLogEntryCategoriesResults = ({ categoriesCount, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx index 09d3746c6ace65..f5007a1d48c4ad 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx @@ -13,7 +13,7 @@ import { encode, RisonValue } from 'rison-node'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common'; import { useTrackPageview } from '../../../../../observability/public'; -import { TimeRange } from '../../../../common/http_api/shared/time_range'; +import { TimeRange } from '../../../../common/time/time_range'; import { bucketSpan } from '../../../../common/log_analysis'; import { TimeKey } from '../../../../common/time'; import { diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/chart.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/chart.tsx index ae5c3b5b93b47f..503d3832015921 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/chart.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/chart.tsx @@ -23,7 +23,7 @@ import moment from 'moment'; import React, { useCallback, useMemo } from 'react'; import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper'; -import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; +import { TimeRange } from '../../../../../../common/time/time_range'; import { MLSeverityScoreCategories, ML_SEVERITY_COLORS, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx index 37032a95e96400..39fb1a5e6ae19c 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx @@ -10,8 +10,8 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import useMount from 'react-use/lib/useMount'; import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; -import { LogEntryAnomaly } from '../../../../../../common/http_api'; -import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; +import { LogEntryAnomaly, isCategoryAnomaly } from '../../../../../../common/log_analysis'; +import { TimeRange } from '../../../../../../common/time/time_range'; import { LogEntryExampleMessages } from '../../../../../components/logging/log_entry_examples/log_entry_examples'; import { useLogSourceContext } from '../../../../../containers/logs/log_source'; import { useLogEntryExamples } from '../../use_log_entry_examples'; @@ -40,7 +40,7 @@ export const AnomaliesTableExpandedRow: React.FunctionComponent<{ exampleCount: EXAMPLE_COUNT, sourceId, startTime: anomaly.startTime, - categoryId: anomaly.categoryId, + categoryId: isCategoryAnomaly(anomaly) ? anomaly.categoryId : undefined, }); useMount(() => { diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx index c89f0329e9f2e4..780e8c7ec5ec97 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx @@ -16,7 +16,7 @@ import { i18n } from '@kbn/i18n'; import React, { useMemo } from 'react'; import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; import { LogEntryRateResults } from '../../use_log_entry_rate_results'; -import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; +import { TimeRange } from '../../../../../../common/time/time_range'; import { getAnnotationsForAll, getLogEntryRateCombinedSeries } from '../helpers/data_formatters'; import { AnomaliesChart } from './chart'; import { AnomaliesTable } from './table'; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx index ab3476cd78eb39..7446b3c3486061 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx @@ -25,10 +25,10 @@ import { LogColumnHeader, } from '../../../../../components/logging/log_text_stream/column_headers'; import { useLinkProps } from '../../../../../hooks/use_link_props'; -import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; +import { TimeRange } from '../../../../../../common/time/time_range'; import { partitionField } from '../../../../../../common/log_analysis/job_parameters'; import { getEntitySpecificSingleMetricViewerLink } from '../../../../../components/logging/log_analysis_results/analyze_in_ml_button'; -import { LogEntryExample } from '../../../../../../common/http_api/log_analysis/results'; +import { LogEntryExample, isCategoryAnomaly } from '../../../../../../common/log_analysis'; import { LogColumnConfiguration, isTimestampLogColumnConfiguration, @@ -36,7 +36,7 @@ import { isMessageLogColumnConfiguration, } from '../../../../../utils/source_configuration'; import { localizedDate } from '../../../../../../common/formatters/datetime'; -import { LogEntryAnomaly } from '../../../../../../common/http_api'; +import { LogEntryAnomaly } from '../../../../../../common/log_analysis'; import { useLogEntryFlyoutContext } from '../../../../../containers/logs/log_flyout'; export const exampleMessageScale = 'medium' as const; @@ -116,7 +116,7 @@ export const LogEntryExampleMessage: React.FunctionComponent = ({ const viewAnomalyInMachineLearningLinkProps = useLinkProps( getEntitySpecificSingleMetricViewerLink(anomaly.jobId, timeRange, { [partitionField]: dataset, - ...(anomaly.categoryId ? { mlcategory: anomaly.categoryId } : {}), + ...(isCategoryAnomaly(anomaly) ? { mlcategory: anomaly.categoryId } : {}), }) ); diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx index 855113d66f5101..4b8c2b02bb8af9 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx @@ -18,16 +18,18 @@ import moment from 'moment'; import { i18n } from '@kbn/i18n'; import React, { useCallback, useMemo } from 'react'; import useSet from 'react-use/lib/useSet'; -import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; +import { TimeRange } from '../../../../../../common/time/time_range'; import { + AnomalyType, formatAnomalyScore, getFriendlyNameForPartitionId, formatOneDecimalPlace, + isCategoryAnomaly, } from '../../../../../../common/log_analysis'; -import { AnomalyType } from '../../../../../../common/http_api/log_analysis'; import { RowExpansionButton } from '../../../../../components/basic_table'; import { AnomaliesTableExpandedRow } from './expanded_row'; import { AnomalySeverityIndicator } from '../../../../../components/logging/log_analysis_results/anomaly_severity_indicator'; +import { RegularExpressionRepresentation } from '../../../../../components/logging/log_analysis_results/category_expression'; import { useKibanaUiSetting } from '../../../../../utils/use_kibana_ui_setting'; import { Page, @@ -50,6 +52,7 @@ interface TableItem { typical: number; actual: number; type: AnomalyType; + categoryRegex?: string; } const anomalyScoreColumnName = i18n.translate( @@ -124,6 +127,7 @@ export const AnomaliesTable: React.FunctionComponent<{ type: anomaly.type, typical: anomaly.typical, actual: anomaly.actual, + categoryRegex: isCategoryAnomaly(anomaly) ? anomaly.categoryRegex : undefined, }; }); }, [results]); @@ -166,9 +170,7 @@ export const AnomaliesTable: React.FunctionComponent<{ { name: anomalyMessageColumnName, truncateText: true, - render: (item: TableItem) => ( - - ), + render: (item: TableItem) => , }, { field: 'startTime', @@ -226,15 +228,9 @@ export const AnomaliesTable: React.FunctionComponent<{ ); }; -const AnomalyMessage = ({ - actual, - typical, - type, -}: { - actual: number; - typical: number; - type: AnomalyType; -}) => { +const AnomalyMessage = ({ anomaly }: { anomaly: TableItem }) => { + const { type, actual, typical } = anomaly; + const moreThanExpectedAnomalyMessage = i18n.translate( 'xpack.infra.logs.analysis.anomaliesTableMoreThanExpectedAnomalyMessage', { @@ -262,9 +258,20 @@ const AnomalyMessage = ({ const ratioMessage = useRatio ? `${formatOneDecimalPlace(ratio)}x` : ''; return ( - - {`${ratioMessage} ${message}`} - + + + + + + {`${ratioMessage} ${message}`} + {anomaly.categoryRegex && ( + <> + {': '} + + + )} + + ); }; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies.ts index 7f90604bfefdd3..f915b0d78c43d0 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies.ts @@ -11,13 +11,13 @@ import { LOG_ANALYSIS_GET_LOG_ENTRY_ANOMALIES_PATH, } from '../../../../../common/http_api/log_analysis'; import { decodeOrThrow } from '../../../../../common/runtime_types'; -import { Sort, Pagination } from '../../../../../common/http_api/log_analysis'; +import { AnomaliesSort, Pagination } from '../../../../../common/log_analysis'; interface RequestArgs { sourceId: string; startTime: number; endTime: number; - sort: Sort; + sort: AnomaliesSort; pagination: Pagination; datasets?: string[]; } diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_anomalies_results.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_anomalies_results.ts index 396c1ad3e1857c..fbfe76f1473f59 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_anomalies_results.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_anomalies_results.ts @@ -9,21 +9,21 @@ import useMount from 'react-use/lib/useMount'; import { useTrackedPromise, CanceledPromiseError } from '../../../utils/use_tracked_promise'; import { callGetLogEntryAnomaliesAPI } from './service_calls/get_log_entry_anomalies'; import { callGetLogEntryAnomaliesDatasetsAPI } from './service_calls/get_log_entry_anomalies_datasets'; +import { GetLogEntryAnomaliesDatasetsSuccessResponsePayload } from '../../../../common/http_api/log_analysis'; import { - Sort, + AnomaliesSort, Pagination, PaginationCursor, - GetLogEntryAnomaliesDatasetsSuccessResponsePayload, LogEntryAnomaly, -} from '../../../../common/http_api/log_analysis'; +} from '../../../../common/log_analysis'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; -export type SortOptions = Sort; +export type SortOptions = AnomaliesSort; export type PaginationOptions = Pick; export type Page = number; export type FetchNextPage = () => void; export type FetchPreviousPage = () => void; -export type ChangeSortOptions = (sortOptions: Sort) => void; +export type ChangeSortOptions = (sortOptions: AnomaliesSort) => void; export type ChangePaginationOptions = (paginationOptions: PaginationOptions) => void; export type LogEntryAnomalies = LogEntryAnomaly[]; type LogEntryAnomaliesDatasets = GetLogEntryAnomaliesDatasetsSuccessResponsePayload['data']['datasets']; @@ -38,7 +38,7 @@ interface ReducerState { paginationCursor: Pagination['cursor'] | undefined; hasNextPage: boolean; paginationOptions: PaginationOptions; - sortOptions: Sort; + sortOptions: AnomaliesSort; timeRange: { start: number; end: number; @@ -53,7 +53,7 @@ type ReducerStateDefaults = Pick< type ReducerAction = | { type: 'changePaginationOptions'; payload: { paginationOptions: PaginationOptions } } - | { type: 'changeSortOptions'; payload: { sortOptions: Sort } } + | { type: 'changeSortOptions'; payload: { sortOptions: AnomaliesSort } } | { type: 'fetchNextPage' } | { type: 'fetchPreviousPage' } | { type: 'changeHasNextPage'; payload: { hasNextPage: boolean } } @@ -144,7 +144,7 @@ export const useLogEntryAnomaliesResults = ({ endTime: number; startTime: number; sourceId: string; - defaultSortOptions: Sort; + defaultSortOptions: AnomaliesSort; defaultPaginationOptions: Pick; onGetLogEntryAnomaliesDatasetsError?: (error: Error) => void; filteredDatasets?: string[]; @@ -225,7 +225,7 @@ export const useLogEntryAnomaliesResults = ({ ); const changeSortOptions = useCallback( - (nextSortOptions: Sort) => { + (nextSortOptions: AnomaliesSort) => { dispatch({ type: 'changeSortOptions', payload: { sortOptions: nextSortOptions } }); }, [dispatch] diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_examples.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_examples.ts index e809ab9cd5a6f2..90b8b03a81602f 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_examples.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_examples.ts @@ -6,7 +6,7 @@ import { useMemo, useState } from 'react'; -import { LogEntryExample } from '../../../../common/http_api'; +import { LogEntryExample } from '../../../../common/log_analysis'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; import { callGetLogEntryExamplesAPI } from './service_calls/get_log_entry_examples'; diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_view_log_in_context.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_view_log_in_context.tsx index 3fa89da5b5e51a..011653fd6eb478 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_view_log_in_context.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_view_log_in_context.tsx @@ -16,7 +16,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import { isEmpty } from 'lodash'; import React, { useCallback, useContext, useMemo } from 'react'; -import { LogEntry } from '../../../../common/http_api'; +import { LogEntry } from '../../../../common/log_entry'; import { ViewLogInContext } from '../../../containers/logs/view_log_in_context'; import { useViewportDimensions } from '../../../utils/use_viewport_dimensions'; import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common'; diff --git a/x-pack/plugins/infra/public/test_utils/entries.ts b/x-pack/plugins/infra/public/test_utils/entries.ts index 04c87d5f73902b..96737fb1753650 100644 --- a/x-pack/plugins/infra/public/test_utils/entries.ts +++ b/x-pack/plugins/infra/public/test_utils/entries.ts @@ -5,7 +5,7 @@ */ import faker from 'faker'; -import { LogEntry } from '../../common/http_api'; +import { LogEntry } from '../../common/log_entry'; import { LogSourceConfiguration } from '../containers/logs/log_source'; export const ENTRIES_EMPTY = { diff --git a/x-pack/plugins/infra/public/utils/log_entry/log_entry.ts b/x-pack/plugins/infra/public/utils/log_entry/log_entry.ts index bb528ee5b18c5c..c69104ad6177e7 100644 --- a/x-pack/plugins/infra/public/utils/log_entry/log_entry.ts +++ b/x-pack/plugins/infra/public/utils/log_entry/log_entry.ts @@ -17,7 +17,7 @@ import { LogMessagePart, LogMessageFieldPart, LogMessageConstantPart, -} from '../../../common/http_api'; +} from '../../../common/log_entry'; export type LogEntryMessageSegment = InfraLogEntryFields.Message; export type LogEntryConstantMessageSegment = InfraLogEntryFields.InfraLogMessageConstantSegmentInlineFragment; diff --git a/x-pack/plugins/infra/public/utils/log_entry/log_entry_highlight.ts b/x-pack/plugins/infra/public/utils/log_entry/log_entry_highlight.ts index abb004911214b2..208316c693d4db 100644 --- a/x-pack/plugins/infra/public/utils/log_entry/log_entry_highlight.ts +++ b/x-pack/plugins/infra/public/utils/log_entry/log_entry_highlight.ts @@ -12,7 +12,7 @@ import { LogFieldColumn, LogMessagePart, LogMessageFieldPart, -} from '../../../common/http_api'; +} from '../../../common/log_entry'; export type LogEntryHighlightColumn = InfraLogEntryHighlightFields.Columns; export type LogEntryHighlightMessageColumn = InfraLogEntryHighlightFields.InfraLogEntryMessageColumnInlineFragment; diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts index 0b1df3abd465a2..4c5debe58ed260 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts @@ -10,10 +10,9 @@ import type { InfraPluginRequestHandlerContext } from '../../../types'; import { LogEntriesSummaryBucket, LogEntriesSummaryHighlightsBucket, - LogEntry, - LogColumn, LogEntriesRequest, } from '../../../../common/http_api'; +import { LogEntry, LogColumn } from '../../../../common/log_entry'; import { InfraSourceConfiguration, InfraSources, diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts index 19ab82c9c5ac11..d04e036b33b215 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogMessagePart } from '../../../../common/http_api/log_entries'; +import { LogMessagePart } from '../../../../common/log_entry'; import { JsonArray, JsonValue } from '../../../../../../../src/plugins/kibana_utils/common'; import { LogMessageFormattingCondition, diff --git a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts index c6a45939122802..fbcc3671f08a2b 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts @@ -12,12 +12,11 @@ import { logEntryCategoriesJobTypes, logEntryRateJobTypes, jobCustomSettingsRT, -} from '../../../common/log_analysis'; -import { - Sort, + LogEntryAnomalyDatasets, + AnomaliesSort, Pagination, - GetLogEntryAnomaliesRequestPayload, -} from '../../../common/http_api/log_analysis'; + isCategoryAnomaly, +} from '../../../common/log_analysis'; import type { MlSystem, MlAnomalyDetectors } from '../../types'; import { createLogEntryAnomaliesQuery, logEntryAnomaliesResponseRT } from './queries'; import { @@ -95,9 +94,9 @@ export async function getLogEntryAnomalies( sourceId: string, startTime: number, endTime: number, - sort: Sort, + sort: AnomaliesSort, pagination: Pagination, - datasets: GetLogEntryAnomaliesRequestPayload['data']['datasets'] + datasets?: LogEntryAnomalyDatasets ) { const finalizeLogEntryAnomaliesSpan = startTracingSpan('get log entry anomalies'); @@ -131,7 +130,7 @@ export async function getLogEntryAnomalies( datasets ); - const data = anomalies.map((anomaly) => { + const parsedAnomalies = anomalies.map((anomaly) => { const { jobId } = anomaly; if (!anomaly.categoryId) { @@ -141,10 +140,41 @@ export async function getLogEntryAnomalies( } }); + const categoryIds = parsedAnomalies.reduce((acc, anomaly) => { + return isCategoryAnomaly(anomaly) ? [...acc, parseInt(anomaly.categoryId, 10)] : acc; + }, []); + + const logEntryCategoriesCountJobId = getJobId( + context.infra.spaceId, + sourceId, + logEntryCategoriesJobTypes[0] + ); + + const { logEntryCategoriesById } = await fetchLogEntryCategories( + context, + logEntryCategoriesCountJobId, + categoryIds + ); + + const parsedAnomaliesWithExpandedCategoryInformation = parsedAnomalies.map((anomaly) => { + if (isCategoryAnomaly(anomaly)) { + if (logEntryCategoriesById[parseInt(anomaly.categoryId, 10)]) { + const { + _source: { regex, terms }, + } = logEntryCategoriesById[parseInt(anomaly.categoryId, 10)]; + return { ...anomaly, ...{ categoryRegex: regex, categoryTerms: terms } }; + } else { + return { ...anomaly, ...{ categoryRegex: '', categoryTerms: '' } }; + } + } else { + return anomaly; + } + }); + const logEntryAnomaliesSpan = finalizeLogEntryAnomaliesSpan(); return { - data, + data: parsedAnomaliesWithExpandedCategoryInformation, paginationCursors, hasMoreEntries, timing: { @@ -208,9 +238,9 @@ async function fetchLogEntryAnomalies( jobIds: string[], startTime: number, endTime: number, - sort: Sort, + sort: AnomaliesSort, pagination: Pagination, - datasets: GetLogEntryAnomaliesRequestPayload['data']['datasets'] + datasets?: LogEntryAnomalyDatasets ) { // We'll request 1 extra entry on top of our pageSize to determine if there are // more entries to be fetched. This avoids scenarios where the client side can't diff --git a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts index 7dd5aae9784f53..071a8a94e009be 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts @@ -5,14 +5,14 @@ */ import type { ILegacyScopedClusterClient } from 'src/core/server'; -import { LogEntryContext } from '../../../common/http_api'; +import { LogEntryContext } from '../../../common/log_entry'; import { compareDatasetsByMaximumAnomalyScore, getJobId, jobCustomSettingsRT, logEntryCategoriesJobTypes, + CategoriesSort, } from '../../../common/log_analysis'; -import { CategorySort } from '../../../common/http_api/log_analysis'; import { startTracingSpan } from '../../../common/performance_tracing'; import { decodeOrThrow } from '../../../common/runtime_types'; import type { MlAnomalyDetectors, MlSystem } from '../../types'; @@ -51,7 +51,7 @@ export async function getTopLogEntryCategories( categoryCount: number, datasets: string[], histograms: HistogramParameters[], - sort: CategorySort + sort: CategoriesSort ) { const finalizeTopLogEntryCategoriesSpan = startTracingSpan('get top categories'); @@ -218,7 +218,7 @@ async function fetchTopLogEntryCategories( endTime: number, categoryCount: number, datasets: string[], - sort: CategorySort + sort: CategoriesSort ) { const finalizeEsSearchSpan = startTracingSpan('Fetch top categories from ES'); diff --git a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_anomalies.ts b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_anomalies.ts index e692ed019cf866..8e01cafcf62ae7 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_anomalies.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_anomalies.ts @@ -14,10 +14,10 @@ import { createDatasetsFilters, } from './common'; import { - Sort, + AnomaliesSort, + LogEntryAnomalyDatasets, Pagination, - GetLogEntryAnomaliesRequestPayload, -} from '../../../../common/http_api/log_analysis'; +} from '../../../../common/log_analysis'; // TODO: Reassess validity of this against ML docs const TIEBREAKER_FIELD = '_doc'; @@ -32,9 +32,9 @@ export const createLogEntryAnomaliesQuery = ( jobIds: string[], startTime: number, endTime: number, - sort: Sort, + sort: AnomaliesSort, pagination: Pagination, - datasets: GetLogEntryAnomaliesRequestPayload['data']['datasets'] + datasets?: LogEntryAnomalyDatasets ) => { const { field } = sort; const { pageSize } = pagination; @@ -118,7 +118,7 @@ export const logEntryAnomaliesResponseRT = rt.intersection([ export type LogEntryAnomaliesResponseRT = rt.TypeOf; -const parsePaginationCursor = (sort: Sort, pagination: Pagination) => { +const parsePaginationCursor = (sort: AnomaliesSort, pagination: Pagination) => { const { cursor } = pagination; const { direction } = sort; diff --git a/x-pack/plugins/infra/server/lib/log_analysis/queries/top_log_entry_categories.ts b/x-pack/plugins/infra/server/lib/log_analysis/queries/top_log_entry_categories.ts index 057054b4272271..f1363900d36963 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/queries/top_log_entry_categories.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/queries/top_log_entry_categories.ts @@ -14,13 +14,13 @@ import { createDatasetsFilters, } from './common'; -import { CategorySort } from '../../../../common/http_api/log_analysis'; +import { CategoriesSort } from '../../../../common/log_analysis'; type CategoryAggregationOrder = | 'filter_record>maximum_record_score' | 'filter_model_plot>sum_actual'; const getAggregationOrderForSortField = ( - field: CategorySort['field'] + field: CategoriesSort['field'] ): CategoryAggregationOrder => { switch (field) { case 'maximumAnomalyScore': @@ -40,7 +40,7 @@ export const createTopLogEntryCategoriesQuery = ( endTime: number, size: number, datasets: string[], - sort: CategorySort + sort: CategoriesSort ) => ({ ...defaultRequestParameters, body: { diff --git a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies.ts b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies.ts index ec2bc6e5ed7393..42d126d4ef0368 100644 --- a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies.ts +++ b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies.ts @@ -11,9 +11,8 @@ import { getLogEntryAnomaliesSuccessReponsePayloadRT, getLogEntryAnomaliesRequestPayloadRT, GetLogEntryAnomaliesRequestPayload, - Sort, - Pagination, } from '../../../../common/http_api/log_analysis'; +import { AnomaliesSort, Pagination } from '../../../../common/log_analysis'; import { createValidationFunction } from '../../../../common/runtime_types'; import { assertHasInfraMlPlugins } from '../../../utils/request_context'; import { getLogEntryAnomalies } from '../../../lib/log_analysis'; @@ -98,7 +97,7 @@ const getSortAndPagination = ( sort: Partial = {}, pagination: Partial = {} ): { - sort: Sort; + sort: AnomaliesSort; pagination: Pagination; } => { const sortDefaults = { diff --git a/x-pack/test/api_integration/apis/metrics_ui/log_entries.ts b/x-pack/test/api_integration/apis/metrics_ui/log_entries.ts index 2d148f4c2c0f7d..79d5e683444321 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/log_entries.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/log_entries.ts @@ -13,10 +13,13 @@ import { LOG_ENTRIES_PATH, logEntriesRequestRT, logEntriesResponseRT, +} from '../../../../plugins/infra/common/http_api'; + +import { LogTimestampColumn, LogFieldColumn, LogMessageColumn, -} from '../../../../plugins/infra/common/http_api'; +} from '../../../../plugins/infra/common/log_entry'; import { FtrProviderContext } from '../../ftr_provider_context'; From 96e4bdc8ae5e008796bb66254b4e9652e88b044e Mon Sep 17 00:00:00 2001 From: Devon Thomson Date: Wed, 27 Jan 2021 13:06:22 -0500 Subject: [PATCH 40/58] Dashboard - Hide Short URL Option (#89338) * fix typo from sub-feature privileges --- .../dashboard/public/application/top_nav/show_share_modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/dashboard/public/application/top_nav/show_share_modal.tsx b/src/plugins/dashboard/public/application/top_nav/show_share_modal.tsx index 660e7635eb99de..ecebef2ec3c9c2 100644 --- a/src/plugins/dashboard/public/application/top_nav/show_share_modal.tsx +++ b/src/plugins/dashboard/public/application/top_nav/show_share_modal.tsx @@ -94,7 +94,7 @@ export function ShowShareModal({ share.toggleShareContextMenu({ anchorElement, allowEmbed: true, - allowShortUrl: !dashboardCapabilities.hideWriteControls || dashboardCapabilities.createShortUrl, + allowShortUrl: dashboardCapabilities.createShortUrl, shareableUrl: setStateToKbnUrl( '_a', dashboardStateManager.getAppState(), From 3c604438b8fcb6588fcc4a77517dcc0392dfc5d6 Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 27 Jan 2021 11:22:26 -0700 Subject: [PATCH 41/58] [kbn/pm] throw an error if package doesn't have a script (#89438) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [kbn/pm] throw an error if package doesn't have a script * actually add the kbn/es build script 🤦‍♂️ Co-authored-by: spalger --- .ci/teamcity/tests/test_projects.sh | 2 +- packages/kbn-es/package.json | 1 + packages/kbn-pm/README.md | 4 ++-- packages/kbn-pm/dist/index.js | 26 ++++++++++++++++++-------- packages/kbn-pm/src/cli.ts | 5 ++++- packages/kbn-pm/src/commands/run.ts | 22 +++++++++++++++------- test/scripts/checks/test_projects.sh | 2 +- 7 files changed, 42 insertions(+), 20 deletions(-) diff --git a/.ci/teamcity/tests/test_projects.sh b/.ci/teamcity/tests/test_projects.sh index 2553650930392b..06dd3607a67991 100755 --- a/.ci/teamcity/tests/test_projects.sh +++ b/.ci/teamcity/tests/test_projects.sh @@ -5,4 +5,4 @@ set -euo pipefail source "$(dirname "${0}")/../util.sh" checks-reporter-with-killswitch "Test Projects" \ - yarn kbn run test --exclude kibana --oss --skip-kibana-plugins + yarn kbn run test --exclude kibana --oss --skip-kibana-plugins --skip-missing diff --git a/packages/kbn-es/package.json b/packages/kbn-es/package.json index c8e25a95594c64..8ea83d744bcb90 100644 --- a/packages/kbn-es/package.json +++ b/packages/kbn-es/package.json @@ -8,6 +8,7 @@ "devOnly": true }, "scripts": { + "build": "node scripts/build", "kbn:bootstrap": "node scripts/build", "kbn:watch": "node scripts/build --watch" }, diff --git a/packages/kbn-pm/README.md b/packages/kbn-pm/README.md index c169b5c75e178b..eb1ac6ffa92aae 100644 --- a/packages/kbn-pm/README.md +++ b/packages/kbn-pm/README.md @@ -150,14 +150,14 @@ e.g. `build` or `test`. Instead of jumping into each package and running `yarn build` you can run: ``` -yarn kbn run build +yarn kbn run build --skip-missing ``` And if needed, you can skip packages in the same way as for bootstrapping, e.g. with `--exclude` and `--skip-kibana-plugins`: ``` -yarn kbn run build --exclude kibana +yarn kbn run build --exclude kibana --skip-missing ``` ### Watching diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 09995a9be30a64..95ab46582723e6 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -179,12 +179,15 @@ function help() { --debug Set log level to debug --quiet Set log level to error --silent Disable log output + + "run" options: + --skip-missing Ignore packages which don't have the requested script ` + '\n'); } async function run(argv) { _utils_log__WEBPACK_IMPORTED_MODULE_6__["log"].setLogLevel(Object(_kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__["pickLevelFromFlags"])(getopts__WEBPACK_IMPORTED_MODULE_1___default()(argv, { - boolean: ['verbose', 'debug', 'quiet', 'silent'] + boolean: ['verbose', 'debug', 'quiet', 'silent', 'skip-missing'] }))); // We can simplify this setup (and remove this extra handling) once Yarn // starts forwarding the `--` directly to this script, see // https://github.com/yarnpkg/yarn/blob/b2d3e1a8fe45ef376b716d597cc79b38702a9320/src/cli/index.js#L174-L182 @@ -52620,7 +52623,8 @@ const RunCommand = { name: 'run', async run(projects, projectGraph, { - extraArgs + extraArgs, + options }) { const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projects, projectGraph); @@ -52631,13 +52635,19 @@ const RunCommand = { const scriptName = extraArgs[0]; const scriptArgs = extraArgs.slice(1); await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async project => { - if (project.hasScript(scriptName)) { - _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].info(`[${project.name}] running "${scriptName}" script`); - await project.runScriptStreaming(scriptName, { - args: scriptArgs - }); - _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].success(`[${project.name}] complete`); + if (!project.hasScript(scriptName)) { + if (!!options['skip-missing']) { + return; + } + + throw new _utils_errors__WEBPACK_IMPORTED_MODULE_0__["CliError"](`[${project.name}] no "${scriptName}" script defined. To skip packages without the "${scriptName}" script pass --skip-missing`); } + + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].info(`[${project.name}] running "${scriptName}" script`); + await project.runScriptStreaming(scriptName, { + args: scriptArgs + }); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].success(`[${project.name}] complete`); }); } diff --git a/packages/kbn-pm/src/cli.ts b/packages/kbn-pm/src/cli.ts index a27587085eab13..e6be8d1821d01a 100644 --- a/packages/kbn-pm/src/cli.ts +++ b/packages/kbn-pm/src/cli.ts @@ -41,6 +41,9 @@ function help() { --debug Set log level to debug --quiet Set log level to error --silent Disable log output + + "run" options: + --skip-missing Ignore packages which don't have the requested script ` + '\n' ); } @@ -49,7 +52,7 @@ export async function run(argv: string[]) { log.setLogLevel( pickLevelFromFlags( getopts(argv, { - boolean: ['verbose', 'debug', 'quiet', 'silent'], + boolean: ['verbose', 'debug', 'quiet', 'silent', 'skip-missing'], }) ) ); diff --git a/packages/kbn-pm/src/commands/run.ts b/packages/kbn-pm/src/commands/run.ts index acbafe07b9a844..fb306f37082fe9 100644 --- a/packages/kbn-pm/src/commands/run.ts +++ b/packages/kbn-pm/src/commands/run.ts @@ -16,7 +16,7 @@ export const RunCommand: ICommand = { description: 'Run script defined in package.json in each package that contains that script.', name: 'run', - async run(projects, projectGraph, { extraArgs }) { + async run(projects, projectGraph, { extraArgs, options }) { const batchedProjects = topologicallyBatchProjects(projects, projectGraph); if (extraArgs.length === 0) { @@ -27,13 +27,21 @@ export const RunCommand: ICommand = { const scriptArgs = extraArgs.slice(1); await parallelizeBatches(batchedProjects, async (project) => { - if (project.hasScript(scriptName)) { - log.info(`[${project.name}] running "${scriptName}" script`); - await project.runScriptStreaming(scriptName, { - args: scriptArgs, - }); - log.success(`[${project.name}] complete`); + if (!project.hasScript(scriptName)) { + if (!!options['skip-missing']) { + return; + } + + throw new CliError( + `[${project.name}] no "${scriptName}" script defined. To skip packages without the "${scriptName}" script pass --skip-missing` + ); } + + log.info(`[${project.name}] running "${scriptName}" script`); + await project.runScriptStreaming(scriptName, { + args: scriptArgs, + }); + log.success(`[${project.name}] complete`); }); }, }; diff --git a/test/scripts/checks/test_projects.sh b/test/scripts/checks/test_projects.sh index 56f15f6839e9d2..be3fe4c4be9d04 100755 --- a/test/scripts/checks/test_projects.sh +++ b/test/scripts/checks/test_projects.sh @@ -3,4 +3,4 @@ source src/dev/ci_setup/setup_env.sh checks-reporter-with-killswitch "Test Projects" \ - yarn kbn run test --exclude kibana --oss --skip-kibana-plugins + yarn kbn run test --exclude kibana --oss --skip-kibana-plugins --skip-missing From 740155e214f018818f0243641d58af9780d0e72e Mon Sep 17 00:00:00 2001 From: Ryland Herrick Date: Wed, 27 Jan 2021 13:08:53 -0600 Subject: [PATCH 42/58] Address intermittent test failure (#89367) After observing the conditions when this test fails, it appears that some (but not all) signals are available. As these signals are generated by a rule via a bulk create, the odds of us retrieving signals in the middle of that bulk creation is very slim (but not impossible). The crux of the error here was: we wait for signals to be generated, but not the ones that we need. Specifically, we are waiting for a single signal to be available, but since we are asserting on sequences of signals, we need several to be available to us. While not perfect (because the signals we receive are not technically guaranteed to be sequence signals), increasing the number of signals that we wait for before proceeding should be sufficient to prevent this failure state. In debugging, it was observed that every test returning 9-10 signals succeeded, while it was possible for the test to return only one signal and fail. --- .../security_and_spaces/tests/generating_signals.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts index c3c7ecd0aba813..00a20abe367ae1 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts @@ -265,7 +265,7 @@ export default ({ getService }: FtrProviderContext) => { }; const { id } = await createRule(supertest, rule); await waitForRuleSuccessOrStatus(supertest, id); - await waitForSignalsToBePresent(supertest, 1, [id]); + await waitForSignalsToBePresent(supertest, 10, [id]); const signalsOpen = await getSignalsByRuleIds(supertest, ['eql-rule']); const sequenceSignal = signalsOpen.hits.hits.find( (signal) => signal._source.signal.depth === 2 From c8ef36ab126a72813de0a400175e02c13aa5fd27 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 27 Jan 2021 13:03:00 -0700 Subject: [PATCH 43/58] skip flaky suite (#89475) --- test/functional/apps/management/_scripted_fields_preview.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/management/_scripted_fields_preview.js b/test/functional/apps/management/_scripted_fields_preview.js index 104d41b7e2a756..46619b89dfc595 100644 --- a/test/functional/apps/management/_scripted_fields_preview.js +++ b/test/functional/apps/management/_scripted_fields_preview.js @@ -13,7 +13,8 @@ export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['settings']); const SCRIPTED_FIELD_NAME = 'myScriptedField'; - describe('scripted fields preview', () => { + // FLAKY: https://github.com/elastic/kibana/issues/89475 + describe.skip('scripted fields preview', () => { before(async function () { await browser.setWindowSize(1200, 800); await PageObjects.settings.createIndexPattern(); From 27d9a9ddaaf1a7d7767bf8accc887ffa7ab737c2 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 27 Jan 2021 13:04:11 -0700 Subject: [PATCH 44/58] skip flaky suite (#89477) --- test/functional/apps/discover/_saved_queries.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/discover/_saved_queries.ts b/test/functional/apps/discover/_saved_queries.ts index 6e6c53ec049859..ec6c455ecc9795 100644 --- a/test/functional/apps/discover/_saved_queries.ts +++ b/test/functional/apps/discover/_saved_queries.ts @@ -26,7 +26,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const savedQueryManagementComponent = getService('savedQueryManagementComponent'); const testSubjects = getService('testSubjects'); - describe('saved queries saved objects', function describeIndexTests() { + // FLAKY: https://github.com/elastic/kibana/issues/89477 + describe.skip('saved queries saved objects', function describeIndexTests() { before(async function () { log.debug('load kibana index with default index pattern'); await esArchiver.load('discover'); From 44b8333141e85ebc882f9ccfb98abaf6e523e3fa Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 27 Jan 2021 13:07:12 -0700 Subject: [PATCH 45/58] skip flaky suite (#89476) --- test/functional/apps/dashboard/dashboard_save.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/dashboard/dashboard_save.ts b/test/functional/apps/dashboard/dashboard_save.ts index 27cbba7db393d0..e36136cd451419 100644 --- a/test/functional/apps/dashboard/dashboard_save.ts +++ b/test/functional/apps/dashboard/dashboard_save.ts @@ -12,7 +12,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['dashboard', 'header']); const listingTable = getService('listingTable'); - describe('dashboard save', function describeIndexTests() { + // FLAKY: https://github.com/elastic/kibana/issues/89476 + describe.skip('dashboard save', function describeIndexTests() { this.tags('includeFirefox'); const dashboardName = 'Dashboard Save Test'; const dashboardNameEnterKey = 'Dashboard Save Test with Enter Key'; From 4499f62dcb7b8296d1cd37193530868ff432ffe9 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 27 Jan 2021 13:08:09 -0700 Subject: [PATCH 46/58] skip flaky suite (#89478) --- test/functional/apps/management/_import_objects.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/management/_import_objects.ts b/test/functional/apps/management/_import_objects.ts index 07811c9c68e45c..754406938e47b6 100644 --- a/test/functional/apps/management/_import_objects.ts +++ b/test/functional/apps/management/_import_objects.ts @@ -23,7 +23,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const log = getService('log'); - describe('import objects', function describeIndexTests() { + // FLAKY: https://github.com/elastic/kibana/issues/89478 + describe.skip('import objects', function describeIndexTests() { describe('.ndjson file', () => { beforeEach(async function () { await kibanaServer.uiSettings.replace({}); From 1ff4256d64cdecca9a993ec0035ca176e918a73e Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 27 Jan 2021 13:38:16 -0700 Subject: [PATCH 47/58] [Maps] migrate maps, maps_file_upload, and maps_legacy_licensing to TS projects (#89439) * [Maps] migrate maps, maps_file_upload, and maps_legacy_licensing to TS projects * include types to avoid rison import errors * add mappings to tsconfig include --- .../add_layer_panel/view.tsx | 2 +- .../layer_panel/join_editor/join_editor.tsx | 2 +- .../layer_settings/layer_settings.tsx | 2 +- .../map_container/map_container.tsx | 2 +- .../map_settings_panel/map_settings_panel.tsx | 2 +- .../connected_components/mb_map/mb_map.tsx | 2 +- .../fit_to_data/fit_to_data.tsx | 2 +- .../tools_control/tools_control.tsx | 2 +- .../toc_entry_actions_popover.tsx | 2 +- .../routes/map_page/map_app/map_app.tsx | 4 +-- x-pack/plugins/maps/public/url_generator.ts | 1 + x-pack/plugins/maps/tsconfig.json | 25 +++++++++++++++++++ x-pack/plugins/maps_file_upload/tsconfig.json | 15 +++++++++++ .../maps_legacy_licensing/tsconfig.json | 14 +++++++++++ x-pack/tsconfig.json | 6 +++++ x-pack/tsconfig.refs.json | 3 +++ 16 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 x-pack/plugins/maps/tsconfig.json create mode 100644 x-pack/plugins/maps_file_upload/tsconfig.json create mode 100644 x-pack/plugins/maps_legacy_licensing/tsconfig.json diff --git a/x-pack/plugins/maps/public/connected_components/add_layer_panel/view.tsx b/x-pack/plugins/maps/public/connected_components/add_layer_panel/view.tsx index e2529fff66f3b5..78a9f82bb698f5 100644 --- a/x-pack/plugins/maps/public/connected_components/add_layer_panel/view.tsx +++ b/x-pack/plugins/maps/public/connected_components/add_layer_panel/view.tsx @@ -26,7 +26,7 @@ const ADD_LAYER_STEP_LABEL = i18n.translate('xpack.maps.addLayerPanel.addLayer', }); const SELECT_WIZARD_LABEL = ADD_LAYER_STEP_LABEL; -interface Props { +export interface Props { addPreviewLayers: (layerDescriptors: LayerDescriptor[]) => void; closeFlyout: () => void; hasPreviewLayers: boolean; diff --git a/x-pack/plugins/maps/public/connected_components/layer_panel/join_editor/join_editor.tsx b/x-pack/plugins/maps/public/connected_components/layer_panel/join_editor/join_editor.tsx index 1bcee961db9e13..d47f130d4ede39 100644 --- a/x-pack/plugins/maps/public/connected_components/layer_panel/join_editor/join_editor.tsx +++ b/x-pack/plugins/maps/public/connected_components/layer_panel/join_editor/join_editor.tsx @@ -25,7 +25,7 @@ import { ILayer } from '../../../classes/layers/layer'; import { JoinDescriptor } from '../../../../common/descriptor_types'; import { IField } from '../../../classes/fields/field'; -interface Props { +export interface Props { joins: JoinDescriptor[]; layer: ILayer; layerDisplayName: string; diff --git a/x-pack/plugins/maps/public/connected_components/layer_panel/layer_settings/layer_settings.tsx b/x-pack/plugins/maps/public/connected_components/layer_panel/layer_settings/layer_settings.tsx index 33d684b320208b..c0462f824cd06d 100644 --- a/x-pack/plugins/maps/public/connected_components/layer_panel/layer_settings/layer_settings.tsx +++ b/x-pack/plugins/maps/public/connected_components/layer_panel/layer_settings/layer_settings.tsx @@ -21,7 +21,7 @@ import { AlphaSlider } from '../../../components/alpha_slider'; import { ValidatedDualRange } from '../../../../../../../src/plugins/kibana_react/public'; import { ILayer } from '../../../classes/layers/layer'; -interface Props { +export interface Props { layer: ILayer; updateLabel: (layerId: string, label: string) => void; updateMinZoom: (layerId: string, minZoom: number) => void; diff --git a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx index 93476f6e14da53..36d07e38708181 100644 --- a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx +++ b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx @@ -35,7 +35,7 @@ import 'mapbox-gl/dist/mapbox-gl.css'; const RENDER_COMPLETE_EVENT = 'renderComplete'; -interface Props { +export interface Props { addFilters: ((filters: Filter[]) => Promise) | null; getFilterActions?: () => Promise; getActionContext?: () => ActionExecutionContext; diff --git a/x-pack/plugins/maps/public/connected_components/map_settings_panel/map_settings_panel.tsx b/x-pack/plugins/maps/public/connected_components/map_settings_panel/map_settings_panel.tsx index 726e2c3be78460..9cbbdec5e3d175 100644 --- a/x-pack/plugins/maps/public/connected_components/map_settings_panel/map_settings_panel.tsx +++ b/x-pack/plugins/maps/public/connected_components/map_settings_panel/map_settings_panel.tsx @@ -23,7 +23,7 @@ import { SpatialFiltersPanel } from './spatial_filters_panel'; import { DisplayPanel } from './display_panel'; import { MapCenter } from '../../../common/descriptor_types'; -interface Props { +export interface Props { cancelChanges: () => void; center: MapCenter; hasMapSettingsChanges: boolean; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 820453f166a463..21a8abcbaa4e91 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -49,7 +49,7 @@ import mbWorkerUrl from '!!file-loader!mapbox-gl/dist/mapbox-gl-csp-worker'; mapboxgl.workerUrl = mbWorkerUrl; mapboxgl.setRTLTextPlugin(mbRtlPlugin); -interface Props { +export interface Props { isMapReady: boolean; settings: MapSettings; layerList: ILayer[]; diff --git a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/fit_to_data/fit_to_data.tsx b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/fit_to_data/fit_to_data.tsx index 3f56d8d50b0f07..edf626612cb698 100644 --- a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/fit_to_data/fit_to_data.tsx +++ b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/fit_to_data/fit_to_data.tsx @@ -10,7 +10,7 @@ import { EuiButtonIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ILayer } from '../../../classes/layers/layer'; -interface Props { +export interface Props { layerList: ILayer[]; fitToBounds: () => void; } diff --git a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.tsx b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.tsx index ef320c73bce2fe..a0f3aa40e75dd6 100644 --- a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.tsx +++ b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.tsx @@ -50,7 +50,7 @@ const DRAW_DISTANCE_LABEL_SHORT = i18n.translate( } ); -interface Props { +export interface Props { cancelDraw: () => void; geoFields: GeoFieldWithIndex[]; initiateDraw: (drawState: DrawState) => void; diff --git a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx index 4d669dfbe235e5..fd0a0d55d2c1bc 100644 --- a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx +++ b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; import { ILayer } from '../../../../../../classes/layers/layer'; import { TOCEntryButton } from '../toc_entry_button'; -interface Props { +export interface Props { cloneLayer: (layerId: string) => void; displayName: string; editLayer: () => void; diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index 817fbf36561039..c0a378f38fc138 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -52,7 +52,7 @@ import { unsavedChangesWarning, } from '../saved_map'; -interface Props { +export interface Props { savedMap: SavedMap; // saveCounter used to trigger MapApp render after SaveMap.save saveCounter: number; @@ -83,7 +83,7 @@ interface Props { setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; } -interface State { +export interface State { initialized: boolean; indexPatterns: IndexPattern[]; savedQuery?: SavedQuery; diff --git a/x-pack/plugins/maps/public/url_generator.ts b/x-pack/plugins/maps/public/url_generator.ts index be6a7f5fe6fa78..7f4215f4b12758 100644 --- a/x-pack/plugins/maps/public/url_generator.ts +++ b/x-pack/plugins/maps/public/url_generator.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import rison from 'rison-node'; import { TimeRange, diff --git a/x-pack/plugins/maps/tsconfig.json b/x-pack/plugins/maps/tsconfig.json new file mode 100644 index 00000000000000..b70459c690c072 --- /dev/null +++ b/x-pack/plugins/maps/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*", + "config.ts", + "../../../typings/**/*", + ], + "references": [ + { "path": "../../../src/core/tsconfig.json" }, + { "path": "../../../src/plugins/maps_legacy/tsconfig.json" }, + { "path": "../features/tsconfig.json" }, + { "path": "../licensing/tsconfig.json" }, + { "path": "../maps_file_upload/tsconfig.json" }, + { "path": "../saved_objects_tagging/tsconfig.json" }, + ] +} diff --git a/x-pack/plugins/maps_file_upload/tsconfig.json b/x-pack/plugins/maps_file_upload/tsconfig.json new file mode 100644 index 00000000000000..f068d62b71739d --- /dev/null +++ b/x-pack/plugins/maps_file_upload/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*", "server/**/*", "mappings.ts"], + "references": [ + { "path": "../../../src/plugins/data/tsconfig.json" }, + { "path": "../../../src/plugins/usage_collection/tsconfig.json" } + ] +} diff --git a/x-pack/plugins/maps_legacy_licensing/tsconfig.json b/x-pack/plugins/maps_legacy_licensing/tsconfig.json new file mode 100644 index 00000000000000..90e8265515a160 --- /dev/null +++ b/x-pack/plugins/maps_legacy_licensing/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["public/**/*"], + "references": [ + { "path": "../licensing/tsconfig.json" }, + ] +} diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index a6eb098b5d678f..4975dcfe885ab4 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -19,6 +19,9 @@ "plugins/event_log/**/*", "plugins/licensing/**/*", "plugins/lens/**/*", + "plugins/maps/**/*", + "plugins/maps_file_upload/**/*", + "plugins/maps_legacy_licensing/**/*", "plugins/searchprofiler/**/*", "plugins/security_solution/cypress/**/*", "plugins/task_manager/**/*", @@ -86,6 +89,9 @@ { "path": "./plugins/event_log/tsconfig.json" }, { "path": "./plugins/licensing/tsconfig.json" }, { "path": "./plugins/lens/tsconfig.json" }, + { "path": "./plugins/maps/tsconfig.json" }, + { "path": "./plugins/maps_file_upload/tsconfig.json" }, + { "path": "./plugins/maps_legacy_licensing/tsconfig.json" }, { "path": "./plugins/searchprofiler/tsconfig.json" }, { "path": "./plugins/task_manager/tsconfig.json" }, { "path": "./plugins/telemetry_collection_xpack/tsconfig.json" }, diff --git a/x-pack/tsconfig.refs.json b/x-pack/tsconfig.refs.json index 6a9e54e2e7adf3..fcbc4d40530e10 100644 --- a/x-pack/tsconfig.refs.json +++ b/x-pack/tsconfig.refs.json @@ -15,6 +15,9 @@ { "path": "./plugins/features/tsconfig.json" }, { "path": "./plugins/graph/tsconfig.json" }, { "path": "./plugins/embeddable_enhanced/tsconfig.json" }, + { "path": "./plugins/maps/tsconfig.json" }, + { "path": "./plugins/maps_file_upload/tsconfig.json" }, + { "path": "./plugins/maps_legacy_licensing/tsconfig.json" }, { "path": "./plugins/searchprofiler/tsconfig.json" }, { "path": "./plugins/task_manager/tsconfig.json" }, { "path": "./plugins/telemetry_collection_xpack/tsconfig.json" }, From 8f3e1cf7fc2c7d10bed9e872ef6c2ed00773375f Mon Sep 17 00:00:00 2001 From: Lee Drengenberg Date: Wed, 27 Jan 2021 14:55:00 -0600 Subject: [PATCH 48/58] unskip getting_started/shakespeare test elasticsearch 64016 (#89346) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- test/functional/apps/getting_started/_shakespeare.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/functional/apps/getting_started/_shakespeare.ts b/test/functional/apps/getting_started/_shakespeare.ts index 95abbf9fa8a78d..5a891af0de93db 100644 --- a/test/functional/apps/getting_started/_shakespeare.ts +++ b/test/functional/apps/getting_started/_shakespeare.ts @@ -30,8 +30,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // https://www.elastic.co/guide/en/kibana/current/tutorial-load-dataset.html - // Failing: See https://github.com/elastic/kibana/issues/82206 - describe.skip('Shakespeare', function describeIndexTests() { + describe('Shakespeare', function describeIndexTests() { // index starts on the first "count" metric at 1 // Each new metric or aggregation added to a visualization gets the next index. // So to modify a metric or aggregation tests need to keep track of the From 5ce916b3088bbf1c55f837ece25fd901177b91e0 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Wed, 27 Jan 2021 16:26:45 -0500 Subject: [PATCH 49/58] [kbn-es] Always use bundled JDK when starting Elasticsearch (#89437) --- packages/kbn-es/src/cli_commands/snapshot.js | 2 -- packages/kbn-es/src/cluster.js | 2 +- packages/kbn-es/src/install/archive.js | 16 +++------------- packages/kbn-es/src/install/snapshot.js | 2 -- 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/packages/kbn-es/src/cli_commands/snapshot.js b/packages/kbn-es/src/cli_commands/snapshot.js index d66c352a356aa2..711992a5895edf 100644 --- a/packages/kbn-es/src/cli_commands/snapshot.js +++ b/packages/kbn-es/src/cli_commands/snapshot.js @@ -62,8 +62,6 @@ exports.run = async (defaults = {}) => { await cluster.extractDataDirectory(installPath, options.dataArchive); } - options.bundledJDK = true; - await cluster.run(installPath, options); } }; diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index 60f8a327594d64..f554dd8a1b8e59 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -279,7 +279,7 @@ exports.Cluster = class Cluster { env: { ...(installPath ? { ES_TMPDIR: path.resolve(installPath, 'ES_TMPDIR') } : {}), ...process.env, - ...(options.bundledJDK ? { JAVA_HOME: '' } : {}), + JAVA_HOME: '', // By default, we want to always unset JAVA_HOME so that the bundled JDK will be used ...(options.esEnvVars || {}), }, stdio: ['ignore', 'pipe', 'pipe'], diff --git a/packages/kbn-es/src/install/archive.js b/packages/kbn-es/src/install/archive.js index 1e9e19f4533afa..80ff4eb6f83b03 100644 --- a/packages/kbn-es/src/install/archive.js +++ b/packages/kbn-es/src/install/archive.js @@ -34,7 +34,6 @@ exports.installArchive = async function installArchive(archive, options = {}) { basePath = BASE_PATH, installPath = path.resolve(basePath, path.basename(archive, '.tar.gz')), log = defaultLog, - bundledJDK = false, esArgs = [], } = options; @@ -64,7 +63,7 @@ exports.installArchive = async function installArchive(archive, options = {}) { await appendToConfig(installPath, 'xpack.security.enabled', 'true'); await appendToConfig(installPath, 'xpack.license.self_generated.type', license); - await configureKeystore(installPath, log, bundledJDK, [ + await configureKeystore(installPath, log, [ ['bootstrap.password', password], ...parseSettings(esArgs, { filter: SettingsFilter.SecureOnly }), ]); @@ -89,20 +88,11 @@ async function appendToConfig(installPath, key, value) { * * @param {String} installPath * @param {ToolingLog} log - * @param {boolean} bundledJDK * @param {Array<[string, string]>} secureSettings List of custom Elasticsearch secure settings to * add into the keystore. */ -async function configureKeystore( - installPath, - log = defaultLog, - bundledJDK = false, - secureSettings -) { - const env = {}; - if (bundledJDK) { - env.JAVA_HOME = ''; - } +async function configureKeystore(installPath, log = defaultLog, secureSettings) { + const env = { JAVA_HOME: '' }; await execa(ES_KEYSTORE_BIN, ['create'], { cwd: installPath, env }); for (const [secureSettingName, secureSettingValue] of secureSettings) { diff --git a/packages/kbn-es/src/install/snapshot.js b/packages/kbn-es/src/install/snapshot.js index 55c0e41ea96409..b9562f20d81b71 100644 --- a/packages/kbn-es/src/install/snapshot.js +++ b/packages/kbn-es/src/install/snapshot.js @@ -61,7 +61,6 @@ exports.installSnapshot = async function installSnapshot({ basePath = BASE_PATH, installPath = path.resolve(basePath, version), log = defaultLog, - bundledJDK = true, esArgs, }) { const { downloadPath } = await exports.downloadSnapshot({ @@ -78,7 +77,6 @@ exports.installSnapshot = async function installSnapshot({ basePath, installPath, log, - bundledJDK, esArgs, }); }; From 445cb2ef87efec7ce0d06baebbe2eadc0d207af4 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Wed, 27 Jan 2021 18:44:17 -0500 Subject: [PATCH 50/58] [Lens] Fix crash in transition from unique count to last value (#88916) * [Lens] Fix transition from unique count to last value * Fix test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../operations/layer_helpers.test.ts | 8 +++---- .../operations/layer_helpers.ts | 7 +----- .../test/functional/apps/lens/smokescreen.ts | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts index 94cf13a5c50a4e..63f8bfb97d8f87 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts @@ -2181,7 +2181,7 @@ describe('state_helpers', () => { expect(errors).toHaveLength(1); }); - it('should consider incompleteColumns before layer columns', () => { + it('should ignore incompleteColumns when checking for errors', () => { const savedRef = jest.fn().mockReturnValue(['error 1']); const incompleteRef = jest.fn(); operationDefinitionMap.testReference.getErrorMessage = savedRef; @@ -2206,9 +2206,9 @@ describe('state_helpers', () => { }, indexPattern ); - expect(savedRef).not.toHaveBeenCalled(); - expect(incompleteRef).toHaveBeenCalled(); - expect(errors).toBeUndefined(); + expect(savedRef).toHaveBeenCalled(); + expect(incompleteRef).not.toHaveBeenCalled(); + expect(errors).toHaveLength(1); delete operationDefinitionMap.testIncompleteReference; }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts index 10618cc7545562..7c0036de621243 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts @@ -870,12 +870,7 @@ export function getErrorMessages( ): string[] | undefined { const errors: string[] = Object.entries(layer.columns) .flatMap(([columnId, column]) => { - // If we're transitioning to another operation, check for "new" incompleteColumns rather - // than "old" saved operation on the layer - const columnFinalRef = - layer.incompleteColumns?.[columnId]?.operationType || column.operationType; - const def = operationDefinitionMap[columnFinalRef]; - + const def = operationDefinitionMap[column.operationType]; if (def.getErrorMessage) { return def.getErrorMessage(layer, columnId, indexPattern); } diff --git a/x-pack/test/functional/apps/lens/smokescreen.ts b/x-pack/test/functional/apps/lens/smokescreen.ts index f2d91c2ae577f9..88682d475146f5 100644 --- a/x-pack/test/functional/apps/lens/smokescreen.ts +++ b/x-pack/test/functional/apps/lens/smokescreen.ts @@ -514,6 +514,28 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); }); + it('should transition from unique count to last value', async () => { + await PageObjects.visualize.navigateToNewVisualization(); + await PageObjects.visualize.clickVisType('lens'); + await PageObjects.lens.goToTimeRange(); + + await PageObjects.lens.configureDimension({ + dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension', + operation: 'cardinality', + field: 'ip', + }); + await PageObjects.lens.configureDimension({ + dimension: 'lnsXY_yDimensionPanel > lns-dimensionTrigger', + operation: 'last_value', + field: 'bytes', + isPreviousIncompatible: true, + }); + + expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_yDimensionPanel')).to.eql( + 'Last value of bytes' + ); + }); + it('should allow to change index pattern', async () => { await PageObjects.lens.switchFirstLayerIndexPattern('log*'); expect(await PageObjects.lens.getFirstLayerIndexPattern()).to.equal('log*'); From 511c9913b38bcc887513aa408765c925f95d43ab Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Wed, 27 Jan 2021 15:48:36 -0800 Subject: [PATCH 51/58] Adds migration settings to Docker (#89501) Signed-off-by: Tyler Smalley --- .../resources/bin/kibana-docker | 105 +++++++++--------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker index 30e3b60dcee836..1598f00354bf89 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker @@ -15,11 +15,17 @@ # --elasticsearch.logQueries=true kibana_vars=( + apm_oss.apmAgentConfigurationIndex + apm_oss.errorIndices + apm_oss.indexPattern + apm_oss.metricsIndices + apm_oss.onboardingIndices + apm_oss.sourcemapIndices + apm_oss.spanIndices + apm_oss.transactionIndices console.enabled console.proxyConfig console.proxyFilter - ops.cGroupOverrides.cpuPath - ops.cGroupOverrides.cpuAcctPath cpu.cgroup.path.override cpuacct.cgroup.path.override csp.rules @@ -41,10 +47,10 @@ kibana_vars=( elasticsearch.ssl.certificateAuthorities elasticsearch.ssl.key elasticsearch.ssl.keyPassphrase - elasticsearch.ssl.keystore.path elasticsearch.ssl.keystore.password - elasticsearch.ssl.truststore.path + elasticsearch.ssl.keystore.path elasticsearch.ssl.truststore.password + elasticsearch.ssl.truststore.path elasticsearch.ssl.verificationMode elasticsearch.username enterpriseSearch.accessCheckTimeout @@ -76,34 +82,42 @@ kibana_vars=( map.tilemap.options.minZoom map.tilemap.options.subdomains map.tilemap.url + migrations.batchSize + migrations.enableV2 + migrations.pollInterval + migrations.scrollDuration + migrations.skip monitoring.cluster_alerts.email_notifications.email_address monitoring.enabled monitoring.kibana.collection.enabled monitoring.kibana.collection.interval monitoring.ui.container.elasticsearch.enabled monitoring.ui.container.logstash.enabled - monitoring.ui.elasticsearch.password - monitoring.ui.elasticsearch.pingTimeout monitoring.ui.elasticsearch.hosts - monitoring.ui.elasticsearch.username monitoring.ui.elasticsearch.logFetchCount + monitoring.ui.elasticsearch.password + monitoring.ui.elasticsearch.pingTimeout monitoring.ui.elasticsearch.ssl.certificateAuthorities monitoring.ui.elasticsearch.ssl.verificationMode + monitoring.ui.elasticsearch.username monitoring.ui.enabled monitoring.ui.max_bucket_size monitoring.ui.min_interval_seconds newsfeed.enabled + ops.cGroupOverrides.cpuAcctPath + ops.cGroupOverrides.cpuPath ops.interval path.data pid.file regionmap security.showInsecureClusterWarning server.basePath - server.customResponseHeaders server.compression.enabled server.compression.referrerWhitelist server.cors server.cors.origin + server.customResponseHeaders + server.customResponseHeaders server.defaultRoute server.host server.keepAliveTimeout @@ -117,20 +131,24 @@ kibana_vars=( server.ssl.certificateAuthorities server.ssl.cipherSuites server.ssl.clientAuthentication - server.customResponseHeaders server.ssl.enabled server.ssl.key server.ssl.keyPassphrase - server.ssl.keystore.path server.ssl.keystore.password - server.ssl.truststore.path - server.ssl.truststore.password + server.ssl.keystore.path server.ssl.redirectHttpFromPort server.ssl.supportedProtocols + server.ssl.truststore.password + server.ssl.truststore.path server.xsrf.disableProtection server.xsrf.whitelist status.allowAnonymous status.v6ApiFormat + telemetry.allowChangingOptInStatus + telemetry.enabled + telemetry.optIn + telemetry.optInStatusUrl + telemetry.sendUsageFrom tilemap.options.attribution tilemap.options.maxZoom tilemap.options.minZoom @@ -142,9 +160,9 @@ kibana_vars=( xpack.actions.enabled xpack.actions.enabledActionTypes xpack.actions.preconfigured - xpack.actions.proxyUrl xpack.actions.proxyHeaders xpack.actions.proxyRejectUnauthorizedCertificates + xpack.actions.proxyUrl xpack.actions.rejectUnauthorized xpack.alerts.healthCheck.interval xpack.alerts.invalidateApiKeysTask.interval @@ -154,37 +172,29 @@ kibana_vars=( xpack.apm.ui.enabled xpack.apm.ui.maxTraceItems xpack.apm.ui.transactionGroupBucketSize - apm_oss.apmAgentConfigurationIndex - apm_oss.indexPattern - apm_oss.errorIndices - apm_oss.onboardingIndices - apm_oss.spanIndices - apm_oss.sourcemapIndices - apm_oss.transactionIndices - apm_oss.metricsIndices xpack.canvas.enabled - xpack.code.ui.enabled xpack.code.disk.thresholdEnabled xpack.code.disk.watermarkLow - xpack.code.maxWorkspace xpack.code.indexRepoFrequencyMs - xpack.code.updateRepoFrequencyMs xpack.code.lsp.verbose - xpack.code.verbose + xpack.code.maxWorkspace xpack.code.security.enableGitCertCheck xpack.code.security.gitHostWhitelist xpack.code.security.gitProtocolWhitelist + xpack.code.ui.enabled + xpack.code.updateRepoFrequencyMs + xpack.code.verbose xpack.encryptedSavedObjects.encryptionKey xpack.encryptedSavedObjects.keyRotation.decryptionOnlyKeys xpack.event_log.enabled - xpack.event_log.logEntries xpack.event_log.indexEntries + xpack.event_log.logEntries xpack.fleet.agents.elasticsearch.host xpack.fleet.agents.kibana.host xpack.fleet.agents.tlsCheckDisabled xpack.fleet.registryUrl - xpack.graph.enabled xpack.graph.canEditDrillDownUrls + xpack.graph.enabled xpack.graph.savePolicy xpack.grokdebugger.enabled xpack.infra.enabled @@ -208,28 +218,28 @@ kibana_vars=( xpack.reporting.capture.browser.chromium.disableSandbox xpack.reporting.capture.browser.chromium.inspect xpack.reporting.capture.browser.chromium.maxScreenshotDimension + xpack.reporting.capture.browser.chromium.proxy.bypass xpack.reporting.capture.browser.chromium.proxy.enabled xpack.reporting.capture.browser.chromium.proxy.server - xpack.reporting.capture.browser.chromium.proxy.bypass xpack.reporting.capture.browser.type xpack.reporting.capture.concurrency xpack.reporting.capture.loadDelay + xpack.reporting.capture.maxAttempts xpack.reporting.capture.settleTime xpack.reporting.capture.timeout + xpack.reporting.capture.timeouts.openUrl + xpack.reporting.capture.timeouts.renderComplete + xpack.reporting.capture.timeouts.waitForElements xpack.reporting.capture.viewport.height xpack.reporting.capture.viewport.width xpack.reporting.capture.zoom xpack.reporting.csv.checkForFormulas - xpack.reporting.csv.escapeFormulaValues xpack.reporting.csv.enablePanelActionDownload - xpack.reporting.csv.useByteOrderMarkEncoding + xpack.reporting.csv.escapeFormulaValues xpack.reporting.csv.maxSizeBytes xpack.reporting.csv.scroll.duration xpack.reporting.csv.scroll.size - xpack.reporting.capture.maxAttempts - xpack.reporting.capture.timeouts.openUrl - xpack.reporting.capture.timeouts.waitForElements - xpack.reporting.capture.timeouts.renderComplete + xpack.reporting.csv.useByteOrderMarkEncoding xpack.reporting.enabled xpack.reporting.encryptionKey xpack.reporting.index @@ -248,43 +258,38 @@ kibana_vars=( xpack.reporting.queue.timeout xpack.reporting.roles.allow xpack.rollup.enabled - xpack.security.audit.enabled xpack.searchprofiler.enabled - xpack.security.authc.providers + xpack.security.audit.enabled xpack.security.authc.oidc.realm - xpack.security.authc.saml.realm + xpack.security.authc.providers xpack.security.authc.saml.maxRedirectURLSize + xpack.security.authc.saml.realm xpack.security.authc.selector.enabled xpack.security.cookieName xpack.security.enabled xpack.security.encryptionKey + xpack.security.loginAssistanceMessage + xpack.security.loginHelp xpack.security.sameSiteCookies xpack.security.secureCookies - xpack.security.sessionTimeout + xpack.security.session.cleanupInterval xpack.security.session.idleTimeout xpack.security.session.lifespan - xpack.security.session.cleanupInterval - xpack.security.loginAssistanceMessage - xpack.security.loginHelp + xpack.security.sessionTimeout xpack.spaces.enabled xpack.spaces.maxSpaces xpack.task_manager.enabled + xpack.task_manager.index xpack.task_manager.max_attempts - xpack.task_manager.poll_interval xpack.task_manager.max_poll_inactivity_cycles - xpack.task_manager.request_capacity - xpack.task_manager.index xpack.task_manager.max_workers - xpack.task_manager.monitored_stats_required_freshness xpack.task_manager.monitored_aggregated_stats_refresh_rate + xpack.task_manager.monitored_stats_required_freshness xpack.task_manager.monitored_stats_running_average_window xpack.task_manager.monitored_task_execution_thresholds + xpack.task_manager.poll_interval + xpack.task_manager.request_capacity xpack.task_manager.version_conflict_threshold - telemetry.allowChangingOptInStatus - telemetry.enabled - telemetry.optIn - telemetry.optInStatusUrl - telemetry.sendUsageFrom ) longopts='' From f2aa5bcd9511b73a119e4a976bc13093a1c018fd Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 27 Jan 2021 16:54:03 -0700 Subject: [PATCH 52/58] [Maps] remove maps_oss TS project (#89502) --- src/plugins/maps_oss/tsconfig.json | 14 -------------- tsconfig.json | 2 -- tsconfig.refs.json | 1 - 3 files changed, 17 deletions(-) delete mode 100644 src/plugins/maps_oss/tsconfig.json diff --git a/src/plugins/maps_oss/tsconfig.json b/src/plugins/maps_oss/tsconfig.json deleted file mode 100644 index 03c30c3c49fd36..00000000000000 --- a/src/plugins/maps_oss/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "composite": true, - "outDir": "./target/types", - "emitDeclarationOnly": true, - "declaration": true, - "declarationMap": true - }, - "include": ["common/**/*", "public/**/*", "server/**/*", "config.ts"], - "references": [ - { "path": "../visualizations/tsconfig.json" }, - ] -} diff --git a/tsconfig.json b/tsconfig.json index 334a3febfddda4..bdd4ba296d1c9f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,7 +28,6 @@ "src/plugins/kibana_utils/**/*", "src/plugins/management/**/*", "src/plugins/maps_legacy/**/*", - "src/plugins/maps_oss/**/*", "src/plugins/navigation/**/*", "src/plugins/newsfeed/**/*", "src/plugins/region_map/**/*", @@ -86,7 +85,6 @@ { "path": "./src/plugins/kibana_utils/tsconfig.json" }, { "path": "./src/plugins/management/tsconfig.json" }, { "path": "./src/plugins/maps_legacy/tsconfig.json" }, - { "path": "./src/plugins/maps_oss/tsconfig.json" }, { "path": "./src/plugins/navigation/tsconfig.json" }, { "path": "./src/plugins/newsfeed/tsconfig.json" }, { "path": "./src/plugins/region_map/tsconfig.json" }, diff --git a/tsconfig.refs.json b/tsconfig.refs.json index a8eecd278160c9..211a50ec1a5391 100644 --- a/tsconfig.refs.json +++ b/tsconfig.refs.json @@ -24,7 +24,6 @@ { "path": "./src/plugins/kibana_utils/tsconfig.json" }, { "path": "./src/plugins/management/tsconfig.json" }, { "path": "./src/plugins/maps_legacy/tsconfig.json" }, - { "path": "./src/plugins/maps_oss/tsconfig.json" }, { "path": "./src/plugins/navigation/tsconfig.json" }, { "path": "./src/plugins/newsfeed/tsconfig.json" }, { "path": "./src/plugins/region_map/tsconfig.json" }, From b2d441214608a71752b3e9ffdb29ccc5c10310bc Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Wed, 27 Jan 2021 16:15:28 -0800 Subject: [PATCH 53/58] [CI] Decrease number of Jest workers (#89504) Signed-off-by: Tyler Smalley --- .ci/teamcity/oss/jest.sh | 2 +- .ci/teamcity/tests/jest.sh | 2 +- test/scripts/test/jest_unit.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci/teamcity/oss/jest.sh b/.ci/teamcity/oss/jest.sh index b323a88ef06bc8..6d9396574c077f 100755 --- a/.ci/teamcity/oss/jest.sh +++ b/.ci/teamcity/oss/jest.sh @@ -10,4 +10,4 @@ source "$(dirname "${0}")/../util.sh" export JOB=kibana-oss-jest checks-reporter-with-killswitch "Jest Unit Tests" \ - node scripts/jest --ci --verbose + node scripts/jest --ci --maxWorkers=5 --verbose diff --git a/.ci/teamcity/tests/jest.sh b/.ci/teamcity/tests/jest.sh index c8b9b075e0e61d..3d60915c1b1b53 100755 --- a/.ci/teamcity/tests/jest.sh +++ b/.ci/teamcity/tests/jest.sh @@ -7,4 +7,4 @@ source "$(dirname "${0}")/../util.sh" export JOB=kibana-jest checks-reporter-with-killswitch "Jest Unit Tests" \ - node scripts/jest --ci --verbose --coverage + node scripts/jest --ci --maxWorkers=5 --verbose diff --git a/test/scripts/test/jest_unit.sh b/test/scripts/test/jest_unit.sh index 14d7268c6f36de..06c159c0a4ace4 100755 --- a/test/scripts/test/jest_unit.sh +++ b/test/scripts/test/jest_unit.sh @@ -3,4 +3,4 @@ source src/dev/ci_setup/setup_env.sh checks-reporter-with-killswitch "Jest Unit Tests" \ - node scripts/jest --ci --verbose --maxWorkers=10 --coverage + node scripts/jest --ci --verbose --maxWorkers=6 --coverage From fd2e9d08212be0c4b43a99c62dd445405ff8092c Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Wed, 27 Jan 2021 16:21:30 -0800 Subject: [PATCH 54/58] Convert default_watch.json to a JS object in order to avoid TS complaints (#89488) * Remove unused defaultWatchJson static member from public JsonWatch model. --- .../application/models/watch/default_watch.js | 40 +++++++++++++++++++ .../models/watch/default_watch.json | 33 --------------- .../application/models/watch/index.d.ts | 1 + .../public/application/models/watch/index.js | 1 + .../application/models/watch/json_watch.js | 12 +++--- .../watch_create_json.test.ts | 15 +++---- .../watch_edit.test.ts | 11 ++--- 7 files changed, 62 insertions(+), 51 deletions(-) create mode 100644 x-pack/plugins/watcher/public/application/models/watch/default_watch.js delete mode 100644 x-pack/plugins/watcher/public/application/models/watch/default_watch.json diff --git a/x-pack/plugins/watcher/public/application/models/watch/default_watch.js b/x-pack/plugins/watcher/public/application/models/watch/default_watch.js new file mode 100644 index 00000000000000..51b28f8bd03324 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/models/watch/default_watch.js @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const defaultWatch = { + trigger: { + schedule: { + interval: '30m', + }, + }, + input: { + search: { + request: { + body: { + size: 0, + query: { + match_all: {}, + }, + }, + indices: ['*'], + }, + }, + }, + condition: { + compare: { + 'ctx.payload.hits.total': { + gte: 10, + }, + }, + }, + actions: { + 'my-logging-action': { + logging: { + text: 'There are {{ctx.payload.hits.total}} documents in your index. Threshold is 10.', + }, + }, + }, +}; diff --git a/x-pack/plugins/watcher/public/application/models/watch/default_watch.json b/x-pack/plugins/watcher/public/application/models/watch/default_watch.json deleted file mode 100644 index 22c78660a0bb0e..00000000000000 --- a/x-pack/plugins/watcher/public/application/models/watch/default_watch.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "trigger": { - "schedule": { - "interval": "30m" - } - }, - "input": { - "search": { - "request": { - "body": { - "size": 0, - "query" : { - "match_all": {} - } - }, - "indices": [ "*" ] - } - } - }, - "condition": { - "compare": { - "ctx.payload.hits.total": { - "gte": 10 - } - }}, - "actions": { - "my-logging-action": { - "logging": { - "text": "There are {{ctx.payload.hits.total}} documents in your index. Threshold is 10." - } - } - } -} diff --git a/x-pack/plugins/watcher/public/application/models/watch/index.d.ts b/x-pack/plugins/watcher/public/application/models/watch/index.d.ts index 73ee2279d3912f..b9158bdd9ed704 100644 --- a/x-pack/plugins/watcher/public/application/models/watch/index.d.ts +++ b/x-pack/plugins/watcher/public/application/models/watch/index.d.ts @@ -5,3 +5,4 @@ */ export const Watch: any; +export const defaultWatch: any; diff --git a/x-pack/plugins/watcher/public/application/models/watch/index.js b/x-pack/plugins/watcher/public/application/models/watch/index.js index 9a74f6e548409d..0741e5c5400df9 100644 --- a/x-pack/plugins/watcher/public/application/models/watch/index.js +++ b/x-pack/plugins/watcher/public/application/models/watch/index.js @@ -5,3 +5,4 @@ */ export { Watch } from './watch'; +export { defaultWatch } from './default_watch'; diff --git a/x-pack/plugins/watcher/public/application/models/watch/json_watch.js b/x-pack/plugins/watcher/public/application/models/watch/json_watch.js index 0e67c8b18ca5e6..24378d42b7451d 100644 --- a/x-pack/plugins/watcher/public/application/models/watch/json_watch.js +++ b/x-pack/plugins/watcher/public/application/models/watch/json_watch.js @@ -6,11 +6,12 @@ import uuid from 'uuid'; import { get } from 'lodash'; -import { BaseWatch } from './base_watch'; -import { ACTION_TYPES, WATCH_TYPES } from '../../../../common/constants'; -import defaultWatchJson from './default_watch.json'; import { i18n } from '@kbn/i18n'; +import { ACTION_TYPES, WATCH_TYPES } from '../../../../common/constants'; +import { BaseWatch } from './base_watch'; +import { defaultWatch } from './default_watch'; + /** * {@code JsonWatch} allows a user to create a Watch by writing the raw JSON. */ @@ -20,11 +21,11 @@ export class JsonWatch extends BaseWatch { props.id = typeof props.id === 'undefined' ? uuid.v4() : props.id; super(props); const existingWatch = get(props, 'watch'); - this.watch = existingWatch ? existingWatch : defaultWatchJson; + this.watch = existingWatch ? existingWatch : defaultWatch; this.watchString = get( props, 'watchString', - JSON.stringify(existingWatch ? existingWatch : defaultWatchJson, null, 2) + JSON.stringify(existingWatch ? existingWatch : defaultWatch, null, 2) ); this.id = props.id; } @@ -113,7 +114,6 @@ export class JsonWatch extends BaseWatch { return new JsonWatch(upstreamWatch); } - static defaultWatchJson = defaultWatchJson; static typeName = i18n.translate('xpack.watcher.models.jsonWatch.typeName', { defaultMessage: 'Advanced Watch', }); diff --git a/x-pack/plugins/watcher/tests_client_integration/watch_create_json.test.ts b/x-pack/plugins/watcher/tests_client_integration/watch_create_json.test.ts index b3fbb8235f251d..9bd8f8bbd7d57d 100644 --- a/x-pack/plugins/watcher/tests_client_integration/watch_create_json.test.ts +++ b/x-pack/plugins/watcher/tests_client_integration/watch_create_json.test.ts @@ -5,11 +5,12 @@ */ import { act } from 'react-dom/test-utils'; + +import { getExecuteDetails } from '../__fixtures__'; +import { defaultWatch } from '../public/application/models/watch'; import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers'; import { WatchCreateJsonTestBed } from './helpers/watch_create_json.helpers'; import { WATCH } from './helpers/jest_constants'; -import defaultWatchJson from '../public/application/models/watch/default_watch.json'; -import { getExecuteDetails } from '../__fixtures__'; const { setup } = pageHelpers.watchCreateJson; @@ -117,7 +118,7 @@ describe(' create route', () => { }, }, ], - watch: defaultWatchJson, + watch: defaultWatch, }) ); }); @@ -172,7 +173,7 @@ describe(' create route', () => { const latestRequest = server.requests[server.requests.length - 1]; - const actionModes = Object.keys(defaultWatchJson.actions).reduce( + const actionModes = Object.keys(defaultWatch.actions).reduce( (actionAccum: any, action) => { actionAccum[action] = 'simulate'; return actionAccum; @@ -186,7 +187,7 @@ describe(' create route', () => { isNew: true, isActive: true, actions: [], - watch: defaultWatchJson, + watch: defaultWatch, }; expect(latestRequest.requestBody).toEqual( @@ -234,7 +235,7 @@ describe(' create route', () => { const latestRequest = server.requests[server.requests.length - 1]; - const actionModes = Object.keys(defaultWatchJson.actions).reduce( + const actionModes = Object.keys(defaultWatch.actions).reduce( (actionAccum: any, action) => { actionAccum[action] = ACTION_MODE; return actionAccum; @@ -248,7 +249,7 @@ describe(' create route', () => { isNew: true, isActive: true, actions: [], - watch: defaultWatchJson, + watch: defaultWatch, }; const triggeredTime = `now+${TRIGGERED_TIME}s`; diff --git a/x-pack/plugins/watcher/tests_client_integration/watch_edit.test.ts b/x-pack/plugins/watcher/tests_client_integration/watch_edit.test.ts index eefe9d03c05ef7..c24d939c9237eb 100644 --- a/x-pack/plugins/watcher/tests_client_integration/watch_edit.test.ts +++ b/x-pack/plugins/watcher/tests_client_integration/watch_edit.test.ts @@ -7,12 +7,13 @@ import { act } from 'react-dom/test-utils'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import axios from 'axios'; +import { getRandomString } from '@kbn/test/jest'; + +import { getWatch } from '../__fixtures__'; +import { defaultWatch } from '../public/application/models/watch'; import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers'; import { WatchEditTestBed } from './helpers/watch_edit.helpers'; import { WATCH } from './helpers/jest_constants'; -import defaultWatchJson from '../public/application/models/watch/default_watch.json'; -import { getWatch } from '../__fixtures__'; -import { getRandomString } from '@kbn/test/jest'; const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); @@ -69,7 +70,7 @@ describe('', () => { expect(exists('jsonWatchForm')).toBe(true); expect(find('nameInput').props().value).toBe(watch.name); expect(find('idInput').props().value).toBe(watch.id); - expect(JSON.parse(codeEditor.props().value as string)).toEqual(defaultWatchJson); + expect(JSON.parse(codeEditor.props().value as string)).toEqual(defaultWatch); // ID should not be editable expect(find('idInput').props().readOnly).toEqual(true); @@ -112,7 +113,7 @@ describe('', () => { }, }, ], - watch: defaultWatchJson, + watch: defaultWatch, }) ); }); From 2572cd291b8e3e703680859bab6c024474608924 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Wed, 27 Jan 2021 18:25:46 -0600 Subject: [PATCH 55/58] [build/docker] Add support for centos ARM builds (#84831) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Tyler Smalley --- src/dev/build/args.test.ts | 68 +++++++++++++++---- src/dev/build/args.ts | 22 ++++-- src/dev/build/build_distributables.ts | 24 ++++--- src/dev/build/cli.ts | 8 ++- .../os_packages/create_os_package_tasks.ts | 54 ++++++++++++--- .../docker_generator/bundle_dockerfiles.ts | 1 - .../os_packages/docker_generator/index.ts | 2 +- .../tasks/os_packages/docker_generator/run.ts | 51 ++++++++------ .../docker_generator/template_context.ts | 2 + .../docker_generator/templates/Dockerfile | 21 ++++-- .../templates/build_docker_sh.template.ts | 6 +- .../templates/dockerfile.template.ts | 1 + 12 files changed, 191 insertions(+), 69 deletions(-) diff --git a/src/dev/build/args.test.ts b/src/dev/build/args.test.ts index 584f0dfe54b74e..745b9d0b910c8b 100644 --- a/src/dev/build/args.test.ts +++ b/src/dev/build/args.test.ts @@ -30,8 +30,9 @@ it('build default and oss dist for current platform, without packages, by defaul "buildOssDist": true, "createArchives": true, "createDebPackage": false, - "createDockerPackage": false, - "createDockerUbiPackage": false, + "createDockerCentOS": false, + "createDockerContexts": false, + "createDockerUBI": false, "createRpmPackage": false, "downloadFreshNode": true, "isRelease": false, @@ -53,8 +54,9 @@ it('builds packages if --all-platforms is passed', () => { "buildOssDist": true, "createArchives": true, "createDebPackage": true, - "createDockerPackage": true, - "createDockerUbiPackage": true, + "createDockerCentOS": true, + "createDockerContexts": true, + "createDockerUBI": true, "createRpmPackage": true, "downloadFreshNode": true, "isRelease": false, @@ -76,8 +78,9 @@ it('limits packages if --rpm passed with --all-platforms', () => { "buildOssDist": true, "createArchives": true, "createDebPackage": false, - "createDockerPackage": false, - "createDockerUbiPackage": false, + "createDockerCentOS": false, + "createDockerContexts": false, + "createDockerUBI": false, "createRpmPackage": true, "downloadFreshNode": true, "isRelease": false, @@ -99,8 +102,9 @@ it('limits packages if --deb passed with --all-platforms', () => { "buildOssDist": true, "createArchives": true, "createDebPackage": true, - "createDockerPackage": false, - "createDockerUbiPackage": false, + "createDockerCentOS": false, + "createDockerContexts": false, + "createDockerUBI": false, "createRpmPackage": false, "downloadFreshNode": true, "isRelease": false, @@ -115,7 +119,7 @@ it('limits packages if --deb passed with --all-platforms', () => { }); it('limits packages if --docker passed with --all-platforms', () => { - expect(readCliArgs(['node', 'scripts/build', '--all-platforms', '--docker'])) + expect(readCliArgs(['node', 'scripts/build', '--all-platforms', '--docker-images'])) .toMatchInlineSnapshot(` Object { "buildOptions": Object { @@ -123,8 +127,9 @@ it('limits packages if --docker passed with --all-platforms', () => { "buildOssDist": true, "createArchives": true, "createDebPackage": false, - "createDockerPackage": true, - "createDockerUbiPackage": true, + "createDockerCentOS": true, + "createDockerContexts": false, + "createDockerUBI": true, "createRpmPackage": false, "downloadFreshNode": true, "isRelease": false, @@ -139,16 +144,24 @@ it('limits packages if --docker passed with --all-platforms', () => { }); it('limits packages if --docker passed with --skip-docker-ubi and --all-platforms', () => { - expect(readCliArgs(['node', 'scripts/build', '--all-platforms', '--docker', '--skip-docker-ubi'])) - .toMatchInlineSnapshot(` + expect( + readCliArgs([ + 'node', + 'scripts/build', + '--all-platforms', + '--docker-images', + '--skip-docker-ubi', + ]) + ).toMatchInlineSnapshot(` Object { "buildOptions": Object { "buildDefaultDist": true, "buildOssDist": true, "createArchives": true, "createDebPackage": false, - "createDockerPackage": true, - "createDockerUbiPackage": false, + "createDockerCentOS": true, + "createDockerContexts": false, + "createDockerUBI": false, "createRpmPackage": false, "downloadFreshNode": true, "isRelease": false, @@ -161,3 +174,28 @@ it('limits packages if --docker passed with --skip-docker-ubi and --all-platform } `); }); + +it('limits packages if --all-platforms passed with --skip-docker-centos', () => { + expect(readCliArgs(['node', 'scripts/build', '--all-platforms', '--skip-docker-centos'])) + .toMatchInlineSnapshot(` + Object { + "buildOptions": Object { + "buildDefaultDist": true, + "buildOssDist": true, + "createArchives": true, + "createDebPackage": true, + "createDockerCentOS": false, + "createDockerContexts": true, + "createDockerUBI": true, + "createRpmPackage": true, + "downloadFreshNode": true, + "isRelease": false, + "targetAllPlatforms": true, + "versionQualifier": "", + }, + "log": , + "showHelp": false, + "unknownFlags": Array [], + } + `); +}); diff --git a/src/dev/build/args.ts b/src/dev/build/args.ts index 5070e325f40a43..2d26d7db3a5e39 100644 --- a/src/dev/build/args.ts +++ b/src/dev/build/args.ts @@ -21,8 +21,10 @@ export function readCliArgs(argv: string[]) { 'skip-os-packages', 'rpm', 'deb', - 'docker', + 'docker-images', + 'docker-contexts', 'skip-docker-ubi', + 'skip-docker-centos', 'release', 'skip-node-download', 'verbose', @@ -42,7 +44,8 @@ export function readCliArgs(argv: string[]) { debug: true, rpm: null, deb: null, - docker: null, + 'docker-images': null, + 'docker-contexts': null, oss: null, 'version-qualifier': '', }, @@ -69,7 +72,7 @@ export function readCliArgs(argv: string[]) { // In order to build a docker image we always need // to generate all the platforms - if (flags.docker) { + if (flags['docker-images'] || flags['docker-contexts']) { flags['all-platforms'] = true; } @@ -79,7 +82,12 @@ export function readCliArgs(argv: string[]) { } // build all if no flags specified - if (flags.rpm === null && flags.deb === null && flags.docker === null) { + if ( + flags.rpm === null && + flags.deb === null && + flags['docker-images'] === null && + flags['docker-contexts'] === null + ) { return true; } @@ -95,8 +103,10 @@ export function readCliArgs(argv: string[]) { createArchives: !Boolean(flags['skip-archives']), createRpmPackage: isOsPackageDesired('rpm'), createDebPackage: isOsPackageDesired('deb'), - createDockerPackage: isOsPackageDesired('docker'), - createDockerUbiPackage: isOsPackageDesired('docker') && !Boolean(flags['skip-docker-ubi']), + createDockerCentOS: + isOsPackageDesired('docker-images') && !Boolean(flags['skip-docker-centos']), + createDockerUBI: isOsPackageDesired('docker-images') && !Boolean(flags['skip-docker-ubi']), + createDockerContexts: isOsPackageDesired('docker-contexts'), targetAllPlatforms: Boolean(flags['all-platforms']), }; diff --git a/src/dev/build/build_distributables.ts b/src/dev/build/build_distributables.ts index 66206738297115..df4ba45517cc11 100644 --- a/src/dev/build/build_distributables.ts +++ b/src/dev/build/build_distributables.ts @@ -19,8 +19,9 @@ export interface BuildOptions { createArchives: boolean; createRpmPackage: boolean; createDebPackage: boolean; - createDockerPackage: boolean; - createDockerUbiPackage: boolean; + createDockerUBI: boolean; + createDockerCentOS: boolean; + createDockerContexts: boolean; versionQualifier: string | undefined; targetAllPlatforms: boolean; } @@ -95,12 +96,19 @@ export async function buildDistributables(log: ToolingLog, options: BuildOptions // control w/ --rpm or --skip-os-packages await run(Tasks.CreateRpmPackage); } - if (options.createDockerPackage) { - // control w/ --docker or --skip-docker-ubi or --skip-os-packages - await run(Tasks.CreateDockerPackage); - if (options.createDockerUbiPackage) { - await run(Tasks.CreateDockerUbiPackage); - } + if (options.createDockerUBI) { + // control w/ --docker-images or --skip-docker-ubi or --skip-os-packages + await run(Tasks.CreateDockerUBI); + } + + if (options.createDockerCentOS) { + // control w/ --docker-images or --skip-docker-centos or --skip-os-packages + await run(Tasks.CreateDockerCentOS); + } + + if (options.createDockerContexts) { + // control w/ --docker-contexts or --skip-os-packages + await run(Tasks.CreateDockerContexts); } /** diff --git a/src/dev/build/cli.ts b/src/dev/build/cli.ts index ca9debfdc1ae18..3e3a0a493f2d14 100644 --- a/src/dev/build/cli.ts +++ b/src/dev/build/cli.ts @@ -38,10 +38,12 @@ if (showHelp) { --skip-archives {dim Don't produce tar/zip archives} --skip-os-packages {dim Don't produce rpm/deb/docker packages} --all-platforms {dim Produce archives for all platforms, not just this one} - --rpm {dim Only build the rpm package} - --deb {dim Only build the deb package} - --docker {dim Only build the docker image} + --rpm {dim Only build the rpm packages} + --deb {dim Only build the deb packages} + --docker-images {dim Only build the Docker images} + --docker-contexts {dim Only build the Docker build contexts} --skip-docker-ubi {dim Don't build the docker ubi image} + --skip-docker-centos {dim Don't build the docker centos image} --release {dim Produce a release-ready distributable} --version-qualifier {dim Suffix version with a qualifier} --skip-node-download {dim Reuse existing downloads of node.js} diff --git a/src/dev/build/tasks/os_packages/create_os_package_tasks.ts b/src/dev/build/tasks/os_packages/create_os_package_tasks.ts index ba57a5f3dbfc99..fd0224d3de13ba 100644 --- a/src/dev/build/tasks/os_packages/create_os_package_tasks.ts +++ b/src/dev/build/tasks/os_packages/create_os_package_tasks.ts @@ -8,7 +8,7 @@ import { Task } from '../../lib'; import { runFpm } from './run_fpm'; -import { runDockerGenerator, runDockerGeneratorForUBI } from './docker_generator'; +import { runDockerGenerator } from './docker_generator'; export const CreateDebPackage: Task = { description: 'Creating deb package', @@ -49,20 +49,56 @@ export const CreateRpmPackage: Task = { }, }; -export const CreateDockerPackage: Task = { - description: 'Creating docker package', +export const CreateDockerCentOS: Task = { + description: 'Creating Docker CentOS image', async run(config, log, build) { - // Builds Docker targets for default and oss - await runDockerGenerator(config, log, build); + await runDockerGenerator(config, log, build, { + ubi: false, + context: false, + architecture: 'x64', + image: true, + }); + await runDockerGenerator(config, log, build, { + ubi: false, + context: false, + architecture: 'aarch64', + image: true, + }); }, }; -export const CreateDockerUbiPackage: Task = { - description: 'Creating docker ubi package', +export const CreateDockerUBI: Task = { + description: 'Creating Docker UBI image', async run(config, log, build) { - // Builds Docker target default with ubi7 base image - await runDockerGeneratorForUBI(config, log, build); + if (!build.isOss()) { + await runDockerGenerator(config, log, build, { + ubi: true, + context: false, + architecture: 'x64', + image: true, + }); + } + }, +}; + +export const CreateDockerContexts: Task = { + description: 'Creating Docker build contexts', + + async run(config, log, build) { + await runDockerGenerator(config, log, build, { + ubi: false, + context: true, + image: false, + }); + + if (!build.isOss()) { + await runDockerGenerator(config, log, build, { + ubi: true, + context: true, + image: false, + }); + } }, }; diff --git a/src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.ts b/src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.ts index 07a86927d5a359..4780457fe80544 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/bundle_dockerfiles.ts @@ -18,7 +18,6 @@ export async function bundleDockerFiles(config: Config, log: ToolingLog, scope: log.info( `Generating kibana${scope.imageFlavor}${scope.ubiImageFlavor} docker build context bundle` ); - const dockerFilesDirName = `kibana${scope.imageFlavor}${scope.ubiImageFlavor}-${scope.version}-docker-build-context`; const dockerFilesBuildDir = resolve(scope.dockerBuildDir, dockerFilesDirName); const dockerFilesOutputDir = config.resolveFromTarget(`${dockerFilesDirName}.tar.gz`); diff --git a/src/dev/build/tasks/os_packages/docker_generator/index.ts b/src/dev/build/tasks/os_packages/docker_generator/index.ts index 1e6e6156c3ed91..229bd5242228c8 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/index.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/index.ts @@ -6,4 +6,4 @@ * Public License, v 1. */ -export { runDockerGenerator, runDockerGeneratorForUBI } from './run'; +export { runDockerGenerator } from './run'; diff --git a/src/dev/build/tasks/os_packages/docker_generator/run.ts b/src/dev/build/tasks/os_packages/docker_generator/run.ts index 26a6a9d6e4a03c..c92de567cb4465 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/run.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/run.ts @@ -26,19 +26,26 @@ export async function runDockerGenerator( config: Config, log: ToolingLog, build: Build, - ubi: boolean = false + flags: { + architecture?: string; + context: boolean; + image: boolean; + ubi: boolean; + } ) { // UBI var config - const baseOSImage = ubi ? 'docker.elastic.co/ubi8/ubi-minimal:latest' : 'centos:8'; + const baseOSImage = flags.ubi ? 'docker.elastic.co/ubi8/ubi-minimal:latest' : 'centos:8'; const ubiVersionTag = 'ubi8'; - const ubiImageFlavor = ubi ? `-${ubiVersionTag}` : ''; + const ubiImageFlavor = flags.ubi ? `-${ubiVersionTag}` : ''; // General docker var config const license = build.isOss() ? 'ASL 2.0' : 'Elastic License'; const imageFlavor = build.isOss() ? '-oss' : ''; const imageTag = 'docker.elastic.co/kibana/kibana'; const version = config.getBuildVersion(); - const artifactTarball = `kibana${imageFlavor}-${version}-linux-x86_64.tar.gz`; + const artifactArchitecture = flags.architecture === 'aarch64' ? 'aarch64' : 'x86_64'; + const artifactPrefix = `kibana${imageFlavor}-${version}-linux`; + const artifactTarball = `${artifactPrefix}-${artifactArchitecture}.tar.gz`; const artifactsDir = config.resolveFromTarget('.'); const dockerBuildDate = new Date().toISOString(); // That would produce oss, default and default-ubi7 @@ -47,10 +54,12 @@ export async function runDockerGenerator( 'kibana-docker', build.isOss() ? `oss` : `default${ubiImageFlavor}` ); + const imageArchitecture = flags.architecture === 'aarch64' ? '-aarch64' : ''; const dockerTargetFilename = config.resolveFromTarget( - `kibana${imageFlavor}${ubiImageFlavor}-${version}-docker-image.tar.gz` + `kibana${imageFlavor}${ubiImageFlavor}-${version}-docker-image${imageArchitecture}.tar.gz` ); const scope: TemplateContext = { + artifactPrefix, artifactTarball, imageFlavor, version, @@ -62,7 +71,8 @@ export async function runDockerGenerator( baseOSImage, ubiImageFlavor, dockerBuildDate, - ubi, + ubi: flags.ubi, + architecture: flags.architecture, revision: config.getBuildSha(), }; @@ -106,20 +116,23 @@ export async function runDockerGenerator( // created from the templates/build_docker_sh.template.js // and we just run that bash script await chmodAsync(`${resolve(dockerBuildDir, 'build_docker.sh')}`, '755'); - await exec(log, `./build_docker.sh`, [], { - cwd: dockerBuildDir, - level: 'info', - }); - - // Pack Dockerfiles and create a target for them - await bundleDockerFiles(config, log, scope); -} -export async function runDockerGeneratorForUBI(config: Config, log: ToolingLog, build: Build) { - // Only run ubi docker image build for default distribution - if (build.isOss()) { - return; + // Only build images on native targets + type HostArchitectureToDocker = Record; + const hostTarget: HostArchitectureToDocker = { + x64: 'x64', + arm64: 'aarch64', + }; + const buildImage = hostTarget[process.arch] === flags.architecture && flags.image; + if (buildImage) { + await exec(log, `./build_docker.sh`, [], { + cwd: dockerBuildDir, + level: 'info', + }); } - await runDockerGenerator(config, log, build, true); + // Pack Dockerfiles and create a target for them + if (flags.context) { + await bundleDockerFiles(config, log, scope); + } } diff --git a/src/dev/build/tasks/os_packages/docker_generator/template_context.ts b/src/dev/build/tasks/os_packages/docker_generator/template_context.ts index 4805ba0ba9bc06..8de2b5e9361e5f 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/template_context.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/template_context.ts @@ -7,6 +7,7 @@ */ export interface TemplateContext { + artifactPrefix: string; artifactTarball: string; imageFlavor: string; version: string; @@ -21,4 +22,5 @@ export interface TemplateContext { usePublicArtifact?: boolean; ubi: boolean; revision: string; + architecture?: string; } diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile b/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile index 1a0e325a2486a4..eb4708b6ac5553 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile @@ -17,17 +17,19 @@ RUN {{packageManager}} install -y findutils tar gzip {{#usePublicArtifact}} RUN cd /opt && \ - curl --retry 8 -s -L -O https://artifacts.elastic.co/downloads/kibana/{{artifactTarball}} && \ + curl --retry 8 -s -L \ + --output kibana.tar.gz \ + https://artifacts.elastic.co/downloads/kibana/{{artifactPrefix}}-$(arch).tar.gz && \ cd - {{/usePublicArtifact}} {{^usePublicArtifact}} -COPY {{artifactTarball}} /opt +COPY {{artifactTarball}} /opt/kibana.tar.gz {{/usePublicArtifact}} RUN mkdir /usr/share/kibana WORKDIR /usr/share/kibana -RUN tar --strip-components=1 -zxf /opt/{{artifactTarball}} +RUN tar --strip-components=1 -zxf /opt/kibana.tar.gz # Ensure that group permissions are the same as user permissions. # This will help when relying on GID-0 to run Kibana, rather than UID-1000. # OpenShift does this, for example. @@ -51,7 +53,7 @@ EXPOSE 5601 RUN for iter in {1..10}; do \ {{packageManager}} update --setopt=tsflags=nodocs -y && \ {{packageManager}} install --setopt=tsflags=nodocs -y \ - fontconfig freetype shadow-utils libnss3.so {{#ubi}}findutils{{/ubi}} && \ + fontconfig freetype shadow-utils nss {{#ubi}}findutils{{/ubi}} && \ {{packageManager}} clean all && exit_code=0 && break || exit_code=$? && echo "{{packageManager}} error: retry $iter in 10s" && \ sleep 10; \ done; \ @@ -59,8 +61,17 @@ RUN for iter in {1..10}; do \ # Add an init process, check the checksum to make sure it's a match RUN set -e ; \ + TINI_BIN="" ; \ + case "$(arch)" in \ + aarch64) \ + TINI_BIN='tini-arm64' ; \ + ;; \ + x86_64) \ + TINI_BIN='tini-amd64' ; \ + ;; \ + *) echo >&2 "Unsupported architecture $(arch)" ; exit 1 ;; \ + esac ; \ TINI_VERSION='v0.19.0' ; \ - TINI_BIN='tini-amd64' ; \ curl --retry 8 -S -L -O "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/${TINI_BIN}" ; \ curl --retry 8 -S -L -O "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/${TINI_BIN}.sha256sum" ; \ sha256sum -c "${TINI_BIN}.sha256sum" ; \ diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.ts b/src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.ts index 5e2a0b72769fe9..93c5f82aa1e424 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/build_docker_sh.template.ts @@ -17,7 +17,9 @@ function generator({ dockerTargetFilename, baseOSImage, ubiImageFlavor, + architecture, }: TemplateContext) { + const fileArchitecture = architecture === 'aarch64' ? 'arm64' : 'amd64'; return dedent(` #!/usr/bin/env bash # @@ -54,9 +56,9 @@ function generator({ retry_docker_pull ${baseOSImage} echo "Building: kibana${imageFlavor}${ubiImageFlavor}-docker"; \\ - docker build -t ${imageTag}${imageFlavor}${ubiImageFlavor}:${version} -f Dockerfile . || exit 1; + docker build -t ${imageTag}${imageFlavor}${ubiImageFlavor}:${version}-${fileArchitecture} -f Dockerfile . || exit 1; - docker save ${imageTag}${imageFlavor}${ubiImageFlavor}:${version} | gzip -c > ${dockerTargetFilename} + docker save ${imageTag}${imageFlavor}${ubiImageFlavor}:${version}-${fileArchitecture} | gzip -c > ${dockerTargetFilename} exit 0 `); diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts b/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts index a5cc2d9527cbfb..f4e9d11ca9c21c 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts @@ -16,6 +16,7 @@ function generator(options: TemplateContext) { const template = readFileSync(resolve(__dirname, './Dockerfile')); return Mustache.render(template.toString(), { packageManager: options.ubiImageFlavor ? 'microdnf' : 'yum', + tiniBin: options.architecture === 'aarch64' ? 'tini-arm64' : 'tini-amd64', ...options, }); } From cf3c746eca9f1d7abe88502bed248a62da3b8175 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Thu, 28 Jan 2021 00:51:01 +0000 Subject: [PATCH 56/58] chore(NA): bazel machinery installation on kbn bootstrap (#89469) * chore(NA): bazel machinery installation on kbn bootstrap * refact(NA): simplify install logic * chore(NA): update kbn pm with last changes --- .bazeliskversion | 1 + .bazelversion | 1 + WORKSPACE.bazel | 3 + package.json | 1 + packages/kbn-pm/dist/index.js | 1863 +++++++++-------- packages/kbn-pm/src/commands/bootstrap.ts | 7 +- packages/kbn-pm/src/utils/bazel/index.ts | 9 + .../kbn-pm/src/utils/bazel/install_tools.ts | 53 + src/dev/precommit_hook/casing_check_config.js | 4 + yarn.lock | 5 + 10 files changed, 1056 insertions(+), 891 deletions(-) create mode 100644 .bazeliskversion create mode 100644 .bazelversion create mode 100644 WORKSPACE.bazel create mode 100644 packages/kbn-pm/src/utils/bazel/index.ts create mode 100644 packages/kbn-pm/src/utils/bazel/install_tools.ts diff --git a/.bazeliskversion b/.bazeliskversion new file mode 100644 index 00000000000000..661e7aeadf36f8 --- /dev/null +++ b/.bazeliskversion @@ -0,0 +1 @@ +1.7.3 diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 00000000000000..fcdb2e109f68cf --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +4.0.0 diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel new file mode 100644 index 00000000000000..0828157524fa16 --- /dev/null +++ b/WORKSPACE.bazel @@ -0,0 +1,3 @@ +workspace( + name = "kibana", +) diff --git a/package.json b/package.json index 42949a70141311..a64995e57a1f7f 100644 --- a/package.json +++ b/package.json @@ -346,6 +346,7 @@ "@babel/register": "^7.12.10", "@babel/traverse": "^7.12.12", "@babel/types": "^7.12.12", + "@bazel/ibazel": "^0.14.0", "@cypress/snapshot": "^2.1.7", "@cypress/webpack-preprocessor": "^5.5.0", "@elastic/apm-rum": "^5.6.1", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 95ab46582723e6..df04965cd8c32b 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(510); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(512); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(248); @@ -106,7 +106,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(251); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "transformDependencies", function() { return _utils_package_json__WEBPACK_IMPORTED_MODULE_4__["transformDependencies"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(509); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(511); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -139,7 +139,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(128); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(503); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(505); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(246); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -8827,9 +8827,9 @@ exports.ToolingLogCollectingWriter = ToolingLogCollectingWriter; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); /* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(129); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(371); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(402); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(403); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(373); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(404); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(405); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -8865,6 +8865,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(368); /* harmony import */ var _utils_yarn_lock__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(365); /* harmony import */ var _utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(369); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(371); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -8881,19 +8882,23 @@ __webpack_require__.r(__webpack_exports__); + const BootstrapCommand = { description: 'Install dependencies and crosslink projects', name: 'bootstrap', async run(projects, projectGraph, { options, - kbn + kbn, + rootPath }) { var _projects$get; const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_4__["topologicallyBatchProjects"])(projects, projectGraph); const kibanaProjectPath = (_projects$get = projects.get('kibana')) === null || _projects$get === void 0 ? void 0 : _projects$get.path; - const extraArgs = [...(options['frozen-lockfile'] === true ? ['--frozen-lockfile'] : []), ...(options['prefer-offline'] === true ? ['--prefer-offline'] : [])]; + const extraArgs = [...(options['frozen-lockfile'] === true ? ['--frozen-lockfile'] : []), ...(options['prefer-offline'] === true ? ['--prefer-offline'] : [])]; // Install bazel machinery tools if needed + + await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["installBazelTools"])(rootPath); // Install monorepo npm dependencies for (const batch of batchedProjects) { for (const project of batch) { @@ -47935,12 +47940,90 @@ function addProjectToTree(tree, pathParts, project) { /* 371 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _install_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(372); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "installBazelTools", function() { return _install_tools__WEBPACK_IMPORTED_MODULE_0__["installBazelTools"]; }); + +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + + +/***/ }), +/* 372 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "installBazelTools", function() { return installBazelTools; }); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(319); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(131); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(246); +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + + + + + +async function readBazelToolsVersionFile(repoRootPath, versionFilename) { + const version = (await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["readFile"])(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(repoRootPath, versionFilename))).toString().split('\n')[0]; + + if (!version) { + throw new Error(`[bazel_tools] Failed on reading bazel tools versions\n ${versionFilename} file do not contain any version set`); + } + + return version; +} + +async function installBazelTools(repoRootPath) { + _log__WEBPACK_IMPORTED_MODULE_3__["log"].debug(`[bazel_tools] reading bazel tools versions from version files`); + const bazeliskVersion = await readBazelToolsVersionFile(repoRootPath, '.bazeliskversion'); + const bazelVersion = await readBazelToolsVersionFile(repoRootPath, '.bazelversion'); // Check what globals are installed + + _log__WEBPACK_IMPORTED_MODULE_3__["log"].debug(`[bazel_tools] verify if bazelisk is installed`); + const { + stdout + } = await Object(_child_process__WEBPACK_IMPORTED_MODULE_1__["spawn"])('yarn', ['global', 'list'], { + stdio: 'pipe' + }); // Install bazelisk if not installed + + if (!stdout.includes(`@bazel/bazelisk@${bazeliskVersion}`)) { + _log__WEBPACK_IMPORTED_MODULE_3__["log"].info(`[bazel_tools] installing Bazel tools`); + _log__WEBPACK_IMPORTED_MODULE_3__["log"].debug(`[bazel_tools] bazelisk is not installed. Installing @bazel/bazelisk@${bazeliskVersion} and bazel@${bazelVersion}`); + await Object(_child_process__WEBPACK_IMPORTED_MODULE_1__["spawn"])('yarn', ['global', 'add', `@bazel/bazelisk@${bazeliskVersion}`], { + env: { + USE_BAZEL_VERSION: bazelVersion + }, + stdio: 'pipe' + }); + } + + _log__WEBPACK_IMPORTED_MODULE_3__["log"].success(`[bazel_tools] all bazel tools are correctly installed`); +} + +/***/ }), +/* 373 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(143); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(372); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(374); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); @@ -48029,20 +48112,20 @@ const CleanCommand = { }; /***/ }), -/* 372 */ +/* 374 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readline = __webpack_require__(373); -const chalk = __webpack_require__(374); -const cliCursor = __webpack_require__(381); -const cliSpinners = __webpack_require__(383); -const logSymbols = __webpack_require__(385); -const stripAnsi = __webpack_require__(394); -const wcwidth = __webpack_require__(396); -const isInteractive = __webpack_require__(400); -const MuteStream = __webpack_require__(401); +const readline = __webpack_require__(375); +const chalk = __webpack_require__(376); +const cliCursor = __webpack_require__(383); +const cliSpinners = __webpack_require__(385); +const logSymbols = __webpack_require__(387); +const stripAnsi = __webpack_require__(396); +const wcwidth = __webpack_require__(398); +const isInteractive = __webpack_require__(402); +const MuteStream = __webpack_require__(403); const TEXT = Symbol('text'); const PREFIX_TEXT = Symbol('prefixText'); @@ -48395,23 +48478,23 @@ module.exports.promise = (action, options) => { /***/ }), -/* 373 */ +/* 375 */ /***/ (function(module, exports) { module.exports = require("readline"); /***/ }), -/* 374 */ +/* 376 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiStyles = __webpack_require__(375); +const ansiStyles = __webpack_require__(377); const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(120); const { stringReplaceAll, stringEncaseCRLFWithFirstIndex -} = __webpack_require__(379); +} = __webpack_require__(381); // `supportsColor.level` → `ansiStyles.color[name]` mapping const levelMapping = [ @@ -48612,7 +48695,7 @@ const chalkTag = (chalk, ...strings) => { } if (template === undefined) { - template = __webpack_require__(380); + template = __webpack_require__(382); } return template(chalk, parts.join('')); @@ -48641,7 +48724,7 @@ module.exports = chalk; /***/ }), -/* 375 */ +/* 377 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48687,7 +48770,7 @@ const setLazyProperty = (object, property, get) => { let colorConvert; const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { if (colorConvert === undefined) { - colorConvert = __webpack_require__(376); + colorConvert = __webpack_require__(378); } const offset = isBackground ? 10 : 0; @@ -48812,11 +48895,11 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module))) /***/ }), -/* 376 */ +/* 378 */ /***/ (function(module, exports, __webpack_require__) { -const conversions = __webpack_require__(377); -const route = __webpack_require__(378); +const conversions = __webpack_require__(379); +const route = __webpack_require__(380); const convert = {}; @@ -48899,7 +48982,7 @@ module.exports = convert; /***/ }), -/* 377 */ +/* 379 */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ @@ -49744,10 +49827,10 @@ convert.rgb.gray = function (rgb) { /***/ }), -/* 378 */ +/* 380 */ /***/ (function(module, exports, __webpack_require__) { -const conversions = __webpack_require__(377); +const conversions = __webpack_require__(379); /* This function routes a model to all other models. @@ -49847,7 +49930,7 @@ module.exports = function (fromModel) { /***/ }), -/* 379 */ +/* 381 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49893,7 +49976,7 @@ module.exports = { /***/ }), -/* 380 */ +/* 382 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50034,12 +50117,12 @@ module.exports = (chalk, temporary) => { /***/ }), -/* 381 */ +/* 383 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(382); +const restoreCursor = __webpack_require__(384); let isHidden = false; @@ -50076,7 +50159,7 @@ exports.toggle = (force, writableStream) => { /***/ }), -/* 382 */ +/* 384 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50092,13 +50175,13 @@ module.exports = onetime(() => { /***/ }), -/* 383 */ +/* 385 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const spinners = Object.assign({}, __webpack_require__(384)); +const spinners = Object.assign({}, __webpack_require__(386)); const spinnersList = Object.keys(spinners); @@ -50116,18 +50199,18 @@ module.exports.default = spinners; /***/ }), -/* 384 */ +/* 386 */ /***/ (function(module) { module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"dots8Bit\":{\"interval\":80,\"frames\":[\"⠀\",\"⠁\",\"⠂\",\"⠃\",\"⠄\",\"⠅\",\"⠆\",\"⠇\",\"⡀\",\"⡁\",\"⡂\",\"⡃\",\"⡄\",\"⡅\",\"⡆\",\"⡇\",\"⠈\",\"⠉\",\"⠊\",\"⠋\",\"⠌\",\"⠍\",\"⠎\",\"⠏\",\"⡈\",\"⡉\",\"⡊\",\"⡋\",\"⡌\",\"⡍\",\"⡎\",\"⡏\",\"⠐\",\"⠑\",\"⠒\",\"⠓\",\"⠔\",\"⠕\",\"⠖\",\"⠗\",\"⡐\",\"⡑\",\"⡒\",\"⡓\",\"⡔\",\"⡕\",\"⡖\",\"⡗\",\"⠘\",\"⠙\",\"⠚\",\"⠛\",\"⠜\",\"⠝\",\"⠞\",\"⠟\",\"⡘\",\"⡙\",\"⡚\",\"⡛\",\"⡜\",\"⡝\",\"⡞\",\"⡟\",\"⠠\",\"⠡\",\"⠢\",\"⠣\",\"⠤\",\"⠥\",\"⠦\",\"⠧\",\"⡠\",\"⡡\",\"⡢\",\"⡣\",\"⡤\",\"⡥\",\"⡦\",\"⡧\",\"⠨\",\"⠩\",\"⠪\",\"⠫\",\"⠬\",\"⠭\",\"⠮\",\"⠯\",\"⡨\",\"⡩\",\"⡪\",\"⡫\",\"⡬\",\"⡭\",\"⡮\",\"⡯\",\"⠰\",\"⠱\",\"⠲\",\"⠳\",\"⠴\",\"⠵\",\"⠶\",\"⠷\",\"⡰\",\"⡱\",\"⡲\",\"⡳\",\"⡴\",\"⡵\",\"⡶\",\"⡷\",\"⠸\",\"⠹\",\"⠺\",\"⠻\",\"⠼\",\"⠽\",\"⠾\",\"⠿\",\"⡸\",\"⡹\",\"⡺\",\"⡻\",\"⡼\",\"⡽\",\"⡾\",\"⡿\",\"⢀\",\"⢁\",\"⢂\",\"⢃\",\"⢄\",\"⢅\",\"⢆\",\"⢇\",\"⣀\",\"⣁\",\"⣂\",\"⣃\",\"⣄\",\"⣅\",\"⣆\",\"⣇\",\"⢈\",\"⢉\",\"⢊\",\"⢋\",\"⢌\",\"⢍\",\"⢎\",\"⢏\",\"⣈\",\"⣉\",\"⣊\",\"⣋\",\"⣌\",\"⣍\",\"⣎\",\"⣏\",\"⢐\",\"⢑\",\"⢒\",\"⢓\",\"⢔\",\"⢕\",\"⢖\",\"⢗\",\"⣐\",\"⣑\",\"⣒\",\"⣓\",\"⣔\",\"⣕\",\"⣖\",\"⣗\",\"⢘\",\"⢙\",\"⢚\",\"⢛\",\"⢜\",\"⢝\",\"⢞\",\"⢟\",\"⣘\",\"⣙\",\"⣚\",\"⣛\",\"⣜\",\"⣝\",\"⣞\",\"⣟\",\"⢠\",\"⢡\",\"⢢\",\"⢣\",\"⢤\",\"⢥\",\"⢦\",\"⢧\",\"⣠\",\"⣡\",\"⣢\",\"⣣\",\"⣤\",\"⣥\",\"⣦\",\"⣧\",\"⢨\",\"⢩\",\"⢪\",\"⢫\",\"⢬\",\"⢭\",\"⢮\",\"⢯\",\"⣨\",\"⣩\",\"⣪\",\"⣫\",\"⣬\",\"⣭\",\"⣮\",\"⣯\",\"⢰\",\"⢱\",\"⢲\",\"⢳\",\"⢴\",\"⢵\",\"⢶\",\"⢷\",\"⣰\",\"⣱\",\"⣲\",\"⣳\",\"⣴\",\"⣵\",\"⣶\",\"⣷\",\"⢸\",\"⢹\",\"⢺\",\"⢻\",\"⢼\",\"⢽\",\"⢾\",\"⢿\",\"⣸\",\"⣹\",\"⣺\",\"⣻\",\"⣼\",\"⣽\",\"⣾\",\"⣿\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕛 \",\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"material\":{\"interval\":17,\"frames\":[\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███████▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"██████████▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"█████████████▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁██████████████▁▁▁▁\",\"▁▁▁██████████████▁▁▁\",\"▁▁▁▁█████████████▁▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁▁█████████████▁▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁▁███████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁▁█████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]},\"grenade\":{\"interval\":80,\"frames\":[\"، \",\"′ \",\" ´ \",\" ‾ \",\" ⸌\",\" ⸊\",\" |\",\" ⁎\",\" ⁕\",\" ෴ \",\" ⁓\",\" \",\" \",\" \"]},\"point\":{\"interval\":125,\"frames\":[\"∙∙∙\",\"●∙∙\",\"∙●∙\",\"∙∙●\",\"∙∙∙\"]},\"layer\":{\"interval\":150,\"frames\":[\"-\",\"=\",\"≡\"]},\"betaWave\":{\"interval\":80,\"frames\":[\"ρββββββ\",\"βρβββββ\",\"ββρββββ\",\"βββρβββ\",\"ββββρββ\",\"βββββρβ\",\"ββββββρ\"]},\"aesthetic\":{\"interval\":80,\"frames\":[\"▰▱▱▱▱▱▱\",\"▰▰▱▱▱▱▱\",\"▰▰▰▱▱▱▱\",\"▰▰▰▰▱▱▱\",\"▰▰▰▰▰▱▱\",\"▰▰▰▰▰▰▱\",\"▰▰▰▰▰▰▰\",\"▰▱▱▱▱▱▱\"]}}"); /***/ }), -/* 385 */ +/* 387 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(386); +const chalk = __webpack_require__(388); const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; @@ -50149,16 +50232,16 @@ module.exports = isSupported ? main : fallbacks; /***/ }), -/* 386 */ +/* 388 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(265); -const ansiStyles = __webpack_require__(387); -const stdoutColor = __webpack_require__(392).stdout; +const ansiStyles = __webpack_require__(389); +const stdoutColor = __webpack_require__(394).stdout; -const template = __webpack_require__(393); +const template = __webpack_require__(395); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -50384,12 +50467,12 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 387 */ +/* 389 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(module) { -const colorConvert = __webpack_require__(388); +const colorConvert = __webpack_require__(390); const wrapAnsi16 = (fn, offset) => function () { const code = fn.apply(colorConvert, arguments); @@ -50557,11 +50640,11 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module))) /***/ }), -/* 388 */ +/* 390 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(389); -var route = __webpack_require__(391); +var conversions = __webpack_require__(391); +var route = __webpack_require__(393); var convert = {}; @@ -50641,11 +50724,11 @@ module.exports = convert; /***/ }), -/* 389 */ +/* 391 */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ -var cssKeywords = __webpack_require__(390); +var cssKeywords = __webpack_require__(392); // NOTE: conversions should only return primitive values (i.e. arrays, or // values that give correct `typeof` results). @@ -51515,7 +51598,7 @@ convert.rgb.gray = function (rgb) { /***/ }), -/* 390 */ +/* 392 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -51674,10 +51757,10 @@ module.exports = { /***/ }), -/* 391 */ +/* 393 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(389); +var conversions = __webpack_require__(391); /* this function routes a model to all other models. @@ -51777,7 +51860,7 @@ module.exports = function (fromModel) { /***/ }), -/* 392 */ +/* 394 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -51915,7 +51998,7 @@ module.exports = { /***/ }), -/* 393 */ +/* 395 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52050,18 +52133,18 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 394 */ +/* 396 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(395); +const ansiRegex = __webpack_require__(397); module.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string; /***/ }), -/* 395 */ +/* 397 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52078,14 +52161,14 @@ module.exports = ({onlyFirst = false} = {}) => { /***/ }), -/* 396 */ +/* 398 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var defaults = __webpack_require__(397) -var combining = __webpack_require__(399) +var defaults = __webpack_require__(399) +var combining = __webpack_require__(401) var DEFAULTS = { nul: 0, @@ -52184,10 +52267,10 @@ function bisearch(ucs) { /***/ }), -/* 397 */ +/* 399 */ /***/ (function(module, exports, __webpack_require__) { -var clone = __webpack_require__(398); +var clone = __webpack_require__(400); module.exports = function(options, defaults) { options = options || {}; @@ -52202,7 +52285,7 @@ module.exports = function(options, defaults) { }; /***/ }), -/* 398 */ +/* 400 */ /***/ (function(module, exports, __webpack_require__) { var clone = (function() { @@ -52374,7 +52457,7 @@ if ( true && module.exports) { /***/ }), -/* 399 */ +/* 401 */ /***/ (function(module, exports) { module.exports = [ @@ -52430,7 +52513,7 @@ module.exports = [ /***/ }), -/* 400 */ +/* 402 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52446,7 +52529,7 @@ module.exports = ({stream = process.stdout} = {}) => { /***/ }), -/* 401 */ +/* 403 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(138) @@ -52597,7 +52680,7 @@ MuteStream.prototype.close = proxy('close') /***/ }), -/* 402 */ +/* 404 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52654,7 +52737,7 @@ const RunCommand = { }; /***/ }), -/* 403 */ +/* 405 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52664,7 +52747,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(247); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(248); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(404); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(406); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -52739,14 +52822,14 @@ const WatchCommand = { }; /***/ }), -/* 404 */ +/* 406 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "waitUntilWatchIsReady", function() { return waitUntilWatchIsReady; }); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8); -/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(405); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(407); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -52802,141 +52885,141 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 405 */ +/* 407 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(406); +/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(408); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__["audit"]; }); -/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(407); +/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(409); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__["auditTime"]; }); -/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(408); +/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(410); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__["buffer"]; }); -/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(409); +/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(411); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__["bufferCount"]; }); -/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(410); +/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(412); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__["bufferTime"]; }); -/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(411); +/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(413); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__["bufferToggle"]; }); -/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(412); +/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(414); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__["bufferWhen"]; }); -/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(413); +/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(415); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__["catchError"]; }); -/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(414); +/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(416); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__["combineAll"]; }); -/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(415); +/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(417); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__["combineLatest"]; }); -/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(416); +/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(418); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__["concat"]; }); /* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(80); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__["concatAll"]; }); -/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(417); +/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(419); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__["concatMap"]; }); -/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(418); +/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(420); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__["concatMapTo"]; }); -/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(419); +/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(421); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "count", function() { return _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__["count"]; }); -/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(420); +/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(422); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__["debounce"]; }); -/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(421); +/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(423); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__["debounceTime"]; }); -/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(422); +/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(424); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__["defaultIfEmpty"]; }); -/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(423); +/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(425); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__["delay"]; }); -/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(425); +/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(427); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__["delayWhen"]; }); -/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(426); +/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(428); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__["dematerialize"]; }); -/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(427); +/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(429); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__["distinct"]; }); -/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(428); +/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(430); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__["distinctUntilChanged"]; }); -/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(429); +/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(431); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__["distinctUntilKeyChanged"]; }); -/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(430); +/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(432); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__["elementAt"]; }); -/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(433); +/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(435); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__["endWith"]; }); -/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(434); +/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(436); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "every", function() { return _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__["every"]; }); -/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(435); +/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(437); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__["exhaust"]; }); -/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(436); +/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(438); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__["exhaustMap"]; }); -/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(437); +/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(439); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__["expand"]; }); /* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(105); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__["filter"]; }); -/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(438); +/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(440); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__["finalize"]; }); -/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(439); +/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(441); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "find", function() { return _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__["find"]; }); -/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(440); +/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(442); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__["findIndex"]; }); -/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(441); +/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(443); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "first", function() { return _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__["first"]; }); /* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(31); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__["groupBy"]; }); -/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(442); +/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(444); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__["ignoreElements"]; }); -/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(443); +/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(445); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__["isEmpty"]; }); -/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(444); +/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(446); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "last", function() { return _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__["last"]; }); /* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(66); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "map", function() { return _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__["map"]; }); -/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(446); +/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(448); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__["mapTo"]; }); -/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(447); +/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(449); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__["materialize"]; }); -/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(448); +/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(450); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "max", function() { return _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__["max"]; }); -/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(451); +/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(453); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__["merge"]; }); /* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(81); @@ -52947,175 +53030,175 @@ __webpack_require__.r(__webpack_exports__); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["flatMap"]; }); -/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(452); +/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(454); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__["mergeMapTo"]; }); -/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(453); +/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(455); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__["mergeScan"]; }); -/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(454); +/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(456); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "min", function() { return _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__["min"]; }); -/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(455); +/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(457); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__["multicast"]; }); /* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(41); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observeOn", function() { return _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__["observeOn"]; }); -/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(456); +/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(458); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(457); +/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(459); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__["pairwise"]; }); -/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(458); +/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(460); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__["partition"]; }); -/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(459); +/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(461); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__["pluck"]; }); -/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(460); +/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(462); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__["publish"]; }); -/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(461); +/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(463); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__["publishBehavior"]; }); -/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(462); +/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(464); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__["publishLast"]; }); -/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(463); +/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(465); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__["publishReplay"]; }); -/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(464); +/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(466); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__["race"]; }); -/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(449); +/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(451); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__["reduce"]; }); -/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(465); +/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(467); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__["repeat"]; }); -/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(466); +/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(468); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__["repeatWhen"]; }); -/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(467); +/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(469); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__["retry"]; }); -/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(468); +/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(470); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__["retryWhen"]; }); /* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(30); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__["refCount"]; }); -/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(469); +/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(471); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__["sample"]; }); -/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(470); +/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(472); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__["sampleTime"]; }); -/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(450); +/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(452); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__["scan"]; }); -/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(471); +/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(473); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__["sequenceEqual"]; }); -/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(472); +/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(474); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "share", function() { return _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__["share"]; }); -/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(473); +/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(475); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__["shareReplay"]; }); -/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(474); +/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(476); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "single", function() { return _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__["single"]; }); -/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(475); +/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(477); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__["skip"]; }); -/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(476); +/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(478); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__["skipLast"]; }); -/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(477); +/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(479); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__["skipUntil"]; }); -/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(478); +/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(480); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__["skipWhile"]; }); -/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(479); +/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(481); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__["startWith"]; }); -/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(480); +/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(482); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__["subscribeOn"]; }); -/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(482); +/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(484); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__["switchAll"]; }); -/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(483); +/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(485); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__["switchMap"]; }); -/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(484); +/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(486); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__["switchMapTo"]; }); -/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(432); +/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(434); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "take", function() { return _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__["take"]; }); -/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(445); +/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(447); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__["takeLast"]; }); -/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(485); +/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(487); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__["takeUntil"]; }); -/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(486); +/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(488); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__["takeWhile"]; }); -/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(487); +/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(489); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__["tap"]; }); -/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(488); +/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(490); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__["throttle"]; }); -/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(489); +/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(491); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__["throttleTime"]; }); -/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(431); +/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(433); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__["throwIfEmpty"]; }); -/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(490); +/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(492); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__["timeInterval"]; }); -/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(491); +/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(493); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__["timeout"]; }); -/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(492); +/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(494); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__["timeoutWith"]; }); -/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(493); +/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(495); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__["timestamp"]; }); -/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(494); +/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(496); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__["toArray"]; }); -/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(495); +/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(497); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "window", function() { return _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__["window"]; }); -/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(496); +/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(498); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__["windowCount"]; }); -/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(497); +/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(499); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__["windowTime"]; }); -/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(498); +/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(500); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__["windowToggle"]; }); -/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(499); +/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(501); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__["windowWhen"]; }); -/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(500); +/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(502); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__["withLatestFrom"]; }); -/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(501); +/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(503); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__["zip"]; }); -/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(502); +/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(504); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__["zipAll"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -53226,7 +53309,7 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 406 */ +/* 408 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53305,14 +53388,14 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 407 */ +/* 409 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return auditTime; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); -/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(406); +/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(408); /* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(108); /** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */ @@ -53328,7 +53411,7 @@ function auditTime(duration, scheduler) { /***/ }), -/* 408 */ +/* 410 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53375,7 +53458,7 @@ var BufferSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 409 */ +/* 411 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53476,7 +53559,7 @@ var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 410 */ +/* 412 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53637,7 +53720,7 @@ function dispatchBufferClose(arg) { /***/ }), -/* 411 */ +/* 413 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53756,7 +53839,7 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 412 */ +/* 414 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53849,7 +53932,7 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 413 */ +/* 415 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53909,7 +53992,7 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 414 */ +/* 416 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53925,7 +54008,7 @@ function combineAll(project) { /***/ }), -/* 415 */ +/* 417 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53957,7 +54040,7 @@ function combineLatest() { /***/ }), -/* 416 */ +/* 418 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53977,7 +54060,7 @@ function concat() { /***/ }), -/* 417 */ +/* 419 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53993,13 +54076,13 @@ function concatMap(project, resultSelector) { /***/ }), -/* 418 */ +/* 420 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return concatMapTo; }); -/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(417); +/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(419); /** PURE_IMPORTS_START _concatMap PURE_IMPORTS_END */ function concatMapTo(innerObservable, resultSelector) { @@ -54009,7 +54092,7 @@ function concatMapTo(innerObservable, resultSelector) { /***/ }), -/* 419 */ +/* 421 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54074,7 +54157,7 @@ var CountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 420 */ +/* 422 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54159,7 +54242,7 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 421 */ +/* 423 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54235,7 +54318,7 @@ function dispatchNext(subscriber) { /***/ }), -/* 422 */ +/* 424 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54285,7 +54368,7 @@ var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 423 */ +/* 425 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54293,7 +54376,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return delay; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(424); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(426); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11); /* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(42); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -54392,7 +54475,7 @@ var DelayMessage = /*@__PURE__*/ (function () { /***/ }), -/* 424 */ +/* 426 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54406,7 +54489,7 @@ function isDate(value) { /***/ }), -/* 425 */ +/* 427 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54552,7 +54635,7 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 426 */ +/* 428 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54590,7 +54673,7 @@ var DeMaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 427 */ +/* 429 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54666,7 +54749,7 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 428 */ +/* 430 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54737,13 +54820,13 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 429 */ +/* 431 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return distinctUntilKeyChanged; }); -/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(428); +/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(430); /** PURE_IMPORTS_START _distinctUntilChanged PURE_IMPORTS_END */ function distinctUntilKeyChanged(key, compare) { @@ -54753,7 +54836,7 @@ function distinctUntilKeyChanged(key, compare) { /***/ }), -/* 430 */ +/* 432 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54761,9 +54844,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return elementAt; }); /* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(62); /* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(431); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(422); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(432); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(433); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(424); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(434); /** PURE_IMPORTS_START _util_ArgumentOutOfRangeError,_filter,_throwIfEmpty,_defaultIfEmpty,_take PURE_IMPORTS_END */ @@ -54785,7 +54868,7 @@ function elementAt(index, defaultValue) { /***/ }), -/* 431 */ +/* 433 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54851,7 +54934,7 @@ function defaultErrorFactory() { /***/ }), -/* 432 */ +/* 434 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54913,7 +54996,7 @@ var TakeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 433 */ +/* 435 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54935,7 +55018,7 @@ function endWith() { /***/ }), -/* 434 */ +/* 436 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54997,7 +55080,7 @@ var EverySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 435 */ +/* 437 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55051,7 +55134,7 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 436 */ +/* 438 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55145,7 +55228,7 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 437 */ +/* 439 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55257,7 +55340,7 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 438 */ +/* 440 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55295,7 +55378,7 @@ var FinallySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 439 */ +/* 441 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55367,13 +55450,13 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 440 */ +/* 442 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return findIndex; }); -/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(439); +/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(441); /** PURE_IMPORTS_START _operators_find PURE_IMPORTS_END */ function findIndex(predicate, thisArg) { @@ -55383,7 +55466,7 @@ function findIndex(predicate, thisArg) { /***/ }), -/* 441 */ +/* 443 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55391,9 +55474,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "first", function() { return first; }); /* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(63); /* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(432); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(422); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(431); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(434); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(424); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(433); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(25); /** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -55410,7 +55493,7 @@ function first(predicate, defaultValue) { /***/ }), -/* 442 */ +/* 444 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55447,7 +55530,7 @@ var IgnoreElementsSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 443 */ +/* 445 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55491,7 +55574,7 @@ var IsEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 444 */ +/* 446 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55499,9 +55582,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "last", function() { return last; }); /* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(63); /* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(445); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(431); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(422); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(447); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(433); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(424); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(25); /** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -55518,7 +55601,7 @@ function last(predicate, defaultValue) { /***/ }), -/* 445 */ +/* 447 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55595,7 +55678,7 @@ var TakeLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 446 */ +/* 448 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55634,7 +55717,7 @@ var MapToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 447 */ +/* 449 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55684,13 +55767,13 @@ var MaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 448 */ +/* 450 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "max", function() { return max; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(449); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(451); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function max(comparer) { @@ -55703,15 +55786,15 @@ function max(comparer) { /***/ }), -/* 449 */ +/* 451 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return reduce; }); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(450); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(445); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(422); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(452); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(447); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(424); /* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(24); /** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */ @@ -55732,7 +55815,7 @@ function reduce(accumulator, seed) { /***/ }), -/* 450 */ +/* 452 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55814,7 +55897,7 @@ var ScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 451 */ +/* 453 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55834,7 +55917,7 @@ function merge() { /***/ }), -/* 452 */ +/* 454 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55859,7 +55942,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) { /***/ }), -/* 453 */ +/* 455 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55968,13 +56051,13 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 454 */ +/* 456 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "min", function() { return min; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(449); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(451); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function min(comparer) { @@ -55987,7 +56070,7 @@ function min(comparer) { /***/ }), -/* 455 */ +/* 457 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56036,7 +56119,7 @@ var MulticastOperator = /*@__PURE__*/ (function () { /***/ }), -/* 456 */ +/* 458 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56126,7 +56209,7 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 457 */ +/* 459 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56174,7 +56257,7 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 458 */ +/* 460 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56197,7 +56280,7 @@ function partition(predicate, thisArg) { /***/ }), -/* 459 */ +/* 461 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56237,14 +56320,14 @@ function plucker(props, length) { /***/ }), -/* 460 */ +/* 462 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return publish; }); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(27); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(455); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(457); /** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */ @@ -56257,14 +56340,14 @@ function publish(selector) { /***/ }), -/* 461 */ +/* 463 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return publishBehavior; }); /* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(32); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(455); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(457); /** PURE_IMPORTS_START _BehaviorSubject,_multicast PURE_IMPORTS_END */ @@ -56275,14 +56358,14 @@ function publishBehavior(value) { /***/ }), -/* 462 */ +/* 464 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return publishLast; }); /* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(50); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(455); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(457); /** PURE_IMPORTS_START _AsyncSubject,_multicast PURE_IMPORTS_END */ @@ -56293,14 +56376,14 @@ function publishLast() { /***/ }), -/* 463 */ +/* 465 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return publishReplay; }); /* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(33); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(455); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(457); /** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */ @@ -56316,7 +56399,7 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) { /***/ }), -/* 464 */ +/* 466 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56343,7 +56426,7 @@ function race() { /***/ }), -/* 465 */ +/* 467 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56408,7 +56491,7 @@ var RepeatSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 466 */ +/* 468 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56502,7 +56585,7 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 467 */ +/* 469 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56555,7 +56638,7 @@ var RetrySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 468 */ +/* 470 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56641,7 +56724,7 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 469 */ +/* 471 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56696,7 +56779,7 @@ var SampleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 470 */ +/* 472 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56756,7 +56839,7 @@ function dispatchNotification(state) { /***/ }), -/* 471 */ +/* 473 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56879,13 +56962,13 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 472 */ +/* 474 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "share", function() { return share; }); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(455); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(457); /* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(27); /** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */ @@ -56902,7 +56985,7 @@ function share() { /***/ }), -/* 473 */ +/* 475 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56971,7 +57054,7 @@ function shareReplayOperator(_a) { /***/ }), -/* 474 */ +/* 476 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57051,7 +57134,7 @@ var SingleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 475 */ +/* 477 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57093,7 +57176,7 @@ var SkipSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 476 */ +/* 478 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57155,7 +57238,7 @@ var SkipLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 477 */ +/* 479 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57212,7 +57295,7 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 478 */ +/* 480 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57268,7 +57351,7 @@ var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 479 */ +/* 481 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57297,13 +57380,13 @@ function startWith() { /***/ }), -/* 480 */ +/* 482 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return subscribeOn; }); -/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(481); +/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(483); /** PURE_IMPORTS_START _observable_SubscribeOnObservable PURE_IMPORTS_END */ function subscribeOn(scheduler, delay) { @@ -57328,7 +57411,7 @@ var SubscribeOnOperator = /*@__PURE__*/ (function () { /***/ }), -/* 481 */ +/* 483 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57392,13 +57475,13 @@ var SubscribeOnObservable = /*@__PURE__*/ (function (_super) { /***/ }), -/* 482 */ +/* 484 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return switchAll; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(483); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(485); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(25); /** PURE_IMPORTS_START _switchMap,_util_identity PURE_IMPORTS_END */ @@ -57410,7 +57493,7 @@ function switchAll() { /***/ }), -/* 483 */ +/* 485 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57498,13 +57581,13 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 484 */ +/* 486 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return switchMapTo; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(483); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(485); /** PURE_IMPORTS_START _switchMap PURE_IMPORTS_END */ function switchMapTo(innerObservable, resultSelector) { @@ -57514,7 +57597,7 @@ function switchMapTo(innerObservable, resultSelector) { /***/ }), -/* 485 */ +/* 487 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57562,7 +57645,7 @@ var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 486 */ +/* 488 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57630,7 +57713,7 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 487 */ +/* 489 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57718,7 +57801,7 @@ var TapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 488 */ +/* 490 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57820,7 +57903,7 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 489 */ +/* 491 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57829,7 +57912,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(55); -/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(488); +/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(490); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */ @@ -57918,7 +58001,7 @@ function dispatchNext(arg) { /***/ }), -/* 490 */ +/* 492 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57926,7 +58009,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return timeInterval; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeInterval", function() { return TimeInterval; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(450); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(452); /* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(91); /* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(66); /** PURE_IMPORTS_START _scheduler_async,_scan,_observable_defer,_map PURE_IMPORTS_END */ @@ -57962,7 +58045,7 @@ var TimeInterval = /*@__PURE__*/ (function () { /***/ }), -/* 491 */ +/* 493 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57970,7 +58053,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return timeout; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); /* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(64); -/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(492); +/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(494); /* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(49); /** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */ @@ -57987,7 +58070,7 @@ function timeout(due, scheduler) { /***/ }), -/* 492 */ +/* 494 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57995,7 +58078,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return timeoutWith; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(424); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(426); /* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(90); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_innerSubscribe PURE_IMPORTS_END */ @@ -58066,7 +58149,7 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 493 */ +/* 495 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58096,13 +58179,13 @@ var Timestamp = /*@__PURE__*/ (function () { /***/ }), -/* 494 */ +/* 496 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return toArray; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(449); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(451); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function toArrayReducer(arr, item, index) { @@ -58119,7 +58202,7 @@ function toArray() { /***/ }), -/* 495 */ +/* 497 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58197,7 +58280,7 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 496 */ +/* 498 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58287,7 +58370,7 @@ var WindowCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 497 */ +/* 499 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58457,7 +58540,7 @@ function dispatchWindowClose(state) { /***/ }), -/* 498 */ +/* 500 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58600,7 +58683,7 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 499 */ +/* 501 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58697,7 +58780,7 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 500 */ +/* 502 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58792,7 +58875,7 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 501 */ +/* 503 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58814,7 +58897,7 @@ function zip() { /***/ }), -/* 502 */ +/* 504 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58830,7 +58913,7 @@ function zipAll(project) { /***/ }), -/* 503 */ +/* 505 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58840,7 +58923,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(248); /* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(370); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(504); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(506); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -58911,7 +58994,7 @@ function toArray(value) { } /***/ }), -/* 504 */ +/* 506 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58919,13 +59002,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Kibana", function() { return Kibana; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(505); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(507); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(is_path_inside__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(365); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(248); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(509); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(511); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -59076,15 +59159,15 @@ class Kibana { } /***/ }), -/* 505 */ +/* 507 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const minimatch = __webpack_require__(150); -const arrayUnion = __webpack_require__(506); -const arrayDiffer = __webpack_require__(507); -const arrify = __webpack_require__(508); +const arrayUnion = __webpack_require__(508); +const arrayDiffer = __webpack_require__(509); +const arrify = __webpack_require__(510); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -59108,7 +59191,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 506 */ +/* 508 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59120,7 +59203,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 507 */ +/* 509 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59135,7 +59218,7 @@ module.exports = arrayDiffer; /***/ }), -/* 508 */ +/* 510 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59165,7 +59248,7 @@ module.exports = arrify; /***/ }), -/* 509 */ +/* 511 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59224,12 +59307,12 @@ function getProjectPaths({ } /***/ }), -/* 510 */ +/* 512 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(511); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(513); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); /* @@ -59242,19 +59325,19 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 511 */ +/* 513 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(512); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(514); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(143); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(509); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(511); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(131); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(246); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(251); @@ -59380,7 +59463,7 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { } /***/ }), -/* 512 */ +/* 514 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59388,14 +59471,14 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { const EventEmitter = __webpack_require__(156); const path = __webpack_require__(4); const os = __webpack_require__(121); -const pMap = __webpack_require__(513); -const arrify = __webpack_require__(508); -const globby = __webpack_require__(514); -const hasGlob = __webpack_require__(710); -const cpFile = __webpack_require__(712); -const junk = __webpack_require__(722); -const pFilter = __webpack_require__(723); -const CpyError = __webpack_require__(725); +const pMap = __webpack_require__(515); +const arrify = __webpack_require__(510); +const globby = __webpack_require__(516); +const hasGlob = __webpack_require__(712); +const cpFile = __webpack_require__(714); +const junk = __webpack_require__(724); +const pFilter = __webpack_require__(725); +const CpyError = __webpack_require__(727); const defaultOptions = { ignoreJunk: true @@ -59546,7 +59629,7 @@ module.exports = (source, destination, { /***/ }), -/* 513 */ +/* 515 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59634,17 +59717,17 @@ module.exports = async ( /***/ }), -/* 514 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); -const arrayUnion = __webpack_require__(515); +const arrayUnion = __webpack_require__(517); const glob = __webpack_require__(147); -const fastGlob = __webpack_require__(517); -const dirGlob = __webpack_require__(703); -const gitignore = __webpack_require__(706); +const fastGlob = __webpack_require__(519); +const dirGlob = __webpack_require__(705); +const gitignore = __webpack_require__(708); const DEFAULT_FILTER = () => false; @@ -59789,12 +59872,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 515 */ +/* 517 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(516); +var arrayUniq = __webpack_require__(518); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -59802,7 +59885,7 @@ module.exports = function () { /***/ }), -/* 516 */ +/* 518 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59871,10 +59954,10 @@ if ('Set' in global) { /***/ }), -/* 517 */ +/* 519 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(518); +const pkg = __webpack_require__(520); module.exports = pkg.async; module.exports.default = pkg.async; @@ -59887,19 +59970,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 518 */ +/* 520 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(519); -var taskManager = __webpack_require__(520); -var reader_async_1 = __webpack_require__(674); -var reader_stream_1 = __webpack_require__(698); -var reader_sync_1 = __webpack_require__(699); -var arrayUtils = __webpack_require__(701); -var streamUtils = __webpack_require__(702); +var optionsManager = __webpack_require__(521); +var taskManager = __webpack_require__(522); +var reader_async_1 = __webpack_require__(676); +var reader_stream_1 = __webpack_require__(700); +var reader_sync_1 = __webpack_require__(701); +var arrayUtils = __webpack_require__(703); +var streamUtils = __webpack_require__(704); /** * Synchronous API. */ @@ -59965,7 +60048,7 @@ function isString(source) { /***/ }), -/* 519 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60003,13 +60086,13 @@ exports.prepare = prepare; /***/ }), -/* 520 */ +/* 522 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(521); +var patternUtils = __webpack_require__(523); /** * Generate tasks based on parent directory of each pattern. */ @@ -60100,16 +60183,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 521 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var globParent = __webpack_require__(522); +var globParent = __webpack_require__(524); var isGlob = __webpack_require__(172); -var micromatch = __webpack_require__(525); +var micromatch = __webpack_require__(527); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -60255,15 +60338,15 @@ exports.matchAny = matchAny; /***/ }), -/* 522 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(4); -var isglob = __webpack_require__(523); -var pathDirname = __webpack_require__(524); +var isglob = __webpack_require__(525); +var pathDirname = __webpack_require__(526); var isWin32 = __webpack_require__(121).platform() === 'win32'; module.exports = function globParent(str) { @@ -60286,7 +60369,7 @@ module.exports = function globParent(str) { /***/ }), -/* 523 */ +/* 525 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -60317,7 +60400,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 524 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60467,7 +60550,7 @@ module.exports.win32 = win32; /***/ }), -/* 525 */ +/* 527 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60478,18 +60561,18 @@ module.exports.win32 = win32; */ var util = __webpack_require__(112); -var braces = __webpack_require__(526); -var toRegex = __webpack_require__(527); -var extend = __webpack_require__(640); +var braces = __webpack_require__(528); +var toRegex = __webpack_require__(529); +var extend = __webpack_require__(642); /** * Local dependencies */ -var compilers = __webpack_require__(642); -var parsers = __webpack_require__(669); -var cache = __webpack_require__(670); -var utils = __webpack_require__(671); +var compilers = __webpack_require__(644); +var parsers = __webpack_require__(671); +var cache = __webpack_require__(672); +var utils = __webpack_require__(673); var MAX_LENGTH = 1024 * 64; /** @@ -61351,7 +61434,7 @@ module.exports = micromatch; /***/ }), -/* 526 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61361,18 +61444,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(527); -var unique = __webpack_require__(549); -var extend = __webpack_require__(550); +var toRegex = __webpack_require__(529); +var unique = __webpack_require__(551); +var extend = __webpack_require__(552); /** * Local dependencies */ -var compilers = __webpack_require__(552); -var parsers = __webpack_require__(565); -var Braces = __webpack_require__(569); -var utils = __webpack_require__(553); +var compilers = __webpack_require__(554); +var parsers = __webpack_require__(567); +var Braces = __webpack_require__(571); +var utils = __webpack_require__(555); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -61676,16 +61759,16 @@ module.exports = braces; /***/ }), -/* 527 */ +/* 529 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(528); -var define = __webpack_require__(534); -var extend = __webpack_require__(542); -var not = __webpack_require__(546); +var safe = __webpack_require__(530); +var define = __webpack_require__(536); +var extend = __webpack_require__(544); +var not = __webpack_require__(548); var MAX_LENGTH = 1024 * 64; /** @@ -61838,10 +61921,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 528 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(529); +var parse = __webpack_require__(531); var types = parse.types; module.exports = function (re, opts) { @@ -61887,13 +61970,13 @@ function isRegExp (x) { /***/ }), -/* 529 */ +/* 531 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(530); -var types = __webpack_require__(531); -var sets = __webpack_require__(532); -var positions = __webpack_require__(533); +var util = __webpack_require__(532); +var types = __webpack_require__(533); +var sets = __webpack_require__(534); +var positions = __webpack_require__(535); module.exports = function(regexpStr) { @@ -62175,11 +62258,11 @@ module.exports.types = types; /***/ }), -/* 530 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(531); -var sets = __webpack_require__(532); +var types = __webpack_require__(533); +var sets = __webpack_require__(534); // All of these are private and only used by randexp. @@ -62292,7 +62375,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 531 */ +/* 533 */ /***/ (function(module, exports) { module.exports = { @@ -62308,10 +62391,10 @@ module.exports = { /***/ }), -/* 532 */ +/* 534 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(531); +var types = __webpack_require__(533); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -62396,10 +62479,10 @@ exports.anyChar = function() { /***/ }), -/* 533 */ +/* 535 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(531); +var types = __webpack_require__(533); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -62419,7 +62502,7 @@ exports.end = function() { /***/ }), -/* 534 */ +/* 536 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62432,8 +62515,8 @@ exports.end = function() { -var isobject = __webpack_require__(535); -var isDescriptor = __webpack_require__(536); +var isobject = __webpack_require__(537); +var isDescriptor = __webpack_require__(538); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -62464,7 +62547,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 535 */ +/* 537 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62483,7 +62566,7 @@ module.exports = function isObject(val) { /***/ }), -/* 536 */ +/* 538 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62496,9 +62579,9 @@ module.exports = function isObject(val) { -var typeOf = __webpack_require__(537); -var isAccessor = __webpack_require__(538); -var isData = __webpack_require__(540); +var typeOf = __webpack_require__(539); +var isAccessor = __webpack_require__(540); +var isData = __webpack_require__(542); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -62512,7 +62595,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 537 */ +/* 539 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -62647,7 +62730,7 @@ function isBuffer(val) { /***/ }), -/* 538 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62660,7 +62743,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(539); +var typeOf = __webpack_require__(541); // accessor descriptor properties var accessor = { @@ -62723,7 +62806,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 539 */ +/* 541 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -62858,7 +62941,7 @@ function isBuffer(val) { /***/ }), -/* 540 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62871,7 +62954,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(541); +var typeOf = __webpack_require__(543); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -62914,7 +62997,7 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 541 */ +/* 543 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -63049,14 +63132,14 @@ function isBuffer(val) { /***/ }), -/* 542 */ +/* 544 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(543); -var assignSymbols = __webpack_require__(545); +var isExtendable = __webpack_require__(545); +var assignSymbols = __webpack_require__(547); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -63116,7 +63199,7 @@ function isEnum(obj, key) { /***/ }), -/* 543 */ +/* 545 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63129,7 +63212,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(544); +var isPlainObject = __webpack_require__(546); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -63137,7 +63220,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 544 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63150,7 +63233,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(535); +var isObject = __webpack_require__(537); function isObjectObject(o) { return isObject(o) === true @@ -63181,7 +63264,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 545 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63228,14 +63311,14 @@ module.exports = function(receiver, objects) { /***/ }), -/* 546 */ +/* 548 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(547); -var safe = __webpack_require__(528); +var extend = __webpack_require__(549); +var safe = __webpack_require__(530); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -63307,14 +63390,14 @@ module.exports = toRegex; /***/ }), -/* 547 */ +/* 549 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(548); -var assignSymbols = __webpack_require__(545); +var isExtendable = __webpack_require__(550); +var assignSymbols = __webpack_require__(547); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -63374,7 +63457,7 @@ function isEnum(obj, key) { /***/ }), -/* 548 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63387,7 +63470,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(544); +var isPlainObject = __webpack_require__(546); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -63395,7 +63478,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 549 */ +/* 551 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63445,13 +63528,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 550 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(551); +var isObject = __webpack_require__(553); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -63485,7 +63568,7 @@ function hasOwn(obj, key) { /***/ }), -/* 551 */ +/* 553 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63505,13 +63588,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 552 */ +/* 554 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(553); +var utils = __webpack_require__(555); module.exports = function(braces, options) { braces.compiler @@ -63794,25 +63877,25 @@ function hasQueue(node) { /***/ }), -/* 553 */ +/* 555 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(554); +var splitString = __webpack_require__(556); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(550); -utils.flatten = __webpack_require__(557); -utils.isObject = __webpack_require__(535); -utils.fillRange = __webpack_require__(558); -utils.repeat = __webpack_require__(564); -utils.unique = __webpack_require__(549); +utils.extend = __webpack_require__(552); +utils.flatten = __webpack_require__(559); +utils.isObject = __webpack_require__(537); +utils.fillRange = __webpack_require__(560); +utils.repeat = __webpack_require__(566); +utils.unique = __webpack_require__(551); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -64144,7 +64227,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 554 */ +/* 556 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64157,7 +64240,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(555); +var extend = __webpack_require__(557); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -64322,14 +64405,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 555 */ +/* 557 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(556); -var assignSymbols = __webpack_require__(545); +var isExtendable = __webpack_require__(558); +var assignSymbols = __webpack_require__(547); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -64389,7 +64472,7 @@ function isEnum(obj, key) { /***/ }), -/* 556 */ +/* 558 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64402,7 +64485,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(544); +var isPlainObject = __webpack_require__(546); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -64410,7 +64493,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 557 */ +/* 559 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64439,7 +64522,7 @@ function flat(arr, res) { /***/ }), -/* 558 */ +/* 560 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64453,10 +64536,10 @@ function flat(arr, res) { var util = __webpack_require__(112); -var isNumber = __webpack_require__(559); -var extend = __webpack_require__(550); -var repeat = __webpack_require__(562); -var toRegex = __webpack_require__(563); +var isNumber = __webpack_require__(561); +var extend = __webpack_require__(552); +var repeat = __webpack_require__(564); +var toRegex = __webpack_require__(565); /** * Return a range of numbers or letters. @@ -64654,7 +64737,7 @@ module.exports = fillRange; /***/ }), -/* 559 */ +/* 561 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64667,7 +64750,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(560); +var typeOf = __webpack_require__(562); module.exports = function isNumber(num) { var type = typeOf(num); @@ -64683,10 +64766,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 560 */ +/* 562 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(561); +var isBuffer = __webpack_require__(563); var toString = Object.prototype.toString; /** @@ -64805,7 +64888,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 561 */ +/* 563 */ /***/ (function(module, exports) { /*! @@ -64832,7 +64915,7 @@ function isSlowBuffer (obj) { /***/ }), -/* 562 */ +/* 564 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64909,7 +64992,7 @@ function repeat(str, num) { /***/ }), -/* 563 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64922,8 +65005,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(562); -var isNumber = __webpack_require__(559); +var repeat = __webpack_require__(564); +var isNumber = __webpack_require__(561); var cache = {}; function toRegexRange(min, max, options) { @@ -65210,7 +65293,7 @@ module.exports = toRegexRange; /***/ }), -/* 564 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65235,14 +65318,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 565 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(566); -var utils = __webpack_require__(553); +var Node = __webpack_require__(568); +var utils = __webpack_require__(555); /** * Braces parsers @@ -65602,15 +65685,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 566 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(535); -var define = __webpack_require__(567); -var utils = __webpack_require__(568); +var isObject = __webpack_require__(537); +var define = __webpack_require__(569); +var utils = __webpack_require__(570); var ownNames; /** @@ -66101,7 +66184,7 @@ exports = module.exports = Node; /***/ }), -/* 567 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66114,7 +66197,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(536); +var isDescriptor = __webpack_require__(538); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -66139,13 +66222,13 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 568 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(560); +var typeOf = __webpack_require__(562); var utils = module.exports; /** @@ -67165,17 +67248,17 @@ function assert(val, message) { /***/ }), -/* 569 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(550); -var Snapdragon = __webpack_require__(570); -var compilers = __webpack_require__(552); -var parsers = __webpack_require__(565); -var utils = __webpack_require__(553); +var extend = __webpack_require__(552); +var Snapdragon = __webpack_require__(572); +var compilers = __webpack_require__(554); +var parsers = __webpack_require__(567); +var utils = __webpack_require__(555); /** * Customize Snapdragon parser and renderer @@ -67276,17 +67359,17 @@ module.exports = Braces; /***/ }), -/* 570 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(571); -var define = __webpack_require__(598); -var Compiler = __webpack_require__(608); -var Parser = __webpack_require__(637); -var utils = __webpack_require__(617); +var Base = __webpack_require__(573); +var define = __webpack_require__(600); +var Compiler = __webpack_require__(610); +var Parser = __webpack_require__(639); +var utils = __webpack_require__(619); var regexCache = {}; var cache = {}; @@ -67457,20 +67540,20 @@ module.exports.Parser = Parser; /***/ }), -/* 571 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(112); -var define = __webpack_require__(572); -var CacheBase = __webpack_require__(573); -var Emitter = __webpack_require__(574); -var isObject = __webpack_require__(535); -var merge = __webpack_require__(592); -var pascal = __webpack_require__(595); -var cu = __webpack_require__(596); +var define = __webpack_require__(574); +var CacheBase = __webpack_require__(575); +var Emitter = __webpack_require__(576); +var isObject = __webpack_require__(537); +var merge = __webpack_require__(594); +var pascal = __webpack_require__(597); +var cu = __webpack_require__(598); /** * Optionally define a custom `cache` namespace to use. @@ -67899,7 +67982,7 @@ module.exports.namespace = namespace; /***/ }), -/* 572 */ +/* 574 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67912,7 +67995,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(536); +var isDescriptor = __webpack_require__(538); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -67937,21 +68020,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 573 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(535); -var Emitter = __webpack_require__(574); -var visit = __webpack_require__(575); -var toPath = __webpack_require__(578); -var union = __webpack_require__(579); -var del = __webpack_require__(583); -var get = __webpack_require__(581); -var has = __webpack_require__(588); -var set = __webpack_require__(591); +var isObject = __webpack_require__(537); +var Emitter = __webpack_require__(576); +var visit = __webpack_require__(577); +var toPath = __webpack_require__(580); +var union = __webpack_require__(581); +var del = __webpack_require__(585); +var get = __webpack_require__(583); +var has = __webpack_require__(590); +var set = __webpack_require__(593); /** * Create a `Cache` constructor that when instantiated will @@ -68205,7 +68288,7 @@ module.exports.namespace = namespace; /***/ }), -/* 574 */ +/* 576 */ /***/ (function(module, exports, __webpack_require__) { @@ -68374,7 +68457,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 575 */ +/* 577 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68387,8 +68470,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(576); -var mapVisit = __webpack_require__(577); +var visit = __webpack_require__(578); +var mapVisit = __webpack_require__(579); module.exports = function(collection, method, val) { var result; @@ -68411,7 +68494,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 576 */ +/* 578 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68424,7 +68507,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(535); +var isObject = __webpack_require__(537); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -68451,14 +68534,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 577 */ +/* 579 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(112); -var visit = __webpack_require__(576); +var visit = __webpack_require__(578); /** * Map `visit` over an array of objects. @@ -68495,7 +68578,7 @@ function isObject(val) { /***/ }), -/* 578 */ +/* 580 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68508,7 +68591,7 @@ function isObject(val) { -var typeOf = __webpack_require__(560); +var typeOf = __webpack_require__(562); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -68535,16 +68618,16 @@ function filter(arr) { /***/ }), -/* 579 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(551); -var union = __webpack_require__(580); -var get = __webpack_require__(581); -var set = __webpack_require__(582); +var isObject = __webpack_require__(553); +var union = __webpack_require__(582); +var get = __webpack_require__(583); +var set = __webpack_require__(584); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -68572,7 +68655,7 @@ function arrayify(val) { /***/ }), -/* 580 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68608,7 +68691,7 @@ module.exports = function union(init) { /***/ }), -/* 581 */ +/* 583 */ /***/ (function(module, exports) { /*! @@ -68664,7 +68747,7 @@ function toString(val) { /***/ }), -/* 582 */ +/* 584 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68677,10 +68760,10 @@ function toString(val) { -var split = __webpack_require__(554); -var extend = __webpack_require__(550); -var isPlainObject = __webpack_require__(544); -var isObject = __webpack_require__(551); +var split = __webpack_require__(556); +var extend = __webpack_require__(552); +var isPlainObject = __webpack_require__(546); +var isObject = __webpack_require__(553); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -68726,7 +68809,7 @@ function isValidKey(key) { /***/ }), -/* 583 */ +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68739,8 +68822,8 @@ function isValidKey(key) { -var isObject = __webpack_require__(535); -var has = __webpack_require__(584); +var isObject = __webpack_require__(537); +var has = __webpack_require__(586); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -68765,7 +68848,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 584 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68778,9 +68861,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(585); -var hasValues = __webpack_require__(587); -var get = __webpack_require__(581); +var isObject = __webpack_require__(587); +var hasValues = __webpack_require__(589); +var get = __webpack_require__(583); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -68791,7 +68874,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 585 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68804,7 +68887,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(586); +var isArray = __webpack_require__(588); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -68812,7 +68895,7 @@ module.exports = function isObject(val) { /***/ }), -/* 586 */ +/* 588 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -68823,7 +68906,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 587 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68866,7 +68949,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 588 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68879,9 +68962,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(535); -var hasValues = __webpack_require__(589); -var get = __webpack_require__(581); +var isObject = __webpack_require__(537); +var hasValues = __webpack_require__(591); +var get = __webpack_require__(583); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -68889,7 +68972,7 @@ module.exports = function(val, prop) { /***/ }), -/* 589 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68902,8 +68985,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(590); -var isNumber = __webpack_require__(559); +var typeOf = __webpack_require__(592); +var isNumber = __webpack_require__(561); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -68956,10 +69039,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 590 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(561); +var isBuffer = __webpack_require__(563); var toString = Object.prototype.toString; /** @@ -69081,7 +69164,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 591 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69094,10 +69177,10 @@ module.exports = function kindOf(val) { -var split = __webpack_require__(554); -var extend = __webpack_require__(550); -var isPlainObject = __webpack_require__(544); -var isObject = __webpack_require__(551); +var split = __webpack_require__(556); +var extend = __webpack_require__(552); +var isPlainObject = __webpack_require__(546); +var isObject = __webpack_require__(553); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -69143,14 +69226,14 @@ function isValidKey(key) { /***/ }), -/* 592 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(593); -var forIn = __webpack_require__(594); +var isExtendable = __webpack_require__(595); +var forIn = __webpack_require__(596); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -69214,7 +69297,7 @@ module.exports = mixinDeep; /***/ }), -/* 593 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69227,7 +69310,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(544); +var isPlainObject = __webpack_require__(546); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -69235,7 +69318,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 594 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69258,7 +69341,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 595 */ +/* 597 */ /***/ (function(module, exports) { /*! @@ -69285,14 +69368,14 @@ module.exports = pascalcase; /***/ }), -/* 596 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(112); -var utils = __webpack_require__(597); +var utils = __webpack_require__(599); /** * Expose class utils @@ -69657,7 +69740,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 597 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69671,10 +69754,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(580); -utils.define = __webpack_require__(598); -utils.isObj = __webpack_require__(535); -utils.staticExtend = __webpack_require__(605); +utils.union = __webpack_require__(582); +utils.define = __webpack_require__(600); +utils.isObj = __webpack_require__(537); +utils.staticExtend = __webpack_require__(607); /** @@ -69685,7 +69768,7 @@ module.exports = utils; /***/ }), -/* 598 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69698,7 +69781,7 @@ module.exports = utils; -var isDescriptor = __webpack_require__(599); +var isDescriptor = __webpack_require__(601); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -69723,7 +69806,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 599 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69736,9 +69819,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(600); -var isAccessor = __webpack_require__(601); -var isData = __webpack_require__(603); +var typeOf = __webpack_require__(602); +var isAccessor = __webpack_require__(603); +var isData = __webpack_require__(605); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -69752,7 +69835,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 600 */ +/* 602 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -69905,7 +69988,7 @@ function isBuffer(val) { /***/ }), -/* 601 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69918,7 +70001,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(602); +var typeOf = __webpack_require__(604); // accessor descriptor properties var accessor = { @@ -69981,10 +70064,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 602 */ +/* 604 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(561); +var isBuffer = __webpack_require__(563); var toString = Object.prototype.toString; /** @@ -70103,7 +70186,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 603 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70116,7 +70199,7 @@ module.exports = function kindOf(val) { -var typeOf = __webpack_require__(604); +var typeOf = __webpack_require__(606); // data descriptor properties var data = { @@ -70165,10 +70248,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 604 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(561); +var isBuffer = __webpack_require__(563); var toString = Object.prototype.toString; /** @@ -70287,7 +70370,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 605 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70300,8 +70383,8 @@ module.exports = function kindOf(val) { -var copy = __webpack_require__(606); -var define = __webpack_require__(598); +var copy = __webpack_require__(608); +var define = __webpack_require__(600); var util = __webpack_require__(112); /** @@ -70384,15 +70467,15 @@ module.exports = extend; /***/ }), -/* 606 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(560); -var copyDescriptor = __webpack_require__(607); -var define = __webpack_require__(598); +var typeOf = __webpack_require__(562); +var copyDescriptor = __webpack_require__(609); +var define = __webpack_require__(600); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -70565,7 +70648,7 @@ module.exports.has = has; /***/ }), -/* 607 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70653,16 +70736,16 @@ function isObject(val) { /***/ }), -/* 608 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(609); -var define = __webpack_require__(598); -var debug = __webpack_require__(611)('snapdragon:compiler'); -var utils = __webpack_require__(617); +var use = __webpack_require__(611); +var define = __webpack_require__(600); +var debug = __webpack_require__(613)('snapdragon:compiler'); +var utils = __webpack_require__(619); /** * Create a new `Compiler` with the given `options`. @@ -70816,7 +70899,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(636); + var sourcemaps = __webpack_require__(638); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -70837,7 +70920,7 @@ module.exports = Compiler; /***/ }), -/* 609 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70850,7 +70933,7 @@ module.exports = Compiler; -var utils = __webpack_require__(610); +var utils = __webpack_require__(612); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -70965,7 +71048,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 610 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70979,8 +71062,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(598); -utils.isObject = __webpack_require__(535); +utils.define = __webpack_require__(600); +utils.isObject = __webpack_require__(537); utils.isString = function(val) { @@ -70995,7 +71078,7 @@ module.exports = utils; /***/ }), -/* 611 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -71004,14 +71087,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(612); + module.exports = __webpack_require__(614); } else { - module.exports = __webpack_require__(615); + module.exports = __webpack_require__(617); } /***/ }), -/* 612 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -71020,7 +71103,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(613); +exports = module.exports = __webpack_require__(615); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -71202,7 +71285,7 @@ function localstorage() { /***/ }), -/* 613 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { @@ -71218,7 +71301,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(614); +exports.humanize = __webpack_require__(616); /** * The currently active debug mode names, and names to skip. @@ -71410,7 +71493,7 @@ function coerce(val) { /***/ }), -/* 614 */ +/* 616 */ /***/ (function(module, exports) { /** @@ -71568,7 +71651,7 @@ function plural(ms, n, name) { /***/ }), -/* 615 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -71584,7 +71667,7 @@ var util = __webpack_require__(112); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(613); +exports = module.exports = __webpack_require__(615); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -71763,7 +71846,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(616); + var net = __webpack_require__(618); stream = new net.Socket({ fd: fd, readable: false, @@ -71822,13 +71905,13 @@ exports.enable(load()); /***/ }), -/* 616 */ +/* 618 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 617 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71838,9 +71921,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(550); -exports.SourceMap = __webpack_require__(618); -exports.sourceMapResolve = __webpack_require__(629); +exports.extend = __webpack_require__(552); +exports.SourceMap = __webpack_require__(620); +exports.sourceMapResolve = __webpack_require__(631); /** * Convert backslash in the given string to forward slashes @@ -71883,7 +71966,7 @@ exports.last = function(arr, n) { /***/ }), -/* 618 */ +/* 620 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -71891,13 +71974,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(619).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(625).SourceMapConsumer; -exports.SourceNode = __webpack_require__(628).SourceNode; +exports.SourceMapGenerator = __webpack_require__(621).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(627).SourceMapConsumer; +exports.SourceNode = __webpack_require__(630).SourceNode; /***/ }), -/* 619 */ +/* 621 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -71907,10 +71990,10 @@ exports.SourceNode = __webpack_require__(628).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(620); -var util = __webpack_require__(622); -var ArraySet = __webpack_require__(623).ArraySet; -var MappingList = __webpack_require__(624).MappingList; +var base64VLQ = __webpack_require__(622); +var util = __webpack_require__(624); +var ArraySet = __webpack_require__(625).ArraySet; +var MappingList = __webpack_require__(626).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -72319,7 +72402,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 620 */ +/* 622 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -72359,7 +72442,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(621); +var base64 = __webpack_require__(623); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -72465,7 +72548,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 621 */ +/* 623 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -72538,7 +72621,7 @@ exports.decode = function (charCode) { /***/ }), -/* 622 */ +/* 624 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -72961,7 +73044,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 623 */ +/* 625 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -72971,7 +73054,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(622); +var util = __webpack_require__(624); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -73088,7 +73171,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 624 */ +/* 626 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73098,7 +73181,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(622); +var util = __webpack_require__(624); /** * Determine whether mappingB is after mappingA with respect to generated @@ -73173,7 +73256,7 @@ exports.MappingList = MappingList; /***/ }), -/* 625 */ +/* 627 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73183,11 +73266,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(622); -var binarySearch = __webpack_require__(626); -var ArraySet = __webpack_require__(623).ArraySet; -var base64VLQ = __webpack_require__(620); -var quickSort = __webpack_require__(627).quickSort; +var util = __webpack_require__(624); +var binarySearch = __webpack_require__(628); +var ArraySet = __webpack_require__(625).ArraySet; +var base64VLQ = __webpack_require__(622); +var quickSort = __webpack_require__(629).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -74261,7 +74344,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 626 */ +/* 628 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74378,7 +74461,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 627 */ +/* 629 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74498,7 +74581,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 628 */ +/* 630 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74508,8 +74591,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(619).SourceMapGenerator; -var util = __webpack_require__(622); +var SourceMapGenerator = __webpack_require__(621).SourceMapGenerator; +var util = __webpack_require__(624); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -74917,17 +75000,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 629 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(630) -var resolveUrl = __webpack_require__(631) -var decodeUriComponent = __webpack_require__(632) -var urix = __webpack_require__(634) -var atob = __webpack_require__(635) +var sourceMappingURL = __webpack_require__(632) +var resolveUrl = __webpack_require__(633) +var decodeUriComponent = __webpack_require__(634) +var urix = __webpack_require__(636) +var atob = __webpack_require__(637) @@ -75225,7 +75308,7 @@ module.exports = { /***/ }), -/* 630 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -75288,7 +75371,7 @@ void (function(root, factory) { /***/ }), -/* 631 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -75306,13 +75389,13 @@ module.exports = resolveUrl /***/ }), -/* 632 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(633) +var decodeUriComponent = __webpack_require__(635) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -75323,7 +75406,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 633 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75424,7 +75507,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 634 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -75447,7 +75530,7 @@ module.exports = urix /***/ }), -/* 635 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75461,7 +75544,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 636 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75469,8 +75552,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(134); var path = __webpack_require__(4); -var define = __webpack_require__(598); -var utils = __webpack_require__(617); +var define = __webpack_require__(600); +var utils = __webpack_require__(619); /** * Expose `mixin()`. @@ -75613,19 +75696,19 @@ exports.comment = function(node) { /***/ }), -/* 637 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(609); +var use = __webpack_require__(611); var util = __webpack_require__(112); -var Cache = __webpack_require__(638); -var define = __webpack_require__(598); -var debug = __webpack_require__(611)('snapdragon:parser'); -var Position = __webpack_require__(639); -var utils = __webpack_require__(617); +var Cache = __webpack_require__(640); +var define = __webpack_require__(600); +var debug = __webpack_require__(613)('snapdragon:parser'); +var Position = __webpack_require__(641); +var utils = __webpack_require__(619); /** * Create a new `Parser` with the given `input` and `options`. @@ -76153,7 +76236,7 @@ module.exports = Parser; /***/ }), -/* 638 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76260,13 +76343,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 639 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(598); +var define = __webpack_require__(600); /** * Store position for a node @@ -76281,14 +76364,14 @@ module.exports = function Position(start, parser) { /***/ }), -/* 640 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(641); -var assignSymbols = __webpack_require__(545); +var isExtendable = __webpack_require__(643); +var assignSymbols = __webpack_require__(547); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -76348,7 +76431,7 @@ function isEnum(obj, key) { /***/ }), -/* 641 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76361,7 +76444,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(544); +var isPlainObject = __webpack_require__(546); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -76369,14 +76452,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 642 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(643); -var extglob = __webpack_require__(658); +var nanomatch = __webpack_require__(645); +var extglob = __webpack_require__(660); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -76453,7 +76536,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 643 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76464,17 +76547,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(112); -var toRegex = __webpack_require__(527); -var extend = __webpack_require__(644); +var toRegex = __webpack_require__(529); +var extend = __webpack_require__(646); /** * Local dependencies */ -var compilers = __webpack_require__(646); -var parsers = __webpack_require__(647); -var cache = __webpack_require__(650); -var utils = __webpack_require__(652); +var compilers = __webpack_require__(648); +var parsers = __webpack_require__(649); +var cache = __webpack_require__(652); +var utils = __webpack_require__(654); var MAX_LENGTH = 1024 * 64; /** @@ -77298,14 +77381,14 @@ module.exports = nanomatch; /***/ }), -/* 644 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(645); -var assignSymbols = __webpack_require__(545); +var isExtendable = __webpack_require__(647); +var assignSymbols = __webpack_require__(547); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -77365,7 +77448,7 @@ function isEnum(obj, key) { /***/ }), -/* 645 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77378,7 +77461,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(544); +var isPlainObject = __webpack_require__(546); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -77386,7 +77469,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 646 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77732,15 +77815,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 647 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(546); -var toRegex = __webpack_require__(527); -var isOdd = __webpack_require__(648); +var regexNot = __webpack_require__(548); +var toRegex = __webpack_require__(529); +var isOdd = __webpack_require__(650); /** * Characters to use in negation regex (we want to "not" match @@ -78126,7 +78209,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 648 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78139,7 +78222,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(649); +var isNumber = __webpack_require__(651); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -78153,7 +78236,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 649 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78181,14 +78264,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 650 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(651))(); +module.exports = new (__webpack_require__(653))(); /***/ }), -/* 651 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78201,7 +78284,7 @@ module.exports = new (__webpack_require__(651))(); -var MapCache = __webpack_require__(638); +var MapCache = __webpack_require__(640); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -78323,7 +78406,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 652 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78336,14 +78419,14 @@ var path = __webpack_require__(4); * Module dependencies */ -var isWindows = __webpack_require__(653)(); -var Snapdragon = __webpack_require__(570); -utils.define = __webpack_require__(654); -utils.diff = __webpack_require__(655); -utils.extend = __webpack_require__(644); -utils.pick = __webpack_require__(656); -utils.typeOf = __webpack_require__(657); -utils.unique = __webpack_require__(549); +var isWindows = __webpack_require__(655)(); +var Snapdragon = __webpack_require__(572); +utils.define = __webpack_require__(656); +utils.diff = __webpack_require__(657); +utils.extend = __webpack_require__(646); +utils.pick = __webpack_require__(658); +utils.typeOf = __webpack_require__(659); +utils.unique = __webpack_require__(551); /** * Returns true if the given value is effectively an empty string @@ -78709,7 +78792,7 @@ utils.unixify = function(options) { /***/ }), -/* 653 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -78737,7 +78820,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 654 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78750,8 +78833,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(535); -var isDescriptor = __webpack_require__(536); +var isobject = __webpack_require__(537); +var isDescriptor = __webpack_require__(538); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -78782,7 +78865,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 655 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78836,7 +78919,7 @@ function diffArray(one, two) { /***/ }), -/* 656 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78849,7 +78932,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(535); +var isObject = __webpack_require__(537); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -78878,7 +78961,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 657 */ +/* 659 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -79013,7 +79096,7 @@ function isBuffer(val) { /***/ }), -/* 658 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79023,18 +79106,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(550); -var unique = __webpack_require__(549); -var toRegex = __webpack_require__(527); +var extend = __webpack_require__(552); +var unique = __webpack_require__(551); +var toRegex = __webpack_require__(529); /** * Local dependencies */ -var compilers = __webpack_require__(659); -var parsers = __webpack_require__(665); -var Extglob = __webpack_require__(668); -var utils = __webpack_require__(667); +var compilers = __webpack_require__(661); +var parsers = __webpack_require__(667); +var Extglob = __webpack_require__(670); +var utils = __webpack_require__(669); var MAX_LENGTH = 1024 * 64; /** @@ -79351,13 +79434,13 @@ module.exports = extglob; /***/ }), -/* 659 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(660); +var brackets = __webpack_require__(662); /** * Extglob compilers @@ -79527,7 +79610,7 @@ module.exports = function(extglob) { /***/ }), -/* 660 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79537,17 +79620,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(661); -var parsers = __webpack_require__(663); +var compilers = __webpack_require__(663); +var parsers = __webpack_require__(665); /** * Module dependencies */ -var debug = __webpack_require__(611)('expand-brackets'); -var extend = __webpack_require__(550); -var Snapdragon = __webpack_require__(570); -var toRegex = __webpack_require__(527); +var debug = __webpack_require__(613)('expand-brackets'); +var extend = __webpack_require__(552); +var Snapdragon = __webpack_require__(572); +var toRegex = __webpack_require__(529); /** * Parses the given POSIX character class `pattern` and returns a @@ -79745,13 +79828,13 @@ module.exports = brackets; /***/ }), -/* 661 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(662); +var posix = __webpack_require__(664); module.exports = function(brackets) { brackets.compiler @@ -79839,7 +79922,7 @@ module.exports = function(brackets) { /***/ }), -/* 662 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79868,14 +79951,14 @@ module.exports = { /***/ }), -/* 663 */ +/* 665 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(664); -var define = __webpack_require__(598); +var utils = __webpack_require__(666); +var define = __webpack_require__(600); /** * Text regex @@ -80094,14 +80177,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 664 */ +/* 666 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(527); -var regexNot = __webpack_require__(546); +var toRegex = __webpack_require__(529); +var regexNot = __webpack_require__(548); var cached; /** @@ -80135,15 +80218,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 665 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(660); -var define = __webpack_require__(666); -var utils = __webpack_require__(667); +var brackets = __webpack_require__(662); +var define = __webpack_require__(668); +var utils = __webpack_require__(669); /** * Characters to use in text regex (we want to "not" match @@ -80298,7 +80381,7 @@ module.exports = parsers; /***/ }), -/* 666 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80311,7 +80394,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(536); +var isDescriptor = __webpack_require__(538); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -80336,14 +80419,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 667 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(546); -var Cache = __webpack_require__(651); +var regex = __webpack_require__(548); +var Cache = __webpack_require__(653); /** * Utils @@ -80412,7 +80495,7 @@ utils.createRegex = function(str) { /***/ }), -/* 668 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80422,16 +80505,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(570); -var define = __webpack_require__(666); -var extend = __webpack_require__(550); +var Snapdragon = __webpack_require__(572); +var define = __webpack_require__(668); +var extend = __webpack_require__(552); /** * Local dependencies */ -var compilers = __webpack_require__(659); -var parsers = __webpack_require__(665); +var compilers = __webpack_require__(661); +var parsers = __webpack_require__(667); /** * Customize Snapdragon parser and renderer @@ -80497,16 +80580,16 @@ module.exports = Extglob; /***/ }), -/* 669 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(658); -var nanomatch = __webpack_require__(643); -var regexNot = __webpack_require__(546); -var toRegex = __webpack_require__(527); +var extglob = __webpack_require__(660); +var nanomatch = __webpack_require__(645); +var regexNot = __webpack_require__(548); +var toRegex = __webpack_require__(529); var not; /** @@ -80587,14 +80670,14 @@ function textRegex(pattern) { /***/ }), -/* 670 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(651))(); +module.exports = new (__webpack_require__(653))(); /***/ }), -/* 671 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80607,13 +80690,13 @@ var path = __webpack_require__(4); * Module dependencies */ -var Snapdragon = __webpack_require__(570); -utils.define = __webpack_require__(672); -utils.diff = __webpack_require__(655); -utils.extend = __webpack_require__(640); -utils.pick = __webpack_require__(656); -utils.typeOf = __webpack_require__(673); -utils.unique = __webpack_require__(549); +var Snapdragon = __webpack_require__(572); +utils.define = __webpack_require__(674); +utils.diff = __webpack_require__(657); +utils.extend = __webpack_require__(642); +utils.pick = __webpack_require__(658); +utils.typeOf = __webpack_require__(675); +utils.unique = __webpack_require__(551); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -80910,7 +80993,7 @@ utils.unixify = function(options) { /***/ }), -/* 672 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80923,8 +81006,8 @@ utils.unixify = function(options) { -var isobject = __webpack_require__(535); -var isDescriptor = __webpack_require__(536); +var isobject = __webpack_require__(537); +var isDescriptor = __webpack_require__(538); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -80955,7 +81038,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 673 */ +/* 675 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -81090,7 +81173,7 @@ function isBuffer(val) { /***/ }), -/* 674 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81109,9 +81192,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(675); -var reader_1 = __webpack_require__(688); -var fs_stream_1 = __webpack_require__(692); +var readdir = __webpack_require__(677); +var reader_1 = __webpack_require__(690); +var fs_stream_1 = __webpack_require__(694); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -81172,15 +81255,15 @@ exports.default = ReaderAsync; /***/ }), -/* 675 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(676); -const readdirAsync = __webpack_require__(684); -const readdirStream = __webpack_require__(687); +const readdirSync = __webpack_require__(678); +const readdirAsync = __webpack_require__(686); +const readdirStream = __webpack_require__(689); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -81264,7 +81347,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 676 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81272,11 +81355,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(677); +const DirectoryReader = __webpack_require__(679); let syncFacade = { - fs: __webpack_require__(682), - forEach: __webpack_require__(683), + fs: __webpack_require__(684), + forEach: __webpack_require__(685), sync: true }; @@ -81305,7 +81388,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 677 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81314,9 +81397,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(138).Readable; const EventEmitter = __webpack_require__(156).EventEmitter; const path = __webpack_require__(4); -const normalizeOptions = __webpack_require__(678); -const stat = __webpack_require__(680); -const call = __webpack_require__(681); +const normalizeOptions = __webpack_require__(680); +const stat = __webpack_require__(682); +const call = __webpack_require__(683); /** * Asynchronously reads the contents of a directory and streams the results @@ -81692,14 +81775,14 @@ module.exports = DirectoryReader; /***/ }), -/* 678 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const globToRegExp = __webpack_require__(679); +const globToRegExp = __webpack_require__(681); module.exports = normalizeOptions; @@ -81876,7 +81959,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 679 */ +/* 681 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -82013,13 +82096,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 680 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(681); +const call = __webpack_require__(683); module.exports = stat; @@ -82094,7 +82177,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 681 */ +/* 683 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82155,14 +82238,14 @@ function callOnce (fn) { /***/ }), -/* 682 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); -const call = __webpack_require__(681); +const call = __webpack_require__(683); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -82226,7 +82309,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 683 */ +/* 685 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82255,7 +82338,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 684 */ +/* 686 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82263,12 +82346,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(685); -const DirectoryReader = __webpack_require__(677); +const maybe = __webpack_require__(687); +const DirectoryReader = __webpack_require__(679); let asyncFacade = { fs: __webpack_require__(134), - forEach: __webpack_require__(686), + forEach: __webpack_require__(688), async: true }; @@ -82310,7 +82393,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 685 */ +/* 687 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82337,7 +82420,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 686 */ +/* 688 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82373,7 +82456,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 687 */ +/* 689 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82381,11 +82464,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(677); +const DirectoryReader = __webpack_require__(679); let streamFacade = { fs: __webpack_require__(134), - forEach: __webpack_require__(686), + forEach: __webpack_require__(688), async: true }; @@ -82405,16 +82488,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 688 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var deep_1 = __webpack_require__(689); -var entry_1 = __webpack_require__(691); -var pathUtil = __webpack_require__(690); +var deep_1 = __webpack_require__(691); +var entry_1 = __webpack_require__(693); +var pathUtil = __webpack_require__(692); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -82480,14 +82563,14 @@ exports.default = Reader; /***/ }), -/* 689 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(690); -var patternUtils = __webpack_require__(521); +var pathUtils = __webpack_require__(692); +var patternUtils = __webpack_require__(523); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -82570,7 +82653,7 @@ exports.default = DeepFilter; /***/ }), -/* 690 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82601,14 +82684,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 691 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(690); -var patternUtils = __webpack_require__(521); +var pathUtils = __webpack_require__(692); +var patternUtils = __webpack_require__(523); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -82693,7 +82776,7 @@ exports.default = EntryFilter; /***/ }), -/* 692 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82713,8 +82796,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(138); -var fsStat = __webpack_require__(693); -var fs_1 = __webpack_require__(697); +var fsStat = __webpack_require__(695); +var fs_1 = __webpack_require__(699); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -82764,14 +82847,14 @@ exports.default = FileSystemStream; /***/ }), -/* 693 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(694); -const statProvider = __webpack_require__(696); +const optionsManager = __webpack_require__(696); +const statProvider = __webpack_require__(698); /** * Asynchronous API. */ @@ -82802,13 +82885,13 @@ exports.statSync = statSync; /***/ }), -/* 694 */ +/* 696 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(695); +const fsAdapter = __webpack_require__(697); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -82821,7 +82904,7 @@ exports.prepare = prepare; /***/ }), -/* 695 */ +/* 697 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82844,7 +82927,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 696 */ +/* 698 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82896,7 +82979,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 697 */ +/* 699 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82927,7 +83010,7 @@ exports.default = FileSystem; /***/ }), -/* 698 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82947,9 +83030,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(138); -var readdir = __webpack_require__(675); -var reader_1 = __webpack_require__(688); -var fs_stream_1 = __webpack_require__(692); +var readdir = __webpack_require__(677); +var reader_1 = __webpack_require__(690); +var fs_stream_1 = __webpack_require__(694); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -83017,7 +83100,7 @@ exports.default = ReaderStream; /***/ }), -/* 699 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83036,9 +83119,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(675); -var reader_1 = __webpack_require__(688); -var fs_sync_1 = __webpack_require__(700); +var readdir = __webpack_require__(677); +var reader_1 = __webpack_require__(690); +var fs_sync_1 = __webpack_require__(702); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -83098,7 +83181,7 @@ exports.default = ReaderSync; /***/ }), -/* 700 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83117,8 +83200,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(693); -var fs_1 = __webpack_require__(697); +var fsStat = __webpack_require__(695); +var fs_1 = __webpack_require__(699); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -83164,7 +83247,7 @@ exports.default = FileSystemSync; /***/ }), -/* 701 */ +/* 703 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83180,7 +83263,7 @@ exports.flatten = flatten; /***/ }), -/* 702 */ +/* 704 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83201,13 +83284,13 @@ exports.merge = merge; /***/ }), -/* 703 */ +/* 705 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const pathType = __webpack_require__(704); +const pathType = __webpack_require__(706); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -83273,13 +83356,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 704 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); -const pify = __webpack_require__(705); +const pify = __webpack_require__(707); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -83322,7 +83405,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 705 */ +/* 707 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83413,17 +83496,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 706 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); const path = __webpack_require__(4); -const fastGlob = __webpack_require__(517); -const gitIgnore = __webpack_require__(707); -const pify = __webpack_require__(708); -const slash = __webpack_require__(709); +const fastGlob = __webpack_require__(519); +const gitIgnore = __webpack_require__(709); +const pify = __webpack_require__(710); +const slash = __webpack_require__(711); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -83521,7 +83604,7 @@ module.exports.sync = options => { /***/ }), -/* 707 */ +/* 709 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -83990,7 +84073,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 708 */ +/* 710 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84065,7 +84148,7 @@ module.exports = (input, options) => { /***/ }), -/* 709 */ +/* 711 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84083,7 +84166,7 @@ module.exports = input => { /***/ }), -/* 710 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84096,7 +84179,7 @@ module.exports = input => { -var isGlob = __webpack_require__(711); +var isGlob = __webpack_require__(713); module.exports = function hasGlob(val) { if (val == null) return false; @@ -84116,7 +84199,7 @@ module.exports = function hasGlob(val) { /***/ }), -/* 711 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -84147,17 +84230,17 @@ module.exports = function isGlob(str) { /***/ }), -/* 712 */ +/* 714 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); const {constants: fsConstants} = __webpack_require__(134); -const pEvent = __webpack_require__(713); -const CpFileError = __webpack_require__(716); -const fs = __webpack_require__(718); -const ProgressEmitter = __webpack_require__(721); +const pEvent = __webpack_require__(715); +const CpFileError = __webpack_require__(718); +const fs = __webpack_require__(720); +const ProgressEmitter = __webpack_require__(723); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -84271,12 +84354,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 713 */ +/* 715 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(714); +const pTimeout = __webpack_require__(716); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -84567,12 +84650,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 714 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(715); +const pFinally = __webpack_require__(717); class TimeoutError extends Error { constructor(message) { @@ -84618,7 +84701,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 715 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84640,12 +84723,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 716 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(717); +const NestedError = __webpack_require__(719); class CpFileError extends NestedError { constructor(message, nested) { @@ -84659,7 +84742,7 @@ module.exports = CpFileError; /***/ }), -/* 717 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(112).inherits; @@ -84715,16 +84798,16 @@ module.exports = NestedError; /***/ }), -/* 718 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(112); const fs = __webpack_require__(133); -const makeDir = __webpack_require__(719); -const pEvent = __webpack_require__(713); -const CpFileError = __webpack_require__(716); +const makeDir = __webpack_require__(721); +const pEvent = __webpack_require__(715); +const CpFileError = __webpack_require__(718); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -84821,7 +84904,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 719 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84829,7 +84912,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(134); const path = __webpack_require__(4); const {promisify} = __webpack_require__(112); -const semver = __webpack_require__(720); +const semver = __webpack_require__(722); const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0'); @@ -84984,7 +85067,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 720 */ +/* 722 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -86586,7 +86669,7 @@ function coerce (version, options) { /***/ }), -/* 721 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86627,7 +86710,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 722 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86673,12 +86756,12 @@ exports.default = module.exports; /***/ }), -/* 723 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(724); +const pMap = __webpack_require__(726); const pFilter = async (iterable, filterer, options) => { const values = await pMap( @@ -86695,7 +86778,7 @@ module.exports.default = pFilter; /***/ }), -/* 724 */ +/* 726 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86774,12 +86857,12 @@ module.exports.default = pMap; /***/ }), -/* 725 */ +/* 727 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(717); +const NestedError = __webpack_require__(719); class CpyError extends NestedError { constructor(message, nested) { diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts index 0ad420899870dd..8cd346a56f2785 100644 --- a/packages/kbn-pm/src/commands/bootstrap.ts +++ b/packages/kbn-pm/src/commands/bootstrap.ts @@ -17,12 +17,13 @@ import { getAllChecksums } from '../utils/project_checksums'; import { BootstrapCacheFile } from '../utils/bootstrap_cache_file'; import { readYarnLock } from '../utils/yarn_lock'; import { validateDependencies } from '../utils/validate_dependencies'; +import { installBazelTools } from '../utils/bazel'; export const BootstrapCommand: ICommand = { description: 'Install dependencies and crosslink projects', name: 'bootstrap', - async run(projects, projectGraph, { options, kbn }) { + async run(projects, projectGraph, { options, kbn, rootPath }) { const batchedProjects = topologicallyBatchProjects(projects, projectGraph); const kibanaProjectPath = projects.get('kibana')?.path; const extraArgs = [ @@ -30,6 +31,10 @@ export const BootstrapCommand: ICommand = { ...(options['prefer-offline'] === true ? ['--prefer-offline'] : []), ]; + // Install bazel machinery tools if needed + await installBazelTools(rootPath); + + // Install monorepo npm dependencies for (const batch of batchedProjects) { for (const project of batch) { const isExternalPlugin = project.path.includes(`${kibanaProjectPath}${sep}plugins`); diff --git a/packages/kbn-pm/src/utils/bazel/index.ts b/packages/kbn-pm/src/utils/bazel/index.ts new file mode 100644 index 00000000000000..957c4bdf7f6aae --- /dev/null +++ b/packages/kbn-pm/src/utils/bazel/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +export * from './install_tools'; diff --git a/packages/kbn-pm/src/utils/bazel/install_tools.ts b/packages/kbn-pm/src/utils/bazel/install_tools.ts new file mode 100644 index 00000000000000..4e19974590e83b --- /dev/null +++ b/packages/kbn-pm/src/utils/bazel/install_tools.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import { resolve } from 'path'; +import { spawn } from '../child_process'; +import { readFile } from '../fs'; +import { log } from '../log'; + +async function readBazelToolsVersionFile(repoRootPath: string, versionFilename: string) { + const version = (await readFile(resolve(repoRootPath, versionFilename))) + .toString() + .split('\n')[0]; + + if (!version) { + throw new Error( + `[bazel_tools] Failed on reading bazel tools versions\n ${versionFilename} file do not contain any version set` + ); + } + + return version; +} + +export async function installBazelTools(repoRootPath: string) { + log.debug(`[bazel_tools] reading bazel tools versions from version files`); + const bazeliskVersion = await readBazelToolsVersionFile(repoRootPath, '.bazeliskversion'); + const bazelVersion = await readBazelToolsVersionFile(repoRootPath, '.bazelversion'); + + // Check what globals are installed + log.debug(`[bazel_tools] verify if bazelisk is installed`); + const { stdout } = await spawn('yarn', ['global', 'list'], { stdio: 'pipe' }); + + // Install bazelisk if not installed + if (!stdout.includes(`@bazel/bazelisk@${bazeliskVersion}`)) { + log.info(`[bazel_tools] installing Bazel tools`); + + log.debug( + `[bazel_tools] bazelisk is not installed. Installing @bazel/bazelisk@${bazeliskVersion} and bazel@${bazelVersion}` + ); + await spawn('yarn', ['global', 'add', `@bazel/bazelisk@${bazeliskVersion}`], { + env: { + USE_BAZEL_VERSION: bazelVersion, + }, + stdio: 'pipe', + }); + } + + log.success(`[bazel_tools] all bazel tools are correctly installed`); +} diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index 1a870e3c878f7a..d18e2e49d6b83a 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -65,6 +65,10 @@ export const IGNORE_FILE_GLOBS = [ 'x-pack/test/fleet_api_integration/apis/fixtures/test_packages/**/*', '.teamcity/**/*', + + // Bazel default files + '**/WORKSPACE.bazel', + '**/BUILD.bazel', ]; /** diff --git a/yarn.lock b/yarn.lock index ed861b58773b9f..8532bd89ec397e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1997,6 +1997,11 @@ resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.0.tgz#860ce718b0b73f4009e153541faff2cb6b85d047" integrity sha512-4Th98KlMHr5+JkxfcoDT//6vY8vM+iSPrLNpHhRyLx2CFYi8e2RfqPLdpbnpo0Q5lQC5hNB79yes07zb02fvCw== +"@bazel/ibazel@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@bazel/ibazel/-/ibazel-0.14.0.tgz#86fa0002bed2ce1123b7ad98d4dd4623a0d93244" + integrity sha512-s0gyec6lArcRDwVfIP6xpY8iEaFpzrSpyErSppd3r2O49pOEg7n6HGS/qJ8ncvme56vrDk6crl/kQ6VAdEO+rg== + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" From 4fc49ece4d8e304032d564a2208fefc961aceaab Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 27 Jan 2021 20:02:12 -0700 Subject: [PATCH 57/58] skip flaky suite (#86950) --- .../apps/dashboard/feature_controls/dashboard_security.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts index 112a855c612013..b5f55180419ef8 100644 --- a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts +++ b/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts @@ -29,7 +29,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const queryBar = getService('queryBar'); const savedQueryManagementComponent = getService('savedQueryManagementComponent'); - describe('dashboard feature controls security', () => { + // FLAKY: https://github.com/elastic/kibana/issues/86950 + describe.skip('dashboard feature controls security', () => { before(async () => { await esArchiver.load('dashboard/feature_controls/security'); await esArchiver.loadIfNeeded('logstash_functional'); From 9b5e41a9c5a55865a1ccd5e9927add448397c271 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Wed, 27 Jan 2021 22:59:33 -0500 Subject: [PATCH 58/58] [Fleet] Do not defined aliases inside datastream template (#89512) Co-authored-by: spalger --- x-pack/plugins/fleet/common/types/models/epm.ts | 1 - .../template/__snapshots__/template.test.ts.snap | 9 +++------ .../services/epm/elasticsearch/template/template.ts | 2 -- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index e09fbfc80b196a..d0df9b73dd88a9 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -326,7 +326,6 @@ export interface IndexTemplate { template: { settings: any; mappings: any; - aliases: object; }; data_stream: { hidden?: boolean }; composed_of: string[]; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap index 0333fb024a7179..2d2478843c4541 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap @@ -95,8 +95,7 @@ exports[`tests loading base.yml: base.yml 1`] = ` "managed_by": "ingest-manager", "managed": true } - }, - "aliases": {} + } }, "data_stream": {}, "composed_of": [], @@ -205,8 +204,7 @@ exports[`tests loading coredns.logs.yml: coredns.logs.yml 1`] = ` "managed_by": "ingest-manager", "managed": true } - }, - "aliases": {} + } }, "data_stream": {}, "composed_of": [], @@ -1699,8 +1697,7 @@ exports[`tests loading system.yml: system.yml 1`] = ` "managed_by": "ingest-manager", "managed": true } - }, - "aliases": {} + } }, "data_stream": {}, "composed_of": [], diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts index fd75139d4cd454..e1fa2a0b18b593 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts @@ -335,8 +335,6 @@ function getBaseTemplate( properties: mappings.properties, _meta, }, - // To be filled with the aliases that we need - aliases: {}, }, data_stream: { hidden }, composed_of: composedOfTemplates,