From c0a14cd41bfa2d7d1c8dc8753a3a0260b2d0c95e Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 27 Mar 2020 16:12:02 +0100 Subject: [PATCH 01/13] Navlink url tracker: Reset navlink on failed redirect (#61460) --- .../kibana/public/discover/kibana_services.ts | 5 +++++ .../public/discover/np_ready/angular/discover.js | 4 ++++ .../core_plugins/kibana/public/discover/plugin.ts | 10 ++++++++-- .../kibana/public/visualize/np_ready/legacy_app.js | 3 +++ .../public/history/redirect_when_missing.tsx | 8 ++++++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts index e1ff274911284..2ceb06f325a9e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts @@ -47,10 +47,15 @@ export function setServices(newServices: any) { services = newServices; } +export const [getUrlTracker, setUrlTracker] = createGetterSetter<{ + setTrackedUrl: (url: string) => void; +}>('urlTracker'); + // EXPORT legacy static dependencies, should be migrated when available in a new version; export { angular }; export { wrapInI18nContext } from 'ui/i18n'; import { search } from '../../../../../plugins/data/public'; +import { createGetterSetter } from '../../../../../plugins/kibana_utils/common'; export const { getRequestInspectorStats, getResponseInspectorStats, tabifyAggResponse } = search; export { unhashUrl, diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index bcf97a21dcde9..630ba22d4f3a6 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -44,6 +44,7 @@ import { getRequestInspectorStats, getResponseInspectorStats, getServices, + getUrlTracker, unhashUrl, subscribeWithScope, tabifyAggResponse, @@ -160,6 +161,9 @@ app.config($routeProvider => { '/management/kibana/objects/savedSearches/' + $route.current.params.id, }, toastNotifications, + onBeforeRedirect() { + getUrlTracker().setTrackedUrl('/discover'); + }, }) ), }); diff --git a/src/legacy/core_plugins/kibana/public/discover/plugin.ts b/src/legacy/core_plugins/kibana/public/discover/plugin.ts index 661c1c052caba..fcac7aa74f54a 100644 --- a/src/legacy/core_plugins/kibana/public/discover/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/discover/plugin.ts @@ -31,7 +31,7 @@ import { registerFeature } from './np_ready/register_feature'; import './kibana_services'; import { EmbeddableStart, EmbeddableSetup } from '../../../../../plugins/embeddable/public'; import { getInnerAngularModule, getInnerAngularModuleEmbeddable } from './get_inner_angular'; -import { setAngularModule, setServices } from './kibana_services'; +import { setAngularModule, setServices, setUrlTracker } from './kibana_services'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; import { ChartsPluginStart } from '../../../../../plugins/charts/public'; import { buildServices } from './build_services'; @@ -92,7 +92,12 @@ export class DiscoverPlugin implements Plugin { public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>; setup(core: CoreSetup, plugins: DiscoverSetupPlugins) { - const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({ + const { + appMounted, + appUnMounted, + stop: stopUrlTracker, + setActiveUrl: setTrackedUrl, + } = createKbnUrlTracker({ baseUrl: core.http.basePath.prepend('/app/kibana'), defaultSubUrl: '#/discover', storageKey: 'lastUrl:discover', @@ -113,6 +118,7 @@ export class DiscoverPlugin implements Plugin { }, ], }); + setUrlTracker({ setTrackedUrl }); this.stopUrlTracking = () => { stopUrlTracker(); }; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js index b0b1ae31a02a5..d1bf4411cac2a 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js @@ -204,6 +204,9 @@ export function initVisualizeApp(app, deps) { '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, }, toastNotifications, + onBeforeRedirect() { + deps.setActiveUrl(VisualizeConstants.LANDING_PAGE_PATH); + }, }) ); }, diff --git a/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx b/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx index cbdeef6fbe96c..8a4cc88999bfe 100644 --- a/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx +++ b/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx @@ -37,6 +37,7 @@ export function redirectWhenMissing({ history, mapping, toastNotifications, + onBeforeRedirect, }: { history: History; /** @@ -48,6 +49,10 @@ export function redirectWhenMissing({ * Toast notifications service to show toasts in error cases. */ toastNotifications: ToastsSetup; + /** + * Optional callback invoked directly before a redirect is triggered + */ + onBeforeRedirect?: (error: SavedObjectNotFound) => void; }) { let localMappingObject: Mapping; @@ -75,6 +80,9 @@ export function redirectWhenMissing({ text: toMountPoint({error.message}), }); + if (onBeforeRedirect) { + onBeforeRedirect(error); + } history.replace(url); }; } From f5e94c4ca38fce285e890c98310eee94d36c14ff Mon Sep 17 00:00:00 2001 From: Robert Oskamp Date: Fri, 27 Mar 2020 16:12:15 +0100 Subject: [PATCH 02/13] [ML] Move get_module Jest tests to functional API test (#61613) This PR removes the flaky listModules and getModule Jest tests and adds them as functional API tests. --- .../data_recognizer/data_recognizer.test.ts | 33 --------- .../api_integration/apis/ml/get_module.ts | 70 +++++++++++++++++++ x-pack/test/api_integration/apis/ml/index.ts | 1 + 3 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 x-pack/test/api_integration/apis/ml/get_module.ts diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts index 277e1547e4b23..bcdc58e61ad7c 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts @@ -17,39 +17,6 @@ describe('ML - data recognizer', () => { } as never) as SavedObjectsClientContract ); - const moduleIds = [ - 'apache_ecs', - 'apm_jsbase', - 'apm_nodejs', - 'apm_transaction', - 'auditbeat_process_docker_ecs', - 'auditbeat_process_hosts_ecs', - 'logs_ui_analysis', - 'logs_ui_categories', - 'metricbeat_system_ecs', - 'nginx_ecs', - 'sample_data_ecommerce', - 'sample_data_weblogs', - 'siem_auditbeat', - 'siem_auditbeat_auth', - 'siem_packetbeat', - 'siem_winlogbeat', - 'siem_winlogbeat_auth', - 'uptime_heartbeat', - ]; - - // check all module IDs are the same as the list above - it('listModules - check all module IDs', async () => { - const modules = await dr.listModules(); - const ids = modules.map(m => m.id); - expect(ids.join()).toEqual(moduleIds.join()); - }); - - it('getModule - load a single module', async () => { - const module = await dr.getModule(moduleIds[0]); - expect(module.id).toEqual(moduleIds[0]); - }); - describe('jobOverrides', () => { it('should apply job overrides correctly', () => { // arrange diff --git a/x-pack/test/api_integration/apis/ml/get_module.ts b/x-pack/test/api_integration/apis/ml/get_module.ts new file mode 100644 index 0000000000000..4478236c494a8 --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/get_module.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../ftr_provider_context'; +import { USER } from '../../../functional/services/machine_learning/security_common'; + +const COMMON_HEADERS = { + 'kbn-xsrf': 'some-xsrf-token', +}; + +const moduleIds = [ + 'apache_ecs', + 'apm_jsbase', + 'apm_nodejs', + 'apm_transaction', + 'auditbeat_process_docker_ecs', + 'auditbeat_process_hosts_ecs', + 'logs_ui_analysis', + 'logs_ui_categories', + 'metricbeat_system_ecs', + 'nginx_ecs', + 'sample_data_ecommerce', + 'sample_data_weblogs', + 'siem_auditbeat', + 'siem_auditbeat_auth', + 'siem_packetbeat', + 'siem_winlogbeat', + 'siem_winlogbeat_auth', + 'uptime_heartbeat', +]; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertestWithoutAuth'); + const mlSecurity = getService('mlSecurity'); + + async function executeGetModuleRequest(module: string, user: USER, rspCode: number) { + const { body } = await supertest + .get(`/api/ml/modules/get_module/${module}`) + .auth(user, mlSecurity.getPasswordForUser(user)) + .set(COMMON_HEADERS) + .expect(rspCode); + + return body; + } + + describe('get_module', function() { + it('lists all modules', async () => { + const rspBody = await executeGetModuleRequest('', USER.ML_POWERUSER, 200); + expect(rspBody).to.be.an(Array); + + const responseModuleIds = rspBody.map((module: { id: string }) => module.id); + expect(responseModuleIds).to.eql(moduleIds); + }); + + for (const moduleId of moduleIds) { + it(`loads module ${moduleId}`, async () => { + const rspBody = await executeGetModuleRequest(moduleId, USER.ML_POWERUSER, 200); + expect(rspBody).to.be.an(Object); + + expect(rspBody.id).to.eql(moduleId); + }); + } + }); +}; diff --git a/x-pack/test/api_integration/apis/ml/index.ts b/x-pack/test/api_integration/apis/ml/index.ts index e2000b661367f..78f99d8d9776a 100644 --- a/x-pack/test/api_integration/apis/ml/index.ts +++ b/x-pack/test/api_integration/apis/ml/index.ts @@ -25,5 +25,6 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./bucket_span_estimator')); loadTestFile(require.resolve('./calculate_model_memory_limit')); loadTestFile(require.resolve('./categorization_field_examples')); + loadTestFile(require.resolve('./get_module')); }); } From 80417f6888a7af91b8df2b0667b372feb8db905a Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Fri, 27 Mar 2020 08:31:34 -0700 Subject: [PATCH 03/13] [Search] Fix async search to encode index pattern in path (#61374) * Fix async search to encode index in path * Update docs * Review feedback & fixing types --- .../kibana-plugin-plugins-data-server.md | 1 + src/plugins/data/server/index.ts | 1 + .../search/es_search/es_search_strategy.ts | 6 +- .../search/es_search/get_total_loaded.test.ts | 36 +++++ .../search/es_search/get_total_loaded.ts | 30 ++++ .../data/server/search/es_search/index.ts | 1 + src/plugins/data/server/search/index.ts | 2 +- src/plugins/data/server/server.api.md | 19 ++- .../server/search/es_search_strategy.test.ts | 144 ++++++++++++++++++ .../server/search/es_search_strategy.ts | 40 ++--- 10 files changed, 251 insertions(+), 29 deletions(-) create mode 100644 src/plugins/data/server/search/es_search/get_total_loaded.test.ts create mode 100644 src/plugins/data/server/search/es_search/get_total_loaded.ts create mode 100644 x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index e756eb9b72905..259d725b3bf0d 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -23,6 +23,7 @@ | Function | Description | | --- | --- | | [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | +| [getTotalLoaded({ total, failed, successful })](./kibana-plugin-plugins-data-server.gettotalloaded.md) | | | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-server.plugin.md) | Static code to be shared externally | | [shouldReadFieldFromDocValues(aggregatable, esType)](./kibana-plugin-plugins-data-server.shouldreadfieldfromdocvalues.md) | | diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 5038b4226fad8..47bef4255347c 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -173,6 +173,7 @@ export { ISearchContext, TSearchStrategyProvider, getDefaultSearchParams, + getTotalLoaded, } from './search'; // Search namespace diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts index b4ee02eefaf84..47cad7aa6b4d7 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts @@ -21,7 +21,7 @@ import { APICaller } from 'kibana/server'; import { SearchResponse } from 'elasticsearch'; import { ES_SEARCH_STRATEGY } from '../../../common/search'; import { ISearchStrategy, TSearchStrategyProvider } from '../i_search_strategy'; -import { getDefaultSearchParams, ISearchContext } from '..'; +import { getDefaultSearchParams, getTotalLoaded, ISearchContext } from '..'; export const esSearchStrategyProvider: TSearchStrategyProvider = ( context: ISearchContext, @@ -46,9 +46,7 @@ export const esSearchStrategyProvider: TSearchStrategyProvider { + it('returns the total/loaded, not including skipped', () => { + const result = getTotalLoaded({ + successful: 10, + failed: 5, + skipped: 5, + total: 100, + }); + + expect(result).toEqual({ + total: 100, + loaded: 15, + }); + }); +}); diff --git a/src/plugins/data/server/search/es_search/get_total_loaded.ts b/src/plugins/data/server/search/es_search/get_total_loaded.ts new file mode 100644 index 0000000000000..b5af600e84eff --- /dev/null +++ b/src/plugins/data/server/search/es_search/get_total_loaded.ts @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ShardsResponse } from 'elasticsearch'; + +/** + * Get the `total`/`loaded` for this response (see `IKibanaSearchResponse`). Note that `skipped` is + * not included as it is already included in `successful`. + * @internal + */ +export function getTotalLoaded({ total, failed, successful }: ShardsResponse) { + const loaded = failed + successful; + return { total, loaded }; +} diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index 5a8b3bc94c679..20006b70730d8 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -20,3 +20,4 @@ export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common/search'; export { esSearchStrategyProvider } from './es_search_strategy'; export { getDefaultSearchParams } from './get_default_search_params'; +export { getTotalLoaded } from './get_total_loaded'; diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts index 15738a3befb27..e08eba1cad831 100644 --- a/src/plugins/data/server/search/index.ts +++ b/src/plugins/data/server/search/index.ts @@ -33,4 +33,4 @@ export { TStrategyTypes } from './strategy_types'; export { TSearchStrategyProvider } from './i_search_strategy'; -export { getDefaultSearchParams } from './es_search'; +export { getDefaultSearchParams, getTotalLoaded } from './es_search'; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 1abc74fe07ccc..c41023eab6d20 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -125,6 +125,7 @@ import { SearchResponse } from 'elasticsearch'; import { SearchShardsParams } from 'elasticsearch'; import { SearchTemplateParams } from 'elasticsearch'; import { ShallowPromise } from '@kbn/utility-types'; +import { ShardsResponse } from 'elasticsearch'; import { SnapshotCreateParams } from 'elasticsearch'; import { SnapshotCreateRepositoryParams } from 'elasticsearch'; import { SnapshotDeleteParams } from 'elasticsearch'; @@ -330,6 +331,12 @@ export function getDefaultSearchParams(config: SharedGlobalConfig): { restTotalHitsAsInt: boolean; }; +// @internal +export function getTotalLoaded({ total, failed, successful }: ShardsResponse): { + total: number; + loaded: number; +}; + // Warning: (ae-missing-release-tag) "IFieldFormatsRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -730,12 +737,12 @@ export type TSearchStrategyProvider = (context: ISearc // src/plugins/data/server/index.ts:102:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:130:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:130:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:181:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:182:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:183:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:184:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:185:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:188:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:182:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:183:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:184:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:185:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:186:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:189:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:64:14 - (ae-forgotten-export) The symbol "ISearchSetup" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts new file mode 100644 index 0000000000000..88c576c70bdf0 --- /dev/null +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -0,0 +1,144 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { coreMock, pluginInitializerContextConfigMock } from '../../../../../src/core/server/mocks'; +import { enhancedEsSearchStrategyProvider } from './es_search_strategy'; + +const mockAsyncResponse = { + id: 'foo', + response: { + _shards: { + total: 10, + failed: 1, + skipped: 2, + successful: 7, + }, + }, +}; + +const mockRollupResponse = { + _shards: { + total: 10, + failed: 1, + skipped: 2, + successful: 7, + }, +}; + +describe('ES search strategy', () => { + const mockCoreSetup = coreMock.createSetup(); + const mockApiCaller = jest.fn(); + const mockSearch = jest.fn(); + const mockConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; + + beforeEach(() => { + mockApiCaller.mockClear(); + mockSearch.mockClear(); + }); + + it('returns a strategy with `search`', () => { + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + expect(typeof esSearch.search).toBe('function'); + }); + + it('makes a POST request to async search with params when no ID is provided', async () => { + mockApiCaller.mockResolvedValueOnce(mockAsyncResponse); + + const params = { index: 'logstash-*', body: { query: {} } }; + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + await esSearch.search({ params }); + + expect(mockApiCaller).toBeCalled(); + expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request'); + const { method, path, body } = mockApiCaller.mock.calls[0][1]; + expect(method).toBe('POST'); + expect(path).toBe('logstash-*/_async_search'); + expect(body).toEqual({ query: {} }); + }); + + it('makes a GET request to async search with ID when ID is provided', async () => { + mockApiCaller.mockResolvedValueOnce(mockAsyncResponse); + + const params = { index: 'logstash-*', body: { query: {} } }; + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + await esSearch.search({ id: 'foo', params }); + + expect(mockApiCaller).toBeCalled(); + expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request'); + const { method, path, body } = mockApiCaller.mock.calls[0][1]; + expect(method).toBe('GET'); + expect(path).toBe('_async_search/foo'); + expect(body).toEqual(undefined); + }); + + it('encodes special characters in the path', async () => { + mockApiCaller.mockResolvedValueOnce(mockAsyncResponse); + + const params = { index: 'foo-程', body: {} }; + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + await esSearch.search({ params }); + + expect(mockApiCaller).toBeCalled(); + expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request'); + const { method, path } = mockApiCaller.mock.calls[0][1]; + expect(method).toBe('POST'); + expect(path).toBe('foo-%E7%A8%8B/_async_search'); + }); + + it('calls the rollup API if the index is a rollup type', async () => { + mockApiCaller.mockResolvedValueOnce(mockRollupResponse); + + const params = { index: 'foo-程', body: {} }; + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + await esSearch.search({ indexType: 'rollup', params }); + + expect(mockApiCaller).toBeCalled(); + expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request'); + const { method, path } = mockApiCaller.mock.calls[0][1]; + expect(method).toBe('POST'); + expect(path).toBe('foo-%E7%A8%8B/_rollup_search'); + }); +}); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 004e57f71464a..612c4fdbac037 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -16,6 +16,7 @@ import { ISearchOptions, ISearchCancel, getDefaultSearchParams, + getTotalLoaded, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; @@ -36,31 +37,21 @@ export const enhancedEsSearchStrategyProvider: TSearchStrategyProvider) - : (response as AsyncSearchResponse).response; - - const id = (response as AsyncSearchResponse).id; - const { total, failed, successful } = rawResponse._shards; - const loaded = failed + successful; - return { id, total, loaded, rawResponse }; + : asyncSearch(caller, { ...request, params }, options); }; const cancel: ISearchCancel = async id => { const method = 'DELETE'; - const path = `_async_search/${id}`; + const path = encodeURI(`_async_search/${id}`); await caller('transport.request', { method, path }); }; return { search, cancel }; }; -function asyncSearch( +async function asyncSearch( caller: APICaller, request: IEnhancedEsSearchRequest, options?: ISearchOptions @@ -69,12 +60,18 @@ function asyncSearch( // If we have an ID, then just poll for that ID, otherwise send the entire request body const method = request.id ? 'GET' : 'POST'; - const path = request.id ? `_async_search/${request.id}` : `${index}/_async_search`; + const path = encodeURI(request.id ? `_async_search/${request.id}` : `${index}/_async_search`); // Wait up to 1s for the response to return const query = toSnakeCase({ waitForCompletion: '1s', ...params }); - return caller('transport.request', { method, path, body, query }, options); + const { response: rawResponse, id } = (await caller( + 'transport.request', + { method, path, body, query }, + options + )) as AsyncSearchResponse; + + return { id, rawResponse, ...getTotalLoaded(rawResponse._shards) }; } async function rollupSearch( @@ -84,9 +81,16 @@ async function rollupSearch( ) { const { body, index, ...params } = request.params; const method = 'POST'; - const path = `${index}/_rollup_search`; + const path = encodeURI(`${index}/_rollup_search`); const query = toSnakeCase(params); - return caller('transport.request', { method, path, body, query }, options); + + const rawResponse = await ((caller( + 'transport.request', + { method, path, body, query }, + options + ) as unknown) as SearchResponse); + + return { rawResponse, ...getTotalLoaded(rawResponse._shards) }; } function toSnakeCase(obj: Record) { From 67397f944d841ed1716ab0add1fc44f215ef8978 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Fri, 27 Mar 2020 15:33:54 +0000 Subject: [PATCH 04/13] [Alerting] fixes styling of loading indicator (#61430) Aligns the loading indicator with the middle of the form and adds some margins from the edges. This has been done on both the alerts list and the connectors list. --- .../components/actions_connectors_list.tsx | 10 +++++++++- .../sections/alerts_list/components/alerts_list.tsx | 6 +++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index 0cb9bbbbfb261..fc07171347e5e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -16,6 +16,8 @@ import { EuiLink, EuiLoadingSpinner, EuiIconTip, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -410,7 +412,13 @@ export const ActionsConnectorsList: React.FunctionComponent = () => { /> {/* Render the view based on if there's data or if they can save */} - {(isLoadingActions || isLoadingActionTypes) && } + {(isLoadingActions || isLoadingActionTypes) && ( + + + + + + )} {data.length !== 0 && table} {data.length === 0 && canSave && !isLoadingActions && !isLoadingActionTypes && emptyPrompt} {data.length === 0 && !canSave && noPermissionPrompt} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx index 8d675148690c7..afd3299f0c2bb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx @@ -467,7 +467,11 @@ export const AlertsList: React.FunctionComponent = () => { {loadedItems.length || isFilterApplied ? ( table ) : alertTypesState.isLoading || alertsState.isLoading ? ( - + + + + + ) : ( emptyPrompt )} From 1246dc35a3730234609b02108d4c57344477ac21 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Fri, 27 Mar 2020 15:34:22 +0000 Subject: [PATCH 05/13] updated es index labels (#61504) Co-authored-by: Elastic Machine --- .../components/builtin_action_types/es_index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx index 8a13c461fb313..d631882e1f581 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx @@ -194,7 +194,7 @@ const IndexActionConnectorFields: React.FunctionComponent @@ -217,7 +217,7 @@ const IndexActionConnectorFields: React.FunctionComponent From 207c0d2e96c2eb572fff47ebb5a19ab655ba5e07 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Fri, 27 Mar 2020 16:25:09 +0000 Subject: [PATCH 06/13] chore(NA): update es legacy client versions (#61477) --- package.json | 4 ++-- x-pack/package.json | 2 +- yarn.lock | 19 ++++++++++++++----- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 9de77aeb042bc..c2763f098b984 100644 --- a/package.json +++ b/package.json @@ -170,8 +170,8 @@ "deepmerge": "^4.2.2", "del": "^5.1.0", "elastic-apm-node": "^3.2.0", - "elasticsearch": "^16.5.0", - "elasticsearch-browser": "^16.5.0", + "elasticsearch": "^16.7.0", + "elasticsearch-browser": "^16.7.0", "execa": "^4.0.0", "expiry-js": "0.1.7", "fast-deep-equal": "^3.1.1", diff --git a/x-pack/package.json b/x-pack/package.json index 1677748e4c9e1..2072b6d8d46e9 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -232,7 +232,7 @@ "dedent": "^0.7.0", "del": "^5.1.0", "dragselect": "1.13.1", - "elasticsearch": "^16.5.0", + "elasticsearch": "^16.7.0", "extract-zip": "^1.7.0", "file-saver": "^1.3.8", "file-type": "^10.9.0", diff --git a/yarn.lock b/yarn.lock index 50cd90c051e43..b5e72e07f1efe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11568,12 +11568,12 @@ elastic-apm-node@^3.2.0: traceparent "^1.0.0" unicode-byte-truncate "^1.0.0" -elasticsearch-browser@^16.5.0: - version "16.5.0" - resolved "https://registry.yarnpkg.com/elasticsearch-browser/-/elasticsearch-browser-16.5.0.tgz#d2efbbf8751bb563e91b74117a14b9211df5cfe9" - integrity sha512-F7npcrmMi3OgQ4fL+7sYLZp5Y9MS6WobVdCA18d9/Eef06x3+UzVE+pRaM71y4/i0N5rt/QrvmijHt25wz5SLw== +elasticsearch-browser@^16.7.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/elasticsearch-browser/-/elasticsearch-browser-16.7.0.tgz#1f32a402cd36a9bb14a9ea6cb70f8e126d4cb9b1" + integrity sha512-UES2Fbnzy4Ivq4QvES4sfk/a5UytJczeJdfxRWa4kuHEllKOffKQLTxJ8Ti86OREpACQxppqvYgzctJuEiIr7Q== -elasticsearch@^16.4.0, elasticsearch@^16.5.0: +elasticsearch@^16.4.0: version "16.5.0" resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-16.5.0.tgz#619a48040be25d345fdddf09fa6042a88c3974d6" integrity sha512-9YbmU2AtM/kQdmp96EI5nu2bjxowdarV6IsKmcS+jQowJ3mhG98J1DCVOtEKuFvsnNaLyKD3aPbCAmb72+WX3w== @@ -11582,6 +11582,15 @@ elasticsearch@^16.4.0, elasticsearch@^16.5.0: chalk "^1.0.0" lodash "^4.17.10" +elasticsearch@^16.7.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-16.7.0.tgz#9055e3f586934d8de5fd407b04050e9d54173333" + integrity sha512-du+//TbjCFEkaG0jNcAC95Fp4B6/X5shnCRIXALFL+M4U5iT3YL5ZVUPNf1NgR7dy/sc8Dvw2Ob6IUJKB7FrCw== + dependencies: + agentkeepalive "^3.4.1" + chalk "^1.0.0" + lodash "^4.17.10" + electron-to-chromium@^1.3.191, electron-to-chromium@^1.3.338: version "1.3.340" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.340.tgz#5d4fe78e984d4211194cf5a52e08069543da146f" From 5afb573736817861740c102a4f42bebea59a93ff Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Fri, 27 Mar 2020 09:30:16 -0700 Subject: [PATCH 07/13] Closes #61291 by debouncing service map hover metric events tracking (#61561) --- .../apm/public/components/app/ServiceMap/Cytoscape.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx index 54a1b4347e29b..7bdc6aebbd9a0 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx @@ -13,6 +13,7 @@ import React, { useRef, useState } from 'react'; +import { debounce } from 'lodash'; import { isRumAgentName } from '../../../../../../../plugins/apm/common/agent_name'; import { AGENT_NAME } from '../../../../../../../plugins/apm/common/elasticsearch_fieldnames'; import { @@ -171,8 +172,13 @@ export function Cytoscape({ } }); }; + // debounce hover tracking so it doesn't spam telemetry with redundant events + const trackNodeEdgeHover = debounce( + () => trackApmEvent({ metric: 'service_map_node_or_edge_hover' }), + 1000 + ); const mouseoverHandler: cytoscape.EventHandler = event => { - trackApmEvent({ metric: 'service_map_node_or_edge_hover' }); + trackNodeEdgeHover(); event.target.addClass('hover'); event.target.connectedEdges().addClass('nodeHover'); }; From 1da53ed23b57c2bbc17c0d1aa448d09427e42a66 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 27 Mar 2020 12:50:49 -0400 Subject: [PATCH 08/13] [Uptime] Fix PingList pagination (#61481) * Add pagination. * Update test files. --- .../plugins/uptime/common/graphql/types.ts | 5 +--- .../__snapshots__/ping_list.test.tsx.snap | 9 ++++---- .../ping_list/__tests__/ping_list.test.tsx | 4 +++- .../functional/ping_list/ping_list.tsx | 23 ++++++++++--------- .../plugins/uptime/public/pages/monitor.tsx | 4 ++++ .../uptime/public/queries/pings_query.ts | 2 ++ .../uptime/server/graphql/pings/resolvers.ts | 3 ++- .../uptime/server/graphql/pings/schema.gql.ts | 2 ++ .../uptime/server/lib/requests/get_pings.ts | 10 +++++++- 9 files changed, 39 insertions(+), 23 deletions(-) diff --git a/x-pack/legacy/plugins/uptime/common/graphql/types.ts b/x-pack/legacy/plugins/uptime/common/graphql/types.ts index bd017e6cfaf4c..c8beb91d807d5 100644 --- a/x-pack/legacy/plugins/uptime/common/graphql/types.ts +++ b/x-pack/legacy/plugins/uptime/common/graphql/types.ts @@ -8,7 +8,6 @@ // Scalars // ==================================================== - export type UnsignedInteger = any; // ==================================================== @@ -367,7 +366,6 @@ export interface DocCount { count: UnsignedInteger; } - export interface Snapshot { counts: SnapshotCount; } @@ -380,7 +378,6 @@ export interface SnapshotCount { total: number; } - /** The primary object returned for monitor states. */ export interface MonitorSummaryResult { /** Used to go to the next page of results */ @@ -524,7 +521,6 @@ export interface SummaryHistogramPoint { down: number; } - export interface AllPingsQueryArgs { /** Optional: the direction to sort by. Accepts 'asc' and 'desc'. Defaults to 'desc'. */ sort?: string | null; @@ -540,6 +536,7 @@ export interface AllPingsQueryArgs { dateRangeEnd: string; /** Optional: agent location to filter by. */ location?: string | null; + page?: number; } export interface GetMonitorStatesQueryArgs { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap index d19de73c16c5f..2e59ec5e57337 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap @@ -364,17 +364,16 @@ exports[`PingList component renders sorted list without errors 1`] = ` onChange={[Function]} pagination={ Object { - "initialPageSize": 20, + "initialPageSize": 25, "pageIndex": 0, - "pageSize": 30, + "pageSize": 10, "pageSizeOptions": Array [ - 5, 10, - 20, + 25, 50, 100, ], - "totalItemCount": 30, + "totalItemCount": 9231, } } responsive={true} diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx index 36586b182de43..68d285bd0baf1 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx @@ -204,9 +204,11 @@ describe('PingList component', () => { loading={false} data={{ allPings }} onPageCountChange={jest.fn()} + onPageIndexChange={jest.fn()} onSelectedLocationChange={(_loc: any[]) => {}} onSelectedStatusChange={jest.fn()} - pageSize={30} + pageIndex={0} + pageSize={10} selectedOption="down" selectedLocation={AllLocationOption.value} /> diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx index d245bc1456e6a..19768c7104e91 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx @@ -41,7 +41,9 @@ interface PingListProps { onSelectedStatusChange: (status: string | undefined) => void; onSelectedLocationChange: (location: any) => void; onPageCountChange: (itemCount: number) => void; + onPageIndexChange: (index: number) => void; pageSize: number; + pageIndex: number; selectedOption: string; selectedLocation: string | undefined; } @@ -78,8 +80,10 @@ export const PingListComponent = ({ data, loading, onPageCountChange, + onPageIndexChange, onSelectedLocationChange, onSelectedStatusChange, + pageIndex, pageSize, selectedOption, selectedLocation, @@ -232,15 +236,11 @@ export const PingListComponent = ({ ]; const pagination: Pagination = { - initialPageSize: 20, - pageIndex: 0, + initialPageSize: 25, + pageIndex, pageSize, - pageSizeOptions: [5, 10, 20, 50, 100], - /** - * we're not currently supporting pagination in this component - * so the first page is the only page - */ - totalItemCount: pageSize, + pageSizeOptions: [10, 25, 50, 100], + totalItemCount: data?.allPings?.total ?? pageSize, }; return ( @@ -323,9 +323,10 @@ export const PingListComponent = ({ itemId="id" itemIdToExpandedRowMap={itemIdToExpandedRowMap} pagination={pagination} - onChange={(criteria: CriteriaWithPagination) => - onPageCountChange(criteria.page!.size) - } + onChange={(criteria: CriteriaWithPagination) => { + onPageCountChange(criteria.page!.size); + onPageIndexChange(criteria.page!.index); + }} /> diff --git a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx index 5871783dffdeb..3de636cac6ecd 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx @@ -51,6 +51,7 @@ export const MonitorPageComponent: React.FC = ({ const { dateRangeStart, dateRangeEnd, selectedPingStatus } = params; const [selectedLocation, setSelectedLocation] = useState(undefined); + const [pingListIndex, setPingListIndex] = useState(0); const sharedVariables = { dateRangeStart, @@ -81,11 +82,14 @@ export const MonitorPageComponent: React.FC = ({ updateUrlParams({ selectedPingStatus: selectedStatus || '' }); refreshApp(); }} + onPageIndexChange={(index: number) => setPingListIndex(index)} + pageIndex={pingListIndex} pageSize={pingListPageCount} selectedOption={selectedPingStatus} selectedLocation={selectedLocation} variables={{ ...sharedVariables, + page: pingListIndex, size: pingListPageCount, status: selectedPingStatus, }} diff --git a/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts b/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts index 203c7ef426c19..ed20fe8eb2931 100644 --- a/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts +++ b/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts @@ -15,6 +15,7 @@ query PingList( $sort: String $size: Int $location: String + $page: Int ) { allPings( dateRangeStart: $dateRangeStart @@ -24,6 +25,7 @@ query PingList( sort: $sort size: $size location: $location + page: $page ) { total locations diff --git a/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts b/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts index 8153d8c8f3b8c..2bb1e13bc4b1f 100644 --- a/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts +++ b/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts @@ -35,7 +35,7 @@ export const createPingsResolvers: CreateUMGraphQLResolvers = ( Query: { async allPings( _resolver, - { monitorId, sort, size, status, dateRangeStart, dateRangeEnd, location }, + { monitorId, sort, size, status, dateRangeStart, dateRangeEnd, location, page }, { APICaller, savedObjectsClient } ): Promise { const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings( @@ -52,6 +52,7 @@ export const createPingsResolvers: CreateUMGraphQLResolvers = ( sort, size, location, + page, }); }, }, diff --git a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts index 4b7ccbec37464..25767fb544104 100644 --- a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts +++ b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts @@ -37,6 +37,8 @@ export const pingsSchema = gql` dateRangeEnd: String! "Optional: agent location to filter by." location: String + "Optional: current page." + page: Int ): PingResults! } diff --git a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts index 59d8aa1ab0e63..c64b5f3ad4af4 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts @@ -32,6 +32,9 @@ export interface GetPingsParams { /** @member location optional location value for use in filtering*/ location?: string | null; + + /** @member page the number to provide to Elasticsearch as the "from" parameter */ + page?: number; } export const getPings: UMElasticsearchQueryFn = async ({ @@ -44,6 +47,7 @@ export const getPings: UMElasticsearchQueryFn = asy sort, size, location, + page, }) => { const sortParam = { sort: [{ '@timestamp': { order: sort ?? 'desc' } }] }; const sizeParam = size ? { size } : undefined; @@ -60,7 +64,7 @@ export const getPings: UMElasticsearchQueryFn = asy postFilterClause = { post_filter: { term: { 'observer.geo.name': location } } }; } const queryContext = { bool: { filter } }; - const params = { + const params: any = { index: dynamicSettings.heartbeatIndices, body: { query: { @@ -81,6 +85,10 @@ export const getPings: UMElasticsearchQueryFn = asy }, }; + if (page) { + params.body.from = page * (size ?? 25); + } + const { hits: { hits, total }, aggregations: aggs, From 7224253936da84769c7a003a9b225416a9759ca8 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 27 Mar 2020 12:53:35 -0400 Subject: [PATCH 09/13] Fix some null reference issues. (#61465) --- x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts | 2 +- x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts index 85749ac66b80c..176963a998685 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts @@ -69,7 +69,7 @@ export const getLatestMonitor: UMElasticsearchQueryFn { const x: number = bucket.key; From 30bdfeda6cbfd4c1fa26e2d49817d8de051cb0f8 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 27 Mar 2020 11:03:57 -0600 Subject: [PATCH 10/13] [Maps] clean-up unsaved state check (#61535) --- .../maps/public/angular/map_controller.js | 7 ++++++- .../components/color/dynamic_color_form.js | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index 519ba0b1e3d96..a19f8cdf5f7fc 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -312,7 +312,12 @@ app.controller( const savedLayerList = savedMap.getLayerList(); const oldConfig = savedLayerList ? savedLayerList : initialLayerListConfig; - return !_.isEqual(layerListConfigOnly, oldConfig); + // savedMap stores layerList as a JSON string using JSON.stringify. + // JSON.stringify removes undefined properties from objects. + // savedMap.getLayerList converts the JSON string back into Javascript array of objects. + // Need to perform the same process for layerListConfigOnly to compare apples to apples + // and avoid undefined properties in layerListConfigOnly triggering unsaved changes. + return !_.isEqual(JSON.parse(JSON.stringify(layerListConfigOnly)), oldConfig); } function isOnMapNow() { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js index a1c15e27c9eb3..5e8f720fcc5e3 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js @@ -28,12 +28,20 @@ export function DynamicColorForm({ }; if (type === COLOR_MAP_TYPE.ORDINAL) { newColorOptions.useCustomColorRamp = useCustomColorMap; - newColorOptions.customColorRamp = customColorMap; - newColorOptions.color = color; + if (customColorMap) { + newColorOptions.customColorRamp = customColorMap; + } + if (color) { + newColorOptions.color = color; + } } else { newColorOptions.useCustomColorPalette = useCustomColorMap; - newColorOptions.customColorPalette = customColorMap; - newColorOptions.colorCategory = color; + if (customColorMap) { + newColorOptions.customColorPalette = customColorMap; + } + if (color) { + newColorOptions.colorCategory = color; + } } onDynamicStyleChange(styleProperty.getStyleName(), newColorOptions); From bec4e3365173d427df76c33955914e4e9f389367 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Fri, 27 Mar 2020 11:25:48 -0600 Subject: [PATCH 11/13] [SIEM] [Cases] Fix comments and user (#61642) --- .../case/components/user_action_tree/index.tsx | 17 ++++++++++------- .../user_action_tree/user_action_item.tsx | 12 ++++++------ .../user_action_tree/user_action_title.tsx | 6 +++--- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx index b3a4b07712857..75013c0afde5d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx @@ -71,14 +71,14 @@ export const UserActionTree = React.memo( ); const handleSaveComment = useCallback( - (id: string, content: string) => { + ({ id, version }: { id: string; version: string }, content: string) => { handleManageMarkdownEditId(id); patchComment({ caseId: caseData.id, commentId: id, commentUpdate: content, fetchUserActions, - version: caseData.version, + version, updateCase, }); }, @@ -178,7 +178,7 @@ export const UserActionTree = React.memo( markdown={MarkdownDescription} onEdit={handleManageMarkdownEditId.bind(null, DESCRIPTION_ID)} onQuote={handleManageQuote.bind(null, caseData.description)} - userName={caseData.createdBy.username} + username={caseData.createdBy.username} /> {caseUserActions.map((action, index) => { @@ -203,13 +203,16 @@ export const UserActionTree = React.memo( content={comment.comment} isEditable={manageMarkdownEditIds.includes(comment.id)} onChangeEditable={handleManageMarkdownEditId} - onSaveContent={handleSaveComment.bind(null, comment.id)} + onSaveContent={handleSaveComment.bind(null, { + id: comment.id, + version: comment.version, + })} /> } onEdit={handleManageMarkdownEditId.bind(null, comment.id)} onQuote={handleManageQuote.bind(null, comment.comment)} outlineComment={handleOutlineComment} - userName={comment.createdBy.username} + username={comment.createdBy.username} updatedAt={comment.updatedAt} /> ); @@ -245,7 +248,7 @@ export const UserActionTree = React.memo( index === lastIndexPushToService && index < caseUserActions.length - 1 } - userName={action.actionBy.username} + username={action.actionBy.username} /> ); } @@ -265,7 +268,7 @@ export const UserActionTree = React.memo( isLoading={isLoadingIds.includes(NEW_ID)} fullName={currentUser != null ? currentUser.fullName : ''} markdown={MarkdownNewComment} - userName={currentUser != null ? currentUser.username : ''} + username={currentUser != null ? currentUser.username : ''} /> ); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx index c1dbe3b5fdbfa..cc36e791e35b4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx @@ -28,11 +28,11 @@ interface UserActionItemProps { labelQuoteAction?: string; labelTitle?: JSX.Element; linkId?: string | null; - fullName: string; + fullName?: string | null; markdown?: React.ReactNode; onEdit?: (id: string) => void; onQuote?: (id: string) => void; - userName: string; + username: string; updatedAt?: string | null; outlineComment?: (id: string) => void; showBottomFooter?: boolean; @@ -125,15 +125,15 @@ export const UserActionItem = ({ outlineComment, showBottomFooter, showTopFooter, - userName, + username, updatedAt, }: UserActionItemProps) => ( - {fullName.length > 0 || userName.length > 0 ? ( - + {(fullName && fullName.length > 0) || username.length > 0 ? ( + ) : ( )} @@ -154,7 +154,7 @@ export const UserActionItem = ({ labelQuoteAction={labelQuoteAction} labelTitle={labelTitle ?? <>} linkId={linkId} - userName={userName} + username={username} updatedAt={updatedAt} onEdit={onEdit} onQuote={onQuote} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx index 391f54da7e972..94185cb4d130c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx @@ -34,7 +34,7 @@ interface UserActionTitleProps { labelTitle: JSX.Element; linkId?: string | null; updatedAt?: string | null; - userName: string; + username: string; onEdit?: (id: string) => void; onQuote?: (id: string) => void; outlineComment?: (id: string) => void; @@ -48,7 +48,7 @@ export const UserActionTitle = ({ labelQuoteAction, labelTitle, linkId, - userName, + username, updatedAt, onEdit, onQuote, @@ -105,7 +105,7 @@ export const UserActionTitle = ({ - {userName} + {username} {labelTitle} From d1214f8893ee427233b1add45298997445c6c596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Fri, 27 Mar 2020 13:37:22 -0400 Subject: [PATCH 12/13] Add close button to expression popovers (#61352) * Add X to trigger expression popovers * Fix jest tests * PR feedback Co-authored-by: Elastic Machine --- .../closable_popover_title.test.tsx | 30 +++++++++++++++ .../components/closable_popover_title.tsx | 37 +++++++++++++++++++ .../expression_items/components/index.ts | 7 ++++ .../expression_items/for_the_last.test.tsx | 11 ++---- .../common/expression_items/for_the_last.tsx | 6 +-- .../expression_items/group_by_over.test.tsx | 11 +++++- .../common/expression_items/group_by_over.tsx | 17 ++++----- .../common/expression_items/of.test.tsx | 11 +++++- .../public/common/expression_items/of.tsx | 14 ++++--- .../expression_items/threshold.test.tsx | 3 +- .../common/expression_items/threshold.tsx | 6 ++- .../common/expression_items/when.test.tsx | 11 +++++- .../public/common/expression_items/when.tsx | 15 +++++--- 13 files changed, 138 insertions(+), 41 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/closable_popover_title.test.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/closable_popover_title.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/index.ts diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/closable_popover_title.test.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/closable_popover_title.test.tsx new file mode 100644 index 0000000000000..8e9daf5f26c40 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/closable_popover_title.test.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as React from 'react'; +import { mount } from 'enzyme'; +import { ClosablePopoverTitle } from './closable_popover_title'; + +describe('closable popover title', () => { + it('renders with defined options', () => { + const onClose = jest.fn(); + const children =
; + const wrapper = mount( + {children} + ); + expect(wrapper.contains(
)).toBeTruthy(); + }); + + it('onClose function gets called', () => { + const onClose = jest.fn(); + const children =
; + const wrapper = mount( + {children} + ); + wrapper.find('EuiButtonIcon').simulate('click'); + expect(onClose).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/closable_popover_title.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/closable_popover_title.tsx new file mode 100644 index 0000000000000..f24dfe987a140 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/closable_popover_title.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiPopoverTitle, EuiFlexGroup, EuiFlexItem, EuiButtonIcon } from '@elastic/eui'; + +interface ClosablePopoverTitleProps { + children: JSX.Element; + onClose: () => void; +} + +export const ClosablePopoverTitle = ({ children, onClose }: ClosablePopoverTitleProps) => { + return ( + + + {children} + + onClose()} + /> + + + + ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/index.ts b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/index.ts new file mode 100644 index 0000000000000..d2ea51d37e84a --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/components/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ClosablePopoverTitle } from './closable_popover_title'; diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/for_the_last.test.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/for_the_last.test.tsx index e66bb1e7b4b9a..95c16fcea914d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/for_the_last.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/for_the_last.test.tsx @@ -5,7 +5,6 @@ */ import * as React from 'react'; import { shallow } from 'enzyme'; -import { EuiPopoverTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { ForLastExpression } from './for_the_last'; @@ -40,12 +39,10 @@ describe('for the last expression', () => { expect(wrapper.find('[value="s"]').length > 0).toBeTruthy(); expect( wrapper.contains( - - - + ) ).toBeTruthy(); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/for_the_last.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/for_the_last.tsx index 673391dd9cbad..defad2b801718 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/for_the_last.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/for_the_last.tsx @@ -10,7 +10,6 @@ import { i18n } from '@kbn/i18n'; import { EuiExpression, EuiPopover, - EuiPopoverTitle, EuiSelect, EuiFlexGroup, EuiFormRow, @@ -20,6 +19,7 @@ import { import { getTimeUnitLabel } from '../lib/get_time_unit_label'; import { TIME_UNITS } from '../../application/constants'; import { getTimeOptions } from '../lib/get_time_options'; +import { ClosablePopoverTitle } from './components'; interface ForLastExpressionProps { timeWindowSize?: number; @@ -82,12 +82,12 @@ export const ForLastExpression = ({ anchorPosition={popupPosition ?? 'downLeft'} >
- + setAlertDurationPopoverOpen(false)}> - + { it('renders with builtin group by types', () => { @@ -97,6 +97,13 @@ describe('group by expression', () => { ); wrapper.simulate('click'); expect(wrapper.find('[value="all"]').length > 0).toBeTruthy(); - expect(wrapper.contains(over)).toBeTruthy(); + expect( + wrapper.contains( + + ) + ).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/group_by_over.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/group_by_over.tsx index 7ca32764dbdfd..6ad52a5416163 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/group_by_over.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/group_by_over.tsx @@ -5,11 +5,11 @@ */ import React, { useState, Fragment } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { EuiExpression, EuiPopover, - EuiPopoverTitle, EuiFlexGroup, EuiFlexItem, EuiFormRow, @@ -18,6 +18,7 @@ import { } from '@elastic/eui'; import { builtInGroupByTypes } from '../constants'; import { GroupByType } from '../types'; +import { ClosablePopoverTitle } from './components'; interface GroupByExpressionProps { groupBy: string; @@ -112,14 +113,12 @@ export const GroupByExpression = ({ anchorPosition={popupPosition ?? 'downRight'} >
- - {i18n.translate( - 'xpack.triggersActionsUI.common.expressionItems.groupByType.overButtonLabel', - { - defaultMessage: 'over', - } - )} - + setGroupByPopoverOpen(false)}> + + { it('renders of builtin aggregation types', () => { @@ -121,6 +121,13 @@ describe('of expression', () => { /> ); wrapper.simulate('click'); - expect(wrapper.contains(of)).toBeTruthy(); + expect( + wrapper.contains( + + ) + ).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/of.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/of.tsx index fdf68cc49572f..70aa4be6b7f87 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/of.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/of.tsx @@ -6,10 +6,10 @@ import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiExpression, EuiPopover, - EuiPopoverTitle, EuiFlexGroup, EuiFlexItem, EuiFormRow, @@ -17,6 +17,7 @@ import { } from '@elastic/eui'; import { builtInAggregationTypes } from '../constants'; import { AggregationType } from '../types'; +import { ClosablePopoverTitle } from './components'; interface OfExpressionProps { aggType: string; @@ -100,11 +101,12 @@ export const OfExpression = ({ zIndex={8000} >
- - {i18n.translate('xpack.triggersActionsUI.common.expressionItems.of.popoverTitle', { - defaultMessage: 'of', - })} - + setAggFieldPopoverOpen(false)}> + + { @@ -64,6 +63,6 @@ describe('threshold expression', () => { onChangeSelectedThresholdComparator={onChangeSelectedThresholdComparator} /> ); - expect(wrapper.contains(Is between)).toBeTruthy(); + expect(wrapper.contains('Is between')).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/threshold.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/threshold.tsx index d0de7ae77a81e..fb3ff9ceb0926 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/threshold.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/threshold.tsx @@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n'; import { EuiExpression, EuiPopover, - EuiPopoverTitle, EuiFlexGroup, EuiFlexItem, EuiFormRow, @@ -19,6 +18,7 @@ import { } from '@elastic/eui'; import { builtInComparators } from '../constants'; import { Comparator } from '../types'; +import { ClosablePopoverTitle } from './components'; interface ThresholdExpressionProps { thresholdComparator: string; @@ -97,7 +97,9 @@ export const ThresholdExpression = ({ anchorPosition={popupPosition ?? 'downLeft'} >
- {comparators[thresholdComparator].text} + setAlertThresholdPopoverOpen(false)}> + <>{comparators[thresholdComparator].text} + { it('renders with builtin aggregation types', () => { @@ -100,6 +100,13 @@ describe('when expression', () => { ); wrapper.simulate('click'); expect(wrapper.find('[value="avg"]').length > 0).toBeTruthy(); - expect(wrapper.contains(when)).toBeTruthy(); + expect( + wrapper.contains( + + ) + ).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/when.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/when.tsx index b20040608ed9e..65184065e359e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/when.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/when.tsx @@ -6,9 +6,11 @@ import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiExpression, EuiPopover, EuiPopoverTitle, EuiSelect } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiExpression, EuiPopover, EuiSelect } from '@elastic/eui'; import { builtInAggregationTypes } from '../constants'; import { AggregationType } from '../types'; +import { ClosablePopoverTitle } from './components'; interface WhenExpressionProps { aggType: string; @@ -64,11 +66,12 @@ export const WhenExpression = ({ anchorPosition={popupPosition ?? 'downLeft'} >
- - {i18n.translate('xpack.triggersActionsUI.common.expressionItems.threshold.popoverTitle', { - defaultMessage: 'when', - })} - + setAggTypePopoverOpen(false)}> + + Date: Fri, 27 Mar 2020 12:40:55 -0500 Subject: [PATCH 13/13] Replace APM agent "Active" setting with "Recording" (#61538) Also change "APM server" to "APM Server" Fixes #61179. --- .../app/ServiceOverview/NoServicesMessage.tsx | 2 +- .../NoServicesMessage.test.tsx.snap | 4 +-- .../ServiceOverview.test.tsx.snap | 2 +- .../__snapshots__/index.test.ts.snap | 10 +++--- .../setting_definitions/general_settings.ts | 33 +++++++++---------- .../setting_definitions/index.test.ts | 13 +++++--- .../instructions/apm_agent_instructions.ts | 2 +- 7 files changed, 35 insertions(+), 31 deletions(-) diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/NoServicesMessage.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/NoServicesMessage.tsx index de058d6ef973a..c1afa433cb614 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/NoServicesMessage.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/NoServicesMessage.tsx @@ -58,7 +58,7 @@ export function NoServicesMessage({ historicalDataFound, status }: Props) {

{i18n.translate('xpack.apm.servicesTable.7xUpgradeServerMessage', { defaultMessage: `Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM server instance(s) to at least 7.0.` + your APM Server instance(s) to at least 7.0.` })}

diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/NoServicesMessage.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/NoServicesMessage.test.tsx.snap index 209b88f73b9e2..227becb9a9c4f 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/NoServicesMessage.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/NoServicesMessage.test.tsx.snap @@ -19,7 +19,7 @@ exports[`NoServicesMessage status: pending and historicalDataFound: false 1`] =

Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM server instance(s) to at least 7.0. + your APM Server instance(s) to at least 7.0.

You may also have old data that needs to be migrated. @@ -64,7 +64,7 @@ exports[`NoServicesMessage status: success and historicalDataFound: false 1`] =

Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM server instance(s) to at least 7.0. + your APM Server instance(s) to at least 7.0.

You may also have old data that needs to be migrated. diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap index d85c83661ea49..dd0c50af2b03f 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap @@ -72,7 +72,7 @@ NodeList [ >

Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM server instance(s) to at least 7.0. + your APM Server instance(s) to at least 7.0.

You may also have old data that needs to be migrated. diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap index 365d8838a24a6..0c585bec22f6c 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap @@ -2,11 +2,6 @@ exports[`settingDefinitions should have correct default values 1`] = ` Array [ - Object { - "key": "active", - "type": "boolean", - "validationName": "(\\"true\\" | \\"false\\")", - }, Object { "key": "api_request_size", "type": "bytes", @@ -105,6 +100,11 @@ Array [ "validationError": "Please specify an integer and a unit", "validationName": "durationRt", }, + Object { + "key": "recording", + "type": "boolean", + "validationName": "(\\"true\\" | \\"false\\")", + }, Object { "key": "server_timeout", "type": "duration", diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts index b83c03c543295..6a0e2d65d1949 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts @@ -13,21 +13,6 @@ import { RawSettingDefinition } from './types'; * Settings added here will show up in the UI and will be validated on the client and server */ export const generalSettings: RawSettingDefinition[] = [ - // Active - { - key: 'active', - type: 'boolean', - defaultValue: 'true', - label: i18n.translate('xpack.apm.agentConfig.active.label', { - defaultMessage: 'Active' - }), - description: i18n.translate('xpack.apm.agentConfig.active.description', { - defaultMessage: - 'A boolean specifying if the agent should be active or not.\nWhen active, the agent instruments incoming HTTP requests, tracks errors and collects and sends metrics.\nWhen inactive, the agent works as a noop, not collecting data and not communicating with the APM Server.\nAs this is a reversible switch, agent threads are not being killed when inactivated, but they will be \nmostly idle in this state, so the overhead should be negligible.\n\nYou can use this setting to dynamically disable Elastic APM at runtime.' - }), - excludeAgents: ['js-base', 'rum-js', 'python', 'dotnet'] - }, - // API Request Size { key: 'api_request_size', @@ -40,7 +25,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'xpack.apm.agentConfig.apiRequestSize.description', { defaultMessage: - 'The maximum total compressed size of the request body which is sent to the APM server intake api via a chunked encoding (HTTP streaming).\nNote that a small overshoot is possible.\n\nAllowed byte units are `b`, `kb` and `mb`. `1kb` is equal to `1024b`.' + 'The maximum total compressed size of the request body which is sent to the APM Server intake api via a chunked encoding (HTTP streaming).\nNote that a small overshoot is possible.\n\nAllowed byte units are `b`, `kb` and `mb`. `1kb` is equal to `1024b`.' } ), excludeAgents: ['js-base', 'rum-js', 'dotnet'] @@ -121,6 +106,20 @@ export const generalSettings: RawSettingDefinition[] = [ excludeAgents: ['js-base', 'rum-js', 'python'] }, + // Recording + { + key: 'recording', + type: 'boolean', + defaultValue: 'true', + label: i18n.translate('xpack.apm.agentConfig.recording.label', { + defaultMessage: 'Recording' + }), + description: i18n.translate('xpack.apm.agentConfig.recording.description', { + defaultMessage: + 'When recording, the agent instruments incoming HTTP requests, tracks errors, and collects and sends metrics. When inactive, the agent works as a noop, not collecting data and not communicating with the APM Server except for polling for updated configuration. As this is a reversible switch, agent threads are not being killed when inactivated, but they will be mostly idle in this state, so the overhead should be negligible. You can use this setting to dynamically control whether Elastic APM is enabled or disabled.' + }) + }, + // SERVER_TIMEOUT { key: 'server_timeout', @@ -133,7 +132,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'xpack.apm.agentConfig.serverTimeout.description', { defaultMessage: - 'If a request to the APM server takes longer than the configured timeout,\nthe request is cancelled and the event (exception or transaction) is discarded.\nSet to 0 to disable timeouts.\n\nWARNING: If timeouts are disabled or set to a high value, your app could experience memory issues if the APM server times out.' + 'If a request to the APM Server takes longer than the configured timeout,\nthe request is cancelled and the event (exception or transaction) is discarded.\nSet to 0 to disable timeouts.\n\nWARNING: If timeouts are disabled or set to a high value, your app could experience memory issues if the APM Server times out.' } ), includeAgents: ['nodejs', 'java', 'go'] diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts index fe55442324c92..b0255d2d828bb 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts @@ -43,12 +43,12 @@ describe('filterByAgent', () => { describe('options per agent', () => { it('go', () => { expect(getSettingKeysForAgent('go')).toEqual([ - 'active', 'api_request_size', 'api_request_time', 'capture_body', 'capture_headers', 'log_level', + 'recording', 'server_timeout', 'span_frames_min_duration', 'stack_trace_limit', @@ -59,7 +59,6 @@ describe('filterByAgent', () => { it('java', () => { expect(getSettingKeysForAgent('java')).toEqual([ - 'active', 'api_request_size', 'api_request_time', 'capture_body', @@ -72,6 +71,7 @@ describe('filterByAgent', () => { 'profiling_inferred_spans_included_classes', 'profiling_inferred_spans_min_duration', 'profiling_inferred_spans_sampling_interval', + 'recording', 'server_timeout', 'span_frames_min_duration', 'stack_trace_limit', @@ -88,24 +88,26 @@ describe('filterByAgent', () => { it('js-base', () => { expect(getSettingKeysForAgent('js-base')).toEqual([ + 'recording', 'transaction_sample_rate' ]); }); it('rum-js', () => { expect(getSettingKeysForAgent('rum-js')).toEqual([ + 'recording', 'transaction_sample_rate' ]); }); it('nodejs', () => { expect(getSettingKeysForAgent('nodejs')).toEqual([ - 'active', 'api_request_size', 'api_request_time', 'capture_body', 'capture_headers', 'log_level', + 'recording', 'server_timeout', 'stack_trace_limit', 'transaction_max_spans', @@ -119,6 +121,7 @@ describe('filterByAgent', () => { 'api_request_time', 'capture_body', 'capture_headers', + 'recording', 'span_frames_min_duration', 'transaction_max_spans', 'transaction_sample_rate' @@ -130,6 +133,7 @@ describe('filterByAgent', () => { 'capture_body', 'capture_headers', 'log_level', + 'recording', 'span_frames_min_duration', 'stack_trace_limit', 'transaction_max_spans', @@ -139,12 +143,12 @@ describe('filterByAgent', () => { it('ruby', () => { expect(getSettingKeysForAgent('ruby')).toEqual([ - 'active', 'api_request_size', 'api_request_time', 'capture_body', 'capture_headers', 'log_level', + 'recording', 'span_frames_min_duration', 'transaction_max_spans', 'transaction_sample_rate' @@ -155,6 +159,7 @@ describe('filterByAgent', () => { expect(getSettingKeysForAgent(undefined)).toEqual([ 'capture_body', 'capture_headers', + 'recording', 'transaction_max_spans', 'transaction_sample_rate' ]); diff --git a/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts b/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts index d076008da9d8e..9695c331e0504 100644 --- a/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts +++ b/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts @@ -437,7 +437,7 @@ export const createJsAgentInstructions = (apmServerUrl = '') => [ title: i18n.translate( 'xpack.apm.tutorial.jsClient.enableRealUserMonitoring.title', { - defaultMessage: 'Enable Real User Monitoring support in APM server' + defaultMessage: 'Enable Real User Monitoring support in APM Server' } ), textPre: i18n.translate(