From a2b96f2edc94e3be4e2a282b8a8e604609347e02 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 10 Dec 2019 17:28:53 +0100 Subject: [PATCH 1/4] move over kql telemetry and scripts api --- src/legacy/core_plugins/kibana/index.js | 4 -- .../server/routes/api/kql_telemetry/index.js | 60 ----------------- .../data/server/kql_telemetry/index.ts} | 6 +- .../kql_telemetry/kql_telemetry_service.ts | 35 ++++++++++ .../data/server/kql_telemetry/route.ts | 64 +++++++++++++++++++ src/plugins/data/server/plugin.ts | 8 +++ .../data/server/scripts/index.ts} | 10 +-- src/plugins/data/server/scripts/route.ts | 31 +++++++++ .../data/server/scripts/scripts_service.ts | 29 +++++++++ 9 files changed, 169 insertions(+), 78 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/server/routes/api/kql_telemetry/index.js rename src/{legacy/core_plugins/kibana/server/routes/api/scripts/index.js => plugins/data/server/kql_telemetry/index.ts} (86%) create mode 100644 src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts create mode 100644 src/plugins/data/server/kql_telemetry/route.ts rename src/{legacy/core_plugins/kibana/server/routes/api/scripts/register_languages.js => plugins/data/server/scripts/index.ts} (79%) create mode 100644 src/plugins/data/server/scripts/route.ts create mode 100644 src/plugins/data/server/scripts/scripts_service.ts diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index 659ca36d84090..d8e56e4b5f0fe 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -27,9 +27,7 @@ import { importApi } from './server/routes/api/import'; import { exportApi } from './server/routes/api/export'; import { homeApi } from './server/routes/api/home'; import { managementApi } from './server/routes/api/management'; -import { scriptsApi } from './server/routes/api/scripts'; import { registerSuggestionsApi } from './server/routes/api/suggestions'; -import { registerKqlTelemetryApi } from './server/routes/api/kql_telemetry'; import { registerFieldFormats } from './server/field_formats/register'; import { registerTutorials } from './server/tutorials/register'; import * as systemApi from './server/lib/system_api'; @@ -327,13 +325,11 @@ export default function (kibana) { // uuid await manageUuid(server); // routes - scriptsApi(server); importApi(server); exportApi(server); homeApi(server); managementApi(server); registerSuggestionsApi(server); - registerKqlTelemetryApi(server); registerFieldFormats(server); registerTutorials(server); makeKQLUsageCollector(usageCollection, server); diff --git a/src/legacy/core_plugins/kibana/server/routes/api/kql_telemetry/index.js b/src/legacy/core_plugins/kibana/server/routes/api/kql_telemetry/index.js deleted file mode 100644 index 04ce8e807ea20..0000000000000 --- a/src/legacy/core_plugins/kibana/server/routes/api/kql_telemetry/index.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Joi from 'joi'; -import Boom from 'boom'; - -export function registerKqlTelemetryApi(server) { - server.route({ - path: '/api/kibana/kql_opt_in_telemetry', - method: 'POST', - config: { - validate: { - payload: Joi.object({ - opt_in: Joi.bool().required(), - }), - }, - tags: ['api'], - }, - handler: async function (request) { - const { savedObjects: { getSavedObjectsRepository } } = server; - const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); - const internalRepository = getSavedObjectsRepository(callWithInternalUser); - - const { - payload: { opt_in: optIn }, - } = request; - - const counterName = optIn ? 'optInCount' : 'optOutCount'; - - try { - await internalRepository.incrementCounter( - 'kql-telemetry', - 'kql-telemetry', - counterName, - ); - } - catch (error) { - return new Boom('Something went wrong', { statusCode: error.status, data: { success: false } }); - } - - return { success: true }; - }, - }); -} diff --git a/src/legacy/core_plugins/kibana/server/routes/api/scripts/index.js b/src/plugins/data/server/kql_telemetry/index.ts similarity index 86% rename from src/legacy/core_plugins/kibana/server/routes/api/scripts/index.js rename to src/plugins/data/server/kql_telemetry/index.ts index 441963b02f14f..0191113d95007 100644 --- a/src/legacy/core_plugins/kibana/server/routes/api/scripts/index.js +++ b/src/plugins/data/server/kql_telemetry/index.ts @@ -17,8 +17,4 @@ * under the License. */ -import { registerLanguages } from './register_languages'; - -export function scriptsApi(server) { - registerLanguages(server); -} +export { KqlTelemetryService } from './kql_telemetry_service'; diff --git a/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts b/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts new file mode 100644 index 0000000000000..5890341eb41d0 --- /dev/null +++ b/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts @@ -0,0 +1,35 @@ +/* + * 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 { CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server'; +import { registerKqlTelemetryRoute } from './route'; + +export class KqlTelemetryService implements Plugin { + constructor(private initializerContext: PluginInitializerContext) {} + + public setup({ http, savedObjects }: CoreSetup) { + registerKqlTelemetryRoute( + http.createRouter(), + savedObjects, + this.initializerContext.logger.get('data', 'kql-telemetry') + ); + } + + public start() {} +} diff --git a/src/plugins/data/server/kql_telemetry/route.ts b/src/plugins/data/server/kql_telemetry/route.ts new file mode 100644 index 0000000000000..3185da22b12b3 --- /dev/null +++ b/src/plugins/data/server/kql_telemetry/route.ts @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, IRouter, Logger } from 'kibana/server'; +import { schema } from '@kbn/config-schema'; + +export function registerKqlTelemetryRoute( + router: IRouter, + savedObjects: CoreSetup['savedObjects'], + logger: Logger +) { + router.post( + { + path: '/api/kibana/kql_opt_in_telemetry', + validate: { + body: schema.object({ + opt_in: schema.boolean(), + }), + }, + }, + async (context, request, response) => { + const internalRepository = savedObjects.createScopedRepository(request); + + const { + body: { opt_in: optIn }, + } = request; + + const counterName = optIn ? 'optInCount' : 'optOutCount'; + + try { + await internalRepository.incrementCounter('kql-telemetry', 'kql-telemetry', counterName); + } catch (error) { + logger.warn(`Unable to increment counter: ${error}`); + return response.customError({ + statusCode: error.status, + body: { + message: 'Something went wrong', + attributes: { + success: false, + }, + }, + }); + } + + return response.ok({ body: { success: true } }); + } + ); +} diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts index e81250e653ebd..bfd04aec5711f 100644 --- a/src/plugins/data/server/plugin.ts +++ b/src/plugins/data/server/plugin.ts @@ -21,18 +21,26 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../.. import { IndexPatternsService } from './index_patterns'; import { ISearchSetup } from './search'; import { SearchService } from './search/search_service'; +import { ScriptsService } from './scripts'; +import { KqlTelemetryService } from './kql_telemetry'; export interface DataPluginSetup { search: ISearchSetup; } export class DataServerPlugin implements Plugin { private readonly searchService: SearchService; + private readonly scriptsService: ScriptsService; + private readonly kqlTelemetryService: KqlTelemetryService; private readonly indexPatterns = new IndexPatternsService(); constructor(initializerContext: PluginInitializerContext) { this.searchService = new SearchService(initializerContext); + this.scriptsService = new ScriptsService(); + this.kqlTelemetryService = new KqlTelemetryService(initializerContext); } public setup(core: CoreSetup) { this.indexPatterns.setup(core); + this.scriptsService.setup(core); + this.kqlTelemetryService.setup(core); return { search: this.searchService.setup(core), }; diff --git a/src/legacy/core_plugins/kibana/server/routes/api/scripts/register_languages.js b/src/plugins/data/server/scripts/index.ts similarity index 79% rename from src/legacy/core_plugins/kibana/server/routes/api/scripts/register_languages.js rename to src/plugins/data/server/scripts/index.ts index 6b27d24dda785..d4a3e70fdbf53 100644 --- a/src/legacy/core_plugins/kibana/server/routes/api/scripts/register_languages.js +++ b/src/plugins/data/server/scripts/index.ts @@ -17,12 +17,4 @@ * under the License. */ -export function registerLanguages(server) { - server.route({ - path: '/api/kibana/scripts/languages', - method: 'GET', - handler: function () { - return ['painless', 'expression']; - } - }); -} +export { ScriptsService } from './scripts_service'; diff --git a/src/plugins/data/server/scripts/route.ts b/src/plugins/data/server/scripts/route.ts new file mode 100644 index 0000000000000..3eb77f09b25cd --- /dev/null +++ b/src/plugins/data/server/scripts/route.ts @@ -0,0 +1,31 @@ +/* + * 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 { IRouter } from 'kibana/server'; + +export function registerScriptsRoute(router: IRouter) { + router.get( + { path: '/api/kibana/scripts/languages', validate: false }, + async (context, request, response) => { + return response.ok({ + body: ['painless', 'expression'], + }); + } + ); +} diff --git a/src/plugins/data/server/scripts/scripts_service.ts b/src/plugins/data/server/scripts/scripts_service.ts new file mode 100644 index 0000000000000..9a3a20a64276d --- /dev/null +++ b/src/plugins/data/server/scripts/scripts_service.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, Plugin } from 'kibana/server'; +import { registerScriptsRoute } from './route'; + +export class ScriptsService implements Plugin { + public setup({ http }: CoreSetup) { + registerScriptsRoute(http.createRouter()); + } + + public start() {} +} From 3937a1d623b172ec29becab9bc46ca409facff62 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 11 Dec 2019 15:34:11 +0100 Subject: [PATCH 2/4] also move usage collector over --- src/legacy/core_plugins/kibana/index.js | 2 -- .../kibana/ui_setting_defaults.js | 3 +- src/plugins/data/common/constants.ts | 20 +++++++++++++ src/plugins/data/common/index.ts | 1 + src/plugins/data/kibana.json | 3 +- .../kql_telemetry/kql_telemetry_service.ts | 15 +++++++++- .../usage_collector/fetch.test.ts} | 30 +++++++++++-------- .../kql_telemetry/usage_collector/fetch.ts} | 15 ++++++---- .../kql_telemetry/usage_collector/index.ts} | 0 .../make_kql_usage_collector.test.ts} | 29 +++++++----------- .../make_kql_usage_collector.ts} | 9 ++++-- src/plugins/data/server/plugin.ts | 14 +++++++-- 12 files changed, 95 insertions(+), 46 deletions(-) create mode 100644 src/plugins/data/common/constants.ts rename src/{legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.test.js => plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts} (85%) rename src/{legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.js => plugins/data/server/kql_telemetry/usage_collector/fetch.ts} (85%) rename src/{legacy/core_plugins/kibana/server/lib/kql_usage_collector/index.js => plugins/data/server/kql_telemetry/usage_collector/index.ts} (100%) rename src/{legacy/core_plugins/kibana/server/lib/kql_usage_collector/make_kql_usage_collector.test.js => plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.test.ts} (62%) rename src/{legacy/core_plugins/kibana/server/lib/kql_usage_collector/make_kql_usage_collector.js => plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.ts} (81%) diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index d8e56e4b5f0fe..542e305c59c02 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -33,7 +33,6 @@ import { registerTutorials } from './server/tutorials/register'; import * as systemApi from './server/lib/system_api'; import mappings from './mappings.json'; import { getUiSettingDefaults } from './ui_setting_defaults'; -import { makeKQLUsageCollector } from './server/lib/kql_usage_collector'; import { registerCspCollector } from './server/lib/csp_usage_collector'; import { injectVars } from './inject_vars'; import { i18n } from '@kbn/i18n'; @@ -332,7 +331,6 @@ export default function (kibana) { registerSuggestionsApi(server); registerFieldFormats(server); registerTutorials(server); - makeKQLUsageCollector(usageCollection, server); registerCspCollector(usageCollection, server); server.expose('systemApi', systemApi); server.injectUiAppVars('kibana', () => injectVars(server)); diff --git a/src/legacy/core_plugins/kibana/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/ui_setting_defaults.js index ca57395481409..f724d7dac2f53 100644 --- a/src/legacy/core_plugins/kibana/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/ui_setting_defaults.js @@ -20,6 +20,7 @@ import moment from 'moment-timezone'; import numeralLanguages from '@elastic/numeral/languages'; import { i18n } from '@kbn/i18n'; +import { DEFAULT_QUERY_LANGUAGE } from '../../../plugins/data/common'; export function getUiSettingDefaults() { const weekdays = moment.weekdays().slice(); @@ -114,7 +115,7 @@ export function getUiSettingDefaults() { }, 'search:queryLanguage': { name: queryLanguageSettingName, - value: 'kuery', + value: DEFAULT_QUERY_LANGUAGE, description: i18n.translate('kbn.advancedSettings.searchQueryLanguageText', { defaultMessage: 'Query language used by the query bar. KQL is a new language built specifically for Kibana.', diff --git a/src/plugins/data/common/constants.ts b/src/plugins/data/common/constants.ts new file mode 100644 index 0000000000000..00786a0c72cf1 --- /dev/null +++ b/src/plugins/data/common/constants.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const DEFAULT_QUERY_LANGUAGE = 'kuery'; diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts index b334342a57ec6..e02045de24e8f 100644 --- a/src/plugins/data/common/index.ts +++ b/src/plugins/data/common/index.ts @@ -24,3 +24,4 @@ export * from './index_patterns'; export * from './es_query'; export * from './utils'; export * from './types'; +export * from './constants'; diff --git a/src/plugins/data/kibana.json b/src/plugins/data/kibana.json index 998eaa55858d2..6553ce8ce4d91 100644 --- a/src/plugins/data/kibana.json +++ b/src/plugins/data/kibana.json @@ -3,5 +3,6 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["uiActions"] + "requiredPlugins": ["uiActions"], + "optionalPlugins": ["usageCollection"] } diff --git a/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts b/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts index 5890341eb41d0..3ba004ab24436 100644 --- a/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts +++ b/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts @@ -17,18 +17,31 @@ * under the License. */ +import { first } from 'rxjs/operators'; import { CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server'; import { registerKqlTelemetryRoute } from './route'; +import { UsageCollectionSetup } from '../../../usage_collection/server'; +import { makeKQLUsageCollector } from './usage_collector'; export class KqlTelemetryService implements Plugin { constructor(private initializerContext: PluginInitializerContext) {} - public setup({ http, savedObjects }: CoreSetup) { + public async setup( + { http, savedObjects }: CoreSetup, + { usageCollection }: { usageCollection?: UsageCollectionSetup } + ) { registerKqlTelemetryRoute( http.createRouter(), savedObjects, this.initializerContext.logger.get('data', 'kql-telemetry') ); + + if (usageCollection) { + const config = await this.initializerContext.config.legacy.globalConfig$ + .pipe(first()) + .toPromise(); + makeKQLUsageCollector(usageCollection, config.kibana.index); + } } public start() {} diff --git a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.test.js b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts similarity index 85% rename from src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.test.js rename to src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts index a5db4602872ee..446320b09757a 100644 --- a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.test.js +++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts @@ -17,18 +17,22 @@ * under the License. */ -jest.mock('../../../ui_setting_defaults', () => ({ - getUiSettingDefaults: () => ({ 'search:queryLanguage': { value: 'lucene' } }), -})); - import { fetchProvider } from './fetch'; +import { APICaller } from 'kibana/server'; + +jest.mock('../../../common', () => ({ + DEFAULT_QUERY_LANGUAGE: 'lucene', +})); -let fetch; -let callCluster; +let fetch: ReturnType; +let callCluster: APICaller; -function setupMockCallCluster(optCount, language) { - callCluster = jest.fn((method, params) => { - if ('id' in params && params.id === 'kql-telemetry:kql-telemetry') { +function setupMockCallCluster( + optCount: { optInCount?: number; optOutCount?: number } | null, + language: string | undefined | null +) { + callCluster = (jest.fn((method, params) => { + if (params && 'id' in params && params.id === 'kql-telemetry:kql-telemetry') { if (optCount === null) { return Promise.resolve({ _index: '.kibana_1', @@ -46,9 +50,9 @@ function setupMockCallCluster(optCount, language) { }, }); } - } else if ('body' in params && params.body.query.term.type === 'config') { + } else if (params && 'body' in params && params.body.query.term.type === 'config') { if (language === 'missingConfigDoc') { - Promise.resolve({ + return Promise.resolve({ hits: { hits: [], }, @@ -69,7 +73,9 @@ function setupMockCallCluster(optCount, language) { }); } } - }); + + throw new Error('invalid call'); + }) as unknown) as APICaller; } describe('makeKQLUsageCollector', () => { diff --git a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.js b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts similarity index 85% rename from src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.js rename to src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts index 74ccf01195fab..9f3437161541f 100644 --- a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/fetch.js +++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts @@ -17,14 +17,14 @@ * under the License. */ -import { getUiSettingDefaults } from '../../../ui_setting_defaults'; import { get } from 'lodash'; +import { APICaller } from 'kibana/server'; +import { DEFAULT_QUERY_LANGUAGE } from '../../../common'; -const uiSettingDefaults = getUiSettingDefaults(); -const defaultSearchQueryLanguageSetting = uiSettingDefaults['search:queryLanguage'].value; +const defaultSearchQueryLanguageSetting = DEFAULT_QUERY_LANGUAGE; -export function fetchProvider(index) { - return async callCluster => { +export function fetchProvider(index: string) { + return async (callCluster: APICaller) => { const [response, config] = await Promise.all([ callCluster('get', { index, @@ -38,7 +38,10 @@ export function fetchProvider(index) { }), ]); - const queryLanguageConfigValue = get(config, 'hits.hits[0]._source.config.search:queryLanguage'); + const queryLanguageConfigValue = get( + config, + 'hits.hits[0]._source.config.search:queryLanguage' + ); // search:queryLanguage can potentially be in four states in the .kibana index: // 1. undefined: this means the user has never touched this setting diff --git a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/index.js b/src/plugins/data/server/kql_telemetry/usage_collector/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/index.js rename to src/plugins/data/server/kql_telemetry/usage_collector/index.ts diff --git a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/make_kql_usage_collector.test.js b/src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.test.ts similarity index 62% rename from src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/make_kql_usage_collector.test.js rename to src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.test.ts index 7737a0fbc2a71..97a714f09474b 100644 --- a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/make_kql_usage_collector.test.js +++ b/src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.test.ts @@ -18,33 +18,26 @@ */ import { makeKQLUsageCollector } from './make_kql_usage_collector'; +import { UsageCollectionSetup } from '../../../../usage_collection/server'; describe('makeKQLUsageCollector', () => { - let server; - let makeUsageCollectorStub; - let registerStub; - let usageCollection; + let usageCollectionMock: jest.Mocked; beforeEach(() => { - makeUsageCollectorStub = jest.fn(); - registerStub = jest.fn(); - usageCollection = { - makeUsageCollector: makeUsageCollectorStub, - registerCollector: registerStub, - }; - server = { - config: () => ({ get: () => '.kibana' }) - }; + usageCollectionMock = ({ + makeUsageCollector: jest.fn(), + registerCollector: jest.fn(), + } as unknown) as jest.Mocked; }); it('should call registerCollector', () => { - makeKQLUsageCollector(usageCollection, server); - expect(registerStub).toHaveBeenCalledTimes(1); + makeKQLUsageCollector(usageCollectionMock, '.kibana'); + expect(usageCollectionMock.registerCollector).toHaveBeenCalledTimes(1); }); it('should call makeUsageCollector with type = kql', () => { - makeKQLUsageCollector(usageCollection, server); - expect(makeUsageCollectorStub).toHaveBeenCalledTimes(1); - expect(makeUsageCollectorStub.mock.calls[0][0].type).toBe('kql'); + makeKQLUsageCollector(usageCollectionMock, '.kibana'); + expect(usageCollectionMock.makeUsageCollector).toHaveBeenCalledTimes(1); + expect(usageCollectionMock.makeUsageCollector.mock.calls[0][0].type).toBe('kql'); }); }); diff --git a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/make_kql_usage_collector.js b/src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.ts similarity index 81% rename from src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/make_kql_usage_collector.js rename to src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.ts index 6d751a9e9ff45..db4c9a8f0b4c7 100644 --- a/src/legacy/core_plugins/kibana/server/lib/kql_usage_collector/make_kql_usage_collector.js +++ b/src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.ts @@ -18,10 +18,13 @@ */ import { fetchProvider } from './fetch'; +import { UsageCollectionSetup } from '../../../../usage_collection/server'; -export function makeKQLUsageCollector(usageCollection, server) { - const index = server.config().get('kibana.index'); - const fetch = fetchProvider(index); +export async function makeKQLUsageCollector( + usageCollection: UsageCollectionSetup, + kibanaIndex: string +) { + const fetch = fetchProvider(kibanaIndex); const kqlUsageCollector = usageCollection.makeUsageCollector({ type: 'kql', fetch, diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts index bfd04aec5711f..9899e96bc0455 100644 --- a/src/plugins/data/server/plugin.ts +++ b/src/plugins/data/server/plugin.ts @@ -23,28 +23,38 @@ import { ISearchSetup } from './search'; import { SearchService } from './search/search_service'; import { ScriptsService } from './scripts'; import { KqlTelemetryService } from './kql_telemetry'; +import { UsageCollectionSetup } from '../../usage_collection/server'; export interface DataPluginSetup { search: ISearchSetup; } + +export interface DataPluginSetupDependencies { + usageCollection?: UsageCollectionSetup; +} + export class DataServerPlugin implements Plugin { private readonly searchService: SearchService; private readonly scriptsService: ScriptsService; private readonly kqlTelemetryService: KqlTelemetryService; private readonly indexPatterns = new IndexPatternsService(); + constructor(initializerContext: PluginInitializerContext) { this.searchService = new SearchService(initializerContext); this.scriptsService = new ScriptsService(); this.kqlTelemetryService = new KqlTelemetryService(initializerContext); } - public setup(core: CoreSetup) { + + public async setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies) { this.indexPatterns.setup(core); this.scriptsService.setup(core); - this.kqlTelemetryService.setup(core); + await this.kqlTelemetryService.setup(core, { usageCollection }); + return { search: this.searchService.setup(core), }; } + public start(core: CoreStart) {} public stop() {} } From a6192037744af6dd016737cdf36d111766cb7d2c Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 20 Dec 2019 11:53:34 +0100 Subject: [PATCH 3/4] hide async kql telemetry service --- .../server/kql_telemetry/kql_telemetry_service.ts | 13 +++++++++---- src/plugins/data/server/plugin.ts | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts b/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts index 3ba004ab24436..8f68e63703d40 100644 --- a/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts +++ b/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts @@ -26,7 +26,7 @@ import { makeKQLUsageCollector } from './usage_collector'; export class KqlTelemetryService implements Plugin { constructor(private initializerContext: PluginInitializerContext) {} - public async setup( + public setup( { http, savedObjects }: CoreSetup, { usageCollection }: { usageCollection?: UsageCollectionSetup } ) { @@ -37,10 +37,15 @@ export class KqlTelemetryService implements Plugin { ); if (usageCollection) { - const config = await this.initializerContext.config.legacy.globalConfig$ + this.initializerContext.config.legacy.globalConfig$ .pipe(first()) - .toPromise(); - makeKQLUsageCollector(usageCollection, config.kibana.index); + .toPromise() + .then(config => makeKQLUsageCollector(usageCollection, config.kibana.index)) + .catch(e => { + this.initializerContext.logger + .get('kql-telemetry') + .warn(`Registering KQL telemetry collector failed: ${e}`); + }); } } diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts index d00477a18663a..591fdb4c4080d 100644 --- a/src/plugins/data/server/plugin.ts +++ b/src/plugins/data/server/plugin.ts @@ -46,7 +46,7 @@ export class DataServerPlugin implements Plugin { this.kqlTelemetryService = new KqlTelemetryService(initializerContext); } - public async setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies) { + public setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies) { this.indexPatterns.setup(core); this.scriptsService.setup(core); this.autocompleteService.setup(core); From 4f8a55f8b5caa48c2c53e901da236c76ebb72375 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 20 Dec 2019 16:07:12 +0100 Subject: [PATCH 4/4] update core api docs for some unknown reason --- .../core/server/kibana-plugin-server.basepath.get.md | 2 +- docs/development/core/server/kibana-plugin-server.basepath.md | 4 ++-- .../core/server/kibana-plugin-server.basepath.set.md | 2 +- src/core/server/server.api.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/development/core/server/kibana-plugin-server.basepath.get.md b/docs/development/core/server/kibana-plugin-server.basepath.get.md index a20bc1a4e3174..6ef7022f10e62 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.get.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.get.md @@ -9,5 +9,5 @@ returns `basePath` value, specific for an incoming request. Signature: ```typescript -get: (request: LegacyRequest | KibanaRequest) => string; +get: (request: KibanaRequest | LegacyRequest) => string; ``` diff --git a/docs/development/core/server/kibana-plugin-server.basepath.md b/docs/development/core/server/kibana-plugin-server.basepath.md index bf91619ac230b..77f50abc60369 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.md @@ -16,11 +16,11 @@ export declare class BasePath | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [get](./kibana-plugin-server.basepath.get.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown, any>) => string | returns basePath value, specific for an incoming request. | +| [get](./kibana-plugin-server.basepath.get.md) | | (request: KibanaRequest<unknown, unknown, unknown, any> | LegacyRequest) => string | returns basePath value, specific for an incoming request. | | [prepend](./kibana-plugin-server.basepath.prepend.md) | | (path: string) => string | Prepends path with the basePath. | | [remove](./kibana-plugin-server.basepath.remove.md) | | (path: string) => string | Removes the prepended basePath from the path. | | [serverBasePath](./kibana-plugin-server.basepath.serverbasepath.md) | | string | returns the server's basePathSee [BasePath.get](./kibana-plugin-server.basepath.get.md) for getting the basePath value for a specific request | -| [set](./kibana-plugin-server.basepath.set.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown, any>, requestSpecificBasePath: string) => void | sets basePath value, specific for an incoming request. | +| [set](./kibana-plugin-server.basepath.set.md) | | (request: KibanaRequest<unknown, unknown, unknown, any> | LegacyRequest, requestSpecificBasePath: string) => void | sets basePath value, specific for an incoming request. | ## Remarks diff --git a/docs/development/core/server/kibana-plugin-server.basepath.set.md b/docs/development/core/server/kibana-plugin-server.basepath.set.md index ac08baa0bb99e..56a7f644d34cc 100644 --- a/docs/development/core/server/kibana-plugin-server.basepath.set.md +++ b/docs/development/core/server/kibana-plugin-server.basepath.set.md @@ -9,5 +9,5 @@ sets `basePath` value, specific for an incoming request. Signature: ```typescript -set: (request: LegacyRequest | KibanaRequest, requestSpecificBasePath: string) => void; +set: (request: KibanaRequest | LegacyRequest, requestSpecificBasePath: string) => void; ``` diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 85c0af8131ccb..eb23915122a58 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -449,11 +449,11 @@ export interface AuthToolkit { export class BasePath { // @internal constructor(serverBasePath?: string); - get: (request: LegacyRequest | KibanaRequest) => string; + get: (request: KibanaRequest | LegacyRequest) => string; prepend: (path: string) => string; remove: (path: string) => string; readonly serverBasePath: string; - set: (request: LegacyRequest | KibanaRequest, requestSpecificBasePath: string) => void; + set: (request: KibanaRequest | LegacyRequest, requestSpecificBasePath: string) => void; } // Warning: (ae-forgotten-export) The symbol "BootstrapArgs" needs to be exported by the entry point index.d.ts