diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx index 01365b51f9788..9461229313f4c 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx @@ -106,7 +106,10 @@ function LayerSettings({ iconType: t.icon || 'empty', }))} idSelected={layer.seriesType} - onChange={seriesType => setSeriesType(seriesType as SeriesType)} + onChange={seriesType => { + trackUiEvent('xy_change_layer_display'); + setSeriesType(seriesType as SeriesType); + }} isIconOnly buttonSize="compressed" /> diff --git a/x-pack/legacy/plugins/lens/server/usage/collectors.ts b/x-pack/legacy/plugins/lens/server/usage/collectors.ts index 305b2eac20849..60eb3c6e3651f 100644 --- a/x-pack/legacy/plugins/lens/server/usage/collectors.ts +++ b/x-pack/legacy/plugins/lens/server/usage/collectors.ts @@ -7,9 +7,8 @@ import moment from 'moment'; import { get } from 'lodash'; import { Server, KibanaConfig } from 'src/legacy/server/kbn_server'; -import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; import { CoreSetup, SavedObjectsLegacyService } from 'src/core/server'; -import { LensUsage } from './types'; +import { LensUsage, LensTelemetryState } from './types'; export function registerLensUsageCollector( core: CoreSetup, @@ -42,16 +41,21 @@ export function registerLensUsageCollector( const lensUsageCollector = plugins.usage.collectorSet.makeUsageCollector({ type: 'lens', - fetch: async (callCluster: CallCluster): Promise => { + fetch: async (): Promise => { try { const docs = await getLatestTaskState(plugins.server); // get the accumulated state from the recurring task - const state = get(docs, '[0].state'); + const state: LensTelemetryState = get(docs, '[0].state'); const dates = Object.keys(state.byDate || {}).map(dateStr => parseInt(dateStr, 10)); + const suggestionDates = Object.keys(state.suggestionsByDate || {}).map(dateStr => + parseInt(dateStr, 10) + ); const eventsLast30: Record = {}; const eventsLast90: Record = {}; + const suggestionsLast30: Record = {}; + const suggestionsLast90: Record = {}; const last30 = moment() .subtract(30, 'days') @@ -69,26 +73,35 @@ export function registerLensUsageCollector( } }); - console.log(state); + suggestionDates.forEach(date => { + if (date > last30) { + addEvents(suggestionsLast30, state.suggestionsByDate[date]); + addEvents(suggestionsLast90, state.suggestionsByDate[date]); + } else if (date > last90) { + addEvents(suggestionsLast90, state.suggestionsByDate[date]); + } + }); + return { ...state.saved, - clicks_last_30_days: eventsLast30, - clicks_last_90_days: eventsLast90, + events_30_days: eventsLast30, + events_90_days: eventsLast90, + suggestions_last_30_days: suggestionsLast30, + suggestions_last_90_days: suggestionsLast90, }; - // return getVisualizationCounts(callCluster, plugins.config); } catch (err) { return { saved_total: 0, saved_last_30_days: 0, saved_last_90_days: 0, - visualization_types_overall: {}, - visualization_types_last_30_days: {}, - visualization_types_last_90_days: {}, - - clicks_last_30_days: {}, - clicks_last_90_days: {}, - suggestion_clicks_last_30_days: {}, - suggestion_clicks_last_90_days: {}, + saved_overall: {}, + saved_30_days: {}, + saved_90_days: {}, + + events_30_days: {}, + events_90_days: {}, + suggestion_events_30_days: {}, + suggestion_events_90_days: {}, }; } }, diff --git a/x-pack/legacy/plugins/lens/server/usage/task.ts b/x-pack/legacy/plugins/lens/server/usage/task.ts index 1df318a2ef45a..3fcbb26001fc3 100644 --- a/x-pack/legacy/plugins/lens/server/usage/task.ts +++ b/x-pack/legacy/plugins/lens/server/usage/task.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Server, SavedObjectsClient as SavedObjectsClientType } from 'src/legacy/server/kbn_server'; +import moment from 'moment'; +import { Server } from 'src/legacy/server/kbn_server'; import { CoreSetup } from 'src/core/server'; import { CallClusterOptions } from 'src/legacy/core_plugins/elasticsearch'; import { SearchParams, SearchResponse, DeleteDocumentByQueryResponse } from 'elasticsearch'; @@ -65,7 +66,7 @@ function scheduleTasks(server: Server) { await taskManager.schedule({ id: TASK_ID, taskType: TELEMETRY_TASK_TYPE, - state: { byDate: {}, saved: {}, runs: 0 }, + state: { byDate: {}, suggestionsByDate: {}, saved: {}, runs: 0 }, params: {}, }); } catch (e) { @@ -77,7 +78,7 @@ function scheduleTasks(server: Server) { // type LensTaskState = LensUsage | {}; -async function doWork( +export async function doWork( prevState: any, server: Server, callCluster: ClusterSearchType & ClusterDeleteType @@ -100,11 +101,25 @@ async function doWork( daily: { date_histogram: { field: 'updated_at', - fixed_interval: '30d', + calendar_interval: '1d', }, aggs: { - names: { - terms: { field: 'lens-ui-telemetry.name', size: 100 }, + groups: { + filters: { + filters: { + suggestionEvent: { + bool: { filter: { term: { 'lens-ui-telemetry.type': 'suggestion' } } }, + }, + regularEvents: { + bool: { must_not: { term: { 'lens-ui-telemetry.type': 'suggestion' } } }, + }, + }, + }, + aggs: { + names: { + terms: { field: 'lens-ui-telemetry.name', size: 100 }, + }, + }, }, }, }, @@ -114,13 +129,39 @@ async function doWork( }); const byDateByType: Record> = prevState.byDate || {}; + const suggestionsByDate: Record> = + prevState.suggestionsByDate || {}; + + Object.keys(byDateByType).forEach(key => { + // Unix time + if (moment(key, 'x').isBefore(moment().subtract(30, 'days'))) { + // Remove this key + delete byDateByType[key]; + return; + } + }); + + Object.keys(suggestionsByDate).forEach(key => { + // Unix time + if (moment(key, 'x').isBefore(moment().subtract(30, 'days'))) { + // Remove this key + delete suggestionsByDate[key]; + return; + } + }); + + metrics.aggregations.daily.buckets.forEach(daily => { + const byType: Record = byDateByType[daily.key] || {}; + daily.groups.buckets.regularEvents.names.buckets.forEach(({ key, doc_count }) => { + byType[key] = doc_count + (byType[daily.key] || 0); + }); + byDateByType[daily.key] = byType; - metrics.aggregations.daily.buckets.forEach(bucket => { - const byType: Record = byDateByType[bucket.key] || {}; - bucket.names.buckets.forEach(({ key, doc_count }) => { - byType[key] = doc_count + (byType[key] || 0); + const suggestionsByType: Record = suggestionsByDate[daily.key] || {}; + daily.groups.buckets.suggestionEvent.names.buckets.forEach(({ key, doc_count }) => { + suggestionsByType[key] = doc_count + (byType[daily.key] || 0); }); - byDateByType[bucket.key] = byType; + suggestionsByDate[daily.key] = suggestionsByType; }); if (metrics.hits.total > 0) { @@ -137,7 +178,10 @@ async function doWork( }); } - return byDateByType; + return { + byDate: byDateByType, + suggestionsByDate, + }; } function telemetryTaskRunner(server: Server) { @@ -162,10 +206,17 @@ function telemetryTaskRunner(server: Server) { return Promise.all([lensTelemetryTask, lensVisualizationTask]) .then(([lensTelemetry, lensVisualizations]) => { + console.log({ + runs: (state.runs || 0) + 1, + byDate: (lensTelemetry && lensTelemetry.byDate) || {}, + suggestionsByDate: (lensTelemetry && lensTelemetry.suggestionsByDate) || {}, + saved: lensVisualizations, + }); return { state: { runs: (state.runs || 0) + 1, - byDate: lensTelemetry || {}, + byDate: (lensTelemetry && lensTelemetry.byDate) || {}, + suggestionsByDate: (lensTelemetry && lensTelemetry.suggestionsByDate) || {}, saved: lensVisualizations, }, runAt: getNextMidnight(), diff --git a/x-pack/legacy/plugins/lens/server/usage/types.ts b/x-pack/legacy/plugins/lens/server/usage/types.ts index 4da3e0cb53812..b09c41dca876b 100644 --- a/x-pack/legacy/plugins/lens/server/usage/types.ts +++ b/x-pack/legacy/plugins/lens/server/usage/types.ts @@ -4,20 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ +export interface LensTelemetryState { + runs: number; + byDate: Record>; + suggestionsByDate: Record>; + saved: LensVisualizationUsage; +} + export interface LensVisualizationUsage { - visualization_types_overall: Record; - visualization_types_last_30_days: Record; - visualization_types_last_90_days: Record; + saved_overall: Record; + saved_30_days: Record; + saved_90_days: Record; saved_total: number; saved_last_30_days: number; saved_last_90_days: number; } export interface LensClickUsage { - clicks_last_30_days: Record; - clicks_last_90_days: Record; - suggestion_clicks_last_30_days: Record; - suggestion_clicks_last_90_days: Record; + events_30_days: Record; + events_90_days: Record; + suggestion_events_30_days: Record; + suggestion_events_90_days: Record; } -export type LensUsage = LensVisualizationUsage & LensClickUsage; \ No newline at end of file +export type LensUsage = LensVisualizationUsage & LensClickUsage; diff --git a/x-pack/legacy/plugins/lens/server/usage/visualization_counts.ts b/x-pack/legacy/plugins/lens/server/usage/visualization_counts.ts index 4402431897d4e..95d3366621f42 100644 --- a/x-pack/legacy/plugins/lens/server/usage/visualization_counts.ts +++ b/x-pack/legacy/plugins/lens/server/usage/visualization_counts.ts @@ -82,9 +82,9 @@ export async function getVisualizationCounts( const buckets = results.aggregations.groups.buckets; return { - visualization_types_overall: buckets.overall.byType.value.types, - visualization_types_last_30_days: buckets.last30.byType.value.types, - visualization_types_last_90_days: buckets.last90.byType.value.types, + saved_overall: buckets.overall.byType.value.types, + saved_30_days: buckets.last30.byType.value.types, + saved_90_days: buckets.last90.byType.value.types, saved_total: buckets.overall.doc_count, saved_last_30_days: buckets.last30.doc_count, saved_last_90_days: buckets.last90.doc_count, diff --git a/x-pack/test/functional/apps/lens/smokescreen.ts b/x-pack/test/functional/apps/lens/smokescreen.ts index 0a1611a3982d5..db7a17cef5dd6 100644 --- a/x-pack/test/functional/apps/lens/smokescreen.ts +++ b/x-pack/test/functional/apps/lens/smokescreen.ts @@ -131,15 +131,15 @@ export default function({ getService, getPageObjects, ...rest }: FtrProviderCont } as KibanaConfig); expect(results).to.have.keys([ - 'visualization_types_overall', - 'visualization_types_last_30_days', - 'visualization_types_last_90_days', + 'saved_overall', + 'saved_30_days', + 'saved_90_days', 'saved_total', 'saved_last_30_days', 'saved_last_90_days', ]); - expect(results.visualization_types_overall).to.eql({ + expect(results.saved_overall).to.eql({ lnsMetric: 1, bar_stacked: 1, });