From 4860e533d93ec5c9c3f81bf703637590a67f47c9 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Mon, 4 Nov 2019 18:02:39 +0200 Subject: [PATCH 01/46] initial push --- .../kbn-analytics/src/metrics/user_agent.ts | 21 +++ src/legacy/core_plugins/telemetry/index.ts | 24 ++- .../core_plugins/telemetry/mappings.json | 7 + .../telemetry/public/hacks/telemetry_init.ts | 3 +- .../telemetry/server/collection_manager.ts | 62 +++++++- .../core_plugins/telemetry/server/fetcher.ts | 141 ++++++++++++++++++ .../core_plugins/telemetry/server/index.ts | 3 +- .../get_telemetry_opt_in.ts | 33 ++++ .../get_telemetry_saved_object.ts} | 13 +- .../get_telemetry_usage_fetcher.ts | 31 ++++ .../server/replace_injected_vars/index.ts | 23 +++ .../replace_injected_vars.ts | 37 +++++ .../server/routes/telemetry_stats.ts | 15 +- .../telemetry_collection/get_local_stats.js | 14 +- .../server/telemetry_collection/get_stats.ts | 29 +--- .../server/telemetry_collection/index.ts | 2 - .../telemetry_collection/get_all_stats.js | 6 +- .../get_stats_with_monitoring.ts | 31 ++-- .../get_stats_with_xpack.ts | 33 +--- 19 files changed, 408 insertions(+), 120 deletions(-) create mode 100644 packages/kbn-analytics/src/metrics/user_agent.ts create mode 100644 src/legacy/core_plugins/telemetry/server/fetcher.ts create mode 100644 src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.ts rename src/legacy/core_plugins/telemetry/server/{get_telemetry_opt_in.ts => replace_injected_vars/get_telemetry_saved_object.ts} (77%) create mode 100644 src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.ts create mode 100644 src/legacy/core_plugins/telemetry/server/replace_injected_vars/index.ts create mode 100644 src/legacy/core_plugins/telemetry/server/replace_injected_vars/replace_injected_vars.ts diff --git a/packages/kbn-analytics/src/metrics/user_agent.ts b/packages/kbn-analytics/src/metrics/user_agent.ts new file mode 100644 index 00000000000000..56ccc6b22a92b2 --- /dev/null +++ b/packages/kbn-analytics/src/metrics/user_agent.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const usageAgent = + window && window.navigator && window.navigator.userAgent ? window.navigator.userAgent : ''; diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index 3271373449eb3a..19968d0c58d36a 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -26,7 +26,7 @@ import { i18n } from '@kbn/i18n'; import mappings from './mappings.json'; import { CONFIG_TELEMETRY, getConfigTelemetryDesc } from './common/constants'; import { getXpackConfigWithDeprecated } from './common/get_xpack_config_with_deprecated'; -import { telemetryPlugin, getTelemetryOptIn } from './server'; +import { telemetryPlugin, replaceTelemetryInjectedVars, FetcherTask } from './server'; import { createLocalizationUsageCollector, @@ -57,6 +57,9 @@ const telemetry = (kibana: any) => { `https://telemetry.elastic.co/xpack/${ENDPOINT_VERSION}/send` ), }), + usageFetcher: Joi.string() + .allow(['server', 'browser']) + .default('browser'), }).default(); }, uiExports: { @@ -77,11 +80,13 @@ const telemetry = (kibana: any) => { }, }, async replaceInjectedVars(originalInjectedVars: any, request: any) { - const telemetryOptedIn = await getTelemetryOptIn(request); - + const telemetryInjectedVars = await replaceTelemetryInjectedVars( + originalInjectedVars, + request + ); return { ...originalInjectedVars, - telemetryOptedIn, + ...telemetryInjectedVars, }; }, injectDefaultVars(server: Server) { @@ -91,20 +96,27 @@ const telemetry = (kibana: any) => { telemetryUrl: getXpackConfigWithDeprecated(config, 'telemetry.url'), telemetryBanner: getXpackConfigWithDeprecated(config, 'telemetry.banner'), telemetryOptedIn: null, + telemetryUsageFetcher: config.get('telemetry.usageFetcher'), }; }, hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'], mappings, }, - init(server: Server) { + init(server: Server, kibanaConfig: any) { const initializerContext = {} as PluginInitializerContext; const coreSetup = ({ http: { server }, log: server.log, } as any) as CoreSetup; + // const coreStart = { + // savedObjects: server.savedObjects, + // } + const npTelemetryPlugin = telemetryPlugin(initializerContext); + npTelemetryPlugin.setup(coreSetup); - telemetryPlugin(initializerContext).setup(coreSetup); + const fetcherTask = new FetcherTask(server, kibanaConfig); + fetcherTask.start(); // register collectors server.usage.collectorSet.register(createLocalizationUsageCollector(server)); diff --git a/src/legacy/core_plugins/telemetry/mappings.json b/src/legacy/core_plugins/telemetry/mappings.json index d83f7f59676306..c1a8884b3bf190 100644 --- a/src/legacy/core_plugins/telemetry/mappings.json +++ b/src/legacy/core_plugins/telemetry/mappings.json @@ -3,6 +3,13 @@ "properties": { "enabled": { "type": "boolean" + }, + "usageFetcher": { + "ignore_above": 256, + "type": "keyword" + }, + "lastReported": { + "type": "date" } } } diff --git a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts index 364871380a529c..5641eacf408ea3 100644 --- a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts +++ b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts @@ -30,8 +30,9 @@ function telemetryInit($injector: any) { const $http = $injector.get('$http'); const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled'); + const usageFetcher = npStart.core.injectedMetadata.getInjectedVar('telemetryUsageFetcher'); - if (telemetryEnabled) { + if (telemetryEnabled && usageFetcher === 'browser') { // no telemetry for non-logged in users if (isUnauthenticated()) { return; diff --git a/src/legacy/core_plugins/telemetry/server/collection_manager.ts b/src/legacy/core_plugins/telemetry/server/collection_manager.ts index fef0a9b0f9f40b..0739d28234a1c5 100644 --- a/src/legacy/core_plugins/telemetry/server/collection_manager.ts +++ b/src/legacy/core_plugins/telemetry/server/collection_manager.ts @@ -17,12 +17,55 @@ * under the License. */ -class TelemetryCollectionManager { - private getterMethod?: any; +import { encryptTelemetry } from './collectors'; + +export type EncryptedStatsGetterConfig = { unencrypted: false } & { + server: any; + start: any; + end: any; + isDev: boolean; +}; + +export type UnencryptedStatsGetterConfig = { unencrypted: true } & { + req: any; + start: any; + end: any; + isDev: boolean; +}; + +export interface StatsCollectionConfig { + callCluster: any; + server: any; + start: any; + end: any; +} + +export type StatsGetterConfig = UnencryptedStatsGetterConfig | EncryptedStatsGetterConfig; + +export type StatsGetter = (config: StatsGetterConfig) => Promise; + +export const getStatsGetterConfig = ( + config: StatsGetterConfig, + esClutser: string +): StatsCollectionConfig => { + const { start, end } = config; + const server = config.unencrypted ? config.req.server : config.server; + const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster( + esClutser + ); + const callCluster = config.unencrypted + ? (...args: any[]) => callWithRequest(config.req, ...args) + : callWithInternalUser; + + return { server, callCluster, start, end }; +}; + +export class TelemetryCollectionManager { + private getterMethod?: StatsGetter; private collectionTitle?: string; private getterMethodPriority = 0; - public setStatsGetter = (statsGetter: any, title: string, priority = 0) => { + public setStatsGetter = (statsGetter: StatsGetter, title: string, priority = 0) => { if (priority >= this.getterMethodPriority) { this.getterMethod = statsGetter; this.collectionTitle = title; @@ -30,7 +73,16 @@ class TelemetryCollectionManager { } }; - getCollectionTitle = () => { + private getStats = async (config: StatsGetterConfig) => { + if (!this.getterMethod) { + throw Error('Stats getter method not set.'); + } + const usageData = await this.getterMethod(config); + + if (config.unencrypted) return usageData; + return encryptTelemetry(usageData, config.isDev); + }; + public getCollectionTitle = () => { return this.collectionTitle; }; @@ -39,7 +91,7 @@ class TelemetryCollectionManager { throw Error('Stats getter method not set.'); } return { - getStats: this.getterMethod, + getStats: this.getStats, priority: this.getterMethodPriority, title: this.collectionTitle, }; diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts new file mode 100644 index 00000000000000..4e77aad30ee7e2 --- /dev/null +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -0,0 +1,141 @@ +/* + * 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 moment from 'moment'; +import fetch from 'node-fetch'; +import { telemetryCollectionManager } from './collection_manager'; +import { REPORT_INTERVAL_MS } from '../common/constants'; +// @ts-ignore + +export class FetcherTask { + private readonly checkDuration = 60000; + private intervalId?: NodeJS.Timeout; + private lastReported?: number; + private isSending = false; + private serverConfigs: any; + private server: any; + + constructor(server: any, serverConfigs: any) { + this.server = server; + this.serverConfigs = serverConfigs; + } + + private getInternalRepository = () => { + const { getSavedObjectsRepository } = this.server.savedObjects; + const { callWithInternalUser } = this.server.plugins.elasticsearch.getCluster('admin'); + const internalRepository = getSavedObjectsRepository(callWithInternalUser); + return internalRepository; + }; + + private getCurrentConfigs = async () => { + const internalRepository = this.getInternalRepository(); + let telemetrySavedConfigs = {}; + try { + const telemetrySavedObject = await internalRepository.get('telemetry', 'telemetry'); + telemetrySavedConfigs = telemetrySavedObject.attributes; + } catch (err) { + // Swallow errors getting telemetry saved object (Saved object NotFound or other errors) + telemetrySavedConfigs = {}; + } + + return { + telemetryOptIn: + typeof telemetrySavedConfigs.enabled === 'boolean' + ? telemetrySavedConfigs.enabled + : this.serverConfigs.optIn, + telemetryUsageFetcher: + typeof telemetrySavedConfigs.usageFetcher === 'undefined' + ? this.serverConfigs.usageFetcher + : telemetrySavedObject.usageFetcher, + telemetryUrl: this.serverConfigs.url, + }; + }; + + private updateLastReported = async () => { + const internalRepository = this.getInternalRepository(); + this.lastReported = Date.now(); + await internalRepository.update('telemetry', 'telemetry', { + lastReported: this.lastReported, + }); + }; + + private checkReportStatus = ({ telemetryOptIn, telemetryUsageFetcher }) => { + if (telemetryOptIn && telemetryUsageFetcher === 'server') { + if (!this.lastReported || Date.now() - this.lastReported > REPORT_INTERVAL_MS) { + return true; + } + } + return false; + }; + private fetchTelemetry = async () => { + const { getStats, title } = telemetryCollectionManager.getStatsGetter(); + this.server.log(['debug', 'telemetry', 'fetcher'], `Fetching usage using ${title} getter.`); + const config = this.server.config(); + + return await getStats({ + unencrypted: false, + server: this.server, + start: moment() + .subtract(20, 'minutes') + .toISOString(), + end: moment().toISOString(), + isDev: config.get('env.dev'), + }); + }; + private sendTelemetry = async (url: string, cluster: any): Promise => { + this.server.log(['debug', 'telemetry', 'fetcher'], `Sending usage stats.`); + await fetch(url, { + method: 'post', + body: cluster, + }); + }; + + private sendIfDue = async () => { + try { + const telemetryConfig = await this.getCurrentConfigs(); + if (this.isSending || !this.checkReportStatus(telemetryConfig)) { + return; + } + + // mark that we are working so future requests are ignored until we're done + this.isSending = true; + const clusters = await this.fetchTelemetry(); + for (const cluster of clusters) { + await this.sendTelemetry(telemetryConfig.telemetryUrl, cluster); + } + + await this.updateLastReported(); + } catch (err) { + this.server.log( + ['warning', 'telemetry', 'fetcher'], + `Error sending telemetry usage data: ${err}` + ); + } + this.isSending = false; + }; + + public start = () => { + this.intervalId = setInterval(() => this.sendIfDue(), this.checkDuration); + }; + public stop = () => { + if (this.intervalId) { + clearInterval(this.intervalId); + } + }; +} diff --git a/src/legacy/core_plugins/telemetry/server/index.ts b/src/legacy/core_plugins/telemetry/server/index.ts index b8ae5fc231fba6..62f56008871dff 100644 --- a/src/legacy/core_plugins/telemetry/server/index.ts +++ b/src/legacy/core_plugins/telemetry/server/index.ts @@ -21,7 +21,8 @@ import { PluginInitializerContext } from 'src/core/server'; import { TelemetryPlugin } from './plugin'; import * as constants from '../common/constants'; -export { getTelemetryOptIn } from './get_telemetry_opt_in'; +export { FetcherTask } from './fetcher'; +export { replaceTelemetryInjectedVars } from './replace_injected_vars'; export { telemetryCollectionManager } from './collection_manager'; export const telemetryPlugin = (initializerContext: PluginInitializerContext) => diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.ts new file mode 100644 index 00000000000000..69692dc38ef850 --- /dev/null +++ b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.ts @@ -0,0 +1,33 @@ +/* + * 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 function getTelemetryOptIn(telemetrySavedObject: any, request: any) { + const isRequestingApplication = request.path.startsWith('/app'); + + // Prevent interstitial screens (such as the space selector) from prompting for telemetry + if (!isRequestingApplication) { + return false; + } + + if (telemetrySavedObject === false || telemetrySavedObject === null) { + return telemetrySavedObject; + } + + return telemetrySavedObject.enabled; +} diff --git a/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_saved_object.ts similarity index 77% rename from src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts rename to src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_saved_object.ts index 9b365d6dd7ae51..a6b576aea2aaa7 100644 --- a/src/legacy/core_plugins/telemetry/server/get_telemetry_opt_in.ts +++ b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_saved_object.ts @@ -17,19 +17,10 @@ * under the License. */ -export async function getTelemetryOptIn(request: any) { - const isRequestingApplication = request.path.startsWith('/app'); - - // Prevent interstitial screens (such as the space selector) from prompting for telemetry - if (!isRequestingApplication) { - return false; - } - - const savedObjectsClient = request.getSavedObjectsClient(); - +export async function getTelemetrySavedObject(savedObjectsClient: any) { try { const { attributes } = await savedObjectsClient.get('telemetry', 'telemetry'); - return attributes.enabled; + return attributes; } catch (error) { if (savedObjectsClient.errors.isNotFoundError(error)) { return null; diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.ts b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.ts new file mode 100644 index 00000000000000..17c508abe62bc4 --- /dev/null +++ b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.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. + */ + +export function getTelemetryUsageFetcher(telemetrySavedObject: any, originalInjectedVars: any) { + const { telemetryUsageFetcher } = originalInjectedVars; + if (!telemetrySavedObject) { + return telemetryUsageFetcher; + } + + if (typeof telemetrySavedObject.usageFetcher === 'undefined') { + return telemetryUsageFetcher; + } + + return telemetrySavedObject.usageFetcher; +} diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/index.ts b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/index.ts new file mode 100644 index 00000000000000..1156d03be07be7 --- /dev/null +++ b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/index.ts @@ -0,0 +1,23 @@ +/* + * 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 { replaceTelemetryInjectedVars } from './replace_injected_vars'; +export { getTelemetryOptIn } from './get_telemetry_opt_in'; +export { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher'; +export { getTelemetrySavedObject } from './get_telemetry_saved_object'; diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/replace_injected_vars.ts new file mode 100644 index 00000000000000..1d96356e4fd4d1 --- /dev/null +++ b/src/legacy/core_plugins/telemetry/server/replace_injected_vars/replace_injected_vars.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getTelemetrySavedObject } from './get_telemetry_saved_object'; +import { getTelemetryOptIn } from './get_telemetry_opt_in'; +import { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher'; + +export async function replaceTelemetryInjectedVars(originalInjectedVars: any, request: any) { + const savedObjectsClient = request.getSavedObjectsClient(); + const telemetrySavedObject = await getTelemetrySavedObject(savedObjectsClient); + const telemetryOptedIn = getTelemetryOptIn(telemetrySavedObject, request); + const telemetryUsageFetcher = getTelemetryUsageFetcher( + telemetrySavedObject, + originalInjectedVars + ); + + return { + telemetryOptedIn, + telemetryUsageFetcher, + }; +} diff --git a/src/legacy/core_plugins/telemetry/server/routes/telemetry_stats.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_stats.ts index 8a91d24b34ed21..e87c041a263a5e 100644 --- a/src/legacy/core_plugins/telemetry/server/routes/telemetry_stats.ts +++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_stats.ts @@ -20,7 +20,6 @@ import Joi from 'joi'; import { boomify } from 'boom'; import { CoreSetup } from 'src/core/server'; -import { encryptTelemetry } from '../collectors'; import { telemetryCollectionManager } from '../collection_manager'; export function registerTelemetryDataRoutes(core: CoreSetup) { @@ -49,12 +48,16 @@ export function registerTelemetryDataRoutes(core: CoreSetup) { try { const { getStats, title } = telemetryCollectionManager.getStatsGetter(); - server.log(['debug', 'telemetry'], `Using Stats Getter: ${title}`); + server.log(['debug', 'telemetry', 'fetcher'], `Fetching usage using ${title} getter.`); - const usageData = await getStats(req, config, start, end, unencrypted); - - if (unencrypted) return usageData; - return encryptTelemetry(usageData, isDev); + return await getStats({ + unencrypted, + server, + req, + start, + end, + isDev, + }); } catch (err) { if (isDev) { // don't ignore errors when running in dev mode diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js index 67fc721306c213..e34e940c581338 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js +++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js @@ -61,18 +61,6 @@ export async function getLocalStatsWithCaller(server, callCluster) { return handleLocalStats(server, clusterInfo, clusterStats, kibana); } - -/** - * Get statistics for the connected Elasticsearch cluster. - * - * @param {Object} req The incoming request - * @param {Boolean} useRequestUser callWithRequest, otherwise callWithInternalUser - * @return {Promise} The cluster object containing telemetry. - */ -export async function getLocalStats(req, { useInternalUser = false } = {}) { - const { server } = req; - const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster('data'); - const callCluster = useInternalUser ? callWithInternalUser : (...args) => callWithRequest(req, ...args); - +export async function getLocalStats({ server, callCluster }) { return await getLocalStatsWithCaller(server, callCluster); } diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts index 024272e0f805ca..4f2e390553a1a8 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts @@ -19,27 +19,10 @@ // @ts-ignore import { getLocalStats } from './get_local_stats'; +import { StatsGetter, getStatsGetterConfig } from '../collection_manager'; -/** - * Get the telemetry data. - * - * @param {Object} req The incoming request. - * @param {Object} config Kibana config. - * @param {String} start The start time of the request (likely 20m ago). - * @param {String} end The end time of the request. - * @param {Boolean} unencrypted Is the request payload going to be unencrypted. - * @return {Promise} An array of telemetry objects. - */ -export async function getStats( - req: any, - config: any, - start: string, - end: string, - unencrypted: boolean -) { - return [ - await getLocalStats(req, { - useInternalUser: !unencrypted, - }), - ]; -} +export const getStats: StatsGetter = async function(config) { + const { callCluster, server } = getStatsGetterConfig(config, 'data'); + + return [await getLocalStats({ callCluster, server })]; +}; diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/index.ts b/src/legacy/core_plugins/telemetry/server/telemetry_collection/index.ts index f33727d82f44ce..f54aaf0ce1bc04 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/index.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/index.ts @@ -19,6 +19,4 @@ // @ts-ignore export { getLocalStats } from './get_local_stats'; - -// @ts-ignore export { getStats } from './get_stats'; diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js index b1e8db1b96005d..69d34859edec61 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js @@ -26,11 +26,7 @@ import { getHighLevelStats } from './get_high_level_stats'; * @param {Date} end The ending range to request data * @return {Promise} The array of clusters joined with the Kibana and Logstash instances. */ -export function getAllStats(req, start, end, { useInternalUser = false } = {}) { - const server = req.server; - const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster('monitoring'); - const callCluster = useInternalUser ? callWithInternalUser : (...args) => callWithRequest(req, ...args); - +export function getAllStats({ server, callCluster, start, end } = {}) { return getAllStatsWithCaller(server, callCluster, start, end); } diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts index fdf46122f13b76..18875e4acd31a7 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts @@ -7,37 +7,24 @@ // @ts-ignore import { getAllStats } from './get_all_stats'; import { getStatsWithXpack } from '../../../xpack_main/server/telemetry_collection'; +import { + StatsGetter, + getStatsGetterConfig, +} from '../../../../../../src/legacy/core_plugins/telemetry/server/collection_manager'; -/** - * Get the telemetry data. - * - * @param {Object} req The incoming request. - * @param {Object} config Kibana config. - * @param {String} start The start time of the request (likely 20m ago). - * @param {String} end The end time of the request. - * @param {Boolean} unencrypted Is the request payload going to be unencrypted. - * @return {Promise} An array of telemetry objects. - */ -export async function getStatsWithMonitoring( - req: any, - config: any, - start: string, - end: string, - unencrypted: boolean -) { +export const getStatsWithMonitoring: StatsGetter = async function(config) { let response = []; - const useInternalUser = !unencrypted; + const { start, end, server, callCluster } = getStatsGetterConfig(config, 'monitoring'); try { - // attempt to collect stats from multiple clusters in monitoring data - response = await getAllStats(req, start, end, { useInternalUser }); + response = await getAllStats({ server, callCluster, start, end }); } catch (err) { // no-op } if (!Array.isArray(response) || response.length === 0) { - response = await getStatsWithXpack(req, config, start, end, unencrypted); + response = await getStatsWithXpack(config); } return response; -} +}; diff --git a/x-pack/legacy/plugins/xpack_main/server/telemetry_collection/get_stats_with_xpack.ts b/x-pack/legacy/plugins/xpack_main/server/telemetry_collection/get_stats_with_xpack.ts index f19695ca065257..1ff3704a7ba1d9 100644 --- a/x-pack/legacy/plugins/xpack_main/server/telemetry_collection/get_stats_with_xpack.ts +++ b/x-pack/legacy/plugins/xpack_main/server/telemetry_collection/get_stats_with_xpack.ts @@ -7,36 +7,19 @@ // @ts-ignore import { getXPack } from './get_xpack'; import { getLocalStats } from '../../../../../../src/legacy/core_plugins/telemetry/server/telemetry_collection'; +import { + StatsGetter, + getStatsGetterConfig, +} from '../../../../../../src/legacy/core_plugins/telemetry/server/collection_manager'; -/** - * Get the telemetry data. - * - * @param {Object} req The incoming request. - * @param {Object} config Kibana config. - * @param {String} start The start time of the request (likely 20m ago). - * @param {String} end The end time of the request. - * @param {Boolean} unencrypted Is the request payload going to be unencrypted. - * @return {Promise} An array of telemetry objects. - */ -export async function getStatsWithXpack( - req: any, - config: any, - start: string, - end: string, - unencrypted: boolean -) { - const useInternalUser = !unencrypted; - const { server } = req; - const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster('data'); - const callCluster = useInternalUser - ? callWithInternalUser - : (...args: any[]) => callWithRequest(req, ...args); +export const getStatsWithXpack: StatsGetter = async function(config) { + const { server, callCluster } = getStatsGetterConfig(config, 'data'); - const localStats = await getLocalStats(req, { useInternalUser }); + const localStats = await getLocalStats({ server, callCluster }); const { license, xpack } = await getXPack(callCluster); localStats.license = license; localStats.stack_stats.xpack = xpack; return [localStats]; -} +}; From d7f7f60f6e1a38c92de799ac62e6c84cbd659798 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Mon, 4 Nov 2019 18:16:54 +0200 Subject: [PATCH 02/46] self code review --- src/legacy/core_plugins/telemetry/index.ts | 7 ++----- .../telemetry/server/collection_manager.ts | 2 +- src/legacy/core_plugins/telemetry/server/fetcher.ts | 12 ++++++++---- .../server/telemetry_collection/get_stats.ts | 4 ++-- .../get_stats_with_monitoring.ts | 4 ++-- .../telemetry_collection/get_stats_with_xpack.ts | 4 ++-- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index 19968d0c58d36a..d461de62ae981c 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -109,11 +109,8 @@ const telemetry = (kibana: any) => { http: { server }, log: server.log, } as any) as CoreSetup; - // const coreStart = { - // savedObjects: server.savedObjects, - // } - const npTelemetryPlugin = telemetryPlugin(initializerContext); - npTelemetryPlugin.setup(coreSetup); + + telemetryPlugin(initializerContext).setup(coreSetup); const fetcherTask = new FetcherTask(server, kibanaConfig); fetcherTask.start(); diff --git a/src/legacy/core_plugins/telemetry/server/collection_manager.ts b/src/legacy/core_plugins/telemetry/server/collection_manager.ts index 0739d28234a1c5..22b9ad5ab802b6 100644 --- a/src/legacy/core_plugins/telemetry/server/collection_manager.ts +++ b/src/legacy/core_plugins/telemetry/server/collection_manager.ts @@ -44,7 +44,7 @@ export type StatsGetterConfig = UnencryptedStatsGetterConfig | EncryptedStatsGet export type StatsGetter = (config: StatsGetterConfig) => Promise; -export const getStatsGetterConfig = ( +export const getStatsCollectionConfig = ( config: StatsGetterConfig, esClutser: string ): StatsCollectionConfig => { diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts index 4e77aad30ee7e2..1a7a34bc302f22 100644 --- a/src/legacy/core_plugins/telemetry/server/fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -21,7 +21,11 @@ import moment from 'moment'; import fetch from 'node-fetch'; import { telemetryCollectionManager } from './collection_manager'; import { REPORT_INTERVAL_MS } from '../common/constants'; -// @ts-ignore + +interface TelemetrySavedConfigs { + enabled?: null | boolean; + usageFetcher?: 'string'; +} export class FetcherTask { private readonly checkDuration = 60000; @@ -45,7 +49,7 @@ export class FetcherTask { private getCurrentConfigs = async () => { const internalRepository = this.getInternalRepository(); - let telemetrySavedConfigs = {}; + let telemetrySavedConfigs: TelemetrySavedConfigs = {}; try { const telemetrySavedObject = await internalRepository.get('telemetry', 'telemetry'); telemetrySavedConfigs = telemetrySavedObject.attributes; @@ -62,7 +66,7 @@ export class FetcherTask { telemetryUsageFetcher: typeof telemetrySavedConfigs.usageFetcher === 'undefined' ? this.serverConfigs.usageFetcher - : telemetrySavedObject.usageFetcher, + : telemetrySavedConfigs.usageFetcher, telemetryUrl: this.serverConfigs.url, }; }; @@ -75,7 +79,7 @@ export class FetcherTask { }); }; - private checkReportStatus = ({ telemetryOptIn, telemetryUsageFetcher }) => { + private checkReportStatus = ({ telemetryOptIn, telemetryUsageFetcher }: any) => { if (telemetryOptIn && telemetryUsageFetcher === 'server') { if (!this.lastReported || Date.now() - this.lastReported > REPORT_INTERVAL_MS) { return true; diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts index 4f2e390553a1a8..b739b20545678a 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_stats.ts @@ -19,10 +19,10 @@ // @ts-ignore import { getLocalStats } from './get_local_stats'; -import { StatsGetter, getStatsGetterConfig } from '../collection_manager'; +import { StatsGetter, getStatsCollectionConfig } from '../collection_manager'; export const getStats: StatsGetter = async function(config) { - const { callCluster, server } = getStatsGetterConfig(config, 'data'); + const { callCluster, server } = getStatsCollectionConfig(config, 'data'); return [await getLocalStats({ callCluster, server })]; }; diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts index 18875e4acd31a7..eaa660f2917393 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts @@ -9,12 +9,12 @@ import { getAllStats } from './get_all_stats'; import { getStatsWithXpack } from '../../../xpack_main/server/telemetry_collection'; import { StatsGetter, - getStatsGetterConfig, + getStatsCollectionConfig, } from '../../../../../../src/legacy/core_plugins/telemetry/server/collection_manager'; export const getStatsWithMonitoring: StatsGetter = async function(config) { let response = []; - const { start, end, server, callCluster } = getStatsGetterConfig(config, 'monitoring'); + const { start, end, server, callCluster } = getStatsCollectionConfig(config, 'monitoring'); try { response = await getAllStats({ server, callCluster, start, end }); diff --git a/x-pack/legacy/plugins/xpack_main/server/telemetry_collection/get_stats_with_xpack.ts b/x-pack/legacy/plugins/xpack_main/server/telemetry_collection/get_stats_with_xpack.ts index 1ff3704a7ba1d9..6915da52636242 100644 --- a/x-pack/legacy/plugins/xpack_main/server/telemetry_collection/get_stats_with_xpack.ts +++ b/x-pack/legacy/plugins/xpack_main/server/telemetry_collection/get_stats_with_xpack.ts @@ -9,11 +9,11 @@ import { getXPack } from './get_xpack'; import { getLocalStats } from '../../../../../../src/legacy/core_plugins/telemetry/server/telemetry_collection'; import { StatsGetter, - getStatsGetterConfig, + getStatsCollectionConfig, } from '../../../../../../src/legacy/core_plugins/telemetry/server/collection_manager'; export const getStatsWithXpack: StatsGetter = async function(config) { - const { server, callCluster } = getStatsGetterConfig(config, 'data'); + const { server, callCluster } = getStatsCollectionConfig(config, 'data'); const localStats = await getLocalStats({ server, callCluster }); const { license, xpack } = await getXPack(callCluster); From 27d6b674d77917e69caebcfb521aa6d12894d635 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Mon, 4 Nov 2019 18:21:17 +0200 Subject: [PATCH 03/46] ignore node-fetch type --- src/legacy/core_plugins/telemetry/server/fetcher.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts index 1a7a34bc302f22..92175e977bc9dd 100644 --- a/src/legacy/core_plugins/telemetry/server/fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -18,6 +18,7 @@ */ import moment from 'moment'; +// @ts-ignore import fetch from 'node-fetch'; import { telemetryCollectionManager } from './collection_manager'; import { REPORT_INTERVAL_MS } from '../common/constants'; From 0037d75b9ccf7c54146294b07090aad5b4b9011c Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Mon, 4 Nov 2019 19:20:42 +0200 Subject: [PATCH 04/46] usageFetcher api --- .../telemetry/server/routes/index.ts | 4 +- .../routes/{opt_in.ts => telemetry_config.ts} | 41 +++++++++++++------ 2 files changed, 31 insertions(+), 14 deletions(-) rename src/legacy/core_plugins/telemetry/server/routes/{opt_in.ts => telemetry_config.ts} (61%) diff --git a/src/legacy/core_plugins/telemetry/server/routes/index.ts b/src/legacy/core_plugins/telemetry/server/routes/index.ts index 12ba541d699f9f..c9e435f916c703 100644 --- a/src/legacy/core_plugins/telemetry/server/routes/index.ts +++ b/src/legacy/core_plugins/telemetry/server/routes/index.ts @@ -18,10 +18,10 @@ */ import { CoreSetup } from 'src/core/server'; -import { registerOptInRoutes } from './opt_in'; +import { registerTelemetryConfigRoutes } from './telemetry_config'; import { registerTelemetryDataRoutes } from './telemetry_stats'; export function registerRoutes(core: CoreSetup) { - registerOptInRoutes(core); + registerTelemetryConfigRoutes(core); registerTelemetryDataRoutes(core); } diff --git a/src/legacy/core_plugins/telemetry/server/routes/opt_in.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts similarity index 61% rename from src/legacy/core_plugins/telemetry/server/routes/opt_in.ts rename to src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts index aabc0259f08fc2..551e3198c439e1 100644 --- a/src/legacy/core_plugins/telemetry/server/routes/opt_in.ts +++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts @@ -21,9 +21,36 @@ import Joi from 'joi'; import { boomify } from 'boom'; import { CoreSetup } from 'src/core/server'; -export function registerOptInRoutes(core: CoreSetup) { +async function updateTelemetrySavedObjectFromReq(req: any) { + const savedObjectsClient = req.getSavedObjectsClient(); + return await savedObjectsClient.update('telemetry', 'telemetry', req.payload); +} + +export function registerTelemetryConfigRoutes(core: CoreSetup) { const { server } = core.http as any; + server.route({ + method: 'POST', + path: '/api/telemetry/v2/usageFetcher', + options: { + validate: { + payload: Joi.object({ + usageFetcher: Joi.string() + .allow(['browser', 'server']) + .required(), + }), + }, + }, + handler: async (req: any, h: any) => { + try { + await updateTelemetrySavedObjectFromReq(req); + } catch (err) { + return boomify(err); + } + return h.response({}).code(200); + }, + }); + server.route({ method: 'POST', path: '/api/telemetry/v2/optIn', @@ -35,18 +62,8 @@ export function registerOptInRoutes(core: CoreSetup) { }, }, handler: async (req: any, h: any) => { - const savedObjectsClient = req.getSavedObjectsClient(); try { - await savedObjectsClient.create( - 'telemetry', - { - enabled: req.payload.enabled, - }, - { - id: 'telemetry', - overwrite: true, - } - ); + await updateTelemetrySavedObjectFromReq(req); } catch (err) { return boomify(err); } From 4436f3f8bfd31c7b6a6f41a0574c6c8891b6d2ed Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 6 Nov 2019 14:12:11 +0200 Subject: [PATCH 05/46] user agent metric --- packages/kbn-analytics/package.json | 2 +- packages/kbn-analytics/src/metrics/index.ts | 16 ++--- .../kbn-analytics/src/metrics/ui_stats.ts | 28 ++++---- .../kbn-analytics/src/metrics/user_agent.ts | 18 ++++- packages/kbn-analytics/src/report.ts | 59 ++++++++++++---- packages/kbn-analytics/src/reporter.ts | 36 +++++++--- .../server/routes/telemetry_config.ts | 13 +++- .../ui_metric/public/hacks/ui_metric_init.ts | 11 +-- .../core_plugins/ui_metric/public/index.ts | 2 +- .../public/services/telemetry_analytics.ts | 29 +++++--- .../ui_metric/server/routes/api/ui_metric.ts | 68 ++++++++++++------- yarn.lock | 2 +- 12 files changed, 192 insertions(+), 92 deletions(-) diff --git a/packages/kbn-analytics/package.json b/packages/kbn-analytics/package.json index e2f3a59e95a47c..b0ac86b465a621 100644 --- a/packages/kbn-analytics/package.json +++ b/packages/kbn-analytics/package.json @@ -17,6 +17,6 @@ "@babel/cli": "7.5.5", "@kbn/dev-utils": "1.0.0", "@kbn/babel-preset": "1.0.0", - "typescript": "3.5.1" + "typescript": "3.5.3" } } diff --git a/packages/kbn-analytics/src/metrics/index.ts b/packages/kbn-analytics/src/metrics/index.ts index 13b9e5dc59e4e2..a98e89ff85ec27 100644 --- a/packages/kbn-analytics/src/metrics/index.ts +++ b/packages/kbn-analytics/src/metrics/index.ts @@ -17,21 +17,19 @@ * under the License. */ -import { UiStatsMetric, UiStatsMetricType } from './ui_stats'; +import { UiStatsMetric } from './ui_stats'; +import { UserAgentMetric } from './user_agent'; + +export { UiStatsMetric, createUiStatsMetric, UiStatsMetricType } from './ui_stats'; -export { - UiStatsMetric, - createUiStatsMetric, - UiStatsMetricReport, - UiStatsMetricType, -} from './ui_stats'; export { Stats } from './stats'; +export { trackUsageAgent } from './user_agent'; -export type Metric = UiStatsMetric; -export type MetricType = keyof typeof METRIC_TYPE; +export type Metric = UiStatsMetric | UserAgentMetric; export enum METRIC_TYPE { COUNT = 'count', LOADED = 'loaded', CLICK = 'click', + USER_AGENT = 'user_agent', } diff --git a/packages/kbn-analytics/src/metrics/ui_stats.ts b/packages/kbn-analytics/src/metrics/ui_stats.ts index 7615fd20645e28..dc8cdcd3e4a1e9 100644 --- a/packages/kbn-analytics/src/metrics/ui_stats.ts +++ b/packages/kbn-analytics/src/metrics/ui_stats.ts @@ -17,37 +17,33 @@ * under the License. */ -import { Stats } from './stats'; import { METRIC_TYPE } from './'; export type UiStatsMetricType = METRIC_TYPE.CLICK | METRIC_TYPE.LOADED | METRIC_TYPE.COUNT; -export interface UiStatsMetricConfig { - type: T; +export interface UiStatsMetricConfig { + type: UiStatsMetricType; appName: string; eventName: string; count?: number; } -export interface UiStatsMetric { - type: T; +export interface UiStatsMetric { + type: UiStatsMetricType; appName: string; eventName: string; count: number; } -export function createUiStatsMetric({ +export function createUiStatsMetric({ type, appName, eventName, count = 1, -}: UiStatsMetricConfig): UiStatsMetric { - return { type, appName, eventName, count }; -} - -export interface UiStatsMetricReport { - key: string; - appName: string; - eventName: string; - type: UiStatsMetricType; - stats: Stats; +}: UiStatsMetricConfig): UiStatsMetric { + return { + type, + appName, + eventName, + count, + }; } diff --git a/packages/kbn-analytics/src/metrics/user_agent.ts b/packages/kbn-analytics/src/metrics/user_agent.ts index 56ccc6b22a92b2..aedc4894d124fe 100644 --- a/packages/kbn-analytics/src/metrics/user_agent.ts +++ b/packages/kbn-analytics/src/metrics/user_agent.ts @@ -16,6 +16,20 @@ * specific language governing permissions and limitations * under the License. */ +import { METRIC_TYPE } from './'; -const usageAgent = - window && window.navigator && window.navigator.userAgent ? window.navigator.userAgent : ''; +export interface UserAgentMetric { + type: METRIC_TYPE.USER_AGENT; + appName: string; + userAgent: string; +} + +export function trackUsageAgent(appName: string): UserAgentMetric { + const userAgent = + window && window.navigator && window.navigator.userAgent ? window.navigator.userAgent : ''; + return { + type: METRIC_TYPE.USER_AGENT, + appName, + userAgent, + }; +} diff --git a/packages/kbn-analytics/src/report.ts b/packages/kbn-analytics/src/report.ts index 6187455fa60a55..fd8f6b3ce1db45 100644 --- a/packages/kbn-analytics/src/report.ts +++ b/packages/kbn-analytics/src/report.ts @@ -17,28 +17,47 @@ * under the License. */ -import { UnreachableCaseError } from './util'; -import { Metric, Stats, UiStatsMetricReport, METRIC_TYPE } from './metrics'; +import { UnreachableCaseError, wrapArray } from './util'; +import { Metric, Stats, UiStatsMetricType, METRIC_TYPE } from './metrics'; +const REPORT_VERSION = 1; export interface Report { + reportVersion: typeof REPORT_VERSION; uiStatsMetrics: { - [key: string]: UiStatsMetricReport; + [key: string]: { + key: string; + appName: string; + eventName: string; + type: UiStatsMetricType; + stats: Stats; + }; + }; + userAgent?: { + [key: string]: { + userAgent: string; + key: string; + type: METRIC_TYPE.USER_AGENT; + appName: string; + }; }; } export class ReportManager { + static REPORT_VERSION = REPORT_VERSION; public report: Report; constructor(report?: Report) { this.report = report || ReportManager.createReport(); } - static createReport() { - return { uiStatsMetrics: {} }; + static createReport(): Report { + return { reportVersion: REPORT_VERSION, uiStatsMetrics: {} }; } public clearReport() { this.report = ReportManager.createReport(); } public isReportEmpty(): boolean { - return Object.keys(this.report.uiStatsMetrics).length === 0; + const noUiStats = Object.keys(this.report.uiStatsMetrics).length === 0; + const noUserAgent = !this.report.userAgent || Object.keys(this.report.userAgent).length === 0; + return noUiStats && noUserAgent; } private incrementStats(count: number, stats?: Stats): Stats { const { min = 0, max = 0, sum = 0 } = stats || {}; @@ -54,28 +73,44 @@ export class ReportManager { sum: newSum, }; } - assignReports(newMetrics: Metric[]) { - newMetrics.forEach(newMetric => this.assignReport(this.report, newMetric)); + assignReports(newMetrics: Metric | Metric[]) { + wrapArray(newMetrics).forEach(newMetric => this.assignReport(this.report, newMetric)); } static createMetricKey(metric: Metric): string { switch (metric.type) { + case METRIC_TYPE.USER_AGENT: { + const { appName, type } = metric; + return `${appName}-${type}`; + } case METRIC_TYPE.CLICK: case METRIC_TYPE.LOADED: case METRIC_TYPE.COUNT: { - const { appName, type, eventName } = metric; + const { appName, eventName, type } = metric; return `${appName}-${type}-${eventName}`; } default: - throw new UnreachableCaseError(metric.type); + throw new UnreachableCaseError(metric); } } private assignReport(report: Report, metric: Metric) { + const key = ReportManager.createMetricKey(metric); switch (metric.type) { + case METRIC_TYPE.USER_AGENT: { + const { appName, type } = metric; + this.report.userAgent = { + [key]: { + key, + appName, + type, + userAgent: metric.userAgent, + }, + }; + return; + } case METRIC_TYPE.CLICK: case METRIC_TYPE.LOADED: case METRIC_TYPE.COUNT: { const { appName, type, eventName, count } = metric; - const key = ReportManager.createMetricKey(metric); const existingStats = (report.uiStatsMetrics[key] || {}).stats; this.report.uiStatsMetrics[key] = { key, @@ -87,7 +122,7 @@ export class ReportManager { return; } default: - throw new UnreachableCaseError(metric.type); + throw new UnreachableCaseError(metric); } } } diff --git a/packages/kbn-analytics/src/reporter.ts b/packages/kbn-analytics/src/reporter.ts index 37d23aa4430902..970887021ffeb1 100644 --- a/packages/kbn-analytics/src/reporter.ts +++ b/packages/kbn-analytics/src/reporter.ts @@ -18,7 +18,7 @@ */ import { wrapArray } from './util'; -import { Metric, UiStatsMetric, createUiStatsMetric } from './metrics'; +import { Metric, UiStatsMetric, createUiStatsMetric, trackUsageAgent } from './metrics'; import { Storage, ReportStorageManager } from './storage'; import { Report, ReportManager } from './report'; @@ -40,10 +40,11 @@ export class Reporter { private reportManager: ReportManager; private storageManager: ReportStorageManager; private debug: boolean; + private retryCount = 0; + private readonly maxRetries = 3; constructor(config: ReporterConfig) { const { http, storage, debug, checkInterval = 10000, storageKey = 'analytics' } = config; - this.http = http; this.checkInterval = checkInterval; this.interval = null; @@ -63,14 +64,14 @@ export class Reporter { this.storageManager.store(this.reportManager.report); } - public start() { + public start = () => { if (!this.interval) { this.interval = setTimeout(() => { this.interval = null; this.sendReports(); }, this.checkInterval); } - } + }; private log(message: any) { if (this.debug) { @@ -79,32 +80,47 @@ export class Reporter { } } - public reportUiStats( + public reportUiStats = ( appName: string, type: UiStatsMetric['type'], eventNames: string | string[], count?: number - ) { + ) => { const metrics = wrapArray(eventNames).map(eventName => { - if (this) this.log(`${type} Metric -> (${appName}:${eventName}):`); + this.log(`${type} Metric -> (${appName}:${eventName}):`); const report = createUiStatsMetric({ type, appName, eventName, count }); this.log(report); return report; }); this.saveToReport(metrics); - } + }; - public async sendReports() { + public reportUserAgent = (appName: string) => { + this.log(`Reporting user-agent.`); + const report = trackUsageAgent(appName); + this.saveToReport([report]); + }; + + public sendReports = async () => { if (!this.reportManager.isReportEmpty()) { try { await this.http(this.reportManager.report); this.flushReport(); + this.retryCount = 0; } catch (err) { + this.retryCount = this.retryCount + 1; this.log(`Error Sending Metrics Report ${err}`); + if (this.retryCount > this.maxRetries) { + this.log(`Max retries reached; Flushing report.`); + this.flushReport(); + } else if (this.reportManager.report.reportVersion !== ReportManager.REPORT_VERSION) { + this.log(`Report Version mismatch; Flushing report.`); + this.flushReport(); + } } } this.start(); - } + }; } export function createReporter(reportedConf: ReporterConfig) { diff --git a/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts index 551e3198c439e1..7b58f3943ed1f8 100644 --- a/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts +++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts @@ -20,10 +20,21 @@ import Joi from 'joi'; import { boomify } from 'boom'; import { CoreSetup } from 'src/core/server'; +import { SavedObjectsErrorHelpers } from '../../../../../core/server'; async function updateTelemetrySavedObjectFromReq(req: any) { const savedObjectsClient = req.getSavedObjectsClient(); - return await savedObjectsClient.update('telemetry', 'telemetry', req.payload); + try { + return await savedObjectsClient.update('telemetry', 'telemetry', req.payload); + } catch (err) { + if (SavedObjectsErrorHelpers.isNotFoundError(err)) { + return await savedObjectsClient.create('telemetry', req.payload, { + id: 'telemetry', + overwrite: true, + }); + } + throw err; + } } export function registerTelemetryConfigRoutes(core: CoreSetup) { diff --git a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts index 7aafc82cfe4c63..8d6df48181b2e5 100644 --- a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts +++ b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts @@ -20,15 +20,18 @@ // @ts-ignore import { uiModules } from 'ui/modules'; import chrome from 'ui/chrome'; -import { createAnalyticsReporter, setTelemetryReporter } from '../services/telemetry_analytics'; +import { + createAnalyticsReporter, + setTelemetryReporter, + trackUserAgent, +} from '../services/telemetry_analytics'; function telemetryInit($injector: any) { const localStorage = $injector.get('localStorage'); const debug = chrome.getInjected('debugUiMetric'); - const $http = $injector.get('$http'); - const basePath = chrome.getBasePath(); - const uiReporter = createAnalyticsReporter({ localStorage, $http, basePath, debug }); + const uiReporter = createAnalyticsReporter({ localStorage, debug }); setTelemetryReporter(uiReporter); + trackUserAgent('kibana'); } uiModules.get('kibana').run(telemetryInit); diff --git a/src/legacy/core_plugins/ui_metric/public/index.ts b/src/legacy/core_plugins/ui_metric/public/index.ts index b1e78b56d05d0a..6e6bf9ea25facb 100644 --- a/src/legacy/core_plugins/ui_metric/public/index.ts +++ b/src/legacy/core_plugins/ui_metric/public/index.ts @@ -17,5 +17,5 @@ * under the License. */ -export { createUiStatsReporter } from './services/telemetry_analytics'; +export { createUiStatsReporter, trackUserAgent } from './services/telemetry_analytics'; export { METRIC_TYPE } from '@kbn/analytics'; diff --git a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts index 7310ee5b5f1720..d456a4949a29de 100644 --- a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts +++ b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts @@ -18,6 +18,9 @@ */ import { createReporter, Reporter, UiStatsMetricType } from '@kbn/analytics'; +import { kfetch } from 'ui/kfetch'; +// @ts-ignore +import { addSystemApiHeader } from 'ui/system_api'; let telemetryReporter: Reporter; @@ -39,27 +42,35 @@ export const createUiStatsReporter = (appName: string) => ( } }; +export const trackUserAgent = (appName: string) => { + if (telemetryReporter) { + return telemetryReporter.reportUserAgent(appName); + } +}; + +export const createUiMetricReporter = (appName: string) => (type: UiStatsMetricType): void => { + if (telemetryReporter) { + return telemetryReporter.reportUiStats(appName, type, eventNames, count); + } +}; + interface AnalyicsReporterConfig { localStorage: any; - basePath: string; debug: boolean; - $http: ng.IHttpService; } export function createAnalyticsReporter(config: AnalyicsReporterConfig) { - const { localStorage, basePath, debug } = config; + const { localStorage, debug } = config; return createReporter({ debug, storage: localStorage, async http(report) { - const url = `${basePath}/api/telemetry/report`; - await fetch(url, { + return kfetch({ method: 'POST', - headers: { - 'kbn-xsrf': 'true', - }, - body: JSON.stringify({ report }), + pathname: '/api/telemetry/report', + body: JSON.stringify(report), + headers: addSystemApiHeader({}), }); }, }); diff --git a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts index 8a7950c46fa317..b2e7d0654f8364 100644 --- a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts +++ b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts @@ -27,15 +27,20 @@ export async function storeReport(server: any, report: Report) { const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); const internalRepository = getSavedObjectsRepository(callWithInternalUser); - const metricKeys = Object.keys(report.uiStatsMetrics); - return Promise.all( - metricKeys.map(async key => { - const metric = report.uiStatsMetrics[key]; + const uiStatsMetrics = report.uiStatsMetrics ? Object.entries(report.uiStatsMetrics) : []; + const userAgents = report.userAgent ? Object.entries(report.userAgent) : []; + return Promise.all([ + ...userAgents.map(async ([key, metric]) => { + const { userAgent } = metric; + const savedObjectId = `${key}:${userAgent}`; + return internalRepository.incrementCounter('ui-metric', savedObjectId, 'count'); + }), + ...uiStatsMetrics.map(async ([key, metric]) => { const { appName, eventName } = metric; const savedObjectId = `${appName}:${eventName}`; return internalRepository.incrementCounter('ui-metric', savedObjectId, 'count'); - }) - ); + }), + ]); } export function registerUiMetricRoute(server: Server) { @@ -45,30 +50,41 @@ export function registerUiMetricRoute(server: Server) { options: { validate: { payload: Joi.object({ - report: Joi.object({ - uiStatsMetrics: Joi.object() - .pattern( - /.*/, - Joi.object({ - key: Joi.string().required(), - type: Joi.string().required(), - appName: Joi.string().required(), - eventName: Joi.string().required(), - stats: Joi.object({ - min: Joi.number(), - sum: Joi.number(), - max: Joi.number(), - avg: Joi.number(), - }).allow(null), - }) - ) - .allow(null), - }), + reportVersion: Joi.number().optional(), + userAgent: Joi.object() + .pattern( + /.*/, + Joi.object({ + key: Joi.string().required(), + type: Joi.string().required(), + appName: Joi.string().required(), + userAgent: Joi.string().required(), + }) + ) + .allow(null) + .optional(), + uiStatsMetrics: Joi.object() + .pattern( + /.*/, + Joi.object({ + key: Joi.string().required(), + type: Joi.string().required(), + appName: Joi.string().required(), + eventName: Joi.string().required(), + stats: Joi.object({ + min: Joi.number(), + sum: Joi.number(), + max: Joi.number(), + avg: Joi.number(), + }).allow(null), + }) + ) + .allow(null), }), }, }, handler: async (req: any, h: any) => { - const { report } = req.payload; + const report = req.payload; try { await storeReport(server, report); diff --git a/yarn.lock b/yarn.lock index 185152e0d0a345..8917e8ec0cecea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27908,7 +27908,7 @@ typescript-fsa@^2.0.0, typescript-fsa@^2.5.0: resolved "https://registry.yarnpkg.com/typescript-fsa/-/typescript-fsa-2.5.0.tgz#1baec01b5e8f5f34c322679d1327016e9e294faf" integrity sha1-G67AG16PXzTDImedEycBbp4pT68= -typescript@3.5.1, typescript@3.5.3, typescript@^3.0.1, typescript@^3.0.3, typescript@^3.2.2, typescript@^3.3.3333, typescript@^3.4.5, typescript@~3.3.3333, typescript@~3.5.3: +typescript@3.5.3, typescript@^3.0.1, typescript@^3.0.3, typescript@^3.2.2, typescript@^3.3.3333, typescript@^3.4.5, typescript@~3.3.3333, typescript@~3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== From 08157697c469bfc38797ec6f4d5934d2a35ee126 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 6 Nov 2019 17:11:00 +0200 Subject: [PATCH 06/46] telemetry plugin collector --- packages/kbn-analytics/src/metrics/index.ts | 2 - .../telemetry/common/constants.ts | 6 ++ src/legacy/core_plugins/telemetry/index.ts | 7 ++- .../telemetry/server/collectors/index.ts | 1 + .../collectors/telemetry_plugin/index.ts | 20 +++++++ .../telemetry_plugin_collector.ts | 56 +++++++++++++++++++ .../core_plugins/telemetry/server/fetcher.ts | 43 ++++++-------- .../core_plugins/telemetry/server/index.ts | 2 +- .../server/routes/telemetry_config.ts | 35 +++--------- .../get_telemetry_opt_in.test.ts | 2 +- .../get_telemetry_opt_in.ts | 15 ++--- .../get_telemetry_usage_fetcher.test.ts | 8 +-- .../get_telemetry_usage_fetcher.ts | 8 +-- .../index.ts | 1 - .../replace_injected_vars.ts | 7 ++- .../get_telemetry_saved_object.test.ts | 0 .../get_telemetry_saved_object.ts | 8 +-- .../server/telemetry_repository/index.ts | 28 ++++++++++ .../update_telemetry_saved_object.ts | 38 +++++++++++++ 19 files changed, 204 insertions(+), 83 deletions(-) create mode 100644 src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/index.ts create mode 100644 src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts rename src/legacy/core_plugins/telemetry/server/{replace_injected_vars => telemetry_config}/get_telemetry_opt_in.test.ts (98%) rename src/legacy/core_plugins/telemetry/server/{replace_injected_vars => telemetry_config}/get_telemetry_opt_in.ts (88%) rename src/legacy/core_plugins/telemetry/server/{replace_injected_vars => telemetry_config}/get_telemetry_usage_fetcher.test.ts (88%) rename src/legacy/core_plugins/telemetry/server/{replace_injected_vars => telemetry_config}/get_telemetry_usage_fetcher.ts (85%) rename src/legacy/core_plugins/telemetry/server/{replace_injected_vars => telemetry_config}/index.ts (93%) rename src/legacy/core_plugins/telemetry/server/{replace_injected_vars => telemetry_config}/replace_injected_vars.ts (91%) rename src/legacy/core_plugins/telemetry/server/{replace_injected_vars => telemetry_repository}/get_telemetry_saved_object.test.ts (100%) rename src/legacy/core_plugins/telemetry/server/{replace_injected_vars => telemetry_repository}/get_telemetry_saved_object.ts (83%) create mode 100644 src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts create mode 100644 src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts diff --git a/packages/kbn-analytics/src/metrics/index.ts b/packages/kbn-analytics/src/metrics/index.ts index a98e89ff85ec27..ceaf53cbc97536 100644 --- a/packages/kbn-analytics/src/metrics/index.ts +++ b/packages/kbn-analytics/src/metrics/index.ts @@ -21,12 +21,10 @@ import { UiStatsMetric } from './ui_stats'; import { UserAgentMetric } from './user_agent'; export { UiStatsMetric, createUiStatsMetric, UiStatsMetricType } from './ui_stats'; - export { Stats } from './stats'; export { trackUsageAgent } from './user_agent'; export type Metric = UiStatsMetric | UserAgentMetric; - export enum METRIC_TYPE { COUNT = 'count', LOADED = 'loaded', diff --git a/src/legacy/core_plugins/telemetry/common/constants.ts b/src/legacy/core_plugins/telemetry/common/constants.ts index ab1397b2cc232e..b80396aac62a1f 100644 --- a/src/legacy/core_plugins/telemetry/common/constants.ts +++ b/src/legacy/core_plugins/telemetry/common/constants.ts @@ -59,6 +59,12 @@ export const PRIVACY_STATEMENT_URL = `https://www.elastic.co/legal/telemetry-pri */ export const KIBANA_LOCALIZATION_STATS_TYPE = 'localization'; +/** + * The type name used to publish telemetry plugin stats. + * @type {string} + */ +export const TELEMETRY_STATS_TYPE = 'telemetry'; + /** * UI metric usage type * @type {string} diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index 2cfefb4ed72309..51d1f6d7549d88 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -32,6 +32,7 @@ import { createLocalizationUsageCollector, createTelemetryUsageCollector, createUiMetricUsageCollector, + createTelemetryPluginUsageCollector, } from './server/collectors'; const ENDPOINT_VERSION = 'v2'; @@ -105,7 +106,7 @@ const telemetry = (kibana: any) => { hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'], mappings, }, - init(server: Server, kibanaConfig: any) { + init(server: Server, pluginConfig: any) { const initializerContext = { env: { packageInfo: { @@ -120,11 +121,11 @@ const telemetry = (kibana: any) => { } as any) as CoreSetup; telemetryPlugin(initializerContext).setup(coreSetup); - - const fetcherTask = new FetcherTask(server, kibanaConfig); + const fetcherTask = new FetcherTask(server, pluginConfig); fetcherTask.start(); // register collectors + server.usage.collectorSet.register(createTelemetryPluginUsageCollector(server)); server.usage.collectorSet.register(createLocalizationUsageCollector(server)); server.usage.collectorSet.register(createTelemetryUsageCollector(server)); server.usage.collectorSet.register(createUiMetricUsageCollector(server)); diff --git a/src/legacy/core_plugins/telemetry/server/collectors/index.ts b/src/legacy/core_plugins/telemetry/server/collectors/index.ts index 0bc1d50fab1be6..f963ecec0477cf 100644 --- a/src/legacy/core_plugins/telemetry/server/collectors/index.ts +++ b/src/legacy/core_plugins/telemetry/server/collectors/index.ts @@ -21,3 +21,4 @@ export { encryptTelemetry } from './encryption'; export { createTelemetryUsageCollector } from './usage'; export { createUiMetricUsageCollector } from './ui_metric'; export { createLocalizationUsageCollector } from './localization'; +export { createTelemetryPluginUsageCollector } from './telemetry_plugin'; diff --git a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/index.ts b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/index.ts new file mode 100644 index 00000000000000..e96c47741f79c9 --- /dev/null +++ b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/index.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 { createTelemetryPluginUsageCollector } from './telemetry_plugin_collector'; diff --git a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts new file mode 100644 index 00000000000000..e0f72d9e59c410 --- /dev/null +++ b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts @@ -0,0 +1,56 @@ +/* + * 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 { TELEMETRY_STATS_TYPE } from '../../../common/constants'; +import { getTelemetrySavedObject } from '../../telemetry_repository'; +export interface TelemetryUsageStats { + optIn?: boolean | null; + usageFetcher?: 'browser' | 'server'; + lastReported?: number; +} + +export function createCollectorFetch(server: any) { + return async function fetchUsageStats(): Promise { + const { getSavedObjectsRepository } = server.savedObjects; + const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); + const internalRepository = getSavedObjectsRepository(callWithInternalUser); + const telemetrySavedObject = await getTelemetrySavedObject(internalRepository); + + if (!telemetrySavedObject) return {}; + + return { + optIn: telemetrySavedObject.enabled, + lastReported: telemetrySavedObject.lastReported, + usageFetcher: telemetrySavedObject.usageFetcher, + }; + }; +} + +/* + * @param {Object} server + * @return {Object} kibana usage stats type collection object + */ +export function createTelemetryPluginUsageCollector(server: any) { + const { collectorSet } = server.usage; + return collectorSet.makeUsageCollector({ + type: TELEMETRY_STATS_TYPE, + isReady: () => true, + fetch: createCollectorFetch(server), + }); +} diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts index 92175e977bc9dd..0521721a4dffed 100644 --- a/src/legacy/core_plugins/telemetry/server/fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -21,24 +21,21 @@ import moment from 'moment'; // @ts-ignore import fetch from 'node-fetch'; import { telemetryCollectionManager } from './collection_manager'; +import { getTelemetryOptIn, getTelemetryUsageFetcher } from './telemetry_config'; +import { getTelemetrySavedObject, updateTelemetrySavedObject } from './telemetry_repository'; import { REPORT_INTERVAL_MS } from '../common/constants'; -interface TelemetrySavedConfigs { - enabled?: null | boolean; - usageFetcher?: 'string'; -} - export class FetcherTask { private readonly checkDuration = 60000; private intervalId?: NodeJS.Timeout; private lastReported?: number; private isSending = false; - private serverConfigs: any; + private telemetryPluginConfig: any; private server: any; - constructor(server: any, serverConfigs: any) { + constructor(server: any, telemetryPluginConfig: any) { this.server = server; - this.serverConfigs = serverConfigs; + this.telemetryPluginConfig = telemetryPluginConfig; } private getInternalRepository = () => { @@ -50,32 +47,24 @@ export class FetcherTask { private getCurrentConfigs = async () => { const internalRepository = this.getInternalRepository(); - let telemetrySavedConfigs: TelemetrySavedConfigs = {}; - try { - const telemetrySavedObject = await internalRepository.get('telemetry', 'telemetry'); - telemetrySavedConfigs = telemetrySavedObject.attributes; - } catch (err) { - // Swallow errors getting telemetry saved object (Saved object NotFound or other errors) - telemetrySavedConfigs = {}; - } + const telemetrySavedObject = await getTelemetrySavedObject(internalRepository); + const telemetryPluginConfig = this.telemetryPluginConfig; + const currentKibanaVersion = ''; return { - telemetryOptIn: - typeof telemetrySavedConfigs.enabled === 'boolean' - ? telemetrySavedConfigs.enabled - : this.serverConfigs.optIn, - telemetryUsageFetcher: - typeof telemetrySavedConfigs.usageFetcher === 'undefined' - ? this.serverConfigs.usageFetcher - : telemetrySavedConfigs.usageFetcher, - telemetryUrl: this.serverConfigs.url, + telemetryOptIn: getTelemetryOptIn({ currentKibanaVersion, telemetrySavedObject }), + telemetryUsageFetcher: getTelemetryUsageFetcher({ + telemetrySavedObject, + telemetryPluginConfig, + }), + telemetryUrl: telemetryPluginConfig.url, }; }; private updateLastReported = async () => { const internalRepository = this.getInternalRepository(); this.lastReported = Date.now(); - await internalRepository.update('telemetry', 'telemetry', { + updateTelemetrySavedObject(internalRepository, { lastReported: this.lastReported, }); }; @@ -88,6 +77,7 @@ export class FetcherTask { } return false; }; + private fetchTelemetry = async () => { const { getStats, title } = telemetryCollectionManager.getStatsGetter(); this.server.log(['debug', 'telemetry', 'fetcher'], `Fetching usage using ${title} getter.`); @@ -103,6 +93,7 @@ export class FetcherTask { isDev: config.get('env.dev'), }); }; + private sendTelemetry = async (url: string, cluster: any): Promise => { this.server.log(['debug', 'telemetry', 'fetcher'], `Sending usage stats.`); await fetch(url, { diff --git a/src/legacy/core_plugins/telemetry/server/index.ts b/src/legacy/core_plugins/telemetry/server/index.ts index 79270fda25f432..02752ca773488e 100644 --- a/src/legacy/core_plugins/telemetry/server/index.ts +++ b/src/legacy/core_plugins/telemetry/server/index.ts @@ -22,7 +22,7 @@ import { TelemetryPlugin } from './plugin'; import * as constants from '../common/constants'; export { FetcherTask } from './fetcher'; -export { replaceTelemetryInjectedVars } from './replace_injected_vars'; +export { replaceTelemetryInjectedVars } from './telemetry_config'; export { telemetryCollectionManager } from './collection_manager'; export const telemetryPlugin = (initializerContext: PluginInitializerContext) => diff --git a/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts index 8e55b98ee2c516..31d465c0bda0a2 100644 --- a/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts +++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts @@ -20,37 +20,16 @@ import Joi from 'joi'; import { boomify } from 'boom'; import { CoreSetup } from 'src/core/server'; -import { SavedObjectsErrorHelpers } from '../../../../../core/server'; +import { + TelemetrySavedObjectAttributes, + updateTelemetrySavedObject, +} from '../telemetry_repository'; interface RegisterOptInRoutesParams { core: CoreSetup; currentKibanaVersion: string; } -export interface TelemetrySavedObjectAttributes { - enabled?: boolean | null; - lastVersionChecked?: string; - usageFetcher?: 'browser' | 'server'; -} - -async function updateTelemetrySavedObjectFromReq( - req: any, - savedObjectAttributes: TelemetrySavedObjectAttributes -) { - const savedObjectsClient = req.getSavedObjectsClient(); - try { - return await savedObjectsClient.update('telemetry', 'telemetry', savedObjectAttributes); - } catch (err) { - if (SavedObjectsErrorHelpers.isNotFoundError(err)) { - return await savedObjectsClient.create('telemetry', savedObjectAttributes, { - id: 'telemetry', - overwrite: true, - }); - } - throw err; - } -} - export function registerTelemetryConfigRoutes({ core, currentKibanaVersion, @@ -72,7 +51,8 @@ export function registerTelemetryConfigRoutes({ handler: async (req: any, h: any) => { try { const attributes: TelemetrySavedObjectAttributes = req.payload; - await updateTelemetrySavedObjectFromReq(req, attributes); + const savedObjectsClient = req.getSavedObjectsClient(); + await updateTelemetrySavedObject(savedObjectsClient, attributes); } catch (err) { return boomify(err); } @@ -96,7 +76,8 @@ export function registerTelemetryConfigRoutes({ enabled: req.payload.enabled, lastVersionChecked: currentKibanaVersion, }; - await updateTelemetrySavedObjectFromReq(req, attributes); + const savedObjectsClient = req.getSavedObjectsClient(); + await updateTelemetrySavedObject(savedObjectsClient, attributes); } catch (err) { return boomify(err); } diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts similarity index 98% rename from src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.test.ts rename to src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts index 9337b48afc866a..fb2d63ba45d117 100644 --- a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.test.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts @@ -18,7 +18,7 @@ */ import { getTelemetryOptIn } from './get_telemetry_opt_in'; -import { TelemetrySavedObject } from './get_telemetry_saved_object'; +import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object'; describe('getTelemetryOptIn', () => { it('returns false when request path is not /app*', () => { diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts similarity index 88% rename from src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.ts rename to src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts index bf2f18f5a11aa7..1e5ae1b9d30420 100644 --- a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_opt_in.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts @@ -18,10 +18,10 @@ */ import semver from 'semver'; -import { TelemetrySavedObject } from './get_telemetry_saved_object'; +import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object'; interface GetTelemetryOptInConfig { - request: any; + request?: any; telemetrySavedObject: TelemetrySavedObject; currentKibanaVersion: string; } @@ -33,11 +33,12 @@ export const getTelemetryOptIn: GetTelemetryOptIn = ({ telemetrySavedObject, currentKibanaVersion, }) => { - const isRequestingApplication = request.path.startsWith('/app'); - - // Prevent interstitial screens (such as the space selector) from prompting for telemetry - if (!isRequestingApplication) { - return false; + if (request) { + const isRequestingApplication = request.path.startsWith('/app'); + // Prevent interstitial screens (such as the space selector) from prompting for telemetry + if (!isRequestingApplication) { + return false; + } } if (telemetrySavedObject === false) { diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts similarity index 88% rename from src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.test.ts rename to src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts index 17b2daa2bbcd28..fb7dddeb750b52 100644 --- a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.test.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts @@ -18,7 +18,7 @@ */ import { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher'; -import { TelemetrySavedObject } from './get_telemetry_saved_object'; +import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object'; describe('getTelemetryUsageFetcher', () => { it('returns kibana.yml config when saved object not found', () => { @@ -64,11 +64,11 @@ interface CallGetTelemetryUsageFetcherParams { function callGetTelemetryUsageFetcher(params: CallGetTelemetryUsageFetcherParams) { const telemetrySavedObject = getMockTelemetrySavedObject(params); - const originalInjectedVars = getMockOriginalInjectedVars(params); - return getTelemetryUsageFetcher({ originalInjectedVars, telemetrySavedObject }); + const telemetryPluginConfig = getMockTelemetryPluginConfig(params); + return getTelemetryUsageFetcher({ telemetryPluginConfig, telemetrySavedObject }); } -function getMockOriginalInjectedVars(params: CallGetTelemetryUsageFetcherParams) { +function getMockTelemetryPluginConfig(params: CallGetTelemetryUsageFetcherParams) { return { telemetryUsageFetcher: params.configUsageFetcher, }; diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts similarity index 85% rename from src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.ts rename to src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts index 965ad7c7111b6d..2368ba321f3e27 100644 --- a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_usage_fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts @@ -16,18 +16,18 @@ * specific language governing permissions and limitations * under the License. */ -import { TelemetrySavedObject } from './get_telemetry_saved_object'; +import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object'; interface GetTelemetryUsageFetcherConfig { - originalInjectedVars: any; + telemetryPluginConfig: any; telemetrySavedObject: TelemetrySavedObject; } export function getTelemetryUsageFetcher({ telemetrySavedObject, - originalInjectedVars, + telemetryPluginConfig, }: GetTelemetryUsageFetcherConfig) { - const { telemetryUsageFetcher } = originalInjectedVars; + const { telemetryUsageFetcher } = telemetryPluginConfig; if (!telemetrySavedObject) { return telemetryUsageFetcher; } diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/index.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/index.ts similarity index 93% rename from src/legacy/core_plugins/telemetry/server/replace_injected_vars/index.ts rename to src/legacy/core_plugins/telemetry/server/telemetry_config/index.ts index 1156d03be07be7..dd078947bef2b3 100644 --- a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/index.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/index.ts @@ -20,4 +20,3 @@ export { replaceTelemetryInjectedVars } from './replace_injected_vars'; export { getTelemetryOptIn } from './get_telemetry_opt_in'; export { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher'; -export { getTelemetrySavedObject } from './get_telemetry_saved_object'; diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts similarity index 91% rename from src/legacy/core_plugins/telemetry/server/replace_injected_vars/replace_injected_vars.ts rename to src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts index 6383aac173013f..5351f757b47ee0 100644 --- a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/replace_injected_vars.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts @@ -17,12 +17,12 @@ * under the License. */ -import { getTelemetrySavedObject } from './get_telemetry_saved_object'; +import { getTelemetrySavedObject } from '../telemetry_repository'; import { getTelemetryOptIn } from './get_telemetry_opt_in'; import { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher'; export async function replaceTelemetryInjectedVars( - originalInjectedVars: any, + telemetryPluginConfig: any, request: any, currentKibanaVersion: string ) { @@ -33,9 +33,10 @@ export async function replaceTelemetryInjectedVars( request, currentKibanaVersion, }); + const telemetryUsageFetcher = getTelemetryUsageFetcher({ telemetrySavedObject, - originalInjectedVars, + telemetryPluginConfig, }); return { diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_saved_object.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.test.ts similarity index 100% rename from src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_saved_object.test.ts rename to src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.test.ts diff --git a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_saved_object.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.ts similarity index 83% rename from src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_saved_object.ts rename to src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.ts index 7db7e0778ab96b..91965ef201ecb5 100644 --- a/src/legacy/core_plugins/telemetry/server/replace_injected_vars/get_telemetry_saved_object.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/get_telemetry_saved_object.ts @@ -17,15 +17,15 @@ * under the License. */ -import { TelemetrySavedObjectAttributes } from '../routes/telemetry_config'; +import { TelemetrySavedObjectAttributes } from './'; import { SavedObjectsErrorHelpers } from '../../../../../core/server'; export type TelemetrySavedObject = TelemetrySavedObjectAttributes | null | false; -type GetTelemetrySavedObject = (savedObjectsClient: any) => Promise; +type GetTelemetrySavedObject = (repository: any) => Promise; -export const getTelemetrySavedObject: GetTelemetrySavedObject = async (savedObjectsClient: any) => { +export const getTelemetrySavedObject: GetTelemetrySavedObject = async (repository: any) => { try { - const { attributes } = await savedObjectsClient.get('telemetry', 'telemetry'); + const { attributes } = await repository.get('telemetry', 'telemetry'); return attributes; } catch (error) { if (SavedObjectsErrorHelpers.isNotFoundError(error)) { diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts new file mode 100644 index 00000000000000..2b891d405bf8bf --- /dev/null +++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts @@ -0,0 +1,28 @@ +/* + * 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 { getTelemetrySavedObject } from './get_telemetry_saved_object'; +export { updateTelemetrySavedObject } from './update_telemetry_saved_object'; + +export interface TelemetrySavedObjectAttributes { + enabled?: boolean | null; + lastVersionChecked?: string; + usageFetcher?: 'browser' | 'server'; + lastReported?: number; +} diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts new file mode 100644 index 00000000000000..b66e01faaa6bc7 --- /dev/null +++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts @@ -0,0 +1,38 @@ +/* + * 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 { TelemetrySavedObjectAttributes } from './'; +import { SavedObjectsErrorHelpers } from '../../../../../core/server'; + +export async function updateTelemetrySavedObject( + savedObjectsClient: any, + savedObjectAttributes: TelemetrySavedObjectAttributes +) { + try { + return await savedObjectsClient.update('telemetry', 'telemetry', savedObjectAttributes); + } catch (err) { + if (SavedObjectsErrorHelpers.isNotFoundError(err)) { + return await savedObjectsClient.create('telemetry', savedObjectAttributes, { + id: 'telemetry', + overwrite: true, + }); + } + throw err; + } +} From df1f45f8ec8ec4d72705c4e764c8ae7a9fd8acd3 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 6 Nov 2019 17:21:25 +0200 Subject: [PATCH 07/46] remove extra unused method --- packages/kbn-analytics/src/reporter.ts | 10 ++++++++-- .../ui_metric/public/services/telemetry_analytics.ts | 6 ------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/kbn-analytics/src/reporter.ts b/packages/kbn-analytics/src/reporter.ts index 970887021ffeb1..ca1d04c44cc3b3 100644 --- a/packages/kbn-analytics/src/reporter.ts +++ b/packages/kbn-analytics/src/reporter.ts @@ -18,7 +18,13 @@ */ import { wrapArray } from './util'; -import { Metric, UiStatsMetric, createUiStatsMetric, trackUsageAgent } from './metrics'; +import { + Metric, + UiStatsMetric, + createUiStatsMetric, + trackUsageAgent, + UiStatsMetricType, +} from './metrics'; import { Storage, ReportStorageManager } from './storage'; import { Report, ReportManager } from './report'; @@ -82,7 +88,7 @@ export class Reporter { public reportUiStats = ( appName: string, - type: UiStatsMetric['type'], + type: UiStatsMetricType, eventNames: string | string[], count?: number ) => { diff --git a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts index d456a4949a29de..7b6801b5a87c1e 100644 --- a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts +++ b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts @@ -48,12 +48,6 @@ export const trackUserAgent = (appName: string) => { } }; -export const createUiMetricReporter = (appName: string) => (type: UiStatsMetricType): void => { - if (telemetryReporter) { - return telemetryReporter.reportUiStats(appName, type, eventNames, count); - } -}; - interface AnalyicsReporterConfig { localStorage: any; debug: boolean; From dae375add7097becb8bf95fdb8e1b5be9420fa92 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 6 Nov 2019 17:22:58 +0200 Subject: [PATCH 08/46] remove unused import --- packages/kbn-analytics/src/reporter.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/kbn-analytics/src/reporter.ts b/packages/kbn-analytics/src/reporter.ts index ca1d04c44cc3b3..dc1d27edd0cb30 100644 --- a/packages/kbn-analytics/src/reporter.ts +++ b/packages/kbn-analytics/src/reporter.ts @@ -18,13 +18,7 @@ */ import { wrapArray } from './util'; -import { - Metric, - UiStatsMetric, - createUiStatsMetric, - trackUsageAgent, - UiStatsMetricType, -} from './metrics'; +import { Metric, createUiStatsMetric, trackUsageAgent, UiStatsMetricType } from './metrics'; import { Storage, ReportStorageManager } from './storage'; import { Report, ReportManager } from './report'; From 01cfc2666300a86896015cfa4580e31110bb5dd8 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 6 Nov 2019 17:33:34 +0200 Subject: [PATCH 09/46] type check --- src/legacy/core_plugins/ui_metric/public/index.ts | 2 +- .../legacy/plugins/infra/public/hooks/use_track_metric.tsx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/ui_metric/public/index.ts b/src/legacy/core_plugins/ui_metric/public/index.ts index 6e6bf9ea25facb..5c327234b1e7cd 100644 --- a/src/legacy/core_plugins/ui_metric/public/index.ts +++ b/src/legacy/core_plugins/ui_metric/public/index.ts @@ -18,4 +18,4 @@ */ export { createUiStatsReporter, trackUserAgent } from './services/telemetry_analytics'; -export { METRIC_TYPE } from '@kbn/analytics'; +export { METRIC_TYPE, UiStatsMetricType } from '@kbn/analytics'; diff --git a/x-pack/legacy/plugins/infra/public/hooks/use_track_metric.tsx b/x-pack/legacy/plugins/infra/public/hooks/use_track_metric.tsx index 4d9ca3704873cb..379b3af3f10637 100644 --- a/x-pack/legacy/plugins/infra/public/hooks/use_track_metric.tsx +++ b/x-pack/legacy/plugins/infra/public/hooks/use_track_metric.tsx @@ -7,6 +7,7 @@ import { useEffect } from 'react'; import { createUiStatsReporter, + UiStatsMetricType, METRIC_TYPE, } from '../../../../../../src/legacy/core_plugins/ui_metric/public'; @@ -36,7 +37,7 @@ function getTrackerForApp(app: string) { interface TrackOptions { app: ObservabilityApp; - metricType?: METRIC_TYPE; + metricType?: UiStatsMetricType; delay?: number; // in ms } type EffectDeps = unknown[]; @@ -76,7 +77,7 @@ export function useTrackPageview( interface TrackEventProps { app: ObservabilityApp; name: string; - metricType?: METRIC_TYPE; + metricType?: UiStatsMetricType; } export function trackEvent({ app, name, metricType = METRIC_TYPE.CLICK }: TrackEventProps) { From b58d0295de27415c9b1bb96f08b35034de33320f Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 6 Nov 2019 22:30:37 +0200 Subject: [PATCH 10/46] fix collections tests --- .../__tests__/get_local_stats.js | 57 ++++--------------- .../telemetry_collection/get_local_stats.js | 6 +- .../__tests__/get_all_stats.js | 28 ++------- .../telemetry_collection/get_all_stats.js | 15 +---- 4 files changed, 18 insertions(+), 88 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js b/src/legacy/core_plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js index d0de9cc365a712..261012e594b1c0 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js +++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js @@ -26,7 +26,6 @@ import { mockGetClusterStats } from './get_cluster_stats'; import { omit } from 'lodash'; import { getLocalStats, - getLocalStatsWithCaller, handleLocalStats, } from '../get_local_stats'; @@ -153,7 +152,7 @@ describe('get_local_stats', () => { }); }); - describe('getLocalStatsWithCaller', () => { + describe('getLocalStats', () => { it('returns expected object without xpack data when X-Pack fails to respond', async () => { const callClusterUsageFailed = sinon.stub(); @@ -162,8 +161,10 @@ describe('get_local_stats', () => { Promise.resolve(clusterInfo), Promise.resolve(clusterStats), ); - - const result = await getLocalStatsWithCaller(getMockServer(), callClusterUsageFailed); + const result = await getLocalStats({ + server: getMockServer(), + callCluster: callClusterUsageFailed, + }); expect(result.cluster_uuid).to.eql(combinedStatsResult.cluster_uuid); expect(result.cluster_name).to.eql(combinedStatsResult.cluster_name); expect(result.cluster_stats).to.eql(combinedStatsResult.cluster_stats); @@ -184,51 +185,13 @@ describe('get_local_stats', () => { Promise.resolve(clusterStats), ); - const result = await getLocalStatsWithCaller(getMockServer(callCluster, kibana), callCluster); + const result = await getLocalStats({ + server: getMockServer(callCluster, kibana), + callCluster, + }); + expect(result.stack_stats.xpack).to.eql(combinedStatsResult.stack_stats.xpack); expect(result.stack_stats.kibana).to.eql(combinedStatsResult.stack_stats.kibana); }); }); - - describe('getLocalStats', () => { - it('uses callWithInternalUser from data cluster', async () => { - const getCluster = sinon.stub(); - const req = { server: getMockServer(getCluster) }; - const callWithInternalUser = sinon.stub(); - - getCluster.withArgs('data').returns({ callWithInternalUser }); - - mockGetLocalStats( - callWithInternalUser, - Promise.resolve(clusterInfo), - Promise.resolve(clusterStats), - ); - - const result = await getLocalStats(req, { useInternalUser: true }); - expect(result.cluster_uuid).to.eql(combinedStatsResult.cluster_uuid); - expect(result.cluster_name).to.eql(combinedStatsResult.cluster_name); - expect(result.version).to.eql(combinedStatsResult.version); - expect(result.cluster_stats).to.eql(combinedStatsResult.cluster_stats); - }); - it('uses callWithRequest from data cluster', async () => { - const getCluster = sinon.stub(); - const req = { server: getMockServer(getCluster) }; - const callWithRequest = sinon.stub(); - - getCluster.withArgs('data').returns({ callWithRequest }); - - mockGetLocalStats( - callWithRequest, - Promise.resolve(clusterInfo), - Promise.resolve(clusterStats), - req - ); - - const result = await getLocalStats(req, { useInternalUser: false }); - expect(result.cluster_uuid).to.eql(combinedStatsResult.cluster_uuid); - expect(result.cluster_name).to.eql(combinedStatsResult.cluster_name); - expect(result.version).to.eql(combinedStatsResult.version); - expect(result.cluster_stats).to.eql(combinedStatsResult.cluster_stats); - }); - }); }); diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js index e34e940c581338..6125dadc3646f4 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js +++ b/src/legacy/core_plugins/telemetry/server/telemetry_collection/get_local_stats.js @@ -51,7 +51,7 @@ export function handleLocalStats(server, clusterInfo, clusterStats, kibana) { * @param {function} callCluster The callWithInternalUser handler (exposed for testing) * @return {Promise} The object containing the current Elasticsearch cluster's telemetry. */ -export async function getLocalStatsWithCaller(server, callCluster) { +export async function getLocalStats({ server, callCluster }) { const [ clusterInfo, clusterStats, kibana ] = await Promise.all([ getClusterInfo(callCluster), // cluster info getClusterStats(callCluster), // cluster stats (not to be confused with cluster _state_) @@ -60,7 +60,3 @@ export async function getLocalStatsWithCaller(server, callCluster) { return handleLocalStats(server, clusterInfo, clusterStats, kibana); } - -export async function getLocalStats({ server, callCluster }) { - return await getLocalStatsWithCaller(server, callCluster); -} diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_all_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_all_stats.js index 0d147b747f2d04..c1425de20d1465 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_all_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_all_stats.js @@ -12,8 +12,7 @@ describe('get_all_stats', () => { const size = 123; const start = 0; const end = 1; - const callWithRequest = sinon.stub(); - const callWithInternalUser = sinon.stub(); + const callCluster = sinon.stub(); const server = { config: sinon.stub().returns({ get: sinon.stub().withArgs('xpack.monitoring.elasticsearch.index_pattern').returns('.monitoring-es-N-*') @@ -21,16 +20,8 @@ describe('get_all_stats', () => { .withArgs('xpack.monitoring.logstash.index_pattern').returns('.monitoring-logstash-N-*') .withArgs('xpack.monitoring.max_bucket_size').returns(size) }), - plugins: { - elasticsearch: { - getCluster: sinon.stub().withArgs('monitoring').returns({ - callWithInternalUser, - callWithRequest - }) - } - } }; - const req = { server }; + const esClusters = [ { cluster_uuid: 'a' }, { cluster_uuid: 'b', random_setting_not_removed: false }, @@ -188,19 +179,13 @@ describe('get_all_stats', () => { } ]; - callWithRequest.withArgs(req, 'search') - .onCall(0).returns(Promise.resolve(clusterUuidsResponse)) - .onCall(1).returns(Promise.resolve(esStatsResponse)) - .onCall(2).returns(Promise.resolve(kibanaStatsResponse)) - .onCall(3).returns(Promise.resolve(logstashStatsResponse)); - - callWithInternalUser.withArgs('search') + callCluster.withArgs('search') .onCall(0).returns(Promise.resolve(clusterUuidsResponse)) .onCall(1).returns(Promise.resolve(esStatsResponse)) .onCall(2).returns(Promise.resolve(kibanaStatsResponse)) .onCall(3).returns(Promise.resolve(logstashStatsResponse)); - expect(await getAllStats(req, start, end)).to.eql(allClusters); + expect(await getAllStats({ callCluster, server, start, end })).to.eql(allClusters); }); it('returns empty clusters', async () => { @@ -208,10 +193,9 @@ describe('get_all_stats', () => { aggregations: { cluster_uuids: { buckets: [ ] } } }; - callWithRequest.withArgs(req, 'search').returns(Promise.resolve(clusterUuidsResponse)); - callWithInternalUser.withArgs('search').returns(Promise.resolve(clusterUuidsResponse)); + callCluster.withArgs('search').returns(Promise.resolve(clusterUuidsResponse)); - expect(await getAllStats(req, start, end)).to.eql([]); + expect(await getAllStats({ callCluster, server, start, end })).to.eql([]); }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js index 69d34859edec61..ce33068725d9ce 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js @@ -17,19 +17,6 @@ import { getKibanaStats } from './get_kibana_stats'; import { getBeatsStats } from './get_beats_stats'; import { getHighLevelStats } from './get_high_level_stats'; - -/** - * Get statistics for all products joined by Elasticsearch cluster. - * - * @param {Object} req The incoming request - * @param {Date} start The starting range to request data - * @param {Date} end The ending range to request data - * @return {Promise} The array of clusters joined with the Kibana and Logstash instances. - */ -export function getAllStats({ server, callCluster, start, end } = {}) { - return getAllStatsWithCaller(server, callCluster, start, end); -} - /** * Get statistics for all products joined by Elasticsearch cluster. * @@ -39,7 +26,7 @@ export function getAllStats({ server, callCluster, start, end } = {}) { * @param {Date} end The ending range to request data * @return {Promise} The array of clusters joined with the Kibana and Logstash instances. */ -function getAllStatsWithCaller(server, callCluster, start, end) { +export function getAllStats({ server, callCluster, start, end } = {}) { return getClusterUuids(server, callCluster, start, end) .then(clusterUuids => { // don't bother doing a further lookup From 16c8e1ddac25151d0f6f4547591019fc04f67695 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 6 Nov 2019 23:37:22 +0200 Subject: [PATCH 11/46] pass kfetch as dep --- .../core_plugins/ui_metric/public/hacks/ui_metric_init.ts | 4 +++- .../ui_metric/public/services/telemetry_analytics.ts | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts index 8d6df48181b2e5..9b0364fe9ce1dc 100644 --- a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts +++ b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts @@ -20,6 +20,7 @@ // @ts-ignore import { uiModules } from 'ui/modules'; import chrome from 'ui/chrome'; +import { kfetch } from 'ui/kfetch'; import { createAnalyticsReporter, setTelemetryReporter, @@ -29,7 +30,8 @@ import { function telemetryInit($injector: any) { const localStorage = $injector.get('localStorage'); const debug = chrome.getInjected('debugUiMetric'); - const uiReporter = createAnalyticsReporter({ localStorage, debug }); + + const uiReporter = createAnalyticsReporter({ localStorage, debug, kfetch }); setTelemetryReporter(uiReporter); trackUserAgent('kibana'); } diff --git a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts index 7b6801b5a87c1e..7ba0706f171195 100644 --- a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts +++ b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts @@ -18,7 +18,6 @@ */ import { createReporter, Reporter, UiStatsMetricType } from '@kbn/analytics'; -import { kfetch } from 'ui/kfetch'; // @ts-ignore import { addSystemApiHeader } from 'ui/system_api'; @@ -51,10 +50,11 @@ export const trackUserAgent = (appName: string) => { interface AnalyicsReporterConfig { localStorage: any; debug: boolean; + kfetch: any; } export function createAnalyticsReporter(config: AnalyicsReporterConfig) { - const { localStorage, debug } = config; + const { localStorage, debug, kfetch } = config; return createReporter({ debug, From 873640fd03a452af9ae2afac2d0e0f138aa0b3c9 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 06:17:17 +0200 Subject: [PATCH 12/46] add ui metrics integration test for user agent --- .../apis/ui_metric/ui_metric.js | 69 +++++++++++++++---- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/test/api_integration/apis/ui_metric/ui_metric.js b/test/api_integration/apis/ui_metric/ui_metric.js index efa6be47b50c9b..111fec0e44095c 100644 --- a/test/api_integration/apis/ui_metric/ui_metric.js +++ b/test/api_integration/apis/ui_metric/ui_metric.js @@ -18,33 +18,41 @@ */ import expect from '@kbn/expect'; -import { ReportManager } from '@kbn/analytics'; +import { ReportManager, METRIC_TYPE } from '@kbn/analytics'; export default function ({ getService }) { const supertest = getService('supertest'); const es = getService('es'); - const createMetric = (eventName) => ({ - key: ReportManager.createMetricKey({ appName: 'myApp', type: 'click', eventName }), + const createStatsMetric = (eventName) => ({ + key: ReportManager.createMetricKey({ appName: 'myApp', type: METRIC_TYPE.CLICK, eventName }), eventName, appName: 'myApp', - type: 'click', + type: METRIC_TYPE.CLICK, stats: { sum: 1, avg: 1, min: 1, max: 1 }, }); + const createUserAgentMetric = (appName) => ({ + key: ReportManager.createMetricKey({ appName, type: METRIC_TYPE.USER_AGENT }), + appName, + type: METRIC_TYPE.USER_AGENT, + userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36', + }); + describe('ui_metric API', () => { - const uiStatsMetric = createMetric('myEvent'); - const report = { - uiStatsMetrics: { - [uiStatsMetric.key]: uiStatsMetric, - } - }; + it('increments the count field in the document defined by the {app}/{action_type} path', async () => { + const uiStatsMetric = createStatsMetric('myEvent'); + const report = { + uiStatsMetrics: { + [uiStatsMetric.key]: uiStatsMetric, + } + }; await supertest .post('/api/telemetry/report') .set('kbn-xsrf', 'kibana') .set('content-type', 'application/json') - .send({ report }) + .send(report) .expect(200); return es.search({ @@ -57,8 +65,40 @@ export default function ({ getService }) { }); it('supports multiple events', async () => { - const uiStatsMetric1 = createMetric('myEvent1'); - const uiStatsMetric2 = createMetric('myEvent2'); + const userAgentMetric = createUserAgentMetric('kibana'); + const uiStatsMetric1 = createStatsMetric('myEvent1'); + const uiStatsMetric2 = createStatsMetric('myEvent2'); + const report = { + userAgent: { + [userAgentMetric.key]: userAgentMetric, + }, + uiStatsMetrics: { + [uiStatsMetric1.key]: uiStatsMetric1, + [uiStatsMetric2.key]: uiStatsMetric2, + } + }; + await supertest + .post('/api/telemetry/report') + .set('kbn-xsrf', 'kibana') + .set('content-type', 'application/json') + .send(report) + .expect(200); + + + const response = await es.search({ + index: '.kibana', + q: 'type:user-action', + }); + + const ids = response.hits.hits.map(({ _id }) => _id); + expect(ids.includes('user-action:myApp:myEvent1')); + expect(ids.includes('user-action:myApp:myEvent2')); + expect(ids.includes(`user-action:kibana-user_agent:${userAgentMetric.userAgent}`)); + }); + + it('supports multiple events', async () => { + const uiStatsMetric1 = createStatsMetric('myEvent1'); + const uiStatsMetric2 = createStatsMetric('myEvent2'); const report = { uiStatsMetrics: { [uiStatsMetric1.key]: uiStatsMetric1, @@ -69,7 +109,7 @@ export default function ({ getService }) { .post('/api/telemetry/report') .set('kbn-xsrf', 'kibana') .set('content-type', 'application/json') - .send({ report }) + .send(report) .expect(200); return es.search({ @@ -81,6 +121,7 @@ export default function ({ getService }) { expect(ids.includes('user-action:myApp:myEvent2')); }); }); + }); } From c1926acdf0e6e463d70eac2dbe78196d52e57709 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 07:20:10 +0200 Subject: [PATCH 13/46] dont start ui metrics when not authenticated --- packages/kbn-analytics/src/index.ts | 2 +- packages/kbn-analytics/src/reporter.ts | 6 ------ .../core_plugins/ui_metric/public/hacks/ui_metric_init.ts | 5 +++++ .../ui_metric/public/services/telemetry_analytics.ts | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/kbn-analytics/src/index.ts b/packages/kbn-analytics/src/index.ts index 63fd115fa75945..6514347b0b1272 100644 --- a/packages/kbn-analytics/src/index.ts +++ b/packages/kbn-analytics/src/index.ts @@ -17,6 +17,6 @@ * under the License. */ -export { createReporter, ReportHTTP, Reporter, ReporterConfig } from './reporter'; +export { ReportHTTP, Reporter, ReporterConfig } from './reporter'; export { UiStatsMetricType, METRIC_TYPE } from './metrics'; export { Report, ReportManager } from './report'; diff --git a/packages/kbn-analytics/src/reporter.ts b/packages/kbn-analytics/src/reporter.ts index dc1d27edd0cb30..21bc8652009c60 100644 --- a/packages/kbn-analytics/src/reporter.ts +++ b/packages/kbn-analytics/src/reporter.ts @@ -122,9 +122,3 @@ export class Reporter { this.start(); }; } - -export function createReporter(reportedConf: ReporterConfig) { - const reporter = new Reporter(reportedConf); - reporter.start(); - return reporter; -} diff --git a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts index 9b0364fe9ce1dc..1447f539bf024e 100644 --- a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts +++ b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts @@ -26,6 +26,7 @@ import { setTelemetryReporter, trackUserAgent, } from '../services/telemetry_analytics'; +import { isUnauthenticated } from '../../../telemetry/public/services'; function telemetryInit($injector: any) { const localStorage = $injector.get('localStorage'); @@ -34,6 +35,10 @@ function telemetryInit($injector: any) { const uiReporter = createAnalyticsReporter({ localStorage, debug, kfetch }); setTelemetryReporter(uiReporter); trackUserAgent('kibana'); + if (isUnauthenticated()) { + return; + } + uiReporter.start(); } uiModules.get('kibana').run(telemetryInit); diff --git a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts index 7ba0706f171195..f06503bba4fe81 100644 --- a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts +++ b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts @@ -17,7 +17,7 @@ * under the License. */ -import { createReporter, Reporter, UiStatsMetricType } from '@kbn/analytics'; +import { Reporter, UiStatsMetricType } from '@kbn/analytics'; // @ts-ignore import { addSystemApiHeader } from 'ui/system_api'; @@ -56,7 +56,7 @@ interface AnalyicsReporterConfig { export function createAnalyticsReporter(config: AnalyicsReporterConfig) { const { localStorage, debug, kfetch } = config; - return createReporter({ + return new Reporter({ debug, storage: localStorage, async http(report) { From 5a62e7d4c0b3dee36a2509633a158b5a9df50c3f Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 07:27:31 +0200 Subject: [PATCH 14/46] user agent count always 1 --- .../core_plugins/ui_metric/server/routes/api/ui_metric.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts index b2e7d0654f8364..717b720a47872c 100644 --- a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts +++ b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts @@ -33,12 +33,14 @@ export async function storeReport(server: any, report: Report) { ...userAgents.map(async ([key, metric]) => { const { userAgent } = metric; const savedObjectId = `${key}:${userAgent}`; - return internalRepository.incrementCounter('ui-metric', savedObjectId, 'count'); + return await internalRepository.update('ui-metric', savedObjectId, { + count: 1, + }); }), ...uiStatsMetrics.map(async ([key, metric]) => { const { appName, eventName } = metric; const savedObjectId = `${appName}:${eventName}`; - return internalRepository.incrementCounter('ui-metric', savedObjectId, 'count'); + return await internalRepository.update('ui-metric', savedObjectId, 'count'); }), ]); } From 64056ea8c492304d4ca6ef16946e0d0185b46e3a Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 11:16:54 +0200 Subject: [PATCH 15/46] fix broken ui-metric integration tests --- .../update_telemetry_saved_object.ts | 6 +- .../ui_metric/server/routes/api/ui_metric.ts | 13 +++-- .../apis/ui_metric/ui_metric.js | 57 ++++--------------- 3 files changed, 26 insertions(+), 50 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts index b66e01faaa6bc7..83d9a368f95be2 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts @@ -28,7 +28,11 @@ export async function updateTelemetrySavedObject( return await savedObjectsClient.update('telemetry', 'telemetry', savedObjectAttributes); } catch (err) { if (SavedObjectsErrorHelpers.isNotFoundError(err)) { - return await savedObjectsClient.create('telemetry', savedObjectAttributes, { + const savedObjectAttributesWithDefaults = { + enabled: null, + ...savedObjectAttributes, + }; + return await savedObjectsClient.create('telemetry', savedObjectAttributesWithDefaults, { id: 'telemetry', overwrite: true, }); diff --git a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts index 717b720a47872c..3c822ca9321f56 100644 --- a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts +++ b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts @@ -33,14 +33,19 @@ export async function storeReport(server: any, report: Report) { ...userAgents.map(async ([key, metric]) => { const { userAgent } = metric; const savedObjectId = `${key}:${userAgent}`; - return await internalRepository.update('ui-metric', savedObjectId, { - count: 1, - }); + return await internalRepository.create( + 'ui-metric', + { count: 1 }, + { + id: savedObjectId, + overwrite: true, + } + ); }), ...uiStatsMetrics.map(async ([key, metric]) => { const { appName, eventName } = metric; const savedObjectId = `${appName}:${eventName}`; - return await internalRepository.update('ui-metric', savedObjectId, 'count'); + return await internalRepository.incrementCounter('ui-metric', savedObjectId, 'count'); }), ]); } diff --git a/test/api_integration/apis/ui_metric/ui_metric.js b/test/api_integration/apis/ui_metric/ui_metric.js index 111fec0e44095c..f0c86f2904638c 100644 --- a/test/api_integration/apis/ui_metric/ui_metric.js +++ b/test/api_integration/apis/ui_metric/ui_metric.js @@ -55,19 +55,18 @@ export default function ({ getService }) { .send(report) .expect(200); - return es.search({ - index: '.kibana', - q: 'type:user-action', - }).then(response => { - const ids = response.hits.hits.map(({ _id }) => _id); - expect(ids.includes('user-action:myApp:myEvent')); - }); + const response = await es.search({ index: '.kibana', q: 'type:ui-metric' }); + const ids = response.hits.hits.map(({ _id }) => _id); + expect(ids.includes('ui-metric:myApp:myEvent')).to.eql(true); }); it('supports multiple events', async () => { const userAgentMetric = createUserAgentMetric('kibana'); - const uiStatsMetric1 = createStatsMetric('myEvent1'); - const uiStatsMetric2 = createStatsMetric('myEvent2'); + const uiStatsMetric1 = createStatsMetric('myEvent'); + const hrTime = process.hrtime(); + const nano = hrTime[0] * 1000000000 + hrTime[1]; + const uniqueEventName = `myEvent${nano}`; + const uiStatsMetric2 = createStatsMetric(uniqueEventName); const report = { userAgent: { [userAgentMetric.key]: userAgentMetric, @@ -84,44 +83,12 @@ export default function ({ getService }) { .send(report) .expect(200); - - const response = await es.search({ - index: '.kibana', - q: 'type:user-action', - }); - + const response = await es.search({ index: '.kibana', q: 'type:ui-metric' }); const ids = response.hits.hits.map(({ _id }) => _id); - expect(ids.includes('user-action:myApp:myEvent1')); - expect(ids.includes('user-action:myApp:myEvent2')); - expect(ids.includes(`user-action:kibana-user_agent:${userAgentMetric.userAgent}`)); - }); - - it('supports multiple events', async () => { - const uiStatsMetric1 = createStatsMetric('myEvent1'); - const uiStatsMetric2 = createStatsMetric('myEvent2'); - const report = { - uiStatsMetrics: { - [uiStatsMetric1.key]: uiStatsMetric1, - [uiStatsMetric2.key]: uiStatsMetric2, - } - }; - await supertest - .post('/api/telemetry/report') - .set('kbn-xsrf', 'kibana') - .set('content-type', 'application/json') - .send(report) - .expect(200); - - return es.search({ - index: '.kibana', - q: 'type:user-action', - }).then(response => { - const ids = response.hits.hits.map(({ _id }) => _id); - expect(ids.includes('user-action:myApp:myEvent1')); - expect(ids.includes('user-action:myApp:myEvent2')); - }); + expect(ids.includes('ui-metric:myApp:myEvent')).to.eql(true); + expect(ids.includes(`ui-metric:myApp:${uniqueEventName}`)).to.eql(true); + expect(ids.includes(`ui-metric:kibana-user_agent:${userAgentMetric.userAgent}`)).to.eql(true); }); - }); } From e51c642d9642b2f41d782ff82db118f6f3808068 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 12:34:13 +0200 Subject: [PATCH 16/46] try using config.get --- src/legacy/core_plugins/telemetry/index.ts | 10 +++------- .../core_plugins/telemetry/server/fetcher.ts | 15 ++++++++------- .../get_telemetry_usage_fetcher.test.ts | 10 ++-------- .../get_telemetry_usage_fetcher.ts | 9 ++++----- .../telemetry_config/replace_injected_vars.ts | 10 +++------- 5 files changed, 20 insertions(+), 34 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index 51d1f6d7549d88..5f8ff25a625c46 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -83,15 +83,11 @@ const telemetry = (kibana: any) => { async replaceInjectedVars(originalInjectedVars: any, request: any) { const currentKibanaVersion = getCurrentKibanaVersion(request.server); const telemetryInjectedVars = await replaceTelemetryInjectedVars( - originalInjectedVars, request, currentKibanaVersion ); - return { - ...originalInjectedVars, - ...telemetryInjectedVars, - }; + return Object.assign(originalInjectedVars, telemetryInjectedVars); }, injectDefaultVars(server: Server) { const config = server.config(); @@ -106,7 +102,7 @@ const telemetry = (kibana: any) => { hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'], mappings, }, - init(server: Server, pluginConfig: any) { + init(server: Server) { const initializerContext = { env: { packageInfo: { @@ -121,7 +117,7 @@ const telemetry = (kibana: any) => { } as any) as CoreSetup; telemetryPlugin(initializerContext).setup(coreSetup); - const fetcherTask = new FetcherTask(server, pluginConfig); + const fetcherTask = new FetcherTask(server); fetcherTask.start(); // register collectors diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts index 0521721a4dffed..49cd725375e7c8 100644 --- a/src/legacy/core_plugins/telemetry/server/fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -24,18 +24,17 @@ import { telemetryCollectionManager } from './collection_manager'; import { getTelemetryOptIn, getTelemetryUsageFetcher } from './telemetry_config'; import { getTelemetrySavedObject, updateTelemetrySavedObject } from './telemetry_repository'; import { REPORT_INTERVAL_MS } from '../common/constants'; +import { getXpackConfigWithDeprecated } from '../common/get_xpack_config_with_deprecated'; export class FetcherTask { private readonly checkDuration = 60000; private intervalId?: NodeJS.Timeout; private lastReported?: number; private isSending = false; - private telemetryPluginConfig: any; private server: any; - constructor(server: any, telemetryPluginConfig: any) { + constructor(server: any) { this.server = server; - this.telemetryPluginConfig = telemetryPluginConfig; } private getInternalRepository = () => { @@ -48,16 +47,18 @@ export class FetcherTask { private getCurrentConfigs = async () => { const internalRepository = this.getInternalRepository(); const telemetrySavedObject = await getTelemetrySavedObject(internalRepository); - const telemetryPluginConfig = this.telemetryPluginConfig; - const currentKibanaVersion = ''; + const config = this.server.config(); + const currentKibanaVersion = config.get('pkg.version'); + const defaultTelemetryUsageFetcher = config.get('telemetry.usageFetcher'); + const telemetryUrl = getXpackConfigWithDeprecated(config, 'telemetry.url'); return { telemetryOptIn: getTelemetryOptIn({ currentKibanaVersion, telemetrySavedObject }), telemetryUsageFetcher: getTelemetryUsageFetcher({ telemetrySavedObject, - telemetryPluginConfig, + defaultTelemetryUsageFetcher, }), - telemetryUrl: telemetryPluginConfig.url, + telemetryUrl, }; }; diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts index fb7dddeb750b52..fcf90fabeca6db 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts @@ -64,14 +64,8 @@ interface CallGetTelemetryUsageFetcherParams { function callGetTelemetryUsageFetcher(params: CallGetTelemetryUsageFetcherParams) { const telemetrySavedObject = getMockTelemetrySavedObject(params); - const telemetryPluginConfig = getMockTelemetryPluginConfig(params); - return getTelemetryUsageFetcher({ telemetryPluginConfig, telemetrySavedObject }); -} - -function getMockTelemetryPluginConfig(params: CallGetTelemetryUsageFetcherParams) { - return { - telemetryUsageFetcher: params.configUsageFetcher, - }; + const defaultTelemetryUsageFetcher = params.configUsageFetcher; + return getTelemetryUsageFetcher({ defaultTelemetryUsageFetcher, telemetrySavedObject }); } function getMockTelemetrySavedObject( diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts index 2368ba321f3e27..435403c0675ca9 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts @@ -19,21 +19,20 @@ import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object'; interface GetTelemetryUsageFetcherConfig { - telemetryPluginConfig: any; + defaultTelemetryUsageFetcher: 'browser' | 'server'; telemetrySavedObject: TelemetrySavedObject; } export function getTelemetryUsageFetcher({ telemetrySavedObject, - telemetryPluginConfig, + defaultTelemetryUsageFetcher, }: GetTelemetryUsageFetcherConfig) { - const { telemetryUsageFetcher } = telemetryPluginConfig; if (!telemetrySavedObject) { - return telemetryUsageFetcher; + return defaultTelemetryUsageFetcher; } if (typeof telemetrySavedObject.usageFetcher === 'undefined') { - return telemetryUsageFetcher; + return defaultTelemetryUsageFetcher; } return telemetrySavedObject.usageFetcher; diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts index 5351f757b47ee0..4d149802ebc786 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts @@ -21,11 +21,7 @@ import { getTelemetrySavedObject } from '../telemetry_repository'; import { getTelemetryOptIn } from './get_telemetry_opt_in'; import { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher'; -export async function replaceTelemetryInjectedVars( - telemetryPluginConfig: any, - request: any, - currentKibanaVersion: string -) { +export async function replaceTelemetryInjectedVars(request: any, currentKibanaVersion: string) { const savedObjectsClient = request.getSavedObjectsClient(); const telemetrySavedObject = await getTelemetrySavedObject(savedObjectsClient); const telemetryOptedIn = getTelemetryOptIn({ @@ -33,10 +29,10 @@ export async function replaceTelemetryInjectedVars( request, currentKibanaVersion, }); - + const defaultTelemetryUsageFetcher = request.server.config().get('telemetry.usageFetcher'); const telemetryUsageFetcher = getTelemetryUsageFetcher({ telemetrySavedObject, - telemetryPluginConfig, + defaultTelemetryUsageFetcher, }); return { From f648bb98644a923a214b1a5d055d8ec09c6f1db4 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 12:36:04 +0200 Subject: [PATCH 17/46] avoid fetching configs if sending --- src/legacy/core_plugins/telemetry/server/fetcher.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts index 49cd725375e7c8..c5c8715d39c810 100644 --- a/src/legacy/core_plugins/telemetry/server/fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -104,9 +104,12 @@ export class FetcherTask { }; private sendIfDue = async () => { + if (this.isSending) { + return; + } try { const telemetryConfig = await this.getCurrentConfigs(); - if (this.isSending || !this.checkReportStatus(telemetryConfig)) { + if (!this.checkReportStatus(telemetryConfig)) { return; } From e394a789956af39d1a7157592831ef977ef3603f Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 13:32:21 +0200 Subject: [PATCH 18/46] type unknown -> string --- src/legacy/core_plugins/telemetry/server/fetcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts index c5c8715d39c810..6a5dce242d6575 100644 --- a/src/legacy/core_plugins/telemetry/server/fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -50,7 +50,7 @@ export class FetcherTask { const config = this.server.config(); const currentKibanaVersion = config.get('pkg.version'); const defaultTelemetryUsageFetcher = config.get('telemetry.usageFetcher'); - const telemetryUrl = getXpackConfigWithDeprecated(config, 'telemetry.url'); + const telemetryUrl = getXpackConfigWithDeprecated(config, 'telemetry.url') as string; return { telemetryOptIn: getTelemetryOptIn({ currentKibanaVersion, telemetrySavedObject }), From 5818d94d04e0efa5417805ba7b8e120e435e6b15 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 13:38:50 +0200 Subject: [PATCH 19/46] check if fetcher is causing the issue --- .../os_packages/docker_generator/resources/bin/kibana-docker | 1 + src/legacy/core_plugins/telemetry/index.ts | 2 +- src/legacy/core_plugins/telemetry/server/fetcher.ts | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker index 0926ef365c894c..61d8300bf6a724 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker @@ -181,6 +181,7 @@ kibana_vars=( xpack.security.secureCookies xpack.security.sessionTimeout telemetry.enabled + telemetry.usageFetcher ) longopts='' diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index 5f8ff25a625c46..a1d72b007a2921 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -118,7 +118,7 @@ const telemetry = (kibana: any) => { telemetryPlugin(initializerContext).setup(coreSetup); const fetcherTask = new FetcherTask(server); - fetcherTask.start(); + fetcherTask.stop(); // register collectors server.usage.collectorSet.register(createTelemetryPluginUsageCollector(server)); diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts index 6a5dce242d6575..24d9adaba01b4e 100644 --- a/src/legacy/core_plugins/telemetry/server/fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -27,7 +27,7 @@ import { REPORT_INTERVAL_MS } from '../common/constants'; import { getXpackConfigWithDeprecated } from '../common/get_xpack_config_with_deprecated'; export class FetcherTask { - private readonly checkDuration = 60000; + private readonly checkDurationMs = 60 * 1000 * 5; private intervalId?: NodeJS.Timeout; private lastReported?: number; private isSending = false; @@ -131,7 +131,7 @@ export class FetcherTask { }; public start = () => { - this.intervalId = setInterval(() => this.sendIfDue(), this.checkDuration); + this.intervalId = setInterval(() => this.sendIfDue(), this.checkDurationMs); }; public stop = () => { if (this.intervalId) { From 120b83299794e01f935312516befd4da8523c34e Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 14:22:47 +0200 Subject: [PATCH 20/46] disable ui_metric from functional tests --- src/legacy/core_plugins/telemetry/index.ts | 16 +++------------- .../telemetry_config/replace_injected_vars.ts | 3 ++- src/legacy/core_plugins/ui_metric/index.ts | 1 + .../ui_metric/public/hacks/ui_metric_init.ts | 11 ++++++----- test/common/config.js | 1 + 5 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index a1d72b007a2921..15ce0b74d467e1 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -81,12 +81,7 @@ const telemetry = (kibana: any) => { }, }, async replaceInjectedVars(originalInjectedVars: any, request: any) { - const currentKibanaVersion = getCurrentKibanaVersion(request.server); - const telemetryInjectedVars = await replaceTelemetryInjectedVars( - request, - currentKibanaVersion - ); - + const telemetryInjectedVars = await replaceTelemetryInjectedVars(request); return Object.assign(originalInjectedVars, telemetryInjectedVars); }, injectDefaultVars(server: Server) { @@ -106,7 +101,7 @@ const telemetry = (kibana: any) => { const initializerContext = { env: { packageInfo: { - version: getCurrentKibanaVersion(server), + version: server.config().get('pkg.version'), }, }, } as PluginInitializerContext; @@ -118,8 +113,7 @@ const telemetry = (kibana: any) => { telemetryPlugin(initializerContext).setup(coreSetup); const fetcherTask = new FetcherTask(server); - fetcherTask.stop(); - + fetcherTask.start(); // register collectors server.usage.collectorSet.register(createTelemetryPluginUsageCollector(server)); server.usage.collectorSet.register(createLocalizationUsageCollector(server)); @@ -131,7 +125,3 @@ const telemetry = (kibana: any) => { // eslint-disable-next-line import/no-default-export export default telemetry; - -function getCurrentKibanaVersion(server: Server): string { - return server.config().get('pkg.version'); -} diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts index 4d149802ebc786..a3517f9a6180ae 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts @@ -21,7 +21,8 @@ import { getTelemetrySavedObject } from '../telemetry_repository'; import { getTelemetryOptIn } from './get_telemetry_opt_in'; import { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher'; -export async function replaceTelemetryInjectedVars(request: any, currentKibanaVersion: string) { +export async function replaceTelemetryInjectedVars(request: any) { + const currentKibanaVersion = request.server.config().get('pkg.version'); const savedObjectsClient = request.getSavedObjectsClient(); const telemetrySavedObject = await getTelemetrySavedObject(savedObjectsClient); const telemetryOptedIn = getTelemetryOptIn({ diff --git a/src/legacy/core_plugins/ui_metric/index.ts b/src/legacy/core_plugins/ui_metric/index.ts index 6c957f23b5c40d..7b1db43627b847 100644 --- a/src/legacy/core_plugins/ui_metric/index.ts +++ b/src/legacy/core_plugins/ui_metric/index.ts @@ -39,6 +39,7 @@ export default function(kibana: any) { injectDefaultVars(server: Server) { const config = server.config(); return { + uiMetricEnabled: config.get('ui_metric.enabled'), debugUiMetric: config.get('ui_metric.debug'), }; }, diff --git a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts index 1447f539bf024e..983434f09922b3 100644 --- a/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts +++ b/src/legacy/core_plugins/ui_metric/public/hacks/ui_metric_init.ts @@ -29,16 +29,17 @@ import { import { isUnauthenticated } from '../../../telemetry/public/services'; function telemetryInit($injector: any) { - const localStorage = $injector.get('localStorage'); + const uiMetricEnabled = chrome.getInjected('uiMetricEnabled'); const debug = chrome.getInjected('debugUiMetric'); + if (!uiMetricEnabled || isUnauthenticated()) { + return; + } + const localStorage = $injector.get('localStorage'); const uiReporter = createAnalyticsReporter({ localStorage, debug, kfetch }); setTelemetryReporter(uiReporter); - trackUserAgent('kibana'); - if (isUnauthenticated()) { - return; - } uiReporter.start(); + trackUserAgent('kibana'); } uiModules.get('kibana').run(telemetryInit); diff --git a/test/common/config.js b/test/common/config.js index 44e4bef99bf620..f6b7dd09d09980 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -56,6 +56,7 @@ export default function () { `--elasticsearch.password=${servers.elasticsearch.password}`, `--kibana.disableWelcomeScreen=true`, '--telemetry.banner=false', + '--ui_metric.enabled=false', `--server.maxPayloadBytes=1679958`, ], }, From c757cb5e541c950a25ef77c0ab5c3df253beb1cd Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 16:04:25 +0200 Subject: [PATCH 21/46] enable ui_metric back again --- test/common/config.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/common/config.js b/test/common/config.js index f6b7dd09d09980..6ee1774ec4c0c3 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -56,11 +56,10 @@ export default function () { `--elasticsearch.password=${servers.elasticsearch.password}`, `--kibana.disableWelcomeScreen=true`, '--telemetry.banner=false', - '--ui_metric.enabled=false', + '--ui_metric.enabled=true', `--server.maxPayloadBytes=1679958`, ], }, - services }; } From 087ad8e0e32e2b7c23aa3fbad3bbc6a1daa2e07b Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 16:10:38 +0200 Subject: [PATCH 22/46] ignore keyword above 256 --- src/legacy/core_plugins/telemetry/mappings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/legacy/core_plugins/telemetry/mappings.json b/src/legacy/core_plugins/telemetry/mappings.json index 33d9cfc5ad154a..5a2ea5733e2ca9 100644 --- a/src/legacy/core_plugins/telemetry/mappings.json +++ b/src/legacy/core_plugins/telemetry/mappings.json @@ -12,6 +12,7 @@ "type": "date" }, "lastVersionChecked": { + "ignore_above": 256, "type": "keyword" } } From 076b06c02bfa59a3d1f21b5deb0130b49cd5641a Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 17:32:14 +0200 Subject: [PATCH 23/46] check requesting app first --- .../server/telemetry_config/get_telemetry_opt_in.ts | 10 ---------- .../server/telemetry_config/replace_injected_vars.ts | 12 ++++++++++-- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts index 1e5ae1b9d30420..edb1594d2818fb 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts @@ -21,7 +21,6 @@ import semver from 'semver'; import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object'; interface GetTelemetryOptInConfig { - request?: any; telemetrySavedObject: TelemetrySavedObject; currentKibanaVersion: string; } @@ -29,18 +28,9 @@ interface GetTelemetryOptInConfig { type GetTelemetryOptIn = (config: GetTelemetryOptInConfig) => null | boolean; export const getTelemetryOptIn: GetTelemetryOptIn = ({ - request, telemetrySavedObject, currentKibanaVersion, }) => { - if (request) { - const isRequestingApplication = request.path.startsWith('/app'); - // Prevent interstitial screens (such as the space selector) from prompting for telemetry - if (!isRequestingApplication) { - return false; - } - } - if (telemetrySavedObject === false) { return false; } diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts index a3517f9a6180ae..65564d99ed4262 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts @@ -22,15 +22,23 @@ import { getTelemetryOptIn } from './get_telemetry_opt_in'; import { getTelemetryUsageFetcher } from './get_telemetry_usage_fetcher'; export async function replaceTelemetryInjectedVars(request: any) { + const defaultTelemetryUsageFetcher = request.server.config().get('telemetry.usageFetcher'); + const isRequestingApplication = request.path.startsWith('/app'); + // Prevent interstitial screens (such as the space selector) from prompting for telemetry + if (!isRequestingApplication) { + return { + telemetryOptedIn: false, + }; + } + const currentKibanaVersion = request.server.config().get('pkg.version'); const savedObjectsClient = request.getSavedObjectsClient(); const telemetrySavedObject = await getTelemetrySavedObject(savedObjectsClient); const telemetryOptedIn = getTelemetryOptIn({ telemetrySavedObject, - request, currentKibanaVersion, }); - const defaultTelemetryUsageFetcher = request.server.config().get('telemetry.usageFetcher'); + const telemetryUsageFetcher = getTelemetryUsageFetcher({ telemetrySavedObject, defaultTelemetryUsageFetcher, From b954daae136cbb54c2dbff57c3a085402a56c4ad Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 17:36:15 +0200 Subject: [PATCH 24/46] clean up after all the debugging :) --- test/common/config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/common/config.js b/test/common/config.js index 6ee1774ec4c0c3..cd29b593cdadbd 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -56,7 +56,6 @@ export default function () { `--elasticsearch.password=${servers.elasticsearch.password}`, `--kibana.disableWelcomeScreen=true`, '--telemetry.banner=false', - '--ui_metric.enabled=true', `--server.maxPayloadBytes=1679958`, ], }, From e5967debf087b8027ae44d6cd374afb76384b188 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 18:18:35 +0200 Subject: [PATCH 25/46] fix tests --- .../get_telemetry_opt_in.test.ts | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts index fb2d63ba45d117..24631ff6003bd7 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts @@ -21,16 +21,6 @@ import { getTelemetryOptIn } from './get_telemetry_opt_in'; import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object'; describe('getTelemetryOptIn', () => { - it('returns false when request path is not /app*', () => { - const params = getCallGetTelemetryOptInParams({ - requestPath: '/foo/bar', - }); - - const result = callGetTelemetryOptIn(params); - - expect(result).toBe(false); - }); - it('returns null when saved object not found', () => { const params = getCallGetTelemetryOptInParams({ savedObjectNotFound: true, @@ -131,7 +121,6 @@ describe('getTelemetryOptIn', () => { }); interface CallGetTelemetryOptInParams { - requestPath: string; savedObjectNotFound: boolean; savedObjectForbidden: boolean; enabled: boolean | null | undefined; @@ -141,7 +130,6 @@ interface CallGetTelemetryOptInParams { } const DefaultParams = { - requestPath: '/app/something', savedObjectNotFound: false, savedObjectForbidden: false, enabled: true, @@ -157,9 +145,8 @@ function getCallGetTelemetryOptInParams( function callGetTelemetryOptIn(params: CallGetTelemetryOptInParams) { const { currentKibanaVersion } = params; - const request = getMockRequest(params); const telemetrySavedObject = getMockTelemetrySavedObject(params); - return getTelemetryOptIn({ request, currentKibanaVersion, telemetrySavedObject }); + return getTelemetryOptIn({ currentKibanaVersion, telemetrySavedObject }); } function getMockTelemetrySavedObject(params: CallGetTelemetryOptInParams): TelemetrySavedObject { @@ -176,9 +163,3 @@ function getMockTelemetrySavedObject(params: CallGetTelemetryOptInParams): Telem lastVersionChecked: params.lastVersionChecked, }; } - -function getMockRequest(params: CallGetTelemetryOptInParams): any { - return { - path: params.requestPath, - }; -} From 7f7b7cc1a6af1db3bd8cb2100e3099f574bc6d64 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 18:52:29 +0200 Subject: [PATCH 26/46] always return 200 for ui metric reporting --- packages/kbn-analytics/src/report.ts | 20 ++++++++++--------- .../public/services/telemetry_analytics.ts | 7 ++++++- .../ui_metric/server/routes/api/ui_metric.ts | 7 +++---- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/kbn-analytics/src/report.ts b/packages/kbn-analytics/src/report.ts index fd8f6b3ce1db45..333bc05d28f9be 100644 --- a/packages/kbn-analytics/src/report.ts +++ b/packages/kbn-analytics/src/report.ts @@ -96,15 +96,17 @@ export class ReportManager { const key = ReportManager.createMetricKey(metric); switch (metric.type) { case METRIC_TYPE.USER_AGENT: { - const { appName, type } = metric; - this.report.userAgent = { - [key]: { - key, - appName, - type, - userAgent: metric.userAgent, - }, - }; + const { appName, type, userAgent } = metric; + if (userAgent) { + this.report.userAgent = { + [key]: { + key, + appName, + type, + userAgent: metric.userAgent, + }, + }; + } return; } case METRIC_TYPE.CLICK: diff --git a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts index f06503bba4fe81..ee928b8a1d9ee8 100644 --- a/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts +++ b/src/legacy/core_plugins/ui_metric/public/services/telemetry_analytics.ts @@ -60,12 +60,17 @@ export function createAnalyticsReporter(config: AnalyicsReporterConfig) { debug, storage: localStorage, async http(report) { - return kfetch({ + const response = await kfetch({ method: 'POST', pathname: '/api/telemetry/report', body: JSON.stringify(report), headers: addSystemApiHeader({}), }); + + if (response.status !== 'ok') { + throw Error('Unable to store report.'); + } + return response; }, }); } diff --git a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts index 3c822ca9321f56..54992b295f7bfd 100644 --- a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts +++ b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts @@ -91,13 +91,12 @@ export function registerUiMetricRoute(server: Server) { }, }, handler: async (req: any, h: any) => { - const report = req.payload; - try { + const report = req.payload; await storeReport(server, report); - return {}; + return { status: 'ok' }; } catch (error) { - return new Boom('Something went wrong', { statusCode: error.status }); + return h.response({ status: 'fail' }).code(200); } }, }); From 4cb7da9293f6232694528c5f3b1e7867b1f20539 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 19:19:50 +0200 Subject: [PATCH 27/46] remove boom import --- src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts index 54992b295f7bfd..b05014718be481 100644 --- a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts +++ b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts @@ -18,7 +18,6 @@ */ import Joi from 'joi'; -import Boom from 'boom'; import { Report } from '@kbn/analytics'; import { Server } from 'hapi'; From f8ab109cba4a5abe28d64d9c20fd545db4118e79 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 19:24:25 +0200 Subject: [PATCH 28/46] logout after removing role/user --- .../feature_controls/advanced_settings_security.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index 0834ff11ced58f..b96e6586278b60 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -64,8 +64,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_advanced_settings_all_role'), security.user.delete('global_advanced_settings_all_user'), - PageObjects.security.logout(), ]); + await PageObjects.security.logout(); }); it('shows management navlink', async () => { From 993fcd7f493bc604ad5dd6ffc10df6fc7c9ada4a Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 7 Nov 2019 21:23:17 +0200 Subject: [PATCH 29/46] undo some changes in tests --- src/legacy/core_plugins/telemetry/index.ts | 6 ++++-- .../telemetry_collection/get_stats_with_monitoring.ts | 2 +- .../feature_controls/advanced_settings_security.ts | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index 15ce0b74d467e1..605c26c37c0c80 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -97,6 +97,10 @@ const telemetry = (kibana: any) => { hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'], mappings, }, + postInit(server: Server) { + const fetcherTask = new FetcherTask(server); + fetcherTask.start(); + }, init(server: Server) { const initializerContext = { env: { @@ -112,8 +116,6 @@ const telemetry = (kibana: any) => { } as any) as CoreSetup; telemetryPlugin(initializerContext).setup(coreSetup); - const fetcherTask = new FetcherTask(server); - fetcherTask.start(); // register collectors server.usage.collectorSet.register(createTelemetryPluginUsageCollector(server)); server.usage.collectorSet.register(createLocalizationUsageCollector(server)); diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts index eaa660f2917393..f784457b46bc3f 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_stats_with_monitoring.ts @@ -14,9 +14,9 @@ import { export const getStatsWithMonitoring: StatsGetter = async function(config) { let response = []; - const { start, end, server, callCluster } = getStatsCollectionConfig(config, 'monitoring'); try { + const { start, end, server, callCluster } = getStatsCollectionConfig(config, 'monitoring'); response = await getAllStats({ server, callCluster, start, end }); } catch (err) { // no-op diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index b96e6586278b60..0834ff11ced58f 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -64,8 +64,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { await Promise.all([ security.role.delete('global_advanced_settings_all_role'), security.user.delete('global_advanced_settings_all_user'), + PageObjects.security.logout(), ]); - await PageObjects.security.logout(); }); it('shows management navlink', async () => { From 88c8faec85d3508e4540159f37a00e7e5514b8e4 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Fri, 8 Nov 2019 02:00:52 +0200 Subject: [PATCH 30/46] inside try catch --- src/legacy/core_plugins/ui_metric/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/legacy/core_plugins/ui_metric/index.ts b/src/legacy/core_plugins/ui_metric/index.ts index 7b1db43627b847..964e3497accba7 100644 --- a/src/legacy/core_plugins/ui_metric/index.ts +++ b/src/legacy/core_plugins/ui_metric/index.ts @@ -46,7 +46,6 @@ export default function(kibana: any) { mappings: require('./mappings.json'), hacks: ['plugins/ui_metric/hacks/ui_metric_init'], }, - init(server: Legacy.Server) { registerUiMetricRoute(server); }, From 8b0692f176451cf9b293e9ae8a70c63d38c62d98 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Fri, 8 Nov 2019 04:07:25 +0200 Subject: [PATCH 31/46] prevent potential race conditions in priorities with = --- packages/kbn-analytics/src/reporter.ts | 2 +- .../telemetry/server/collection_manager.ts | 4 +-- .../telemetry_plugin_collector.ts | 30 +++++++++++++------ .../server/telemetry_repository/index.ts | 2 +- .../advanced_settings_security.ts | 2 -- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/packages/kbn-analytics/src/reporter.ts b/packages/kbn-analytics/src/reporter.ts index 21bc8652009c60..f712272cd818b1 100644 --- a/packages/kbn-analytics/src/reporter.ts +++ b/packages/kbn-analytics/src/reporter.ts @@ -44,7 +44,7 @@ export class Reporter { private readonly maxRetries = 3; constructor(config: ReporterConfig) { - const { http, storage, debug, checkInterval = 10000, storageKey = 'analytics' } = config; + const { http, storage, debug, checkInterval = 90000, storageKey = 'analytics' } = config; this.http = http; this.checkInterval = checkInterval; this.interval = null; diff --git a/src/legacy/core_plugins/telemetry/server/collection_manager.ts b/src/legacy/core_plugins/telemetry/server/collection_manager.ts index 22b9ad5ab802b6..589f104873a433 100644 --- a/src/legacy/core_plugins/telemetry/server/collection_manager.ts +++ b/src/legacy/core_plugins/telemetry/server/collection_manager.ts @@ -63,10 +63,10 @@ export const getStatsCollectionConfig = ( export class TelemetryCollectionManager { private getterMethod?: StatsGetter; private collectionTitle?: string; - private getterMethodPriority = 0; + private getterMethodPriority = -1; public setStatsGetter = (statsGetter: StatsGetter, title: string, priority = 0) => { - if (priority >= this.getterMethodPriority) { + if (priority > this.getterMethodPriority) { this.getterMethod = statsGetter; this.collectionTitle = title; this.getterMethodPriority = priority; diff --git a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts index e0f72d9e59c410..147d5b6079578d 100644 --- a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts +++ b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts @@ -18,7 +18,8 @@ */ import { TELEMETRY_STATS_TYPE } from '../../../common/constants'; -import { getTelemetrySavedObject } from '../../telemetry_repository'; +import { getTelemetrySavedObject, TelemetrySavedObject } from '../../telemetry_repository'; +import { getTelemetryOptIn, getTelemetryUsageFetcher } from '../../telemetry_config'; export interface TelemetryUsageStats { optIn?: boolean | null; usageFetcher?: 'browser' | 'server'; @@ -27,17 +28,28 @@ export interface TelemetryUsageStats { export function createCollectorFetch(server: any) { return async function fetchUsageStats(): Promise { - const { getSavedObjectsRepository } = server.savedObjects; - const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); - const internalRepository = getSavedObjectsRepository(callWithInternalUser); - const telemetrySavedObject = await getTelemetrySavedObject(internalRepository); + const config = server.config(); + const defaultTelemetryUsageFetcher = config.get('telemetry.usageFetcher'); + const currentKibanaVersion = config.get('pkg.version'); - if (!telemetrySavedObject) return {}; + let telemetrySavedObject: TelemetrySavedObject = {}; + + try { + const { getSavedObjectsRepository } = server.savedObjects; + const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); + const internalRepository = getSavedObjectsRepository(callWithInternalUser); + telemetrySavedObject = await getTelemetrySavedObject(internalRepository); + } catch (err) { + // no-op + } return { - optIn: telemetrySavedObject.enabled, - lastReported: telemetrySavedObject.lastReported, - usageFetcher: telemetrySavedObject.usageFetcher, + optIn: getTelemetryOptIn({ currentKibanaVersion, telemetrySavedObject }), + lastReported: telemetrySavedObject ? telemetrySavedObject.lastReported : undefined, + usageFetcher: getTelemetryUsageFetcher({ + telemetrySavedObject, + defaultTelemetryUsageFetcher, + }), }; }; } diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts index 2b891d405bf8bf..966b84924e48c1 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts @@ -17,7 +17,7 @@ * under the License. */ -export { getTelemetrySavedObject } from './get_telemetry_saved_object'; +export { getTelemetrySavedObject, TelemetrySavedObject } from './get_telemetry_saved_object'; export { updateTelemetrySavedObject } from './update_telemetry_saved_object'; export interface TelemetrySavedObjectAttributes { diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index 0834ff11ced58f..d60b286e3337ae 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -47,7 +47,6 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); await PageObjects.security.logout(); - await PageObjects.security.login( 'global_advanced_settings_all_user', 'global_advanced_settings_all_user-password', @@ -55,7 +54,6 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { expectSpaceSelector: false, } ); - await kibanaServer.uiSettings.replace({}); await PageObjects.settings.navigateTo(); }); From 176ac34e528a667a3aeb1ee5b04b6d18970c9eb6 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Mon, 11 Nov 2019 12:21:09 +0200 Subject: [PATCH 32/46] use snake_case for telemetry plugin collection --- .../telemetry_plugin/telemetry_plugin_collector.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts index 147d5b6079578d..243f8c75c6741b 100644 --- a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts +++ b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts @@ -21,9 +21,9 @@ import { TELEMETRY_STATS_TYPE } from '../../../common/constants'; import { getTelemetrySavedObject, TelemetrySavedObject } from '../../telemetry_repository'; import { getTelemetryOptIn, getTelemetryUsageFetcher } from '../../telemetry_config'; export interface TelemetryUsageStats { - optIn?: boolean | null; - usageFetcher?: 'browser' | 'server'; - lastReported?: number; + opt_in_status?: boolean | null; + usage_fetcher?: 'browser' | 'server'; + last_reported?: number; } export function createCollectorFetch(server: any) { @@ -44,9 +44,9 @@ export function createCollectorFetch(server: any) { } return { - optIn: getTelemetryOptIn({ currentKibanaVersion, telemetrySavedObject }), - lastReported: telemetrySavedObject ? telemetrySavedObject.lastReported : undefined, - usageFetcher: getTelemetryUsageFetcher({ + opt_in_status: getTelemetryOptIn({ currentKibanaVersion, telemetrySavedObject }), + last_reported: telemetrySavedObject ? telemetrySavedObject.lastReported : undefined, + usage_fetcher: getTelemetryUsageFetcher({ telemetrySavedObject, defaultTelemetryUsageFetcher, }), From 495fc81dda8799ab87df9bc1c4f7365395ecdbfd Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 20:38:48 +0200 Subject: [PATCH 33/46] usageFetcher -> sendUsageFrom --- .../resources/bin/kibana-docker | 2 +- src/legacy/core_plugins/telemetry/index.ts | 2 +- .../telemetry_plugin_collector.ts | 4 ++-- .../core_plugins/telemetry/server/fetcher.ts | 4 ++-- .../get_telemetry_usage_fetcher.test.ts | 18 +++++++++--------- .../get_telemetry_usage_fetcher.ts | 8 ++++---- .../telemetry_config/replace_injected_vars.ts | 4 ++-- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker index 61d8300bf6a724..6609b905b81eca 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker @@ -181,7 +181,7 @@ kibana_vars=( xpack.security.secureCookies xpack.security.sessionTimeout telemetry.enabled - telemetry.usageFetcher + telemetry.sendUsageFrom ) longopts='' diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index 75bc478d44598a..dd2418f16e06f3 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -104,7 +104,7 @@ const telemetry = (kibana: any) => { getXpackConfigWithDeprecated(config, 'telemetry.banner'), telemetryOptedIn: config.get('telemetry.optIn'), allowChangingOptInStatus: config.get('telemetry.allowChangingOptInStatus'), - telemetryUsageFetcher: config.get('telemetry.usageFetcher'), + telemetryUsageFetcher: config.get('telemetry.sendUsageFrom'), }; }, hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'], diff --git a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts index 824a9d8fe1a80f..e092ceb5e85932 100644 --- a/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts +++ b/src/legacy/core_plugins/telemetry/server/collectors/telemetry_plugin/telemetry_plugin_collector.ts @@ -29,7 +29,7 @@ export interface TelemetryUsageStats { export function createCollectorFetch(server: any) { return async function fetchUsageStats(): Promise { const config = server.config(); - const configTelemetryUsageFetcher = config.get('telemetry.usageFetcher'); + const configTelemetrySendUsageFrom = config.get('telemetry.sendUsageFrom'); const allowChangingOptInStatus = config.get('telemetry.allowChangingOptInStatus'); const configTelemetryOptIn = config.get('telemetry.optIn'); const currentKibanaVersion = config.get('pkg.version'); @@ -55,7 +55,7 @@ export function createCollectorFetch(server: any) { last_reported: telemetrySavedObject ? telemetrySavedObject.lastReported : undefined, usage_fetcher: getTelemetryUsageFetcher({ telemetrySavedObject, - configTelemetryUsageFetcher, + configTelemetrySendUsageFrom, }), }; }; diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts index f2ddceeb407f8c..3eee8f37c762c3 100644 --- a/src/legacy/core_plugins/telemetry/server/fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -49,7 +49,7 @@ export class FetcherTask { const telemetrySavedObject = await getTelemetrySavedObject(internalRepository); const config = this.server.config(); const currentKibanaVersion = config.get('pkg.version'); - const configTelemetryUsageFetcher = config.get('telemetry.usageFetcher'); + const configTelemetrySendUsageFrom = config.get('telemetry.sendUsageFrom'); const allowChangingOptInStatus = config.get('telemetry.allowChangingOptInStatus'); const configTelemetryOptIn = config.get('telemetry.optIn'); const telemetryUrl = getXpackConfigWithDeprecated(config, 'telemetry.url') as string; @@ -63,7 +63,7 @@ export class FetcherTask { }), telemetryUsageFetcher: getTelemetryUsageFetcher({ telemetrySavedObject, - configTelemetryUsageFetcher, + configTelemetrySendUsageFrom, }), telemetryUrl, }; diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts index 01c0c9929438ae..74865fbd17198c 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts @@ -24,7 +24,7 @@ describe('getTelemetryUsageFetcher', () => { it('returns kibana.yml config when saved object not found', () => { const params: CallGetTelemetryUsageFetcherParams = { savedObjectNotFound: true, - configUsageFetcher: 'browser', + configSendUsageFrom: 'browser', }; const result = callGetTelemetryUsageFetcher(params); @@ -35,7 +35,7 @@ describe('getTelemetryUsageFetcher', () => { it('returns kibana.yml config when saved object forbidden', () => { const params: CallGetTelemetryUsageFetcherParams = { savedObjectForbidden: true, - configUsageFetcher: 'browser', + configSendUsageFrom: 'browser', }; const result = callGetTelemetryUsageFetcher(params); @@ -45,8 +45,8 @@ describe('getTelemetryUsageFetcher', () => { it('returns kibana.yml config when saved object usageFetcher is undefined', () => { const params: CallGetTelemetryUsageFetcherParams = { - savedUsageFetcher: undefined, - configUsageFetcher: 'server', + savedSendUsagefrom: undefined, + configSendUsageFrom: 'server', }; const result = callGetTelemetryUsageFetcher(params); @@ -58,14 +58,14 @@ describe('getTelemetryUsageFetcher', () => { interface CallGetTelemetryUsageFetcherParams { savedObjectNotFound?: boolean; savedObjectForbidden?: boolean; - savedUsageFetcher?: 'browser' | 'server'; - configUsageFetcher: 'browser' | 'server'; + savedSendUsagefrom?: 'browser' | 'server'; + configSendUsageFrom: 'browser' | 'server'; } function callGetTelemetryUsageFetcher(params: CallGetTelemetryUsageFetcherParams) { const telemetrySavedObject = getMockTelemetrySavedObject(params); - const configTelemetryUsageFetcher = params.configUsageFetcher; - return getTelemetryUsageFetcher({ configTelemetryUsageFetcher, telemetrySavedObject }); + const configTelemetrySendUsageFrom = params.configSendUsageFrom; + return getTelemetryUsageFetcher({ configTelemetrySendUsageFrom, telemetrySavedObject }); } function getMockTelemetrySavedObject( @@ -80,6 +80,6 @@ function getMockTelemetrySavedObject( } return { - usageFetcher: params.savedUsageFetcher, + usageFetcher: params.savedSendUsagefrom, }; } diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts index a49b572657af3b..db85977b3b6140 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts @@ -19,20 +19,20 @@ import { TelemetrySavedObject } from '../telemetry_repository/get_telemetry_saved_object'; interface GetTelemetryUsageFetcherConfig { - configTelemetryUsageFetcher: 'browser' | 'server'; + configTelemetrySendUsageFrom: 'browser' | 'server'; telemetrySavedObject: TelemetrySavedObject; } export function getTelemetryUsageFetcher({ telemetrySavedObject, - configTelemetryUsageFetcher, + configTelemetrySendUsageFrom, }: GetTelemetryUsageFetcherConfig) { if (!telemetrySavedObject) { - return configTelemetryUsageFetcher; + return configTelemetrySendUsageFrom; } if (typeof telemetrySavedObject.usageFetcher === 'undefined') { - return configTelemetryUsageFetcher; + return configTelemetrySendUsageFrom; } return telemetrySavedObject.usageFetcher; diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts index 79a774161215e2..8c5edad4e9f72b 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts @@ -24,7 +24,7 @@ import { getTelemetryAllowChangingOptInStatus } from './get_telemetry_allow_chan export async function replaceTelemetryInjectedVars(request: any) { const config = request.server.config(); - const configTelemetryUsageFetcher = config().get('telemetry.usageFetcher'); + const configTelemetrySendUsageFrom = config().get('telemetry.sendUsageFrom'); const configTelemetryOptIn = config().get('telemetry.optIn'); const configTelemetryAllowChangingOptInStatus = config().get( 'telemetry.allowChangingOptInStatus' @@ -54,7 +54,7 @@ export async function replaceTelemetryInjectedVars(request: any) { }); const telemetryUsageFetcher = getTelemetryUsageFetcher({ - configTelemetryUsageFetcher, + configTelemetrySendUsageFrom, telemetrySavedObject, }); From 832841a81e80075cc1bfd03fa365c3fa36d9d85b Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 20:43:04 +0200 Subject: [PATCH 34/46] more replacements --- src/legacy/core_plugins/telemetry/index.ts | 2 +- .../core_plugins/telemetry/public/hacks/telemetry_init.ts | 4 ++-- src/legacy/core_plugins/telemetry/server/fetcher.ts | 6 +++--- .../server/telemetry_config/replace_injected_vars.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index dd2418f16e06f3..bbb6c0374f7296 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -104,7 +104,7 @@ const telemetry = (kibana: any) => { getXpackConfigWithDeprecated(config, 'telemetry.banner'), telemetryOptedIn: config.get('telemetry.optIn'), allowChangingOptInStatus: config.get('telemetry.allowChangingOptInStatus'), - telemetryUsageFetcher: config.get('telemetry.sendUsageFrom'), + telemetrySendUsageFrom: config.get('telemetry.sendUsageFrom'), }; }, hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'], diff --git a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts index 5641eacf408ea3..1f63b68e69421a 100644 --- a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts +++ b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts @@ -30,9 +30,9 @@ function telemetryInit($injector: any) { const $http = $injector.get('$http'); const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled'); - const usageFetcher = npStart.core.injectedMetadata.getInjectedVar('telemetryUsageFetcher'); + const sendUsageFrom = npStart.core.injectedMetadata.getInjectedVar('telemetrySendUsageFrom'); - if (telemetryEnabled && usageFetcher === 'browser') { + if (telemetryEnabled && sendUsageFrom === 'browser') { // no telemetry for non-logged in users if (isUnauthenticated()) { return; diff --git a/src/legacy/core_plugins/telemetry/server/fetcher.ts b/src/legacy/core_plugins/telemetry/server/fetcher.ts index 3eee8f37c762c3..43883395eac99c 100644 --- a/src/legacy/core_plugins/telemetry/server/fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/fetcher.ts @@ -61,7 +61,7 @@ export class FetcherTask { allowChangingOptInStatus, configTelemetryOptIn, }), - telemetryUsageFetcher: getTelemetryUsageFetcher({ + telemetrySendUsageFrom: getTelemetryUsageFetcher({ telemetrySavedObject, configTelemetrySendUsageFrom, }), @@ -77,8 +77,8 @@ export class FetcherTask { }); }; - private shouldSendReport = ({ telemetryOptIn, telemetryUsageFetcher }: any) => { - if (telemetryOptIn && telemetryUsageFetcher === 'server') { + private shouldSendReport = ({ telemetryOptIn, telemetrySendUsageFrom }: any) => { + if (telemetryOptIn && telemetrySendUsageFrom === 'server') { if (!this.lastReported || Date.now() - this.lastReported > REPORT_INTERVAL_MS) { return true; } diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts index 8c5edad4e9f72b..7c33aebb4cfdb8 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts @@ -53,13 +53,13 @@ export async function replaceTelemetryInjectedVars(request: any) { currentKibanaVersion, }); - const telemetryUsageFetcher = getTelemetryUsageFetcher({ + const telemetrySendUsageFrom = getTelemetryUsageFetcher({ configTelemetrySendUsageFrom, telemetrySavedObject, }); return { telemetryOptedIn, - telemetryUsageFetcher, + telemetrySendUsageFrom, }; } From 3956c1f986f59655a0ecc8357812545fed1a7dad Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 20:51:22 +0200 Subject: [PATCH 35/46] remove extra unused route --- src/legacy/core_plugins/telemetry/index.ts | 2 +- .../core_plugins/telemetry/mappings.json | 2 +- .../server/routes/telemetry_config.ts | 27 +------------------ .../get_telemetry_usage_fetcher.test.ts | 4 +-- .../get_telemetry_usage_fetcher.ts | 4 +-- .../server/telemetry_repository/index.ts | 2 +- 6 files changed, 8 insertions(+), 33 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index bbb6c0374f7296..0f3ba4795ab8c4 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -68,7 +68,7 @@ const telemetry = (kibana: any) => { `https://telemetry.elastic.co/xpack/${ENDPOINT_VERSION}/send` ), }), - usageFetcher: Joi.string() + sendUsageFrom: Joi.string() .allow(['server', 'browser']) .default('browser'), }).default(); diff --git a/src/legacy/core_plugins/telemetry/mappings.json b/src/legacy/core_plugins/telemetry/mappings.json index 5a2ea5733e2ca9..95c6ebfc7dc793 100644 --- a/src/legacy/core_plugins/telemetry/mappings.json +++ b/src/legacy/core_plugins/telemetry/mappings.json @@ -4,7 +4,7 @@ "enabled": { "type": "boolean" }, - "usageFetcher": { + "sendUsageFrom": { "ignore_above": 256, "type": "keyword" }, diff --git a/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts index 8c14adfc485b3c..440f83277340ab 100644 --- a/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts +++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_config.ts @@ -20,13 +20,12 @@ import Joi from 'joi'; import { boomify } from 'boom'; import { CoreSetup } from 'src/core/server'; +import { getTelemetryAllowChangingOptInStatus } from '../telemetry_config'; import { TelemetrySavedObjectAttributes, updateTelemetrySavedObject, } from '../telemetry_repository'; -import { getTelemetryAllowChangingOptInStatus } from '../telemetry_config'; - interface RegisterOptInRoutesParams { core: CoreSetup; currentKibanaVersion: string; @@ -38,30 +37,6 @@ export function registerTelemetryConfigRoutes({ }: RegisterOptInRoutesParams) { const { server } = core.http as any; - server.route({ - method: 'POST', - path: '/api/telemetry/v2/usageFetcher', - options: { - validate: { - payload: Joi.object({ - usageFetcher: Joi.string() - .allow(['browser', 'server']) - .required(), - }), - }, - }, - handler: async (req: any, h: any) => { - try { - const attributes: TelemetrySavedObjectAttributes = req.payload; - const savedObjectsClient = req.getSavedObjectsClient(); - await updateTelemetrySavedObject(savedObjectsClient, attributes); - } catch (err) { - return boomify(err); - } - return h.response({}).code(200); - }, - }); - server.route({ method: 'POST', path: '/api/telemetry/v2/optIn', diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts index 74865fbd17198c..f2f99104433a39 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.test.ts @@ -43,7 +43,7 @@ describe('getTelemetryUsageFetcher', () => { expect(result).toBe('browser'); }); - it('returns kibana.yml config when saved object usageFetcher is undefined', () => { + it('returns kibana.yml config when saved object sendUsageFrom is undefined', () => { const params: CallGetTelemetryUsageFetcherParams = { savedSendUsagefrom: undefined, configSendUsageFrom: 'server', @@ -80,6 +80,6 @@ function getMockTelemetrySavedObject( } return { - usageFetcher: params.savedSendUsagefrom, + sendUsageFrom: params.savedSendUsagefrom, }; } diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts index db85977b3b6140..98f2d6b0c7bbfe 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_usage_fetcher.ts @@ -31,9 +31,9 @@ export function getTelemetryUsageFetcher({ return configTelemetrySendUsageFrom; } - if (typeof telemetrySavedObject.usageFetcher === 'undefined') { + if (typeof telemetrySavedObject.sendUsageFrom === 'undefined') { return configTelemetrySendUsageFrom; } - return telemetrySavedObject.usageFetcher; + return telemetrySavedObject.sendUsageFrom; } diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts index 98f66bfe72f3e6..f3629abc1620cc 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/index.ts @@ -23,7 +23,7 @@ export { updateTelemetrySavedObject } from './update_telemetry_saved_object'; export interface TelemetrySavedObjectAttributes { enabled?: boolean | null; lastVersionChecked?: string; - usageFetcher?: 'browser' | 'server'; + sendUsageFrom?: 'browser' | 'server'; lastReported?: number; telemetryAllowChangingOptInStatus?: boolean; } From 925c3e4e0e2931e6dfb7576c2b0b5a0b401cf6ef Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 20:52:30 +0200 Subject: [PATCH 36/46] config() -> config --- .../server/telemetry_config/replace_injected_vars.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts index 7c33aebb4cfdb8..b300e9d2a392f3 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts @@ -24,8 +24,8 @@ import { getTelemetryAllowChangingOptInStatus } from './get_telemetry_allow_chan export async function replaceTelemetryInjectedVars(request: any) { const config = request.server.config(); - const configTelemetrySendUsageFrom = config().get('telemetry.sendUsageFrom'); - const configTelemetryOptIn = config().get('telemetry.optIn'); + const configTelemetrySendUsageFrom = config.get('telemetry.sendUsageFrom'); + const configTelemetryOptIn = config.get('telemetry.optIn'); const configTelemetryAllowChangingOptInStatus = config().get( 'telemetry.allowChangingOptInStatus' ); @@ -38,7 +38,7 @@ export async function replaceTelemetryInjectedVars(request: any) { }; } - const currentKibanaVersion = config().get('pkg.version'); + const currentKibanaVersion = config.get('pkg.version'); const savedObjectsClient = request.getSavedObjectsClient(); const telemetrySavedObject = await getTelemetrySavedObject(savedObjectsClient); const allowChangingOptInStatus = getTelemetryAllowChangingOptInStatus({ From 703f1f308f16ee8a52361aaa64659094a89860b1 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 20:58:07 +0200 Subject: [PATCH 37/46] Update src/legacy/core_plugins/telemetry/index.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Mike Côté --- src/legacy/core_plugins/telemetry/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index 0f3ba4795ab8c4..149fa99938563c 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -92,7 +92,7 @@ const telemetry = (kibana: any) => { }, async replaceInjectedVars(originalInjectedVars: any, request: any) { const telemetryInjectedVars = await replaceTelemetryInjectedVars(request); - return Object.assign(originalInjectedVars, telemetryInjectedVars); + return Object.assign({}, originalInjectedVars, telemetryInjectedVars); }, injectDefaultVars(server: Server) { const config = server.config(); From ec4dabf003e914df4f4ff95042e684b223271fd9 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 20:58:23 +0200 Subject: [PATCH 38/46] Update src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Mike Côté --- .../core_plugins/ui_metric/server/routes/api/ui_metric.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts index b05014718be481..e2de23ea806e44 100644 --- a/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts +++ b/src/legacy/core_plugins/ui_metric/server/routes/api/ui_metric.ts @@ -95,7 +95,7 @@ export function registerUiMetricRoute(server: Server) { await storeReport(server, report); return { status: 'ok' }; } catch (error) { - return h.response({ status: 'fail' }).code(200); + return { status: 'fail' }; } }, }); From 17e431871d96c9bed2ea9c5a19b6fd77eaaf2ad2 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 21:02:10 +0200 Subject: [PATCH 39/46] config() -> config --- .../server/telemetry_config/replace_injected_vars.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts index b300e9d2a392f3..c9b4f4ebcd6503 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/replace_injected_vars.ts @@ -26,9 +26,7 @@ export async function replaceTelemetryInjectedVars(request: any) { const config = request.server.config(); const configTelemetrySendUsageFrom = config.get('telemetry.sendUsageFrom'); const configTelemetryOptIn = config.get('telemetry.optIn'); - const configTelemetryAllowChangingOptInStatus = config().get( - 'telemetry.allowChangingOptInStatus' - ); + const configTelemetryAllowChangingOptInStatus = config.get('telemetry.allowChangingOptInStatus'); const isRequestingApplication = request.path.startsWith('/app'); // Prevent interstitial screens (such as the space selector) from prompting for telemetry From 29a6a677aad110ee81a864fc9359eb9cae91ab9a Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 21:19:22 +0200 Subject: [PATCH 40/46] fix SO update logic given the current changes --- .../telemetry_repository/update_telemetry_saved_object.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts b/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts index 83d9a368f95be2..b66e01faaa6bc7 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_repository/update_telemetry_saved_object.ts @@ -28,11 +28,7 @@ export async function updateTelemetrySavedObject( return await savedObjectsClient.update('telemetry', 'telemetry', savedObjectAttributes); } catch (err) { if (SavedObjectsErrorHelpers.isNotFoundError(err)) { - const savedObjectAttributesWithDefaults = { - enabled: null, - ...savedObjectAttributes, - }; - return await savedObjectsClient.create('telemetry', savedObjectAttributesWithDefaults, { + return await savedObjectsClient.create('telemetry', savedObjectAttributes, { id: 'telemetry', overwrite: true, }); From 944599ae6351b2e004b43c3a233f39976bd3bc9c Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 23:27:41 +0200 Subject: [PATCH 41/46] fix opt in check --- .../core_plugins/telemetry/public/hacks/telemetry_init.ts | 3 ++- .../core_plugins/telemetry/public/services/telemetry_opt_in.ts | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts index 1f63b68e69421a..10a49fb010c00f 100644 --- a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts +++ b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts @@ -30,9 +30,10 @@ function telemetryInit($injector: any) { const $http = $injector.get('$http'); const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled'); + const telemetryOptedIn = npStart.core.injectedMetadata.getInjectedVar('telemetryOptedIn'); const sendUsageFrom = npStart.core.injectedMetadata.getInjectedVar('telemetrySendUsageFrom'); - if (telemetryEnabled && sendUsageFrom === 'browser') { + if (telemetryEnabled && telemetryOptedIn && sendUsageFrom === 'browser') { // no telemetry for non-logged in users if (isUnauthenticated()) { return; diff --git a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts index 4d27bad352cd4d..f7b09b1befafaf 100644 --- a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts +++ b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts @@ -41,6 +41,9 @@ export function TelemetryOptInProvider($injector: any, chrome: any) { bannerId = id; }, setOptIn: async (enabled: boolean) => { + if (!allowChangingOptInStatus) { + return; + } setCanTrackUiMetrics(enabled); const $http = $injector.get('$http'); From 452730835f934dc1cd0abbb0b34ac4b7ef1a4820 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 23:32:50 +0200 Subject: [PATCH 42/46] triple check --- .../telemetry/server/telemetry_config/get_telemetry_opt_in.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts index f889cabd5e9a68..3cf10f703775e5 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts @@ -43,7 +43,7 @@ export const getTelemetryOptIn: GetTelemetryOptIn = ({ return false; } - if (telemetrySavedObject === null || telemetrySavedObject.enabled == null) { + if (telemetrySavedObject === null || telemetrySavedObject.enabled === null) { return null; } From 62f65ea6fdccd1f85ccb9726e0385bbd46f81dee Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 12 Nov 2019 23:36:09 +0200 Subject: [PATCH 43/46] check for non boolean --- .../server/telemetry_config/get_telemetry_opt_in.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts index 3cf10f703775e5..b2a2f603dcf10b 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts @@ -43,14 +43,14 @@ export const getTelemetryOptIn: GetTelemetryOptIn = ({ return false; } - if (telemetrySavedObject === null || telemetrySavedObject.enabled === null) { + if (telemetrySavedObject === null || typeof telemetrySavedObject.enabled !== 'boolean') { return null; } - const enabled = !!telemetrySavedObject.enabled; + const savedOptIn = telemetrySavedObject.enabled; // if enabled is true, return it - if (enabled === true) return enabled; + if (savedOptIn === true) return savedOptIn; // Additional check if they've already opted out (enabled: false): // - if the Kibana version has changed by at least a minor version, @@ -62,7 +62,7 @@ export const getTelemetryOptIn: GetTelemetryOptIn = ({ if (typeof lastKibanaVersion !== 'string') return null; // if version hasn't changed, just return enabled value - if (lastKibanaVersion === currentKibanaVersion) return enabled; + if (lastKibanaVersion === currentKibanaVersion) return savedOptIn; const lastSemver = parseSemver(lastKibanaVersion); const currentSemver = parseSemver(currentKibanaVersion); @@ -77,7 +77,7 @@ export const getTelemetryOptIn: GetTelemetryOptIn = ({ } // current version X.Y is not greater than last version X.Y, return enabled - return enabled; + return savedOptIn; }; function parseSemver(version: string): semver.SemVer | null { From cd0730e07217fdef22a4f58bc9011134a0c14fa4 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 13 Nov 2019 00:14:40 +0200 Subject: [PATCH 44/46] take into account older settings --- .../telemetry/public/hacks/telemetry_init.ts | 7 +++++- .../welcome_banner/handle_old_settings.js | 24 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts index 10a49fb010c00f..009f3d92d88cb3 100644 --- a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts +++ b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts @@ -25,12 +25,17 @@ import { isUnauthenticated } from '../services'; import { Telemetry } from './telemetry'; // @ts-ignore import { fetchTelemetry } from './fetch_telemetry'; +// @ts-ignore +import { isOptInHandleOldSettings } from './welcome_banner/handle_old_settings'; function telemetryInit($injector: any) { const $http = $injector.get('$http'); + const Private = $injector.get('Private'); + const config = $injector.get('config'); + const telemetryOptInProvider = Private(TelemetryOptInProvider); const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled'); - const telemetryOptedIn = npStart.core.injectedMetadata.getInjectedVar('telemetryOptedIn'); + const telemetryOptedIn = isOptInHandleOldSettings(config, telemetryOptInProvider); const sendUsageFrom = npStart.core.injectedMetadata.getInjectedVar('telemetrySendUsageFrom'); if (telemetryEnabled && telemetryOptedIn && sendUsageFrom === 'browser') { diff --git a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.js b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.js index 31091e19520533..4f0f2983477e07 100644 --- a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.js +++ b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.js @@ -27,8 +27,9 @@ import { CONFIG_TELEMETRY } from '../../../common/constants'; * @param {Object} config The advanced settings config object. * @return {Boolean} {@code true} if the banner should still be displayed. {@code false} if the banner should not be displayed. */ +const CONFIG_ALLOW_REPORT = 'xPackMonitoring:allowReport'; + export async function handleOldSettings(config, telemetryOptInProvider) { - const CONFIG_ALLOW_REPORT = 'xPackMonitoring:allowReport'; const CONFIG_SHOW_BANNER = 'xPackMonitoring:showBanner'; const oldAllowReportSetting = config.get(CONFIG_ALLOW_REPORT, null); const oldTelemetrySetting = config.get(CONFIG_TELEMETRY, null); @@ -62,3 +63,24 @@ export async function handleOldSettings(config, telemetryOptInProvider) { return true; } + + +export async function isOptInHandleOldSettings(config, telemetryOptInProvider) { + const currentOptInSettting = telemetryOptInProvider.getOptIn(); + + if (typeof currentOptInSettting === 'boolean') { + return currentOptInSettting; + } + + const oldTelemetrySetting = config.get(CONFIG_TELEMETRY, null); + if (typeof oldTelemetrySetting === 'boolean') { + return oldTelemetrySetting; + } + + const oldAllowReportSetting = config.get(CONFIG_ALLOW_REPORT, null); + if (typeof oldAllowReportSetting === 'boolean') { + return oldAllowReportSetting; + } + + return null; +} From 88f1b73f9eb4e0ac534106eba330b03182fb7b02 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 13 Nov 2019 00:31:28 +0200 Subject: [PATCH 45/46] import TelemetryOptInProvider --- src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts index 009f3d92d88cb3..1930d65d5c09b9 100644 --- a/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts +++ b/src/legacy/core_plugins/telemetry/public/hacks/telemetry_init.ts @@ -27,6 +27,7 @@ import { Telemetry } from './telemetry'; import { fetchTelemetry } from './fetch_telemetry'; // @ts-ignore import { isOptInHandleOldSettings } from './welcome_banner/handle_old_settings'; +import { TelemetryOptInProvider } from '../services'; function telemetryInit($injector: any) { const $http = $injector.get('$http'); From 2c126882e05013b429a603bbb3e8f643706b1403 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 13 Nov 2019 07:51:32 +0200 Subject: [PATCH 46/46] update test case --- .../telemetry_config/get_telemetry_opt_in.test.ts | 15 ++++++++++++--- .../telemetry_config/get_telemetry_opt_in.ts | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts index 24631ff6003bd7..efc4a020e0ff05 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.test.ts @@ -123,10 +123,12 @@ describe('getTelemetryOptIn', () => { interface CallGetTelemetryOptInParams { savedObjectNotFound: boolean; savedObjectForbidden: boolean; - enabled: boolean | null | undefined; lastVersionChecked?: any; // should be a string, but test with non-strings currentKibanaVersion: string; result?: boolean | null; + enabled: boolean | null | undefined; + configTelemetryOptIn: boolean | null; + allowChangingOptInStatus: boolean; } const DefaultParams = { @@ -135,6 +137,8 @@ const DefaultParams = { enabled: true, lastVersionChecked: '8.0.0', currentKibanaVersion: '8.0.0', + configTelemetryOptIn: null, + allowChangingOptInStatus: true, }; function getCallGetTelemetryOptInParams( @@ -144,9 +148,14 @@ function getCallGetTelemetryOptInParams( } function callGetTelemetryOptIn(params: CallGetTelemetryOptInParams) { - const { currentKibanaVersion } = params; + const { currentKibanaVersion, configTelemetryOptIn, allowChangingOptInStatus } = params; const telemetrySavedObject = getMockTelemetrySavedObject(params); - return getTelemetryOptIn({ currentKibanaVersion, telemetrySavedObject }); + return getTelemetryOptIn({ + currentKibanaVersion, + telemetrySavedObject, + allowChangingOptInStatus, + configTelemetryOptIn, + }); } function getMockTelemetrySavedObject(params: CallGetTelemetryOptInParams): TelemetrySavedObject { diff --git a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts index b2a2f603dcf10b..057a8b0c47958c 100644 --- a/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts +++ b/src/legacy/core_plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts @@ -24,7 +24,7 @@ interface GetTelemetryOptInConfig { telemetrySavedObject: TelemetrySavedObject; currentKibanaVersion: string; allowChangingOptInStatus: boolean; - configTelemetryOptIn: boolean; + configTelemetryOptIn: boolean | null; } type GetTelemetryOptIn = (config: GetTelemetryOptInConfig) => null | boolean;