From f286f8f6e1031e6ab1c0069c33ce7a8da69ac0ab Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Wed, 19 Aug 2020 19:52:56 -0400 Subject: [PATCH 1/3] [SECURITY_SOLUTION] Task/add auto refresh to endpoint list (#74856) --- .../components/endpoint/route_capture.tsx | 8 +- .../public/management/common/constants.ts | 4 + .../pages/endpoint_hosts/store/action.ts | 16 ++- .../pages/endpoint_hosts/store/index.test.ts | 3 + .../endpoint_hosts/store/middleware.test.ts | 33 +++++ .../pages/endpoint_hosts/store/middleware.ts | 133 ++++++++++-------- .../pages/endpoint_hosts/store/reducer.ts | 9 ++ .../pages/endpoint_hosts/store/selectors.ts | 4 + .../management/pages/endpoint_hosts/types.ts | 4 + .../pages/endpoint_hosts/view/index.test.tsx | 120 +++++++++++----- .../pages/endpoint_hosts/view/index.tsx | 58 +++++++- .../apps/endpoint/endpoint_list.ts | 110 +++++++++------ .../page_objects/endpoint_page.ts | 4 +- 13 files changed, 355 insertions(+), 151 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/route_capture.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/route_capture.tsx index 7340d639070ab..cfc8847b0bef6 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/route_capture.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/route_capture.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { memo } from 'react'; +import React, { memo, useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import { useDispatch } from 'react-redux'; import { AppLocation } from '../../../../common/endpoint/types'; @@ -17,7 +17,11 @@ import { AppAction } from '../../store/actions'; export const RouteCapture = memo(({ children }) => { const location: AppLocation = useLocation(); const dispatch: (action: AppAction) => unknown = useDispatch(); - dispatch({ type: 'userChangedUrl', payload: location }); + + useEffect(() => { + dispatch({ type: 'userChangedUrl', payload: location }); + }); + return <>{children}; }); diff --git a/x-pack/plugins/security_solution/public/management/common/constants.ts b/x-pack/plugins/security_solution/public/management/common/constants.ts index 39d42114f9939..06f0f09bcf54d 100644 --- a/x-pack/plugins/security_solution/public/management/common/constants.ts +++ b/x-pack/plugins/security_solution/public/management/common/constants.ts @@ -24,3 +24,7 @@ export const MANAGEMENT_STORE_POLICY_LIST_NAMESPACE = 'policyList'; export const MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE = 'policyDetails'; /** Namespace within the Management state where endpoint-host state is maintained */ export const MANAGEMENT_STORE_ENDPOINTS_NAMESPACE = 'endpoints'; + +// --[ DEFAULTS ]--------------------------------------------------------------------------- +/** The default polling interval to start all polling pages */ +export const DEFAULT_POLL_INTERVAL = 10000; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts index 2e188af41d2d7..5f36af2a2d8ea 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts @@ -86,6 +86,18 @@ interface ServerReturnedEndpointExistValue { payload: boolean; } +interface UserUpdatedEndpointListRefreshOptions { + type: 'userUpdatedEndpointListRefreshOptions'; + payload: { + isAutoRefreshEnabled?: boolean; + autoRefreshInterval?: number; + }; +} + +interface AppRequestedEndpointList { + type: 'appRequestedEndpointList'; +} + export type EndpointAction = | ServerReturnedEndpointList | ServerFailedToReturnEndpointList @@ -100,4 +112,6 @@ export type EndpointAction = | ServerReturnedEndpointExistValue | ServerCancelledPolicyItemsLoading | ServerReturnedEndpointPackageInfo - | ServerReturnedEndpointNonExistingPolicies; + | AppRequestedEndpointList + | ServerReturnedEndpointNonExistingPolicies + | UserUpdatedEndpointListRefreshOptions; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/index.test.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/index.test.ts index b3ab3443809c8..3a095644b3b41 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/index.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/index.test.ts @@ -10,6 +10,7 @@ import { listData } from './selectors'; import { mockEndpointResultList } from './mock_endpoint_result_list'; import { EndpointAction } from './action'; import { endpointListReducer } from './reducer'; +import { DEFAULT_POLL_INTERVAL } from '../../../common/constants'; describe('EndpointList store concerns', () => { let store: Store; @@ -52,6 +53,8 @@ describe('EndpointList store concerns', () => { endpointPackageInfo: undefined, nonExistingPolicies: {}, endpointsExist: true, + isAutoRefreshEnabled: true, + autoRefreshInterval: DEFAULT_POLL_INTERVAL, }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts index 77ade5bcc6971..15e89f9771382 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts @@ -23,6 +23,11 @@ import { endpointListReducer } from './reducer'; import { endpointMiddlewareFactory } from './middleware'; import { getEndpointListPath } from '../../../common/routing'; +jest.mock('../../policy/store/policy_list/services/ingest', () => ({ + sendGetEndpointSecurityPackage: () => Promise.resolve({}), + sendGetAgentConfigList: () => Promise.resolve({ items: [] }), +})); + describe('endpoint list middleware', () => { let fakeCoreStart: jest.Mocked; let depsStart: DepsStartMock; @@ -71,4 +76,32 @@ describe('endpoint list middleware', () => { }); expect(listData(getState())).toEqual(apiResponse.hosts); }); + + it('handles `appRequestedEndpointList`', async () => { + const apiResponse = getEndpointListApiResponse(); + fakeHttpServices.post.mockResolvedValue(apiResponse); + expect(fakeHttpServices.post).not.toHaveBeenCalled(); + + // First change the URL + dispatch({ + type: 'userChangedUrl', + payload: { + ...history.location, + pathname: getEndpointListPath({ name: 'endpointList' }), + }, + }); + await waitForAction('serverReturnedEndpointList'); + + // Then request the Endpoint List + dispatch({ + type: 'appRequestedEndpointList', + }); + await waitForAction('serverReturnedEndpointList'); + expect(fakeHttpServices.post).toHaveBeenCalledWith('/api/endpoint/metadata', { + body: JSON.stringify({ + paging_properties: [{ page_index: '0' }, { page_size: '10' }], + }), + }); + expect(listData(getState())).toEqual(apiResponse.hosts); + }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts index f56f28bfef39a..2650aa4865228 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts @@ -25,31 +25,31 @@ import { import { AGENT_POLICY_SAVED_OBJECT_TYPE } from '../../../../../../ingest_manager/common'; export const endpointMiddlewareFactory: ImmutableMiddlewareFactory = (coreStart) => { + // eslint-disable-next-line complexity return ({ getState, dispatch }) => (next) => async (action) => { next(action); - const state = getState(); // Endpoint list if ( - action.type === 'userChangedUrl' && - isOnEndpointPage(state) && - hasSelectedEndpoint(state) !== true + (action.type === 'userChangedUrl' || action.type === 'appRequestedEndpointList') && + isOnEndpointPage(getState()) && + hasSelectedEndpoint(getState()) !== true ) { - if (!endpointPackageInfo(state)) { - sendGetEndpointSecurityPackage(coreStart.http) - .then((packageInfo) => { - dispatch({ - type: 'serverReturnedEndpointPackageInfo', - payload: packageInfo, - }); - }) - .catch((error) => { - // eslint-disable-next-line no-console - console.error(error); + if (!endpointPackageInfo(getState())) { + try { + const packageInfo = await sendGetEndpointSecurityPackage(coreStart.http); + dispatch({ + type: 'serverReturnedEndpointPackageInfo', + payload: packageInfo, }); + } catch (error) { + // Ignore Errors, since this should not hinder the user's ability to use the UI + // eslint-disable-next-line no-console + console.error(error); + } } - const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(state); + const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(getState()); let endpointResponse; try { @@ -65,22 +65,23 @@ export const endpointMiddlewareFactory: ImmutableMiddlewareFactory { - if (missingPolicies !== undefined) { - dispatch({ - type: 'serverReturnedEndpointNonExistingPolicies', - payload: missingPolicies, - }); - } - }) + try { + const missingPolicies = await getNonExistingPoliciesForEndpointsList( + coreStart.http, + endpointResponse.hosts, + nonExistingPolicies(getState()) + ); + if (missingPolicies !== undefined) { + dispatch({ + type: 'serverReturnedEndpointNonExistingPolicies', + payload: missingPolicies, + }); + } + } catch (error) { // Ignore Errors, since this should not hinder the user's ability to use the UI // eslint-disable-next-line no-console - .catch((error) => console.error(error)); + console.error(error); + } } catch (error) { dispatch({ type: 'serverFailedToReturnEndpointList', @@ -132,18 +133,23 @@ export const endpointMiddlewareFactory: ImmutableMiddlewareFactory { - if (missingPolicies !== undefined) { - dispatch({ - type: 'serverReturnedEndpointNonExistingPolicies', - payload: missingPolicies, - }); - } - }) + try { + const missingPolicies = await getNonExistingPoliciesForEndpointsList( + coreStart.http, + response.hosts, + nonExistingPolicies(getState()) + ); + if (missingPolicies !== undefined) { + dispatch({ + type: 'serverReturnedEndpointNonExistingPolicies', + payload: missingPolicies, + }); + } + } catch (error) { // Ignore Errors, since this should not hinder the user's ability to use the UI // eslint-disable-next-line no-console - .catch((error) => console.error(error)); + console.error(error); + } } catch (error) { dispatch({ type: 'serverFailedToReturnEndpointList', @@ -185,7 +192,7 @@ export const endpointMiddlewareFactory: ImmutableMiddlewareFactory( `/api/endpoint/metadata/${selectedEndpoint}` @@ -194,22 +201,24 @@ export const endpointMiddlewareFactory: ImmutableMiddlewareFactory { - if (missingPolicies !== undefined) { - dispatch({ - type: 'serverReturnedEndpointNonExistingPolicies', - payload: missingPolicies, - }); - } - }) + + try { + const missingPolicies = await getNonExistingPoliciesForEndpointsList( + coreStart.http, + [response], + nonExistingPolicies(getState()) + ); + if (missingPolicies !== undefined) { + dispatch({ + type: 'serverReturnedEndpointNonExistingPolicies', + payload: missingPolicies, + }); + } + } catch (error) { // Ignore Errors, since this should not hinder the user's ability to use the UI // eslint-disable-next-line no-console - .catch((error) => console.error(error)); + console.error(error); + } } catch (error) { dispatch({ type: 'serverFailedToReturnEndpointDetails', diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/reducer.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/reducer.ts index d4fe3310eac0a..060321fa40401 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/reducer.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/reducer.ts @@ -9,6 +9,7 @@ import { EndpointState } from '../types'; import { AppAction } from '../../../../common/store/actions'; import { ImmutableReducer } from '../../../../common/store'; import { Immutable } from '../../../../../common/endpoint/types'; +import { DEFAULT_POLL_INTERVAL } from '../../../common/constants'; export const initialEndpointListState: Immutable = { hosts: [], @@ -30,6 +31,8 @@ export const initialEndpointListState: Immutable = { endpointPackageInfo: undefined, nonExistingPolicies: {}, endpointsExist: true, + isAutoRefreshEnabled: true, + autoRefreshInterval: DEFAULT_POLL_INTERVAL, }; /* eslint-disable-next-line complexity */ @@ -131,6 +134,12 @@ export const endpointListReducer: ImmutableReducer = ( ...state, endpointsExist: action.payload, }; + } else if (action.type === 'userUpdatedEndpointListRefreshOptions') { + return { + ...state, + isAutoRefreshEnabled: action.payload.isAutoRefreshEnabled ?? state.isAutoRefreshEnabled, + autoRefreshInterval: action.payload.autoRefreshInterval ?? state.autoRefreshInterval, + }; } else if (action.type === 'userChangedUrl') { const newState: Immutable = { ...state, diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts index 2c6fc6d5a75e1..68ba71b7bbc94 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts @@ -45,6 +45,10 @@ export const selectedPolicyId = (state: Immutable) => state.selec export const endpointPackageInfo = (state: Immutable) => state.endpointPackageInfo; +export const isAutoRefreshEnabled = (state: Immutable) => state.isAutoRefreshEnabled; + +export const autoRefreshInterval = (state: Immutable) => state.autoRefreshInterval; + export const endpointPackageVersion = createSelector( endpointPackageInfo, (info) => info?.version ?? undefined diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts index 7e75285560bd3..5a6a1af7bd7e8 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts @@ -54,6 +54,10 @@ export interface EndpointState { nonExistingPolicies: Record; /** Tracks whether hosts exist and helps control if onboarding should be visible */ endpointsExist: boolean; + /** Is auto-refresh enabled */ + isAutoRefreshEnabled: boolean; + /** The current auto refresh interval for data in ms */ + autoRefreshInterval: number; } /** diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx index a504390344e37..5ab9df79ee14b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx @@ -149,6 +149,9 @@ describe('when on the list page', () => { }); }); }); + afterEach(() => { + jest.clearAllMocks(); + }); it('should display rows in the table', async () => { const renderResult = render(); @@ -243,10 +246,85 @@ describe('when on the list page', () => { }); }); + describe('when polling on Endpoint List', () => { + beforeEach(async () => { + await reactTestingLibrary.act(() => { + const hostListData = mockEndpointResultList({ total: 4 }).hosts; + + setEndpointListApiMockImplementation(coreStart.http, { + endpointsResults: hostListData, + }); + + const pollInterval = 10; + store.dispatch({ + type: 'userUpdatedEndpointListRefreshOptions', + payload: { + autoRefreshInterval: pollInterval, + }, + }); + }); + }); + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should update data after some time', async () => { + let renderResult = render(); + await reactTestingLibrary.act(async () => { + await middlewareSpy.waitForAction('serverReturnedEndpointList'); + }); + const total = await renderResult.findAllByTestId('endpointListTableTotal'); + expect(total[0].textContent).toEqual('4 Hosts'); + + setEndpointListApiMockImplementation(coreStart.http, { + endpointsResults: mockEndpointResultList({ total: 1 }).hosts, + }); + + await reactTestingLibrary.act(async () => { + await middlewareSpy.waitForAction('appRequestedEndpointList'); + await middlewareSpy.waitForAction('serverReturnedEndpointList'); + }); + + renderResult = render(); + + const updatedTotal = await renderResult.findAllByTestId('endpointListTableTotal'); + expect(updatedTotal[0].textContent).toEqual('1 Host'); + }); + }); + describe('when there is a selected host in the url', () => { let hostDetails: HostInfo; let agentId: string; let renderAndWaitForData: () => Promise>; + const mockEndpointListApi = (mockedPolicyResponse?: HostPolicyResponse) => { + const { + // eslint-disable-next-line @typescript-eslint/naming-convention + host_status, + metadata: { host, ...details }, + } = mockEndpointDetailsApiResult(); + + hostDetails = { + host_status, + metadata: { + ...details, + host: { + ...host, + id: '1', + }, + }, + }; + + agentId = hostDetails.metadata.elastic.agent.id; + + const policy = docGenerator.generatePolicyPackagePolicy(); + policy.id = hostDetails.metadata.Endpoint.policy.applied.id; + + setEndpointListApiMockImplementation(coreStart.http, { + endpointsResults: [hostDetails], + endpointPackagePolicies: [policy], + policyResponse: mockedPolicyResponse, + }); + }; const createPolicyResponse = ( overallStatus: HostPolicyResponseActionStatus = HostPolicyResponseActionStatus.success @@ -313,32 +391,7 @@ describe('when on the list page', () => { }; beforeEach(async () => { - const { - // eslint-disable-next-line @typescript-eslint/naming-convention - host_status, - metadata: { host, ...details }, - } = mockEndpointDetailsApiResult(); - - hostDetails = { - host_status, - metadata: { - ...details, - host: { - ...host, - id: '1', - }, - }, - }; - - agentId = hostDetails.metadata.elastic.agent.id; - - const policy = docGenerator.generatePolicyPackagePolicy(); - policy.id = hostDetails.metadata.Endpoint.policy.applied.id; - - setEndpointListApiMockImplementation(coreStart.http, { - endpointsResults: [hostDetails], - endpointPackagePolicies: [policy], - }); + mockEndpointListApi(); reactTestingLibrary.act(() => { history.push('/endpoints?selected_endpoint=1'); @@ -407,9 +460,6 @@ describe('when on the list page', () => { it('should display Success overall policy status', async () => { const renderResult = await renderAndWaitForData(); - reactTestingLibrary.act(() => { - dispatchServerReturnedEndpointPolicyResponse(HostPolicyResponseActionStatus.success); - }); const policyStatusLink = await renderResult.findByTestId('policyStatusValue'); expect(policyStatusLink.textContent).toEqual('Success'); @@ -420,10 +470,8 @@ describe('when on the list page', () => { }); it('should display Warning overall policy status', async () => { + mockEndpointListApi(createPolicyResponse(HostPolicyResponseActionStatus.warning)); const renderResult = await renderAndWaitForData(); - reactTestingLibrary.act(() => { - dispatchServerReturnedEndpointPolicyResponse(HostPolicyResponseActionStatus.warning); - }); const policyStatusLink = await renderResult.findByTestId('policyStatusValue'); expect(policyStatusLink.textContent).toEqual('Warning'); @@ -434,10 +482,8 @@ describe('when on the list page', () => { }); it('should display Failed overall policy status', async () => { + mockEndpointListApi(createPolicyResponse(HostPolicyResponseActionStatus.failure)); const renderResult = await renderAndWaitForData(); - reactTestingLibrary.act(() => { - dispatchServerReturnedEndpointPolicyResponse(HostPolicyResponseActionStatus.failure); - }); const policyStatusLink = await renderResult.findByTestId('policyStatusValue'); expect(policyStatusLink.textContent).toEqual('Failed'); @@ -448,10 +494,8 @@ describe('when on the list page', () => { }); it('should display Unknown overall policy status', async () => { + mockEndpointListApi(createPolicyResponse('' as HostPolicyResponseActionStatus)); const renderResult = await renderAndWaitForData(); - reactTestingLibrary.act(() => { - dispatchServerReturnedEndpointPolicyResponse('' as HostPolicyResponseActionStatus); - }); const policyStatusLink = await renderResult.findByTestId('policyStatusValue'); expect(policyStatusLink.textContent).toEqual('Unknown'); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index 8b8ac3a1d3587..8d08ac4e59a87 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -14,6 +14,8 @@ import { EuiHealth, EuiToolTip, EuiSelectableProps, + EuiSuperDatePicker, + EuiSpacer, } from '@elastic/eui'; import { useHistory } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; @@ -31,6 +33,7 @@ import { import { useNavigateByRouterEventHandler } from '../../../../common/hooks/endpoint/use_navigate_by_router_event_handler'; import { CreateStructuredSelector } from '../../../../common/store'; import { Immutable, HostInfo } from '../../../../../common/endpoint/types'; +import { DEFAULT_POLL_INTERVAL } from '../../../common/constants'; import { PolicyEmptyState, HostsEmptyState } from '../../../components/management_empty_state'; import { FormattedDate } from '../../../../common/components/formatted_date'; import { useNavigateToAppEventHandler } from '../../../../common/hooks/endpoint/use_navigate_to_app_event_handler'; @@ -84,6 +87,8 @@ export const EndpointList = () => { policyItemsLoading, endpointPackageVersion, endpointsExist, + autoRefreshInterval, + isAutoRefreshEnabled, } = useEndpointSelector(selector); const { formatUrl, search } = useFormatUrl(SecurityPageName.administration); @@ -135,6 +140,27 @@ export const EndpointList = () => { } ); + const onRefresh = useCallback(() => { + dispatch({ + type: 'appRequestedEndpointList', + }); + }, [dispatch]); + + const onRefreshChange = useCallback( + (evt) => { + dispatch({ + type: 'userUpdatedEndpointListRefreshOptions', + payload: { + isAutoRefreshEnabled: !evt.isPaused, + autoRefreshInterval: evt.refreshInterval, + }, + }); + }, + [dispatch] + ); + + const NOOP = useCallback(() => {}, []); + const handleDeployEndpointsClick = useNavigateToAppEventHandler< AgentPolicyDetailsDeployAgentAction >('ingestManager', { @@ -368,6 +394,20 @@ export const EndpointList = () => { handleCreatePolicyClick, ]); + const hasListData = listData && listData.length > 0; + + const refreshStyle = useMemo(() => { + return { display: hasListData ? 'flex' : 'none', maxWidth: 200 }; + }, [hasListData]); + + const refreshIsPaused = useMemo(() => { + return !hasListData ? false : hasSelectedEndpoint ? true : !isAutoRefreshEnabled; + }, [hasListData, hasSelectedEndpoint, isAutoRefreshEnabled]); + + const refreshInterval = useMemo(() => { + return !hasListData ? DEFAULT_POLL_INTERVAL : autoRefreshInterval; + }, [hasListData, autoRefreshInterval]); + return ( { } > {hasSelectedEndpoint && } - {listData && listData.length > 0 && ( + { + <> +
+ +
+ + + } + {hasListData && ( <> { const pageObjects = getPageObjects(['common', 'endpoint', 'header', 'endpointPageUtils']); const esArchiver = getService('esArchiver'); const testSubjects = getService('testSubjects'); + const expectedData = [ + [ + 'Hostname', + 'Agent Status', + 'Integration', + 'Configuration Status', + 'Operating System', + 'IP Address', + 'Version', + 'Last Active', + ], + [ + 'cadmann-4.example.com', + 'Error', + 'Default', + 'Failure', + 'windows 10.0', + '10.192.213.130, 10.70.28.129', + '6.6.1', + 'Jan 24, 2020 @ 16:06:09.541', + ], + [ + 'thurlow-9.example.com', + 'Error', + 'Default', + 'Success', + 'windows 10.0', + '10.46.229.234', + '6.0.0', + 'Jan 24, 2020 @ 16:06:09.541', + ], + [ + 'rezzani-7.example.com', + 'Error', + 'Default', + 'Failure', + 'windows 10.0', + '10.101.149.26, 2606:a000:ffc0:39:11ef:37b9:3371:578c', + '6.8.0', + 'Jan 24, 2020 @ 16:06:09.541', + ], + ]; + describe('endpoint list', function () { this.tags('ciGroup7'); const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms)); + describe('when initially navigating to page', () => { + before(async () => { + await pageObjects.endpoint.navigateToEndpointList(); + }); + after(async () => { + await deleteMetadataStream(getService); + }); + + it('finds no data in list and prompts onboarding to add policy', async () => { + await testSubjects.exists('emptyPolicyTable'); + }); + + it('finds data after load and polling', async () => { + await esArchiver.load('endpoint/metadata/api_feature', { useCreate: true }); + await pageObjects.endpoint.waitForTableToHaveData('endpointListTable', 10000); + const tableData = await pageObjects.endpointPageUtils.tableData('endpointListTable'); + expect(tableData).to.eql(expectedData); + }); + }); + describe('when there is data,', () => { before(async () => { await esArchiver.load('endpoint/metadata/api_feature', { useCreate: true }); @@ -32,48 +94,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('displays table data', async () => { - const expectedData = [ - [ - 'Hostname', - 'Agent Status', - 'Integration', - 'Configuration Status', - 'Operating System', - 'IP Address', - 'Version', - 'Last Active', - ], - [ - 'cadmann-4.example.com', - 'Error', - 'Default', - 'Failure', - 'windows 10.0', - '10.192.213.130, 10.70.28.129', - '6.6.1', - 'Jan 24, 2020 @ 16:06:09.541', - ], - [ - 'thurlow-9.example.com', - 'Error', - 'Default', - 'Success', - 'windows 10.0', - '10.46.229.234', - '6.0.0', - 'Jan 24, 2020 @ 16:06:09.541', - ], - [ - 'rezzani-7.example.com', - 'Error', - 'Default', - 'Failure', - 'windows 10.0', - '10.101.149.26, 2606:a000:ffc0:39:11ef:37b9:3371:578c', - '6.8.0', - 'Jan 24, 2020 @ 16:06:09.541', - ], - ]; const tableData = await pageObjects.endpointPageUtils.tableData('endpointListTable'); expect(tableData).to.eql(expectedData); }); @@ -147,7 +167,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('displays details row headers', async () => { - const expectedData = [ + const expectedHeaders = [ 'OS', 'Last Seen', 'Alerts', @@ -160,7 +180,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const keys = await pageObjects.endpoint.endpointFlyoutDescriptionKeys( 'endpointDetailsFlyout' ); - expect(keys).to.eql(expectedData); + expect(keys).to.eql(expectedHeaders); }); it('displays details row descriptions', async () => { diff --git a/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts b/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts index f89ee5fe2729b..351084909a0dc 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts @@ -24,8 +24,8 @@ export function EndpointPageProvider({ getService, getPageObjects }: FtrProvider await pageObjects.header.waitUntilLoadingHasFinished(); }, - async waitForTableToHaveData(dataTestSubj: string) { - await retry.waitForWithTimeout('table to have data', 2000, async () => { + async waitForTableToHaveData(dataTestSubj: string, timeout = 2000) { + await retry.waitForWithTimeout('table to have data', timeout, async () => { const tableData = await pageObjects.endpointPageUtils.tableData(dataTestSubj); if (tableData[1][0] === 'No items found') { return false; From 4b46316395a52da7b75fe2bf30985a8d9011be99 Mon Sep 17 00:00:00 2001 From: DeDe Morton Date: Wed, 19 Aug 2020 18:02:34 -0700 Subject: [PATCH 2/3] Edit text strings for Ingest Manager Overview and Add data pages (#74818) * Edit Ingest Manager text strings in Overview and Add Data pages * Add fixes from review * remove blank line * Change configurations to policies * Remove "configuration" from text Co-authored-by: Elastic Machine --- .../ingest_manager/components/alpha_flyout.tsx | 2 +- .../enrollment_instructions/manual/index.tsx | 12 ++++++------ .../ingest_manager/components/settings_flyout.tsx | 7 ++++--- .../applications/ingest_manager/layouts/default.tsx | 2 +- .../components/agent_enrollment_flyout/index.tsx | 4 ++-- .../agent_enrollment_flyout/managed_instructions.tsx | 4 ++-- .../standalone_instructions.tsx | 8 ++++---- .../components/agent_enrollment_flyout/steps.tsx | 6 +++--- .../ingest_manager/sections/overview/index.tsx | 2 +- 9 files changed, 24 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx index 110d6de02c12b..e07f467d5f037 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx @@ -45,7 +45,7 @@ export const AlphaFlyout: React.FunctionComponent = ({ onClose }) => {

@@ -83,19 +83,19 @@ systemctl start elastic-agent`; + + {macOsLinuxTarCommand} + + ./elastic-agent run, }} /> - - - {macOsLinuxTarCommand} - ); }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx index be1b3df8a0c3e..9a9557f77c40c 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx @@ -139,7 +139,8 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { id: 'disabled', disabled: true, label: i18n.translate('xpack.ingestManager.settings.autoUpgradeDisabledLabel', { - defaultMessage: 'Manually manage agent binary versions. Requires Gold license.', + defaultMessage: + 'Manually manage agent binary versions. Requires a Gold subscription.', }), }, ]} @@ -167,7 +168,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { 'xpack.ingestManager.settings.integrationUpgradeEnabledFieldLabel', { defaultMessage: - 'Automatically update integrations to the latest version to receive the latest assets. Agent policies may need to be updated in order to use new features.', + 'Automatically update integrations to the latest version to get the latest assets. You might need to update agent policies to use new features.', } ), }, @@ -210,7 +211,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx index 3a68cb948eb2d..726da7a790b97 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx @@ -111,7 +111,7 @@ export const DefaultLayout: React.FunctionComponent = ({ > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx index f85d0bea74f22..414c4e0d7ad2c 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx @@ -48,13 +48,13 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ setMode('managed')}> setMode('standalone')}> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx index 3821d8a2384ca..b02893057c9c3 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx @@ -60,7 +60,7 @@ export const ManagedInstructions: React.FunctionComponent = ({ agentPolic @@ -72,7 +72,7 @@ export const ManagedInstructions: React.FunctionComponent = ({ agentPolic <> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx index c2da0b704eaff..abe834e7db19c 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx @@ -81,7 +81,7 @@ export const StandaloneInstructions: React.FunctionComponent = ({ agentPo elastic-agent.yml, ESUsernameVariable: ES_USERNAME, @@ -129,7 +129,7 @@ export const StandaloneInstructions: React.FunctionComponent = ({ agentPo {RUN_INSTRUCTIONS} @@ -157,7 +157,7 @@ export const StandaloneInstructions: React.FunctionComponent = ({ agentPo @@ -170,7 +170,7 @@ export const StandaloneInstructions: React.FunctionComponent = ({ agentPo diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx index a70741d1df7f7..0ae61ff421ffa 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx @@ -14,14 +14,14 @@ import { AgentPolicy } from '../../../../types'; export const DownloadStep = () => { return { title: i18n.translate('xpack.ingestManager.agentEnrollment.stepDownloadAgentTitle', { - defaultMessage: 'Download the Elastic Agent', + defaultMessage: 'Download the Elastic Agent to your host', }), children: ( <> @@ -33,7 +33,7 @@ export const DownloadStep = () => { > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx index 187b701dc4167..0d8788bce2a1d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx @@ -71,7 +71,7 @@ export const IngestManagerOverview: React.FunctionComponent = () => {

From 28df9266a0b8906e2cf6537aa12b118dfdd7082d Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Thu, 20 Aug 2020 06:40:08 +0200 Subject: [PATCH 3/3] adds metric_vis_renderer (#57694) --- .../common/ast/build_function.test.ts | 17 +++ .../expressions/common/ast/build_function.ts | 12 +- src/plugins/vis_type_metric/kibana.json | 2 +- .../__snapshots__/metric_vis_fn.test.ts.snap | 2 +- .../public/__snapshots__/to_ast.test.ts.snap | 73 +++++++++++ .../metric_vis_component.test.tsx.snap | 40 +++--- .../components/metric_vis_component.test.tsx | 38 +++--- .../components/metric_vis_component.tsx | 21 ++-- .../vis_type_metric/public/metric_vis_fn.ts | 8 +- .../public/metric_vis_renderer.tsx | 54 ++++++++ .../vis_type_metric/public/metric_vis_type.ts | 5 +- src/plugins/vis_type_metric/public/plugin.ts | 7 +- .../vis_type_metric/public/services.ts | 3 + .../vis_type_metric/public/to_ast.test.ts | 54 ++++++++ src/plugins/vis_type_metric/public/to_ast.ts | 103 ++++++++++++++++ .../visualizations/public/components/index.ts | 2 + .../components/visualization_container.tsx} | 17 +-- src/plugins/visualizations/public/index.ts | 2 + .../__snapshots__/build_pipeline.test.ts.snap | 8 +- .../public/legacy/build_pipeline.test.ts | 39 +----- .../public/legacy/build_pipeline.ts | 115 ++++++------------ src/plugins/visualizations/public/types.ts | 14 ++- src/plugins/visualizations/public/vis.ts | 4 +- .../public/vis_types/base_vis_type.ts | 9 +- .../snapshots/baseline/combined_test3.json | 2 +- .../snapshots/baseline/final_output_test.json | 2 +- .../snapshots/baseline/metric_all_data.json | 2 +- .../baseline/metric_multi_metric_data.json | 2 +- .../baseline/metric_percentage_mode.json | 2 +- .../baseline/metric_single_metric_data.json | 2 +- .../snapshots/baseline/partial_test_2.json | 2 +- .../snapshots/baseline/step_output_test3.json | 2 +- .../snapshots/session/combined_test3.json | 2 +- .../snapshots/session/final_output_test.json | 2 +- .../snapshots/session/metric_all_data.json | 2 +- .../session/metric_multi_metric_data.json | 2 +- .../session/metric_percentage_mode.json | 2 +- .../session/metric_single_metric_data.json | 2 +- .../snapshots/session/partial_test_2.json | 2 +- .../snapshots/session/step_output_test3.json | 2 +- 40 files changed, 463 insertions(+), 218 deletions(-) create mode 100644 src/plugins/vis_type_metric/public/__snapshots__/to_ast.test.ts.snap create mode 100644 src/plugins/vis_type_metric/public/metric_vis_renderer.tsx create mode 100644 src/plugins/vis_type_metric/public/to_ast.test.ts create mode 100644 src/plugins/vis_type_metric/public/to_ast.ts rename src/plugins/{vis_type_metric/public/metric_vis_type.test.ts => visualizations/public/components/visualization_container.tsx} (68%) diff --git a/src/plugins/expressions/common/ast/build_function.test.ts b/src/plugins/expressions/common/ast/build_function.test.ts index a2b54f31f6f8f..1f914d6f471e6 100644 --- a/src/plugins/expressions/common/ast/build_function.test.ts +++ b/src/plugins/expressions/common/ast/build_function.test.ts @@ -79,6 +79,11 @@ describe('buildExpressionFunction()', () => { `); }); + test('ignores any args in initial state which value is undefined', () => { + const fn = buildExpressionFunction('hello', { world: undefined }); + expect(fn.arguments).not.toHaveProperty('world'); + }); + test('returns all expected properties', () => { const fn = buildExpressionFunction('hello', { world: [true] }); expect(Object.keys(fn)).toMatchInlineSnapshot(` @@ -264,6 +269,18 @@ describe('buildExpressionFunction()', () => { `); }); + test('does not add new argument if the value is undefined', () => { + const fn = buildExpressionFunction('hello', { world: [true] }); + fn.addArgument('foo', undefined); + expect(fn.toAst().arguments).toMatchInlineSnapshot(` + Object { + "world": Array [ + true, + ], + } + `); + }); + test('mutates a function already associated with an expression', () => { const fn = buildExpressionFunction('hello', { world: [true] }); const exp = buildExpression([fn]); diff --git a/src/plugins/expressions/common/ast/build_function.ts b/src/plugins/expressions/common/ast/build_function.ts index 5a1bd615d6450..6cd16b2bc1354 100644 --- a/src/plugins/expressions/common/ast/build_function.ts +++ b/src/plugins/expressions/common/ast/build_function.ts @@ -183,8 +183,10 @@ export function buildExpressionFunction< acc[key] = value.map((v) => { return isExpressionAst(v) ? buildExpression(v) : v; }); - } else { + } else if (value !== undefined) { acc[key] = isExpressionAst(value) ? [buildExpression(value)] : [value]; + } else { + delete acc[key]; } return acc; }, initialArgs as FunctionBuilderArguments); @@ -195,10 +197,12 @@ export function buildExpressionFunction< arguments: args, addArgument(key, value) { - if (!args.hasOwnProperty(key)) { - args[key] = []; + if (value !== undefined) { + if (!args.hasOwnProperty(key)) { + args[key] = []; + } + args[key].push(value); } - args[key].push(value); return this; }, diff --git a/src/plugins/vis_type_metric/kibana.json b/src/plugins/vis_type_metric/kibana.json index b2ebc91471e9d..26ca09e22f26e 100644 --- a/src/plugins/vis_type_metric/kibana.json +++ b/src/plugins/vis_type_metric/kibana.json @@ -4,6 +4,6 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "visualizations", "charts","expressions"], + "requiredPlugins": ["data", "visualizations", "charts", "expressions"], "requiredBundles": ["kibanaUtils", "kibanaReact"] } diff --git a/src/plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap b/src/plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap index 44414cedf966a..706d2a902aa90 100644 --- a/src/plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap +++ b/src/plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap @@ -2,7 +2,7 @@ exports[`interpreter/functions#metric returns an object with the correct structure 1`] = ` Object { - "as": "visualization", + "as": "metric_vis", "type": "render", "value": Object { "params": Object { diff --git a/src/plugins/vis_type_metric/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_type_metric/public/__snapshots__/to_ast.test.ts.snap new file mode 100644 index 0000000000000..117c188c6cce2 --- /dev/null +++ b/src/plugins/vis_type_metric/public/__snapshots__/to_ast.test.ts.snap @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`metric vis toExpressionAst function with percentage mode should have percentage format 1`] = ` +Object { + "chain": Array [ + Object { + "arguments": Object { + "aggConfigs": Array [ + "[]", + ], + "includeFormatHints": Array [ + false, + ], + "index": Array [ + "123", + ], + "metricsAtAllLevels": Array [ + false, + ], + "partialRows": Array [ + false, + ], + }, + "function": "esaggs", + "type": "function", + }, + Object { + "arguments": Object { + "percentageMode": Array [ + true, + ], + }, + "function": "metricVis", + "type": "function", + }, + ], + "type": "expression", +} +`; + +exports[`metric vis toExpressionAst function without params 1`] = ` +Object { + "chain": Array [ + Object { + "arguments": Object { + "aggConfigs": Array [ + "[]", + ], + "includeFormatHints": Array [ + false, + ], + "index": Array [ + "123", + ], + "metricsAtAllLevels": Array [ + false, + ], + "partialRows": Array [ + false, + ], + }, + "function": "esaggs", + "type": "function", + }, + Object { + "arguments": Object {}, + "function": "metricVis", + "type": "function", + }, + ], + "type": "expression", +} +`; diff --git a/src/plugins/vis_type_metric/public/components/__snapshots__/metric_vis_component.test.tsx.snap b/src/plugins/vis_type_metric/public/components/__snapshots__/metric_vis_component.test.tsx.snap index 47ca3f1e0465e..f07fdfa682d87 100644 --- a/src/plugins/vis_type_metric/public/components/__snapshots__/metric_vis_component.test.tsx.snap +++ b/src/plugins/vis_type_metric/public/components/__snapshots__/metric_vis_component.test.tsx.snap @@ -1,9 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`MetricVisComponent should render correct structure for multi-value metrics 1`] = ` -
+Array [ + />, -
+ />, +] `; exports[`MetricVisComponent should render correct structure for single metric 1`] = ` -
- -
+ } + showLabel={true} +/> `; diff --git a/src/plugins/vis_type_metric/public/components/metric_vis_component.test.tsx b/src/plugins/vis_type_metric/public/components/metric_vis_component.test.tsx index ba32fb2712e68..b56d4e4f62e41 100644 --- a/src/plugins/vis_type_metric/public/components/metric_vis_component.test.tsx +++ b/src/plugins/vis_type_metric/public/components/metric_vis_component.test.tsx @@ -21,7 +21,6 @@ import React from 'react'; import { shallow } from 'enzyme'; import { MetricVisComponent, MetricVisComponentProps } from './metric_vis_component'; -import { ExprVis } from '../../../visualizations/public'; jest.mock('../services', () => ({ getFormatService: () => ({ @@ -41,29 +40,30 @@ const baseVisData = { } as any; describe('MetricVisComponent', function () { - const vis: ExprVis = { - params: { - metric: { - colorSchema: 'Green to Red', - colorsRange: [{ from: 0, to: 1000 }], - style: {}, - labels: { - show: true, - }, - }, - dimensions: { - metrics: [{ accessor: 0 }], - bucket: null, + const visParams = { + type: 'metric', + addTooltip: false, + addLegend: false, + metric: { + colorSchema: 'Green to Red', + colorsRange: [{ from: 0, to: 1000 }], + style: {}, + labels: { + show: true, }, }, - } as any; + dimensions: { + metrics: [{ accessor: 0 } as any], + bucket: undefined, + }, + }; const getComponent = (propOverrides: Partial = {} as Partial) => { const props: Props = { - vis, - visParams: vis.params as any, + visParams: visParams as any, visData: baseVisData, renderComplete: jest.fn(), + fireEvent: jest.fn(), ...propOverrides, }; @@ -88,9 +88,9 @@ describe('MetricVisComponent', function () { rows: [{ 'col-0': 182, 'col-1': 445842.4634666484 }], }, visParams: { - ...vis.params, + ...visParams, dimensions: { - ...vis.params.dimensions, + ...visParams.dimensions, metrics: [{ accessor: 0 }, { accessor: 1 }], }, }, diff --git a/src/plugins/vis_type_metric/public/components/metric_vis_component.tsx b/src/plugins/vis_type_metric/public/components/metric_vis_component.tsx index 4385826762612..9ce3820ee4e23 100644 --- a/src/plugins/vis_type_metric/public/components/metric_vis_component.tsx +++ b/src/plugins/vis_type_metric/public/components/metric_vis_component.tsx @@ -27,13 +27,13 @@ import { KibanaDatatable } from '../../../expressions/public'; import { getHeatmapColors } from '../../../charts/public'; import { VisParams, MetricVisMetric } from '../types'; import { getFormatService } from '../services'; -import { SchemaConfig, ExprVis } from '../../../visualizations/public'; +import { SchemaConfig } from '../../../visualizations/public'; import { Range } from '../../../expressions/public'; export interface MetricVisComponentProps { visParams: VisParams; visData: Input; - vis: ExprVis; + fireEvent: (event: any) => void; renderComplete: () => void; } @@ -166,10 +166,17 @@ export class MetricVisComponent extends Component { return; } const table = this.props.visData; - this.props.vis.API.events.filter({ - table, - column: dimensions.bucket.accessor, - row: metric.rowIndex, + this.props.fireEvent({ + name: 'filterBucket', + data: { + data: [ + { + table, + column: dimensions.bucket.accessor, + row: metric.rowIndex, + }, + ], + }, }); }; @@ -199,6 +206,6 @@ export class MetricVisComponent extends Component { const metrics = this.processTableGroups(this.props.visData); metricsHtml = metrics.map(this.renderMetric); } - return
{metricsHtml}
; + return metricsHtml; } } diff --git a/src/plugins/vis_type_metric/public/metric_vis_fn.ts b/src/plugins/vis_type_metric/public/metric_vis_fn.ts index 3d16fed0fa385..b58be63581724 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_fn.ts +++ b/src/plugins/vis_type_metric/public/metric_vis_fn.ts @@ -53,12 +53,14 @@ interface RenderValue { params: any; } -export const createMetricVisFn = (): ExpressionFunctionDefinition< +export type MetricVisExpressionFunctionDefinition = ExpressionFunctionDefinition< 'metricVis', Input, Arguments, Render -> => ({ +>; + +export const createMetricVisFn = (): MetricVisExpressionFunctionDefinition => ({ name: 'metricVis', type: 'render', inputTypes: ['kibana_datatable'], @@ -175,7 +177,7 @@ export const createMetricVisFn = (): ExpressionFunctionDefinition< return { type: 'render', - as: 'visualization', + as: 'metric_vis', value: { visData: input, visType, diff --git a/src/plugins/vis_type_metric/public/metric_vis_renderer.tsx b/src/plugins/vis_type_metric/public/metric_vis_renderer.tsx new file mode 100644 index 0000000000000..2bae668b080ea --- /dev/null +++ b/src/plugins/vis_type_metric/public/metric_vis_renderer.tsx @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { MetricVisComponent } from './components/metric_vis_component'; +import { getI18n } from './services'; +import { VisualizationContainer } from '../../visualizations/public'; +import { ExpressionRenderDefinition } from '../../expressions/common/expression_renderers'; + +export const metricVisRenderer: () => ExpressionRenderDefinition = () => ({ + name: 'metric_vis', + displayName: 'metric visualization', + reuseDomNode: true, + render: async (domNode: HTMLElement, config: any, handlers: any) => { + const { visData, visConfig } = config; + + const I18nContext = getI18n().Context; + + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); + + render( + + + + + , + domNode + ); + }, +}); diff --git a/src/plugins/vis_type_metric/public/metric_vis_type.ts b/src/plugins/vis_type_metric/public/metric_vis_type.ts index b7e9213283bee..6b4d6e151693f 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_type.ts +++ b/src/plugins/vis_type_metric/public/metric_vis_type.ts @@ -18,12 +18,11 @@ */ import { i18n } from '@kbn/i18n'; - -import { MetricVisComponent } from './components/metric_vis_component'; import { MetricVisOptions } from './components/metric_vis_options'; import { ColorSchemas, colorSchemas, ColorModes } from '../../charts/public'; import { AggGroupNames } from '../../data/public'; import { Schemas } from '../../vis_default_editor/public'; +import { toExpressionAst } from './to_ast'; export const createMetricVisTypeDefinition = () => ({ name: 'metric', @@ -32,8 +31,8 @@ export const createMetricVisTypeDefinition = () => ({ description: i18n.translate('visTypeMetric.metricDescription', { defaultMessage: 'Display a calculation as a single number', }), + toExpressionAst, visConfig: { - component: MetricVisComponent, defaults: { addTooltip: true, addLegend: false, diff --git a/src/plugins/vis_type_metric/public/plugin.ts b/src/plugins/vis_type_metric/public/plugin.ts index a3951fa46c21c..b9e094aa76889 100644 --- a/src/plugins/vis_type_metric/public/plugin.ts +++ b/src/plugins/vis_type_metric/public/plugin.ts @@ -25,8 +25,9 @@ import { createMetricVisFn } from './metric_vis_fn'; import { createMetricVisTypeDefinition } from './metric_vis_type'; import { ChartsPluginSetup } from '../../charts/public'; import { DataPublicPluginStart } from '../../data/public'; -import { setFormatService } from './services'; +import { setFormatService, setI18n } from './services'; import { ConfigSchema } from '../config'; +import { metricVisRenderer } from './metric_vis_renderer'; /** @internal */ export interface MetricVisPluginSetupDependencies { @@ -53,10 +54,12 @@ export class MetricVisPlugin implements Plugin { { expressions, visualizations, charts }: MetricVisPluginSetupDependencies ) { expressions.registerFunction(createMetricVisFn); - visualizations.createReactVisualization(createMetricVisTypeDefinition()); + expressions.registerRenderer(metricVisRenderer); + visualizations.createBaseVisualization(createMetricVisTypeDefinition()); } public start(core: CoreStart, { data }: MetricVisPluginStartDependencies) { + setI18n(core.i18n); setFormatService(data.fieldFormats); } } diff --git a/src/plugins/vis_type_metric/public/services.ts b/src/plugins/vis_type_metric/public/services.ts index 681afbaf0b268..0e19cfdce228d 100644 --- a/src/plugins/vis_type_metric/public/services.ts +++ b/src/plugins/vis_type_metric/public/services.ts @@ -17,9 +17,12 @@ * under the License. */ +import { I18nStart } from 'kibana/public'; import { createGetterSetter } from '../../kibana_utils/common'; import { DataPublicPluginStart } from '../../data/public'; export const [getFormatService, setFormatService] = createGetterSetter< DataPublicPluginStart['fieldFormats'] >('metric data.fieldFormats'); + +export const [getI18n, setI18n] = createGetterSetter('I18n'); diff --git a/src/plugins/vis_type_metric/public/to_ast.test.ts b/src/plugins/vis_type_metric/public/to_ast.test.ts new file mode 100644 index 0000000000000..e741e64c0422b --- /dev/null +++ b/src/plugins/vis_type_metric/public/to_ast.test.ts @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { toExpressionAst } from './to_ast'; +import { Vis } from '../../visualizations/public'; + +describe('metric vis toExpressionAst function', () => { + let vis: Vis; + + beforeEach(() => { + vis = { + isHierarchical: () => false, + type: {}, + params: { + percentageMode: false, + }, + data: { + indexPattern: { id: '123' } as any, + aggs: { + getResponseAggs: () => [], + aggs: [], + } as any, + }, + } as any; + }); + + it('without params', () => { + vis.params = { metric: {} }; + const actual = toExpressionAst(vis, {}); + expect(actual).toMatchSnapshot(); + }); + + it('with percentage mode should have percentage format', () => { + vis.params = { metric: { percentageMode: true } }; + const actual = toExpressionAst(vis, {}); + expect(actual).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/vis_type_metric/public/to_ast.ts b/src/plugins/vis_type_metric/public/to_ast.ts new file mode 100644 index 0000000000000..7eefd8328ab76 --- /dev/null +++ b/src/plugins/vis_type_metric/public/to_ast.ts @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { get } from 'lodash'; +import { getVisSchemas, SchemaConfig, Vis } from '../../visualizations/public'; +import { buildExpression, buildExpressionFunction } from '../../expressions/public'; +import { MetricVisExpressionFunctionDefinition } from './metric_vis_fn'; +import { EsaggsExpressionFunctionDefinition } from '../../data/common/search/expressions'; + +const prepareDimension = (params: SchemaConfig) => { + const visdimension = buildExpressionFunction('visdimension', { accessor: params.accessor }); + + if (params.format) { + visdimension.addArgument('format', params.format.id); + visdimension.addArgument('formatParams', JSON.stringify(params.format.params)); + } + + return buildExpression([visdimension]); +}; + +export const toExpressionAst = (vis: Vis, params: any) => { + // soon this becomes: const esaggs = vis.data.aggs!.toExpressionAst(); + const esaggs = buildExpressionFunction('esaggs', { + index: vis.data.indexPattern!.id!, + metricsAtAllLevels: vis.isHierarchical(), + partialRows: vis.type.requiresPartialRows || vis.params.showPartialRows || false, + aggConfigs: JSON.stringify(vis.data.aggs!.aggs), + includeFormatHints: false, + }); + + const schemas = getVisSchemas(vis, params); + + const { + percentageMode, + useRanges, + colorSchema, + metricColorMode, + colorsRange, + labels, + invertColors, + style, + } = vis.params.metric; + + // fix formatter for percentage mode + if (get(vis.params, 'metric.percentageMode') === true) { + schemas.metric.forEach((metric: SchemaConfig) => { + metric.format = { id: 'percent' }; + }); + } + + // @ts-expect-error + const metricVis = buildExpressionFunction('metricVis', { + percentageMode, + colorSchema, + colorMode: metricColorMode, + useRanges, + invertColors, + showLabels: labels && labels.show, + }); + + if (style) { + metricVis.addArgument('bgFill', style.bgFill); + metricVis.addArgument('font', buildExpression(`font size=${style.fontSize}`)); + metricVis.addArgument('subText', style.subText); + } + + if (colorsRange) { + colorsRange.forEach((range: any) => { + metricVis.addArgument( + 'colorRange', + buildExpression(`range from=${range.from} to=${range.to}`) + ); + }); + } + + if (schemas.group) { + metricVis.addArgument('bucket', prepareDimension(schemas.group[0])); + } + + schemas.metric.forEach((metric) => { + metricVis.addArgument('metric', prepareDimension(metric)); + }); + + const ast = buildExpression([esaggs, metricVis]); + + return ast.toAst(); +}; diff --git a/src/plugins/visualizations/public/components/index.ts b/src/plugins/visualizations/public/components/index.ts index 73685de81d68e..195a49f9e0d54 100644 --- a/src/plugins/visualizations/public/components/index.ts +++ b/src/plugins/visualizations/public/components/index.ts @@ -18,3 +18,5 @@ */ export { Visualization } from './visualization'; +export { VisualizationContainer } from './visualization_container'; +export { VisualizationNoResults } from './visualization_noresults'; diff --git a/src/plugins/vis_type_metric/public/metric_vis_type.test.ts b/src/plugins/visualizations/public/components/visualization_container.tsx similarity index 68% rename from src/plugins/vis_type_metric/public/metric_vis_type.test.ts rename to src/plugins/visualizations/public/components/visualization_container.tsx index 636118c692aaa..d6f87d4cea123 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_type.test.ts +++ b/src/plugins/visualizations/public/components/visualization_container.tsx @@ -17,13 +17,14 @@ * under the License. */ -import { createMetricVisTypeDefinition } from './metric_vis_type'; -import { MetricVisComponent } from './components/metric_vis_component'; +import React, { ReactNode } from 'react'; -describe('metric_vis - createMetricVisTypeDefinition', () => { - it('has metric vis component set', () => { - const def = createMetricVisTypeDefinition(); +interface VisualizationContainerProps { + className?: string; + children: ReactNode; +} - expect(def.visConfig.component).toBe(MetricVisComponent); - }); -}); +export const VisualizationContainer = (props: VisualizationContainerProps) => { + const classes = `visualization ${props.className}`; + return
{props.children}
; +}; diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index 49cfbe76aa9d0..17c292a1b183b 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -31,6 +31,8 @@ export function plugin(initializerContext: PluginInitializerContext) { export { Vis } from './vis'; export { TypesService } from './vis_types/types_service'; export { VISUALIZE_EMBEDDABLE_TYPE, VIS_EVENT_TO_TRIGGER } from './embeddable'; +export { VisualizationContainer, VisualizationNoResults } from './components'; +export { getSchemas as getVisSchemas } from './legacy/build_pipeline'; /** @public types */ export { VisualizationsSetup, VisualizationsStart }; diff --git a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap index 90c1d4472d5ea..df29c078d23e4 100644 --- a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap +++ b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap @@ -1,17 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`visualize loader pipeline helpers: build pipeline buildPipeline calls toExpression on vis_type if it exists 1`] = `"kibana | kibana_context | testing custom expressions"`; +exports[`visualize loader pipeline helpers: build pipeline buildPipeline calls toExpression on vis_type if it exists 1`] = `"kibana | kibana_context | test"`; exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles input_control_vis function 1`] = `"input_control_vis visConfig='{\\"some\\":\\"nested\\",\\"data\\":{\\"here\\":true}}' "`; exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles markdown function 1`] = `"markdownvis '## hello _markdown_' font={font size=12} openLinksInNewTab=true "`; -exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles metric function with buckets 1`] = `"metricvis metric={visdimension 0 } metric={visdimension 1 } "`; - -exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles metric function with percentage mode should have percentage format 1`] = `"metricvis percentageMode=true metric={visdimension 0 format='percent' } "`; - -exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles metric function without buckets 1`] = `"metricvis metric={visdimension 0 } metric={visdimension 1 } "`; - exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles metrics/tsvb function 1`] = `"tsvb params='{\\"foo\\":\\"bar\\"}' uiState='{}' "`; exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles pie function 1`] = `"kibana_pie visConfig='{\\"dimensions\\":{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"},\\"buckets\\":[1,2]}}' "`; diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts index 9ecd321963e8a..50fa5ac64e2a1 100644 --- a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts @@ -29,6 +29,7 @@ import { import { Vis } from '..'; import { dataPluginMock } from '../../../../plugins/data/public/mocks'; import { IndexPattern, IAggConfigs } from '../../../../plugins/data/public'; +import { parseExpression } from '../../../expressions/common'; describe('visualize loader pipeline helpers: build pipeline', () => { describe('prepareJson', () => { @@ -217,42 +218,6 @@ describe('visualize loader pipeline helpers: build pipeline', () => { }); }); - describe('handles metric function', () => { - it('without buckets', () => { - const params = { metric: {} }; - const schemas = { - ...schemasDef, - metric: [ - { ...schemaConfig, accessor: 0 }, - { ...schemaConfig, accessor: 1 }, - ], - }; - const actual = buildPipelineVisFunction.metric(params, schemas, uiState); - expect(actual).toMatchSnapshot(); - }); - - it('with buckets', () => { - const params = { metric: {} }; - const schemas = { - ...schemasDef, - metric: [ - { ...schemaConfig, accessor: 0 }, - { ...schemaConfig, accessor: 1 }, - ], - group: [{ accessor: 2 }], - }; - const actual = buildPipelineVisFunction.metric(params, schemas, uiState); - expect(actual).toMatchSnapshot(); - }); - - it('with percentage mode should have percentage format', () => { - const params = { metric: { percentageMode: true } }; - const schemas = { ...schemasDef }; - const actual = buildPipelineVisFunction.metric(params, schemas, uiState); - expect(actual).toMatchSnapshot(); - }); - }); - describe('handles tagcloud function', () => { it('without buckets', () => { const actual = buildPipelineVisFunction.tagcloud({}, schemasDef, uiState); @@ -331,7 +296,7 @@ describe('visualize loader pipeline helpers: build pipeline', () => { }, // @ts-ignore type: { - toExpression: () => 'testing custom expressions', + toExpressionAst: () => parseExpression('test'), }, } as unknown) as Vis; const expression = await buildPipeline(vis, { diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.ts b/src/plugins/visualizations/public/legacy/build_pipeline.ts index d52e2fcc13bff..ebd240c79287a 100644 --- a/src/plugins/visualizations/public/legacy/build_pipeline.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.ts @@ -19,7 +19,7 @@ import { get } from 'lodash'; import moment from 'moment'; -import { SerializedFieldFormat } from '../../../../plugins/expressions/public'; +import { formatExpression, SerializedFieldFormat } from '../../../../plugins/expressions/public'; import { IAggConfig, search, TimefilterContract } from '../../../../plugins/data/public'; import { Vis, VisParams } from '../types'; const { isDateHistogramBucketAggConfig } = search.aggs; @@ -80,7 +80,7 @@ const vislibCharts: string[] = [ 'line', ]; -const getSchemas = ( +export const getSchemas = ( vis: Vis, opts: { timeRange?: any; @@ -287,52 +287,6 @@ export const buildPipelineVisFunction: BuildPipelineVisFunction = { }; return `kibana_table ${prepareJson('visConfig', visConfig)}`; }, - metric: (params, schemas) => { - const { - percentageMode, - useRanges, - colorSchema, - metricColorMode, - colorsRange, - labels, - invertColors, - style, - } = params.metric; - const { metrics, bucket } = buildVisConfig.metric(schemas).dimensions; - - // fix formatter for percentage mode - if (get(params, 'metric.percentageMode') === true) { - metrics.forEach((metric: SchemaConfig) => { - metric.format = { id: 'percent' }; - }); - } - - let expr = `metricvis `; - expr += prepareValue('percentageMode', percentageMode); - expr += prepareValue('colorSchema', colorSchema); - expr += prepareValue('colorMode', metricColorMode); - expr += prepareValue('useRanges', useRanges); - expr += prepareValue('invertColors', invertColors); - expr += prepareValue('showLabels', labels && labels.show); - if (style) { - expr += prepareValue('bgFill', style.bgFill); - expr += prepareValue('font', `{font size=${style.fontSize}}`, true); - expr += prepareValue('subText', style.subText); - expr += prepareDimension('bucket', bucket); - } - - if (colorsRange) { - colorsRange.forEach((range: any) => { - expr += prepareValue('colorRange', `{range from=${range.from} to=${range.to}}`, true); - }); - } - - metrics.forEach((metric: SchemaConfig) => { - expr += prepareDimension('metric', metric); - }); - - return expr; - }, tagcloud: (params, schemas) => { const { scale, orientation, minFontSize, maxFontSize, showLabel } = params; const { metric, bucket } = buildVisConfig.tagcloud(schemas); @@ -390,14 +344,6 @@ const buildVisConfig: BuildVisConfigFunction = { } return visConfig; }, - metric: (schemas) => { - const visConfig = { dimensions: {} } as any; - visConfig.dimensions.metrics = schemas.metric; - if (schemas.group) { - visConfig.dimensions.bucket = schemas.group[0]; - } - return visConfig; - }, tagcloud: (schemas) => { const visConfig = {} as any; visConfig.metric = schemas.metric[0]; @@ -507,39 +453,46 @@ export const buildPipeline = async ( } pipeline += '| '; - // request handler - if (vis.type.requestHandler === 'courier') { - pipeline += `esaggs + if (vis.type.toExpressionAst) { + const visAst = await vis.type.toExpressionAst(vis, params); + pipeline += formatExpression(visAst); + } else { + // request handler + if (vis.type.requestHandler === 'courier') { + pipeline += `esaggs ${prepareString('index', indexPattern!.id)} metricsAtAllLevels=${vis.isHierarchical()} partialRows=${vis.type.requiresPartialRows || vis.params.showPartialRows || false} ${prepareJson('aggConfigs', vis.data.aggs!.aggs)} | `; - } + } - const schemas = getSchemas(vis, { - timeRange: params.timeRange, - timefilter: params.timefilter, - }); - if (buildPipelineVisFunction[vis.type.name]) { - pipeline += buildPipelineVisFunction[vis.type.name]({ title, ...vis.params }, schemas, uiState); - } else if (vislibCharts.includes(vis.type.name)) { - const visConfig = { ...vis.params }; - visConfig.dimensions = await buildVislibDimensions(vis, params); - - pipeline += `vislib type='${vis.type.name}' ${prepareJson('visConfig', visConfig)}`; - } else if (vis.type.toExpression) { - pipeline += await vis.type.toExpression(vis, params); - } else { - const visConfig = { ...vis.params }; - visConfig.dimensions = schemas; - pipeline += `visualization type='${vis.type.name}' + const schemas = getSchemas(vis, { + timeRange: params.timeRange, + timefilter: params.timefilter, + }); + if (buildPipelineVisFunction[vis.type.name]) { + pipeline += buildPipelineVisFunction[vis.type.name]( + { title, ...vis.params }, + schemas, + uiState + ); + } else if (vislibCharts.includes(vis.type.name)) { + const visConfig = { ...vis.params }; + visConfig.dimensions = await buildVislibDimensions(vis, params); + + pipeline += `vislib type='${vis.type.name}' ${prepareJson('visConfig', visConfig)}`; + } else { + const visConfig = { ...vis.params }; + visConfig.dimensions = schemas; + pipeline += `visualization type='${vis.type.name}' ${prepareJson('visConfig', visConfig)} metricsAtAllLevels=${vis.isHierarchical()} partialRows=${vis.type.requiresPartialRows || vis.params.showPartialRows || false} `; - if (indexPattern) { - pipeline += `${prepareString('index', indexPattern.id)} `; - if (vis.data.aggs) { - pipeline += `${prepareJson('aggConfigs', vis.data.aggs!.aggs)}`; + if (indexPattern) { + pipeline += `${prepareString('index', indexPattern.id)} `; + if (vis.data.aggs) { + pipeline += `${prepareJson('aggConfigs', vis.data.aggs!.aggs)}`; + } } } } diff --git a/src/plugins/visualizations/public/types.ts b/src/plugins/visualizations/public/types.ts index daf275297fb82..f47ffbbe921a2 100644 --- a/src/plugins/visualizations/public/types.ts +++ b/src/plugins/visualizations/public/types.ts @@ -18,7 +18,11 @@ */ import { SavedObject } from '../../../plugins/saved_objects/public'; -import { AggConfigOptions, SearchSourceFields } from '../../../plugins/data/public'; +import { + AggConfigOptions, + SearchSourceFields, + TimefilterContract, +} from '../../../plugins/data/public'; import { SerializedVis, Vis, VisParams } from './vis'; export { Vis, SerializedVis, VisParams }; @@ -60,3 +64,11 @@ export interface VisResponseValue { visConfig: object; params?: object; } + +export interface VisToExpressionAstParams { + timefilter: TimefilterContract; + timeRange?: any; + abortSignal?: AbortSignal; +} + +export type VisToExpressionAst = (vis: Vis, params: VisToExpressionAstParams) => string; diff --git a/src/plugins/visualizations/public/vis.ts b/src/plugins/visualizations/public/vis.ts index e8ae48cdce145..b4fc9df1c6ecc 100644 --- a/src/plugins/visualizations/public/vis.ts +++ b/src/plugins/visualizations/public/vis.ts @@ -202,8 +202,8 @@ export class Vis { }; } - toAST() { - return this.type.toAST(this.params); + toExpressionAst() { + return this.type.toExpressionAst(this.params); } // deprecated diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index 1a3a426398e36..fa0bbfc5e250a 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import { VisualizationControllerConstructor } from '../types'; +import { VisToExpressionAst, VisualizationControllerConstructor } from '../types'; import { TriggerContextMapping } from '../../../ui_actions/public'; import { Adapters } from '../../../inspector/public'; @@ -31,7 +31,7 @@ export interface BaseVisTypeOptions { image?: string; stage?: 'experimental' | 'beta' | 'production'; options?: Record; - visualization: VisualizationControllerConstructor; + visualization: VisualizationControllerConstructor | undefined; visConfig?: Record; editor?: any; editorConfig?: Record; @@ -42,6 +42,7 @@ export interface BaseVisTypeOptions { setup?: unknown; useCustomNoDataScreen?: boolean; inspectorAdapters?: Adapters | (() => Adapters); + toExpressionAst?: VisToExpressionAst; } export class BaseVisType { @@ -54,7 +55,7 @@ export class BaseVisType { stage: 'experimental' | 'beta' | 'production'; isExperimental: boolean; options: Record; - visualization: VisualizationControllerConstructor; + visualization: VisualizationControllerConstructor | undefined; visConfig: Record; editor: any; editorConfig: Record; @@ -66,6 +67,7 @@ export class BaseVisType { setup?: unknown; useCustomNoDataScreen: boolean; inspectorAdapters?: Adapters | (() => Adapters); + toExpressionAst?: VisToExpressionAst; constructor(opts: BaseVisTypeOptions) { if (!opts.icon && !opts.image) { @@ -102,6 +104,7 @@ export class BaseVisType { this.hierarchicalData = opts.hierarchicalData || false; this.useCustomNoDataScreen = opts.useCustomNoDataScreen || false; this.inspectorAdapters = opts.inspectorAdapters; + this.toExpressionAst = opts.toExpressionAst; } public get schemas() { diff --git a/test/interpreter_functional/snapshots/baseline/combined_test3.json b/test/interpreter_functional/snapshots/baseline/combined_test3.json index af9fe198d88ea..2760875119197 100644 --- a/test/interpreter_functional/snapshots/baseline/combined_test3.json +++ b/test/interpreter_functional/snapshots/baseline/combined_test3.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/final_output_test.json b/test/interpreter_functional/snapshots/baseline/final_output_test.json index af9fe198d88ea..2760875119197 100644 --- a/test/interpreter_functional/snapshots/baseline/final_output_test.json +++ b/test/interpreter_functional/snapshots/baseline/final_output_test.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_all_data.json b/test/interpreter_functional/snapshots/baseline/metric_all_data.json index 9b0122c157481..ae72bcfa6d5ec 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_all_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_all_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json b/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json index 2d6e756a7f0a3..8568215fd9e1a 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_percentage_mode.json b/test/interpreter_functional/snapshots/baseline/metric_percentage_mode.json index 37c6885d76cb0..d11e1dfb925f1 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_percentage_mode.json +++ b/test/interpreter_functional/snapshots/baseline/metric_percentage_mode.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":1000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":true,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":1000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":true,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json b/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json index 60a0e450906a2..b160e05935f17 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/partial_test_2.json b/test/interpreter_functional/snapshots/baseline/partial_test_2.json index af9fe198d88ea..2760875119197 100644 --- a/test/interpreter_functional/snapshots/baseline/partial_test_2.json +++ b/test/interpreter_functional/snapshots/baseline/partial_test_2.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/step_output_test3.json b/test/interpreter_functional/snapshots/baseline/step_output_test3.json index af9fe198d88ea..2760875119197 100644 --- a/test/interpreter_functional/snapshots/baseline/step_output_test3.json +++ b/test/interpreter_functional/snapshots/baseline/step_output_test3.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/combined_test3.json b/test/interpreter_functional/snapshots/session/combined_test3.json index af9fe198d88ea..2760875119197 100644 --- a/test/interpreter_functional/snapshots/session/combined_test3.json +++ b/test/interpreter_functional/snapshots/session/combined_test3.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/final_output_test.json b/test/interpreter_functional/snapshots/session/final_output_test.json index af9fe198d88ea..2760875119197 100644 --- a/test/interpreter_functional/snapshots/session/final_output_test.json +++ b/test/interpreter_functional/snapshots/session/final_output_test.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_all_data.json b/test/interpreter_functional/snapshots/session/metric_all_data.json index 9b0122c157481..ae72bcfa6d5ec 100644 --- a/test/interpreter_functional/snapshots/session/metric_all_data.json +++ b/test/interpreter_functional/snapshots/session/metric_all_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json b/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json index 2d6e756a7f0a3..8568215fd9e1a 100644 --- a/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json +++ b/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_percentage_mode.json b/test/interpreter_functional/snapshots/session/metric_percentage_mode.json index 37c6885d76cb0..d11e1dfb925f1 100644 --- a/test/interpreter_functional/snapshots/session/metric_percentage_mode.json +++ b/test/interpreter_functional/snapshots/session/metric_percentage_mode.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":1000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":true,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":1000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":true,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_single_metric_data.json b/test/interpreter_functional/snapshots/session/metric_single_metric_data.json index 60a0e450906a2..b160e05935f17 100644 --- a/test/interpreter_functional/snapshots/session/metric_single_metric_data.json +++ b/test/interpreter_functional/snapshots/session/metric_single_metric_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"},{"id":"col-2-1","meta":{"aggConfigParams":{"field":"bytes"},"indexPatternId":"logstash-*","type":"max"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/partial_test_2.json b/test/interpreter_functional/snapshots/session/partial_test_2.json index af9fe198d88ea..2760875119197 100644 --- a/test/interpreter_functional/snapshots/session/partial_test_2.json +++ b/test/interpreter_functional/snapshots/session/partial_test_2.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/step_output_test3.json b/test/interpreter_functional/snapshots/session/step_output_test3.json index af9fe198d88ea..2760875119197 100644 --- a/test/interpreter_functional/snapshots/session/step_output_test3.json +++ b/test/interpreter_functional/snapshots/session/step_output_test3.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"metric"}} \ No newline at end of file