diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index ba27dc7538cff..fde583cf907e4 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -10112,122 +10112,6 @@ } } } - }, - "vis_type_table": { - "properties": { - "total": { - "type": "long" - }, - "total_split": { - "type": "long" - }, - "split_columns": { - "properties": { - "total": { - "type": "long" - }, - "enabled": { - "type": "long" - } - } - }, - "split_rows": { - "properties": { - "total": { - "type": "long" - }, - "enabled": { - "type": "long" - } - } - } - } - }, - "vis_type_timeseries": { - "properties": { - "timeseries_use_last_value_mode_total": { - "type": "long", - "_meta": { - "description": "Number of TSVB visualizations using \"last value\" as a time range" - } - }, - "timeseries_use_es_indices_total": { - "type": "long", - "_meta": { - "description": "Number of TSVB visualizations using elasticsearch indices" - } - }, - "timeseries_table_use_aggregate_function": { - "type": "long", - "_meta": { - "description": "Number of TSVB table visualizations using aggregate function" - } - }, - "timeseries_types": { - "properties": { - "table": { - "type": "long" - }, - "gauge": { - "type": "long" - }, - "markdown": { - "type": "long" - }, - "top_n": { - "type": "long" - }, - "timeseries": { - "type": "long" - }, - "metric": { - "type": "long" - } - } - } - } - }, - "vis_type_vega": { - "properties": { - "vega_lib_specs_total": { - "type": "long" - }, - "vega_lite_lib_specs_total": { - "type": "long" - }, - "vega_use_map_total": { - "type": "long" - } - } - }, - "visualization_types": { - "properties": { - "DYNAMIC_KEY": { - "properties": { - "total": { - "type": "long" - }, - "spaces_min": { - "type": "long" - }, - "spaces_max": { - "type": "long" - }, - "spaces_avg": { - "type": "long" - }, - "saved_7_days_total": { - "type": "long" - }, - "saved_30_days_total": { - "type": "long" - }, - "saved_90_days_total": { - "type": "long" - } - } - } - } } } } diff --git a/src/plugins/vis_types/heatmap/public/editor/components/index.tsx b/src/plugins/vis_types/heatmap/public/editor/components/index.tsx index 59db84b0db665..cac64d00af9cd 100644 --- a/src/plugins/vis_types/heatmap/public/editor/components/index.tsx +++ b/src/plugins/vis_types/heatmap/public/editor/components/index.tsx @@ -13,13 +13,12 @@ import { HeatmapVisParams, HeatmapTypeProps } from '../../types'; const HeatmapOptionsLazy = lazy(() => import('./heatmap')); export const getHeatmapOptions = - ({ showElasticChartsOptions, palettes, trackUiMetric }: HeatmapTypeProps) => + ({ showElasticChartsOptions, palettes }: HeatmapTypeProps) => (props: VisEditorOptionsProps) => ( ); diff --git a/src/plugins/vis_types/heatmap/public/plugin.ts b/src/plugins/vis_types/heatmap/public/plugin.ts index c84c8830318c2..44357cceaa86b 100644 --- a/src/plugins/vis_types/heatmap/public/plugin.ts +++ b/src/plugins/vis_types/heatmap/public/plugin.ts @@ -34,16 +34,10 @@ export class VisTypeHeatmapPlugin { { visualizations, charts, usageCollection }: VisTypeHeatmapSetupDependencies ) { if (!core.uiSettings.get(LEGACY_HEATMAP_CHARTS_LIBRARY)) { - const trackUiMetric = usageCollection?.reportUiCounter.bind( - usageCollection, - 'vis_type_heatmap' - ); - visualizations.createBaseVisualization( heatmapVisType({ showElasticChartsOptions: true, palettes: charts.palettes, - trackUiMetric, }) ); } diff --git a/src/plugins/vis_types/heatmap/public/types.ts b/src/plugins/vis_types/heatmap/public/types.ts index 9d41a132f00b1..e29b77746b070 100644 --- a/src/plugins/vis_types/heatmap/public/types.ts +++ b/src/plugins/vis_types/heatmap/public/types.ts @@ -5,7 +5,6 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { UiCounterMetricType } from '@kbn/analytics'; import type { Position } from '@elastic/charts'; import type { ChartsPluginSetup, Style, Labels, ColorSchemas } from '@kbn/charts-plugin/public'; import { Range } from '@kbn/expressions-plugin/public'; @@ -14,7 +13,6 @@ import { LegendSize } from '@kbn/visualizations-plugin/public'; export interface HeatmapTypeProps { showElasticChartsOptions?: boolean; palettes?: ChartsPluginSetup['palettes']; - trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; } export interface HeatmapVisParams { diff --git a/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx b/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx index ee2893f2cb190..e5a92ca03f5cc 100644 --- a/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx +++ b/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx @@ -20,7 +20,6 @@ import { SplitTooltip } from './split_tooltip'; export const getHeatmapVisTypeDefinition = ({ showElasticChartsOptions = false, palettes, - trackUiMetric, }: HeatmapTypeProps): VisTypeDefinition => ({ name: 'heatmap', title: i18n.translate('visTypeHeatmap.heatmap.heatmapTitle', { defaultMessage: 'Heat map' }), @@ -68,7 +67,6 @@ export const getHeatmapVisTypeDefinition = ({ optionsTemplate: getHeatmapOptions({ showElasticChartsOptions, palettes, - trackUiMetric, }), schemas: [ { diff --git a/src/plugins/vis_types/pie/public/editor/components/index.tsx b/src/plugins/vis_types/pie/public/editor/components/index.tsx index f21af20f6b2af..4290634cdeb78 100644 --- a/src/plugins/vis_types/pie/public/editor/components/index.tsx +++ b/src/plugins/vis_types/pie/public/editor/components/index.tsx @@ -14,13 +14,12 @@ import { PieTypeProps } from '../../types'; const PieOptionsLazy = lazy(() => import('./pie')); export const getPieOptions = - ({ showElasticChartsOptions, palettes, trackUiMetric }: PieTypeProps) => + ({ showElasticChartsOptions, palettes }: PieTypeProps) => (props: VisEditorOptionsProps) => ( ); diff --git a/src/plugins/vis_types/pie/public/editor/components/pie.tsx b/src/plugins/vis_types/pie/public/editor/components/pie.tsx index cd1e565861d78..a22f29415d5b5 100644 --- a/src/plugins/vis_types/pie/public/editor/components/pie.tsx +++ b/src/plugins/vis_types/pie/public/editor/components/pie.tsx @@ -7,7 +7,6 @@ */ import React, { useState, useEffect, useCallback } from 'react'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiPanel, EuiTitle, @@ -223,9 +222,6 @@ const PieOptions = (props: PieOptionsProps) => { value={stateParams.nestedLegend} disabled={stateParams.legendDisplay === LegendDisplay.HIDE} setValue={(paramName, value) => { - if (props.trackUiMetric) { - props.trackUiMetric(METRIC_TYPE.CLICK, 'nested_legend_switched'); - } setValue(paramName, value); }} data-test-subj="visTypePieNestedLegendSwitch" @@ -253,9 +249,6 @@ const PieOptions = (props: PieOptionsProps) => { activePalette={stateParams.palette} paramName="palette" setPalette={(paramName, value) => { - if (props.trackUiMetric) { - props.trackUiMetric(METRIC_TYPE.CLICK, 'palette_selected'); - } setValue(paramName, value); }} /> @@ -296,9 +289,6 @@ const PieOptions = (props: PieOptionsProps) => { : stateParams.labels.position || LabelPositions.DEFAULT } setValue={(paramName, value) => { - if (props.trackUiMetric) { - props.trackUiMetric(METRIC_TYPE.CLICK, 'label_position_selected'); - } setLabels(paramName, value); }} data-test-subj="visTypePieLabelPositionSelect" @@ -338,9 +328,6 @@ const PieOptions = (props: PieOptionsProps) => { paramName="valuesFormat" value={stateParams.labels.valuesFormat || ValueFormats.PERCENT} setValue={(paramName, value) => { - if (props.trackUiMetric) { - props.trackUiMetric(METRIC_TYPE.CLICK, 'values_format_selected'); - } setLabels(paramName, value); }} data-test-subj="visTypePieValueFormatsSelect" diff --git a/src/plugins/vis_types/pie/public/plugin.ts b/src/plugins/vis_types/pie/public/plugin.ts index ac219d29b5479..480cf0c49db63 100644 --- a/src/plugins/vis_types/pie/public/plugin.ts +++ b/src/plugins/vis_types/pie/public/plugin.ts @@ -43,12 +43,10 @@ export class VisTypePiePlugin { { visualizations, charts, usageCollection }: VisTypePieSetupDependencies ) { if (!core.uiSettings.get(LEGACY_PIE_CHARTS_LIBRARY, false)) { - const trackUiMetric = usageCollection?.reportUiCounter.bind(usageCollection, 'vis_type_pie'); visualizations.createBaseVisualization( pieVisType({ showElasticChartsOptions: true, palettes: charts.palettes, - trackUiMetric, }) ); } diff --git a/src/plugins/vis_types/pie/public/types/types.ts b/src/plugins/vis_types/pie/public/types/types.ts index 968e04fd59075..a13ed368d8dec 100644 --- a/src/plugins/vis_types/pie/public/types/types.ts +++ b/src/plugins/vis_types/pie/public/types/types.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { UiCounterMetricType } from '@kbn/analytics'; import { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; import { ChartsPluginSetup } from '@kbn/charts-plugin/public'; @@ -28,5 +27,4 @@ export interface Dimensions { export interface PieTypeProps { showElasticChartsOptions?: boolean; palettes?: ChartsPluginSetup['palettes']; - trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; } diff --git a/src/plugins/vis_types/pie/public/vis_type/pie.ts b/src/plugins/vis_types/pie/public/vis_type/pie.ts index 113c277d5e210..6d48507cf47a3 100644 --- a/src/plugins/vis_types/pie/public/vis_type/pie.ts +++ b/src/plugins/vis_types/pie/public/vis_type/pie.ts @@ -25,7 +25,6 @@ import { getPieOptions } from '../editor/components'; export const getPieVisTypeDefinition = ({ showElasticChartsOptions = false, palettes, - trackUiMetric, }: PieTypeProps): VisTypeDefinition => ({ name: 'pie', title: i18n.translate('visTypePie.pie.pieTitle', { defaultMessage: 'Pie' }), @@ -68,7 +67,6 @@ export const getPieVisTypeDefinition = ({ optionsTemplate: getPieOptions({ showElasticChartsOptions, palettes, - trackUiMetric, }), schemas: [ { diff --git a/src/plugins/vis_types/table/kibana.json b/src/plugins/vis_types/table/kibana.json index a56965a214349..28b21fc55f453 100644 --- a/src/plugins/vis_types/table/kibana.json +++ b/src/plugins/vis_types/table/kibana.json @@ -14,7 +14,6 @@ "share", "visDefaultEditor" ], - "optionalPlugins": ["usageCollection"], "owner": { "name": "Vis Editors", "githubTeam": "kibana-vis-editors" diff --git a/src/plugins/vis_types/table/server/index.ts b/src/plugins/vis_types/table/server/index.ts index 0d1eade453f6c..a7f63648ba422 100644 --- a/src/plugins/vis_types/table/server/index.ts +++ b/src/plugins/vis_types/table/server/index.ts @@ -6,21 +6,14 @@ * Side Public License, v 1. */ -import { CoreSetup, PluginConfigDescriptor } from '@kbn/core/server'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; - +import { PluginConfigDescriptor } from '@kbn/core/server'; import { configSchema, ConfigSchema } from '../config'; -import { registerVisTypeTableUsageCollector } from './usage_collector'; export const config: PluginConfigDescriptor = { schema: configSchema, }; export const plugin = () => ({ - setup(core: CoreSetup, plugins: { usageCollection?: UsageCollectionSetup }) { - if (plugins.usageCollection) { - registerVisTypeTableUsageCollector(plugins.usageCollection); - } - }, + setup() {}, start() {}, }); diff --git a/src/plugins/vis_types/table/server/usage_collector/get_stats.test.ts b/src/plugins/vis_types/table/server/usage_collector/get_stats.test.ts deleted file mode 100644 index cba5bce0c5bbf..0000000000000 --- a/src/plugins/vis_types/table/server/usage_collector/get_stats.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { getStats } from './get_stats'; -import type { SavedObjectsClientContract } from '@kbn/core/server'; - -const mockVisualizations = { - saved_objects: [ - { - attributes: { - visState: - '{"type": "table","aggs": [{ "schema": "metric" }, { "schema": "bucket" }, { "schema": "split", "enabled": true }], "params": { "row": true }}', - }, - }, - { - attributes: { - visState: - '{"type": "table","aggs": [{ "schema": "metric" }, { "schema": "bucket" }, { "schema": "split", "enabled": false }], "params": { "row": true }}', - }, - }, - { - attributes: { - visState: - '{"type": "table","aggs": [{ "schema": "metric" }, { "schema": "split", "enabled": true }], "params": { "row": false }}', - }, - }, - { - attributes: { - visState: '{"type": "table","aggs": [{ "schema": "metric" }, { "schema": "bucket" }]}', - }, - }, - { - attributes: { visState: '{"type": "histogram"}' }, - }, - ], -}; - -describe('vis_type_table getStats', () => { - const mockSoClient = { - createPointInTimeFinder: jest.fn().mockResolvedValue({ - close: jest.fn(), - find: function* asyncGenerator() { - yield mockVisualizations; - }, - }), - } as unknown as SavedObjectsClientContract; - - test('Returns stats from saved objects for table vis only', async () => { - const result = await getStats(mockSoClient); - - expect(mockSoClient.createPointInTimeFinder).toHaveBeenCalledWith({ - type: 'visualization', - perPage: 1000, - namespaces: ['*'], - }); - - expect(result).toEqual({ - total: 4, - total_split: 3, - split_columns: { - total: 1, - enabled: 1, - }, - split_rows: { - total: 2, - enabled: 1, - }, - }); - }); -}); diff --git a/src/plugins/vis_types/table/server/usage_collector/get_stats.ts b/src/plugins/vis_types/table/server/usage_collector/get_stats.ts deleted file mode 100644 index 288a48a20cc81..0000000000000 --- a/src/plugins/vis_types/table/server/usage_collector/get_stats.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import type { - ISavedObjectsRepository, - SavedObjectsClientContract, - SavedObjectsFindResult, -} from '@kbn/core/server'; -import type { SavedVisState } from '@kbn/visualizations-plugin/common'; -import { VIS_TYPE_TABLE } from '../../common'; - -export interface VisTypeTableUsage { - /** - * Total number of table type visualizations - */ - total: number; - /** - * Total number of table visualizations, using "Split table" agg - */ - total_split: number; - /** - * Split table by columns stats - */ - split_columns: { - total: number; - enabled: number; - }; - /** - * Split table by rows stats - */ - split_rows: { - total: number; - enabled: number; - }; -} - -/* - * Parse the response data into telemetry payload - */ -export async function getStats( - soClient: SavedObjectsClientContract | ISavedObjectsRepository -): Promise { - const finder = await soClient.createPointInTimeFinder({ - type: 'visualization', - perPage: 1000, - namespaces: ['*'], - }); - - const stats: VisTypeTableUsage = { - total: 0, - total_split: 0, - split_columns: { - total: 0, - enabled: 0, - }, - split_rows: { - total: 0, - enabled: 0, - }, - }; - - const doTelemetry = ({ aggs, params }: SavedVisState) => { - stats.total += 1; - - const hasSplitAgg = aggs.find((agg) => agg.schema === 'split'); - - if (hasSplitAgg) { - stats.total_split += 1; - - const isSplitRow = params.row; - const isSplitEnabled = hasSplitAgg.enabled; - const container = isSplitRow ? stats.split_rows : stats.split_columns; - - container.total += 1; - container.enabled = isSplitEnabled ? container.enabled + 1 : container.enabled; - } - }; - - for await (const response of finder.find()) { - (response.saved_objects || []).forEach(({ attributes }: SavedObjectsFindResult) => { - if (attributes?.visState) { - try { - const visState: SavedVisState = JSON.parse(attributes.visState); - - if (visState.type === VIS_TYPE_TABLE) { - doTelemetry(visState); - } - } catch { - // nothing to be here, "so" not valid - } - } - }); - } - await finder.close(); - - return stats; -} diff --git a/src/plugins/vis_types/table/server/usage_collector/index.ts b/src/plugins/vis_types/table/server/usage_collector/index.ts deleted file mode 100644 index 6a2e893a354e0..0000000000000 --- a/src/plugins/vis_types/table/server/usage_collector/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { registerVisTypeTableUsageCollector } from './register_usage_collector'; diff --git a/src/plugins/vis_types/table/server/usage_collector/register_usage_collector.test.ts b/src/plugins/vis_types/table/server/usage_collector/register_usage_collector.test.ts deleted file mode 100644 index 7d6c4e54ff8fd..0000000000000 --- a/src/plugins/vis_types/table/server/usage_collector/register_usage_collector.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { - createUsageCollectionSetupMock, - createCollectorFetchContextMock, -} from '@kbn/usage-collection-plugin/server/mocks'; -import { registerVisTypeTableUsageCollector } from './register_usage_collector'; -import { getStats } from './get_stats'; - -jest.mock('./get_stats', () => ({ - getStats: jest.fn().mockResolvedValue({ somestat: 1 }), -})); - -describe('registerVisTypeTableUsageCollector', () => { - test('Usage collector configs fit the shape', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVisTypeTableUsageCollector(mockCollectorSet); - expect(mockCollectorSet.makeUsageCollector).toBeCalledTimes(1); - expect(mockCollectorSet.registerCollector).toBeCalledTimes(1); - expect(mockCollectorSet.makeUsageCollector).toHaveBeenCalledWith({ - type: 'vis_type_table', - isReady: expect.any(Function), - fetch: expect.any(Function), - schema: { - total: { type: 'long' }, - total_split: { type: 'long' }, - split_columns: { - total: { type: 'long' }, - enabled: { type: 'long' }, - }, - split_rows: { - total: { type: 'long' }, - enabled: { type: 'long' }, - }, - }, - }); - const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; - expect(usageCollectorConfig.isReady()).toBe(true); - }); - - test('Usage collector config.fetch calls getStats', async () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVisTypeTableUsageCollector(mockCollectorSet); - const usageCollector = mockCollectorSet.makeUsageCollector.mock.results[0].value; - const mockCollectorFetchContext = createCollectorFetchContextMock(); - const fetchResult = await usageCollector.fetch(mockCollectorFetchContext); - expect(getStats).toBeCalledTimes(1); - expect(getStats).toBeCalledWith(mockCollectorFetchContext.soClient); - expect(fetchResult).toEqual({ somestat: 1 }); - }); -}); diff --git a/src/plugins/vis_types/table/server/usage_collector/register_usage_collector.ts b/src/plugins/vis_types/table/server/usage_collector/register_usage_collector.ts deleted file mode 100644 index 75cc7c0b11f1a..0000000000000 --- a/src/plugins/vis_types/table/server/usage_collector/register_usage_collector.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import { getStats, VisTypeTableUsage } from './get_stats'; - -export function registerVisTypeTableUsageCollector(collectorSet: UsageCollectionSetup) { - const collector = collectorSet.makeUsageCollector({ - type: 'vis_type_table', - isReady: () => true, - schema: { - total: { type: 'long' }, - total_split: { type: 'long' }, - split_columns: { - total: { type: 'long' }, - enabled: { type: 'long' }, - }, - split_rows: { - total: { type: 'long' }, - enabled: { type: 'long' }, - }, - }, - fetch: ({ soClient }) => getStats(soClient), - }); - collectorSet.registerCollector(collector); -} diff --git a/src/plugins/vis_types/table/tsconfig.json b/src/plugins/vis_types/table/tsconfig.json index 578b10fb09be8..6df0a83853142 100644 --- a/src/plugins/vis_types/table/tsconfig.json +++ b/src/plugins/vis_types/table/tsconfig.json @@ -17,7 +17,6 @@ { "path": "../../data/tsconfig.json" }, { "path": "../../visualizations/tsconfig.json" }, { "path": "../../share/tsconfig.json" }, - { "path": "../../usage_collection/tsconfig.json" }, { "path": "../../expressions/tsconfig.json" }, { "path": "../../kibana_utils/tsconfig.json" }, { "path": "../../kibana_react/tsconfig.json" }, diff --git a/src/plugins/vis_types/timeseries/kibana.json b/src/plugins/vis_types/timeseries/kibana.json index 8f12e7c4d3ca5..199b0e00242d3 100644 --- a/src/plugins/vis_types/timeseries/kibana.json +++ b/src/plugins/vis_types/timeseries/kibana.json @@ -5,7 +5,7 @@ "server": true, "ui": true, "requiredPlugins": ["charts", "data", "expressions", "visualizations", "inspector", "dataViews"], - "optionalPlugins": ["home","usageCollection"], + "optionalPlugins": ["home"], "requiredBundles": ["unifiedSearch", "kibanaUtils", "kibanaReact", "fieldFormats"], "owner": { "name": "Vis Editors", diff --git a/src/plugins/vis_types/timeseries/server/plugin.ts b/src/plugins/vis_types/timeseries/server/plugin.ts index 31ca2667ed3a7..6ca50032aa689 100644 --- a/src/plugins/vis_types/timeseries/server/plugin.ts +++ b/src/plugins/vis_types/timeseries/server/plugin.ts @@ -18,7 +18,6 @@ import { import { firstValueFrom, Observable } from 'rxjs'; import { Server } from '@hapi/hapi'; import { map } from 'rxjs/operators'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { HomeServerPluginSetup } from '@kbn/home-plugin/server'; import { PluginStart } from '@kbn/data-plugin/server'; import type { DataViewsService } from '@kbn/data-views-plugin/common'; @@ -41,14 +40,11 @@ import { } from './lib/search_strategies'; import type { TimeseriesVisData, VisPayload } from '../common/types'; -import { registerTimeseriesUsageCollector } from './usage_collector'; - export interface LegacySetup { server: Server; } interface VisTypeTimeseriesPluginSetupDependencies { - usageCollection?: UsageCollectionSetup; home?: HomeServerPluginSetup; } @@ -128,10 +124,6 @@ export class VisTypeTimeseriesPlugin implements Plugin { visDataRoutes(router, framework); fieldsRoutes(router, framework); - if (plugins.usageCollection) { - registerTimeseriesUsageCollector(plugins.usageCollection, plugins.home); - } - return { getVisData: async ( requestContext: VisTypeTimeseriesRequestHandlerContext, diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.mock.ts b/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.mock.ts deleted file mode 100644 index bb52d215c67e8..0000000000000 --- a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.mock.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export const mockStats = { somestat: 1 }; -export const mockGetStats = jest.fn().mockResolvedValue(mockStats); - -jest.doMock('./get_usage_collector', () => ({ - getStats: mockGetStats, -})); diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.test.ts b/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.test.ts deleted file mode 100644 index 6304e7e6518ba..0000000000000 --- a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.test.ts +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { getStats } from './get_usage_collector'; -import { createCollectorFetchContextMock } from '@kbn/usage-collection-plugin/server/mocks'; -import type { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server'; -import { TIME_RANGE_DATA_MODES } from '../../common/enums'; - -const mockedSavedObject = { - saved_objects: [ - { - attributes: { - visState: JSON.stringify({ - type: 'metrics', - title: 'TSVB visualization 1', - params: { - type: 'gauge', - time_range_mode: TIME_RANGE_DATA_MODES.ENTIRE_TIME_RANGE, - use_kibana_indexes: true, - }, - }), - }, - }, - { - attributes: { - visState: JSON.stringify({ - type: 'metrics', - title: 'TSVB visualization 2', - params: { - type: 'top_n', - time_range_mode: TIME_RANGE_DATA_MODES.LAST_VALUE, - use_kibana_indexes: false, - }, - }), - }, - }, - { - attributes: { - visState: JSON.stringify({ - type: 'metrics', - title: 'TSVB visualization 3', - params: { - type: 'markdown', - time_range_mode: undefined, - use_kibana_indexes: false, - }, - }), - }, - }, - { - attributes: { - visState: JSON.stringify({ - type: 'metrics', - title: 'TSVB visualization 4', - params: { - type: 'table', - series: [ - { - aggregate_by: 'test', - aggregate_function: 'max', - }, - ], - }, - }), - }, - }, - ], -} as SavedObjectsFindResponse; - -const mockedSavedObjectsByValue = [ - { - attributes: { - panelsJSON: JSON.stringify({ - type: 'visualization', - embeddableConfig: { - savedVis: { - type: 'metrics', - params: { - type: 'markdown', - time_range_mode: TIME_RANGE_DATA_MODES.LAST_VALUE, - use_kibana_indexes: false, - }, - }, - }, - }), - }, - }, - { - attributes: { - panelsJSON: JSON.stringify({ - type: 'visualization', - embeddableConfig: { - savedVis: { - type: 'metrics', - params: { - type: 'timeseries', - time_range_mode: TIME_RANGE_DATA_MODES.ENTIRE_TIME_RANGE, - use_kibana_indexes: true, - }, - }, - }, - }), - }, - }, - { - attributes: { - panelsJSON: JSON.stringify({ - type: 'visualization', - embeddableConfig: { - savedVis: { - type: 'metrics', - params: { - type: 'table', - series: [ - { - aggregate_by: 'test1', - aggregate_function: 'sum', - }, - ], - use_kibana_indexes: true, - }, - }, - }, - }), - }, - }, -]; - -const getMockCollectorFetchContext = ( - savedObjects: SavedObjectsFindResponse, - savedObjectsByValue: unknown[] = [] -) => { - const fetchParamsMock = createCollectorFetchContextMock(); - - fetchParamsMock.soClient = { - find: jest.fn().mockResolvedValue({ - saved_objects: savedObjectsByValue, - }), - createPointInTimeFinder: jest.fn().mockResolvedValue({ - close: jest.fn(), - find: function* asyncGenerator() { - yield savedObjects; - }, - }), - } as unknown as SavedObjectsClientContract; - return fetchParamsMock; -}; - -describe('Timeseries visualization usage collector', () => { - test('Returns undefined when no results found (undefined)', async () => { - const mockCollectorFetchContext = getMockCollectorFetchContext( - { saved_objects: [] } as unknown as SavedObjectsFindResponse, - [] - ); - const result = await getStats(mockCollectorFetchContext.soClient); - - expect(result).toBeUndefined(); - }); - - test('Returns undefined when no timeseries saved objects found', async () => { - const mockCollectorFetchContext = getMockCollectorFetchContext({ - saved_objects: [ - { - attributes: { visState: '{"type": "area"}' }, - }, - { - attributes: { - panelsJSON: JSON.stringify({ - type: 'visualization', - embeddableConfig: { - savedVis: { - type: 'area', - }, - }, - }), - }, - }, - ], - } as SavedObjectsFindResponse); - - const result = await getStats(mockCollectorFetchContext.soClient); - - expect(result).toBeUndefined(); - }); - - test('Returns undefined when aggregate function is null', async () => { - const mockCollectorFetchContext = getMockCollectorFetchContext({ - saved_objects: [ - { - attributes: { - panelsJSON: JSON.stringify({ - type: 'visualization', - embeddableConfig: { - savedVis: { - type: 'metrics', - params: { - type: 'table', - series: [ - { - aggregate_by: null, - aggregate_function: null, - }, - ], - }, - }, - }, - }), - }, - }, - { - attributes: { - panelsJSON: JSON.stringify({ - type: 'visualization', - embeddableConfig: { - savedVis: { - type: 'metrics', - params: { - type: 'table', - series: [ - { - axis_position: 'right', - }, - ], - }, - }, - }, - }), - }, - }, - ], - } as SavedObjectsFindResponse); - - const result = await getStats(mockCollectorFetchContext.soClient); - - expect(result).toBeUndefined(); - }); - - test('Summarizes visualizations response data', async () => { - const mockCollectorFetchContext = getMockCollectorFetchContext( - mockedSavedObject, - mockedSavedObjectsByValue - ); - const result = await getStats(mockCollectorFetchContext.soClient); - - expect(result).toStrictEqual({ - timeseries_use_last_value_mode_total: 5, - timeseries_use_es_indices_total: 4, - timeseries_table_use_aggregate_function: 2, - timeseries_types: { - gauge: 1, - markdown: 2, - metric: 0, - table: 2, - timeseries: 1, - top_n: 1, - }, - }); - }); -}); diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.ts b/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.ts deleted file mode 100644 index 1a6c060cd7f96..0000000000000 --- a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.ts +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { findByValueEmbeddables } from '@kbn/dashboard-plugin/server'; - -import type { - SavedObjectsClientContract, - ISavedObjectsRepository, - SavedObjectsFindResult, -} from '@kbn/core/server'; -import type { HomeServerPluginSetup } from '@kbn/home-plugin/server'; -import type { SavedVisState } from '@kbn/visualizations-plugin/common'; -import { TIME_RANGE_DATA_MODES } from '../../common/enums'; -import type { Panel } from '../../common/types'; - -export interface TimeseriesUsage { - timeseries_use_last_value_mode_total: number; - timeseries_use_es_indices_total: number; - timeseries_table_use_aggregate_function: number; - timeseries_types: { - table: number; - gauge: number; - markdown: number; - top_n: number; - timeseries: number; - metric: number; - }; -} - -const doTelemetryFoVisualizations = async ( - soClient: SavedObjectsClientContract | ISavedObjectsRepository, - calculateTelemetry: (savedVis: SavedVisState) => void -) => { - const finder = await soClient.createPointInTimeFinder({ - type: 'visualization', - perPage: 1000, - namespaces: ['*'], - }); - - for await (const response of finder.find()) { - (response.saved_objects || []).forEach(({ attributes }: SavedObjectsFindResult) => { - if (attributes?.visState) { - try { - const visState: SavedVisState = JSON.parse(attributes.visState); - - calculateTelemetry(visState); - } catch { - // nothing to be here, "so" not valid - } - } - }); - } - await finder.close(); -}; - -const doTelemetryForByValueVisualizations = async ( - soClient: SavedObjectsClientContract | ISavedObjectsRepository, - telemetryUseLastValueMode: (savedVis: SavedVisState) => void -) => { - const byValueVisualizations = await findByValueEmbeddables(soClient, 'visualization'); - - for (const item of byValueVisualizations) { - telemetryUseLastValueMode(item.savedVis as unknown as SavedVisState); - } -}; - -const getDefaultTSVBVisualizations = (home?: HomeServerPluginSetup) => { - const titles: string[] = []; - const sampleDataSets = home?.sampleData.getSampleDatasets() ?? []; - - sampleDataSets.forEach((sampleDataSet) => - sampleDataSet.savedObjects.forEach((savedObject) => { - try { - if (savedObject.type === 'visualization') { - const visState = JSON.parse(savedObject.attributes?.visState); - - if (visState.type === 'metrics') { - titles.push(visState.title); - } - } - } catch (e) { - // Let it go, visState is invalid and we'll don't need to handle it - } - }) - ); - - return titles; -}; - -export const getStats = async ( - soClient: SavedObjectsClientContract | ISavedObjectsRepository, - home?: HomeServerPluginSetup -): Promise => { - const timeseriesUsage = { - timeseries_use_last_value_mode_total: 0, - timeseries_use_es_indices_total: 0, - timeseries_table_use_aggregate_function: 0, - timeseries_types: { - gauge: 0, - markdown: 0, - metric: 0, - table: 0, - timeseries: 0, - top_n: 0, - }, - }; - - // we want to exclude the TSVB Sample Data visualizations from the stats - // in order to have more accurate results - const excludedFromStatsVisualizations = getDefaultTSVBVisualizations(home); - - function telemetryUseLastValueMode(visState: SavedVisState) { - if ( - visState.type === 'metrics' && - visState.params.type !== 'timeseries' && - (!visState.params.time_range_mode || - visState.params.time_range_mode === TIME_RANGE_DATA_MODES.LAST_VALUE) && - !excludedFromStatsVisualizations.includes(visState.title) - ) { - timeseriesUsage.timeseries_use_last_value_mode_total++; - } - } - - function telemetryUseESIndices(visState: SavedVisState) { - if ( - visState.type === 'metrics' && - !visState.params.use_kibana_indexes && - !excludedFromStatsVisualizations.includes(visState.title) - ) { - timeseriesUsage.timeseries_use_es_indices_total++; - } - } - - function telemetryTableAggFunction(visState: SavedVisState) { - if ( - visState.type === 'metrics' && - visState.params.type === 'table' && - visState.params.series && - visState.params.series.length > 0 && - !excludedFromStatsVisualizations.includes(visState.title) - ) { - const usesAggregateFunction = visState.params.series.some( - (s) => s.aggregate_by && s.aggregate_function - ); - if (usesAggregateFunction) { - timeseriesUsage.timeseries_table_use_aggregate_function++; - } - } - } - - function telemetryPanelTypes(visState: SavedVisState) { - if (visState.type === 'metrics' && !excludedFromStatsVisualizations.includes(visState.title)) { - timeseriesUsage.timeseries_types[visState.params.type]++; - } - } - await Promise.all([ - // last value usage telemetry - doTelemetryFoVisualizations(soClient, telemetryUseLastValueMode), - doTelemetryForByValueVisualizations(soClient, telemetryUseLastValueMode), - // elasticsearch indices usage telemetry - doTelemetryFoVisualizations(soClient, telemetryUseESIndices), - doTelemetryForByValueVisualizations(soClient, telemetryUseESIndices), - // table aggregate function telemetry - doTelemetryFoVisualizations(soClient, telemetryTableAggFunction), - doTelemetryForByValueVisualizations(soClient, telemetryTableAggFunction), - // panel types usage telemetry - doTelemetryFoVisualizations(soClient, telemetryPanelTypes), - doTelemetryForByValueVisualizations(soClient, telemetryPanelTypes), - ]); - - return timeseriesUsage.timeseries_use_last_value_mode_total || - timeseriesUsage.timeseries_use_es_indices_total || - timeseriesUsage.timeseries_table_use_aggregate_function || - Object.values(timeseriesUsage.timeseries_types).some((visualizationCount) => visualizationCount) - ? timeseriesUsage - : undefined; -}; diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/index.ts b/src/plugins/vis_types/timeseries/server/usage_collector/index.ts deleted file mode 100644 index 7f72662e154ea..0000000000000 --- a/src/plugins/vis_types/timeseries/server/usage_collector/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { registerTimeseriesUsageCollector } from './register_timeseries_collector'; diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.test.ts b/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.test.ts deleted file mode 100644 index 2c4f0f08d216c..0000000000000 --- a/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { mockStats, mockGetStats } from './get_usage_collector.mock'; -import { createUsageCollectionSetupMock } from '@kbn/usage-collection-plugin/server/mocks'; -import { createCollectorFetchContextMock } from '@kbn/usage-collection-plugin/server/mocks'; -import { registerTimeseriesUsageCollector } from './register_timeseries_collector'; - -describe('registerTimeseriesUsageCollector', () => { - it('makes a usage collector and registers it`', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerTimeseriesUsageCollector(mockCollectorSet); - expect(mockCollectorSet.makeUsageCollector).toBeCalledTimes(1); - expect(mockCollectorSet.registerCollector).toBeCalledTimes(1); - }); - - it('makeUsageCollector configs fit the shape', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerTimeseriesUsageCollector(mockCollectorSet); - expect(mockCollectorSet.makeUsageCollector).toHaveBeenCalledWith({ - type: 'vis_type_timeseries', - isReady: expect.any(Function), - fetch: expect.any(Function), - schema: expect.any(Object), - }); - const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; - expect(usageCollectorConfig.isReady()).toBe(true); - }); - - it('makeUsageCollector config.isReady returns true', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerTimeseriesUsageCollector(mockCollectorSet); - const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; - expect(usageCollectorConfig.isReady()).toBe(true); - }); - - it('makeUsageCollector config.fetch calls getStats', async () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerTimeseriesUsageCollector(mockCollectorSet); - const usageCollector = mockCollectorSet.makeUsageCollector.mock.results[0].value; - const mockedCollectorFetchContext = createCollectorFetchContextMock(); - const fetchResult = await usageCollector.fetch(mockedCollectorFetchContext); - expect(mockGetStats).toBeCalledTimes(1); - expect(mockGetStats).toBeCalledWith(mockedCollectorFetchContext.soClient, undefined); - expect(fetchResult).toBe(mockStats); - }); -}); diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.ts b/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.ts deleted file mode 100644 index d06bf7f3a64b5..0000000000000 --- a/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import type { HomeServerPluginSetup } from '@kbn/home-plugin/server'; -import { getStats, TimeseriesUsage } from './get_usage_collector'; - -export function registerTimeseriesUsageCollector( - collectorSet: UsageCollectionSetup, - home?: HomeServerPluginSetup -) { - const collector = collectorSet.makeUsageCollector({ - type: 'vis_type_timeseries', - isReady: () => true, - schema: { - timeseries_use_last_value_mode_total: { - type: 'long', - _meta: { description: 'Number of TSVB visualizations using "last value" as a time range' }, - }, - timeseries_use_es_indices_total: { - type: 'long', - _meta: { description: 'Number of TSVB visualizations using elasticsearch indices' }, - }, - timeseries_table_use_aggregate_function: { - type: 'long', - _meta: { description: 'Number of TSVB table visualizations using aggregate function' }, - }, - timeseries_types: { - table: { type: 'long' }, - gauge: { type: 'long' }, - markdown: { type: 'long' }, - top_n: { type: 'long' }, - timeseries: { type: 'long' }, - metric: { type: 'long' }, - }, - }, - fetch: async ({ soClient }) => await getStats(soClient, home), - }); - - collectorSet.registerCollector(collector); -} diff --git a/src/plugins/vis_types/timeseries/tsconfig.json b/src/plugins/vis_types/timeseries/tsconfig.json index 43d66c3bd030e..be96a71b9a580 100644 --- a/src/plugins/vis_types/timeseries/tsconfig.json +++ b/src/plugins/vis_types/timeseries/tsconfig.json @@ -23,7 +23,6 @@ { "path": "../../dashboard/tsconfig.json" }, { "path": "../../kibana_utils/tsconfig.json" }, { "path": "../../kibana_react/tsconfig.json" }, - { "path": "../../usage_collection/tsconfig.json" }, { "path": "../../unified_search/tsconfig.json" } ] } diff --git a/src/plugins/vis_types/vega/kibana.json b/src/plugins/vis_types/vega/kibana.json index d3e0da54d848f..423f044aa3275 100644 --- a/src/plugins/vis_types/vega/kibana.json +++ b/src/plugins/vis_types/vega/kibana.json @@ -4,7 +4,7 @@ "server": true, "ui": true, "requiredPlugins": ["data", "visualizations", "mapsEms", "expressions", "inspector", "dataViews"], - "optionalPlugins": ["home","usageCollection"], + "optionalPlugins": ["home"], "requiredBundles": ["kibanaUtils", "kibanaReact", "visDefaultEditor"], "owner": { "name": "Vis Editors", diff --git a/src/plugins/vis_types/vega/server/plugin.ts b/src/plugins/vis_types/vega/server/plugin.ts index e5e9bdaefe987..6f43a79c99262 100644 --- a/src/plugins/vis_types/vega/server/plugin.ts +++ b/src/plugins/vis_types/vega/server/plugin.ts @@ -7,25 +7,16 @@ */ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '@kbn/core/server'; -import { registerVegaUsageCollector } from './usage_collector'; import { - ConfigObservable, VisTypeVegaPluginSetupDependencies, VisTypeVegaPluginSetup, VisTypeVegaPluginStart, } from './types'; export class VisTypeVegaPlugin implements Plugin { - private readonly config: ConfigObservable; - - constructor(initializerContext: PluginInitializerContext) { - this.config = initializerContext.config.legacy.globalConfig$; - } + constructor(initializerContext: PluginInitializerContext) {} public setup(core: CoreSetup, { home, usageCollection }: VisTypeVegaPluginSetupDependencies) { - if (usageCollection) { - registerVegaUsageCollector(usageCollection, this.config, { home }); - } return {}; } diff --git a/src/plugins/vis_types/vega/server/usage_collector/get_usage_collector.mock.ts b/src/plugins/vis_types/vega/server/usage_collector/get_usage_collector.mock.ts deleted file mode 100644 index bb52d215c67e8..0000000000000 --- a/src/plugins/vis_types/vega/server/usage_collector/get_usage_collector.mock.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export const mockStats = { somestat: 1 }; -export const mockGetStats = jest.fn().mockResolvedValue(mockStats); - -jest.doMock('./get_usage_collector', () => ({ - getStats: mockGetStats, -})); diff --git a/src/plugins/vis_types/vega/server/usage_collector/get_usage_collector.test.ts b/src/plugins/vis_types/vega/server/usage_collector/get_usage_collector.test.ts deleted file mode 100644 index e7154ea2b7da6..0000000000000 --- a/src/plugins/vis_types/vega/server/usage_collector/get_usage_collector.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { getStats } from './get_usage_collector'; -import { createCollectorFetchContextMock } from '@kbn/usage-collection-plugin/server/mocks'; -import type { HomeServerPluginSetup } from '@kbn/home-plugin/server'; -import type { SavedObjectsClientContract } from '@kbn/core/server'; - -const mockedSavedObjects = [ - // vega-lite lib spec - { - attributes: { - visState: JSON.stringify({ - type: 'vega', - params: { - spec: '{"$schema": "https://vega.github.io/schema/vega-lite/v5.json" }', - }, - }), - }, - }, - // vega lib spec - { - attributes: { - visState: JSON.stringify({ - type: 'vega', - params: { - spec: '{"$schema": "https://vega.github.io/schema/vega/v5.json" }', - }, - }), - }, - }, - // map layout - { - attributes: { - visState: JSON.stringify({ - type: 'vega', - params: { - spec: '{"$schema": "https://vega.github.io/schema/vega/v3.json" \n "config": { "kibana" : { "type": "map" }} }', - }, - }), - }, - }, -]; - -const getMockCollectorFetchContext = (savedObjects?: unknown[]) => { - const fetchParamsMock = createCollectorFetchContextMock(); - - fetchParamsMock.soClient = { - createPointInTimeFinder: jest.fn().mockResolvedValue({ - close: jest.fn(), - find: function* asyncGenerator() { - yield { saved_objects: savedObjects }; - }, - }), - } as unknown as SavedObjectsClientContract; - - return fetchParamsMock; -}; - -describe('Vega visualization usage collector', () => { - const mockDeps = { - home: { - sampleData: { - getSampleDatasets: jest.fn().mockReturnValue([ - { - savedObjects: [ - { - type: 'visualization', - attributes: { - visState: JSON.stringify({ - type: 'vega', - title: 'sample vega visualization', - params: { - spec: '{"$schema": "https://vega.github.io/schema/vega/v5.json" }', - }, - }), - }, - }, - ], - }, - ]), - }, - } as unknown as HomeServerPluginSetup, - }; - - test('Returns undefined when no results found (undefined)', async () => { - const result = await getStats(getMockCollectorFetchContext().soClient, mockDeps); - - expect(result).toBeUndefined(); - }); - - test('Returns undefined when no results found (0 results)', async () => { - const result = await getStats(getMockCollectorFetchContext([]).soClient, mockDeps); - - expect(result).toBeUndefined(); - }); - - test('Returns undefined when no vega saved objects found', async () => { - const mockCollectorFetchContext = getMockCollectorFetchContext([ - { - _id: 'visualization:myvis-123', - _source: { - type: 'visualization', - visualization: { visState: '{"type": "area"}' }, - }, - }, - ]); - const result = await getStats(mockCollectorFetchContext.soClient, mockDeps); - - expect(result).toBeUndefined(); - }); - - test('Should ingnore sample data visualizations', async () => { - const mockCollectorFetchContext = getMockCollectorFetchContext([ - { - attributes: { - visState: JSON.stringify({ - type: 'vega', - title: 'sample vega visualization', - params: { - spec: '{"$schema": "https://vega.github.io/schema/vega/v5.json" }', - }, - }), - }, - }, - ]); - - const result = await getStats(mockCollectorFetchContext.soClient, mockDeps); - - expect(result).toBeUndefined(); - }); - - test('Summarizes visualizations response data', async () => { - const mockCollectorFetchContext = getMockCollectorFetchContext(mockedSavedObjects); - const result = await getStats(mockCollectorFetchContext.soClient, mockDeps); - - expect(result).toMatchObject({ - vega_lib_specs_total: 2, - vega_lite_lib_specs_total: 1, - vega_use_map_total: 1, - }); - }); -}); diff --git a/src/plugins/vis_types/vega/server/usage_collector/get_usage_collector.ts b/src/plugins/vis_types/vega/server/usage_collector/get_usage_collector.ts deleted file mode 100644 index 21afe9f141b88..0000000000000 --- a/src/plugins/vis_types/vega/server/usage_collector/get_usage_collector.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { parse } from 'hjson'; - -import type { SavedObjectsClientContract, SavedObjectsFindResult } from '@kbn/core/server'; -import type { SavedVisState } from '@kbn/visualizations-plugin/common'; -import type { VegaSavedObjectAttributes, VisTypeVegaPluginSetupDependencies } from '../types'; - -type UsageCollectorDependencies = Pick; -type VegaType = 'vega' | 'vega-lite'; - -export interface VegaUsage { - vega_lib_specs_total: number; - vega_lite_lib_specs_total: number; - vega_use_map_total: number; -} - -function isVegaType(attributes: any): attributes is VegaSavedObjectAttributes { - return attributes && attributes.type === 'vega' && attributes.params?.spec; -} - -const checkVegaSchemaType = (schemaURL: string, type: VegaType) => - schemaURL.includes(`//vega.github.io/schema/${type}/`); - -const getDefaultVegaVisualizations = (home: UsageCollectorDependencies['home']) => { - const titles: string[] = []; - const sampleDataSets = home?.sampleData.getSampleDatasets() ?? []; - - sampleDataSets.forEach((sampleDataSet) => - sampleDataSet.savedObjects.forEach((savedObject) => { - try { - if (savedObject.type === 'visualization') { - const visState = JSON.parse(savedObject.attributes?.visState); - - if (isVegaType(visState)) { - titles.push(visState.title); - } - } - } catch (e) { - // Let it go, visState is invalid and we'll don't need to handle it - } - }) - ); - - return titles; -}; - -export const getStats = async ( - soClient: SavedObjectsClientContract, - { home }: UsageCollectorDependencies -): Promise => { - let shouldPublishTelemetry = false; - - const vegaUsage = { - vega_lib_specs_total: 0, - vega_lite_lib_specs_total: 0, - vega_use_map_total: 0, - }; - - // we want to exclude the Vega Sample Data visualizations from the stats - // in order to have more accurate results - const excludedFromStatsVisualizations = getDefaultVegaVisualizations(home); - - const finder = await soClient.createPointInTimeFinder({ - type: 'visualization', - perPage: 1000, - namespaces: ['*'], - }); - - const doTelemetry = ({ params }: SavedVisState) => { - try { - const spec = parse(params.spec as string, { legacyRoot: false }); - - if (spec) { - shouldPublishTelemetry = true; - - if (checkVegaSchemaType(spec.$schema, 'vega')) { - vegaUsage.vega_lib_specs_total++; - } - if (checkVegaSchemaType(spec.$schema, 'vega-lite')) { - vegaUsage.vega_lite_lib_specs_total++; - } - if (spec.config?.kibana?.type === 'map') { - vegaUsage.vega_use_map_total++; - } - } - } catch (e) { - // Let it go, the data is invalid and we'll don't need to handle it - } - }; - - for await (const response of finder.find()) { - (response.saved_objects || []).forEach(({ attributes }: SavedObjectsFindResult) => { - if (attributes?.visState) { - try { - const visState: SavedVisState = JSON.parse(attributes.visState); - - if (isVegaType(visState) && !excludedFromStatsVisualizations.includes(visState.title)) { - doTelemetry(visState); - } - } catch { - // nothing to be here, "so" not valid - } - } - }); - } - await finder.close(); - - return shouldPublishTelemetry ? vegaUsage : undefined; -}; diff --git a/src/plugins/vis_types/vega/server/usage_collector/index.ts b/src/plugins/vis_types/vega/server/usage_collector/index.ts deleted file mode 100644 index 3e7903f960d64..0000000000000 --- a/src/plugins/vis_types/vega/server/usage_collector/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { registerVegaUsageCollector } from './register_vega_collector'; diff --git a/src/plugins/vis_types/vega/server/usage_collector/register_vega_collector.test.ts b/src/plugins/vis_types/vega/server/usage_collector/register_vega_collector.test.ts deleted file mode 100644 index 098515d15d9df..0000000000000 --- a/src/plugins/vis_types/vega/server/usage_collector/register_vega_collector.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { - createUsageCollectionSetupMock, - createCollectorFetchContextMock, -} from '@kbn/usage-collection-plugin/server/mocks'; -import { mockStats, mockGetStats } from './get_usage_collector.mock'; -import { registerVegaUsageCollector } from './register_vega_collector'; - -import type { HomeServerPluginSetup } from '@kbn/home-plugin/server'; -import type { ConfigObservable } from '../types'; - -describe('registerVegaUsageCollector', () => { - const mockDeps = { home: {} as unknown as HomeServerPluginSetup }; - const mockConfig = {} as ConfigObservable; - - test('makes a usage collector and registers it`', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVegaUsageCollector(mockCollectorSet, mockConfig, mockDeps); - expect(mockCollectorSet.makeUsageCollector).toBeCalledTimes(1); - expect(mockCollectorSet.registerCollector).toBeCalledTimes(1); - }); - - test('makeUsageCollector configs fit the shape', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVegaUsageCollector(mockCollectorSet, mockConfig, mockDeps); - expect(mockCollectorSet.makeUsageCollector).toHaveBeenCalledWith({ - type: 'vis_type_vega', - isReady: expect.any(Function), - fetch: expect.any(Function), - schema: expect.any(Object), - }); - const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; - expect(usageCollectorConfig.isReady()).toBe(true); - }); - - test('makeUsageCollector config.isReady returns true', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVegaUsageCollector(mockCollectorSet, mockConfig, mockDeps); - const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; - expect(usageCollectorConfig.isReady()).toBe(true); - }); - - test('makeUsageCollector config.fetch calls getStats', async () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVegaUsageCollector(mockCollectorSet, mockConfig, mockDeps); - const usageCollector = mockCollectorSet.makeUsageCollector.mock.results[0].value; - const mockedCollectorFetchContext = createCollectorFetchContextMock(); - const fetchResult = await usageCollector.fetch(mockedCollectorFetchContext); - expect(mockGetStats).toBeCalledTimes(1); - expect(mockGetStats).toBeCalledWith(mockedCollectorFetchContext.soClient, mockDeps); - expect(fetchResult).toBe(mockStats); - }); -}); diff --git a/src/plugins/vis_types/vega/server/usage_collector/register_vega_collector.ts b/src/plugins/vis_types/vega/server/usage_collector/register_vega_collector.ts deleted file mode 100644 index adf35f81396d1..0000000000000 --- a/src/plugins/vis_types/vega/server/usage_collector/register_vega_collector.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import { getStats, VegaUsage } from './get_usage_collector'; -import type { ConfigObservable, VisTypeVegaPluginSetupDependencies } from '../types'; - -export function registerVegaUsageCollector( - collectorSet: UsageCollectionSetup, - config: ConfigObservable, - dependencies: Pick -) { - const collector = collectorSet.makeUsageCollector({ - type: 'vis_type_vega', - isReady: () => true, - schema: { - vega_lib_specs_total: { type: 'long' }, - vega_lite_lib_specs_total: { type: 'long' }, - vega_use_map_total: { type: 'long' }, - }, - fetch: async ({ soClient }) => await getStats(soClient, dependencies), - }); - - collectorSet.registerCollector(collector); -} diff --git a/src/plugins/vis_types/vega/tsconfig.json b/src/plugins/vis_types/vega/tsconfig.json index ccb4bbfb34454..7aa32cbda7201 100644 --- a/src/plugins/vis_types/vega/tsconfig.json +++ b/src/plugins/vis_types/vega/tsconfig.json @@ -23,7 +23,6 @@ { "path": "../../expressions/tsconfig.json" }, { "path": "../../inspector/tsconfig.json" }, { "path": "../../home/tsconfig.json" }, - { "path": "../../usage_collection/tsconfig.json" }, { "path": "../../kibana_utils/tsconfig.json" }, { "path": "../../kibana_react/tsconfig.json" }, { "path": "../../vis_default_editor/tsconfig.json" }, diff --git a/src/plugins/vis_types/xy/public/editor/components/options/point_series/elastic_charts_options.tsx b/src/plugins/vis_types/xy/public/editor/components/options/point_series/elastic_charts_options.tsx index 8a633e9bda53e..ed57c5427027b 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/point_series/elastic_charts_options.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/point_series/elastic_charts_options.tsx @@ -9,20 +9,18 @@ import React, { useState, useEffect } from 'react'; import type { PaletteRegistry } from '@kbn/coloring'; import { i18n } from '@kbn/i18n'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiFormRow, EuiRange } from '@elastic/eui'; import { SelectOption, SwitchOption, PalettePicker } from '@kbn/vis-default-editor-plugin/public'; import { ChartType } from '../../../../../common'; import { VisParams } from '../../../../types'; import { ValidationVisOptionsProps } from '../../common'; -import { getPalettesService, getTrackUiMetric } from '../../../../services'; +import { getPalettesService } from '../../../../services'; import { getFittingFunctions } from '../../../collections'; const fittingFunctions = getFittingFunctions(); export function ElasticChartsOptions(props: ValidationVisOptionsProps) { - const trackUiMetric = getTrackUiMetric(); const [palettesRegistry, setPalettesRegistry] = useState(null); const { stateParams, setValue, aggs } = props; @@ -58,9 +56,6 @@ export function ElasticChartsOptions(props: ValidationVisOptionsProps paramName="detailedTooltip" value={stateParams.detailedTooltip} setValue={(paramName, value) => { - if (trackUiMetric) { - trackUiMetric(METRIC_TYPE.CLICK, 'detailed_tooltip_switched'); - } setValue(paramName, value); }} /> @@ -75,9 +70,6 @@ export function ElasticChartsOptions(props: ValidationVisOptionsProps paramName="fittingFunction" value={stateParams.fittingFunction ?? fittingFunctions[2].value} setValue={(paramName, value) => { - if (trackUiMetric) { - trackUiMetric(METRIC_TYPE.CLICK, 'fitting_function_selected'); - } setValue(paramName, value); }} /> @@ -89,9 +81,6 @@ export function ElasticChartsOptions(props: ValidationVisOptionsProps activePalette={stateParams.palette} paramName="palette" setPalette={(paramName, value) => { - if (trackUiMetric) { - trackUiMetric(METRIC_TYPE.CLICK, 'palette_selected'); - } setValue(paramName, value); }} /> diff --git a/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.test.tsx b/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.test.tsx index dbd1bed390574..ae8327c6c9df0 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.test.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.test.tsx @@ -16,7 +16,6 @@ import { ChartType } from '../../../../../common'; import { getAggs, getVis, getStateParams } from './point_series.mocks'; jest.mock('../../../../services', () => ({ - getTrackUiMetric: jest.fn(() => null), getPalettesService: jest.fn(() => { return { getPalettes: jest.fn(), diff --git a/src/plugins/vis_types/xy/public/plugin.ts b/src/plugins/vis_types/xy/public/plugin.ts index 00b036594e4d4..81689401a8750 100644 --- a/src/plugins/vis_types/xy/public/plugin.ts +++ b/src/plugins/vis_types/xy/public/plugin.ts @@ -19,7 +19,6 @@ import { setUISettings, setDocLinks, setPalettesService, - setTrackUiMetric, setActiveCursor, } from './services'; @@ -85,9 +84,6 @@ export class VisTypeXyPlugin expressions.registerFunction(expressionFunctions.visScale); visTypesDefinitions.forEach(visualizations.createBaseVisualization); - - setTrackUiMetric(usageCollection?.reportUiCounter.bind(usageCollection, 'vis_type_xy')); - return {}; } diff --git a/src/plugins/vis_types/xy/public/services.ts b/src/plugins/vis_types/xy/public/services.ts index 6ee38238c9cf4..b8a4cc94294d0 100644 --- a/src/plugins/vis_types/xy/public/services.ts +++ b/src/plugins/vis_types/xy/public/services.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { UiCounterMetricType } from '@kbn/analytics'; import { CoreSetup, DocLinksStart } from '@kbn/core/public'; import { createGetterSetter } from '@kbn/kibana-utils-plugin/public'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; @@ -31,8 +30,3 @@ export const [getPalettesService, setPalettesService] = createGetterSetter('xy charts.palette'); export const [getDocLinks, setDocLinks] = createGetterSetter('DocLinks'); - -export const [getTrackUiMetric, setTrackUiMetric] = - createGetterSetter<(metricType: UiCounterMetricType, eventName: string | string[]) => void>( - 'trackUiMetric' - ); diff --git a/src/plugins/visualizations/kibana.json b/src/plugins/visualizations/kibana.json index 9223f36b36816..62627208561da 100644 --- a/src/plugins/visualizations/kibana.json +++ b/src/plugins/visualizations/kibana.json @@ -18,7 +18,7 @@ "dataViews", "dataViewEditor" ], - "optionalPlugins": ["home", "share", "usageCollection", "spaces", "savedObjectsTaggingOss"], + "optionalPlugins": ["home", "share", "spaces", "savedObjectsTaggingOss"], "requiredBundles": ["kibanaUtils", "discover", "kibanaReact"], "extraPublicDirs": ["common/constants", "common/utils", "common/expression_functions"], "owner": { diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts index f8975b705caf6..49a083647fbf8 100644 --- a/src/plugins/visualizations/public/mocks.ts +++ b/src/plugins/visualizations/public/mocks.ts @@ -14,7 +14,6 @@ import { expressionsPluginMock } from '@kbn/expressions-plugin/public/mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { indexPatternEditorPluginMock } from '@kbn/data-view-editor-plugin/public/mocks'; -import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/public/mocks'; import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; import { inspectorPluginMock } from '@kbn/inspector-plugin/public/mocks'; import { savedObjectsPluginMock } from '@kbn/saved-objects-plugin/public/mocks'; @@ -52,7 +51,6 @@ const createInstance = async () => { embeddable: embeddablePluginMock.createSetupContract(), expressions: expressionsPluginMock.createSetupContract(), inspector: inspectorPluginMock.createSetupContract(), - usageCollection: usageCollectionPluginMock.createSetupContract(), urlForwarding: urlForwardingPluginMock.createSetupContract(), uiActions: uiActionsPluginMock.createSetupContract(), }); diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 7c704a8916af8..2bd233a5db049 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -33,7 +33,6 @@ import type { ApplicationStart, SavedObjectsClientContract, } from '@kbn/core/public'; -import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import type { UiActionsStart, UiActionsSetup } from '@kbn/ui-actions-plugin/public'; import type { SavedObjectsStart } from '@kbn/saved-objects-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; @@ -50,7 +49,6 @@ import type { NavigationPublicPluginStart as NavigationStart } from '@kbn/naviga import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public'; import type { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public'; import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public'; -import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; import type { ScreenshotModePluginStart } from '@kbn/screenshot-mode-plugin/public'; import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; @@ -78,7 +76,6 @@ import { setHttp, setSearch, setSavedObjects, - setUsageCollector, setExpressions, setUiActions, setTimeFilter, @@ -112,7 +109,6 @@ export interface VisualizationsSetupDeps { expressions: ExpressionsSetup; inspector: InspectorSetup; uiActions: UiActionsSetup; - usageCollection: UsageCollectionSetup; urlForwarding: UrlForwardingSetup; home?: HomePublicPluginSetup; share?: SharePluginSetup; @@ -136,7 +132,6 @@ export interface VisualizationsStartDeps { savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart; share?: SharePluginStart; urlForwarding: UrlForwardingStart; - usageCollection?: UsageCollectionStart; screenshotMode: ScreenshotModePluginStart; fieldFormats: FieldFormatsStart; } @@ -171,7 +166,6 @@ export class VisualizationsPlugin { expressions, embeddable, - usageCollection, data, home, urlForwarding, @@ -289,7 +283,6 @@ export class VisualizationsPlugin setHeaderActionMenu: params.setHeaderActionMenu, savedObjectsTagging: pluginsStart.savedObjectsTaggingOss?.getTaggingApi(), presentationUtil: pluginsStart.presentationUtil, - usageCollection: pluginsStart.usageCollection, getKibanaVersion: () => this.initializerContext.env.packageInfo.version, spaces: pluginsStart.spaces, visEditorsRegistry, @@ -335,7 +328,6 @@ export class VisualizationsPlugin } setUISettings(core.uiSettings); - setUsageCollector(usageCollection); setTheme(core.theme); expressions.registerFunction(rangeExpressionFunction); @@ -361,7 +353,6 @@ export class VisualizationsPlugin savedObjects, spaces, savedObjectsTaggingOss, - usageCollection, fieldFormats, }: VisualizationsStartDeps ): VisualizationsStart { diff --git a/src/plugins/visualizations/public/services.ts b/src/plugins/visualizations/public/services.ts index df2ed019c308b..f87597b07462b 100644 --- a/src/plugins/visualizations/public/services.ts +++ b/src/plugins/visualizations/public/services.ts @@ -20,7 +20,6 @@ import type { ExecutionContextSetup, } from '@kbn/core/public'; import type { DataPublicPluginStart, TimefilterContract } from '@kbn/data-plugin/public'; -import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; @@ -54,11 +53,6 @@ export const [getTimeFilter, setTimeFilter] = createGetterSetter('Search'); -export const [getUsageCollector, setUsageCollector] = createGetterSetter( - 'UsageCollection', - false -); - export const [getExpressions, setExpressions] = createGetterSetter('Expressions'); export const [getUiActions, setUiActions] = createGetterSetter('UiActions'); diff --git a/src/plugins/visualizations/public/visualize_app/types.ts b/src/plugins/visualizations/public/visualize_app/types.ts index cf46e0fc4ff1e..e7e213d3a6416 100644 --- a/src/plugins/visualizations/public/visualize_app/types.ts +++ b/src/plugins/visualizations/public/visualize_app/types.ts @@ -37,7 +37,6 @@ import type { UrlForwardingStart } from '@kbn/url-forwarding-plugin/public'; import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public'; -import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; import type { SavedSearch } from '@kbn/discover-plugin/public'; import type { Vis, @@ -107,7 +106,6 @@ export interface VisualizeServices extends CoreStart { setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; savedObjectsTagging?: SavedObjectsTaggingApi; presentationUtil: PresentationUtilPluginStart; - usageCollection?: UsageCollectionStart; getKibanaVersion: () => string; spaces?: SpacesPluginStart; theme: ThemeServiceStart; diff --git a/src/plugins/visualizations/public/visualize_app/utils/get_table_columns.tsx b/src/plugins/visualizations/public/visualize_app/utils/get_table_columns.tsx index 5775d4e5bf535..a2b75d5868b64 100644 --- a/src/plugins/visualizations/public/visualize_app/utils/get_table_columns.tsx +++ b/src/plugins/visualizations/public/visualize_app/utils/get_table_columns.tsx @@ -7,7 +7,6 @@ */ import React from 'react'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiBetaBadge, EuiButton, @@ -25,16 +24,6 @@ import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plug import { RedirectAppLinks } from '@kbn/kibana-react-plugin/public'; import { VisualizationListItem } from '../..'; import { getVisualizeListItemLink } from './get_visualize_list_item_link'; -import { getUsageCollector } from '../../services'; -import { VISUALIZE_APP_NAME } from '../../../common/constants'; - -const doTelemetryForAddEvent = (visType?: string) => { - const usageCollection = getUsageCollector(); - - if (usageCollection && visType) { - usageCollection.reportUiCounter(VISUALIZE_APP_NAME, METRIC_TYPE.CLICK, `${visType}:add`); - } -}; const getBadge = (item: VisualizationListItem) => { if (item.stage === 'beta') { @@ -106,12 +95,8 @@ export const getTableColumns = ( // In case an error occurs i.e. the vis has wrong type, we render the vis but without the link !error ? ( - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} { - doTelemetryForAddEvent(typeof type === 'string' ? type : type?.name); - }} data-test-subj={`visListingTitleLink-${title.split(' ').join('-')}`} > {field} diff --git a/src/plugins/visualizations/public/visualize_app/utils/get_top_nav_config.tsx b/src/plugins/visualizations/public/visualize_app/utils/get_top_nav_config.tsx index 0fb7f9b818260..8b9b42201a442 100644 --- a/src/plugins/visualizations/public/visualize_app/utils/get_top_nav_config.tsx +++ b/src/plugins/visualizations/public/visualize_app/utils/get_top_nav_config.tsx @@ -9,7 +9,6 @@ import React from 'react'; import moment from 'moment'; import { i18n } from '@kbn/i18n'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiBetaBadgeProps } from '@elastic/eui'; import { parse } from 'query-string'; @@ -40,7 +39,7 @@ import { VisualizeAppStateContainer, VisualizeEditorVisInstance, } from '../types'; -import { VISUALIZE_APP_NAME, VisualizeConstants } from '../../../common/constants'; +import { VisualizeConstants } from '../../../common/constants'; import { getEditBreadcrumbs } from './breadcrumbs'; import { VISUALIZE_APP_LOCATOR, VisualizeLocatorParams } from '../../../common/locator'; import { getUiActions } from '../../services'; @@ -121,7 +120,6 @@ export const getTopNavConfig = ( i18n: { Context: I18nContext }, savedObjectsTagging, presentationUtil, - usageCollection, getKibanaVersion, savedObjects, }: VisualizeServices @@ -129,16 +127,6 @@ export const getTopNavConfig = ( const { vis, embeddableHandler } = visInstance; const savedVis = visInstance.savedVis; - const doTelemetryForSaveEvent = (visType: string) => { - if (usageCollection) { - usageCollection.reportUiCounter( - originatingApp ?? VISUALIZE_APP_NAME, - METRIC_TYPE.CLICK, - `${visType}:save` - ); - } - }; - /** * Called when the user clicks "Save" button. */ @@ -523,8 +511,6 @@ export const getTopNavConfig = ( return { id: true }; } - doTelemetryForSaveEvent(vis.type.name); - // We're adding the viz to a library so we need to save it and then // add to a dashboard if necessary const response = await doSave(saveOptions); @@ -642,8 +628,6 @@ export const getTopNavConfig = ( } }, run: async () => { - doTelemetryForSaveEvent(vis.type.name); - if (!savedVis?.id) { return createVisReference(); } diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx index 839ba364719a2..4ceb93b7ec061 100644 --- a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx @@ -18,7 +18,6 @@ import { SavedObjectsStart, DocLinksStart, } from '@kbn/core/public'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import { EmbeddableStateTransfer } from '@kbn/embeddable-plugin/public'; import { SearchSelection } from './search_selection'; import { GroupSelection } from './group_selection'; @@ -36,7 +35,6 @@ interface TypeSelectionProps { uiSettings: IUiSettingsClient; docLinks: DocLinksStart; savedObjects: SavedObjectsStart; - usageCollection?: UsageCollectionSetup; application: ApplicationStart; outsideVisualizeApp?: boolean; stateTransfer?: EmbeddableStateTransfer; @@ -75,11 +73,6 @@ class NewVisModal extends React.Component { - test('Returns 2 days that have passed from the current date', () => { - const pastDate = moment().subtract(2, 'days').startOf('day').toString(); - - expect(getPastDays(pastDate)).toEqual(2); - }); - - test('Returns 30 days that have passed from the current date', () => { - const pastDate = moment().subtract(30, 'days').startOf('day').toString(); - - expect(getPastDays(pastDate)).toEqual(30); - }); -}); diff --git a/src/plugins/visualizations/server/usage_collector/get_past_days.ts b/src/plugins/visualizations/server/usage_collector/get_past_days.ts deleted file mode 100644 index 2ffd09ba3c7d9..0000000000000 --- a/src/plugins/visualizations/server/usage_collector/get_past_days.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export const getPastDays = (dateString: string): number => { - const date = new Date(dateString); - const today = new Date(); - const diff = Math.abs(date.getTime() - today.getTime()); - return Math.trunc(diff / (1000 * 60 * 60 * 24)); -}; diff --git a/src/plugins/visualizations/server/usage_collector/get_usage_collector.mock.ts b/src/plugins/visualizations/server/usage_collector/get_usage_collector.mock.ts deleted file mode 100644 index b1dca4f7f71e4..0000000000000 --- a/src/plugins/visualizations/server/usage_collector/get_usage_collector.mock.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export const mockStats = { somestat: 1 }; -export const mockGetStats = jest.fn().mockResolvedValue(mockStats); -jest.doMock('./get_usage_collector', () => ({ - getStats: mockGetStats, -})); diff --git a/src/plugins/visualizations/server/usage_collector/get_usage_collector.test.ts b/src/plugins/visualizations/server/usage_collector/get_usage_collector.test.ts deleted file mode 100644 index 38e0036feec24..0000000000000 --- a/src/plugins/visualizations/server/usage_collector/get_usage_collector.test.ts +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import moment from 'moment'; -import { getStats } from './get_usage_collector'; -import type { SavedObjectsClientContract } from '@kbn/core/server'; - -const defaultMockSavedObjects = [ - { - id: 'visualization:coolviz-123', - attributes: { visState: '{"type": "shell_beads"}' }, - updated_at: moment().subtract(7, 'days').startOf('day').toString(), - }, -]; - -const enlargedMockSavedObjects = [ - // default space - { - id: 'visualization:coolviz-123', - namespaces: ['default'], - attributes: { visState: '{"type": "cave_painting"}' }, - updated_at: moment().subtract(7, 'days').startOf('day').toString(), - }, - { - id: 'visualization:coolviz-456', - namespaces: ['default'], - attributes: { visState: '{"type": "printing_press"}' }, - updated_at: moment().subtract(20, 'days').startOf('day').toString(), - }, - { - id: 'meat:visualization:coolviz-789', - namespaces: ['default'], - attributes: { visState: '{"type": "floppy_disk"}' }, - updated_at: moment().subtract(2, 'months').startOf('day').toString(), - }, - // meat space - { - id: 'meat:visualization:coolviz-789', - namespaces: ['meat'], - attributes: { visState: '{"type": "cave_painting"}' }, - updated_at: moment().subtract(89, 'days').startOf('day').toString(), - }, - { - id: 'meat:visualization:coolviz-789', - namespaces: ['meat'], - attributes: { visState: '{"type": "cuneiform"}' }, - updated_at: moment().subtract(5, 'months').startOf('day').toString(), - }, - { - id: 'meat:visualization:coolviz-789', - namespaces: ['meat'], - attributes: { visState: '{"type": "cuneiform"}' }, - updated_at: moment().subtract(2, 'days').startOf('day').toString(), - }, - { - id: 'meat:visualization:coolviz-789', - attributes: { visState: '{"type": "floppy_disk"}' }, - updated_at: moment().subtract(7, 'days').startOf('day').toString(), - }, - // cyber space - { - id: 'cyber:visualization:coolviz-789', - namespaces: ['cyber'], - attributes: { visState: '{"type": "floppy_disk"}' }, - updated_at: moment().subtract(7, 'months').startOf('day').toString(), - }, - { - id: 'cyber:visualization:coolviz-789', - namespaces: ['cyber'], - attributes: { visState: '{"type": "floppy_disk"}' }, - updated_at: moment().subtract(3, 'days').startOf('day').toString(), - }, - { - id: 'cyber:visualization:coolviz-123', - namespaces: ['cyber'], - attributes: { visState: '{"type": "cave_painting"}' }, - updated_at: moment().subtract(15, 'days').startOf('day').toString(), - }, -]; - -describe('Visualizations usage collector', () => { - const getMockCallCluster = (savedObjects: unknown[]) => - ({ - createPointInTimeFinder: jest.fn().mockResolvedValue({ - close: jest.fn(), - find: function* asyncGenerator() { - yield { saved_objects: savedObjects }; - }, - }), - } as unknown as SavedObjectsClientContract); - - test('Returns undefined when no results found (undefined)', async () => { - const result = await getStats(getMockCallCluster(undefined as any)); - - expect(result).toBeUndefined(); - }); - - test('Returns undefined when no results found (0 results)', async () => { - const result = await getStats(getMockCallCluster([])); - expect(result).toBeUndefined(); - }); - - test('Summarizes visualizations response data', async () => { - const result = await getStats(getMockCallCluster(defaultMockSavedObjects)); - - expect(result).toMatchObject({ - shell_beads: { - spaces_avg: 1, - spaces_max: 1, - spaces_min: 1, - total: 1, - saved_7_days_total: 1, - saved_30_days_total: 1, - saved_90_days_total: 1, - }, - }); - }); - - test('Summarizes visualizations response data per Space', async () => { - const expectedStats = { - cave_painting: { - total: 3, - spaces_min: 1, - spaces_max: 1, - spaces_avg: 1, - saved_7_days_total: 1, - saved_30_days_total: 2, - saved_90_days_total: 3, - }, - printing_press: { - total: 1, - spaces_min: 1, - spaces_max: 1, - spaces_avg: 1, - saved_7_days_total: 0, - saved_30_days_total: 1, - saved_90_days_total: 1, - }, - cuneiform: { - total: 2, - spaces_min: 2, - spaces_max: 2, - spaces_avg: 2, - saved_7_days_total: 1, - saved_30_days_total: 1, - saved_90_days_total: 1, - }, - floppy_disk: { - total: 4, - spaces_min: 2, - spaces_max: 2, - spaces_avg: 2, - saved_7_days_total: 2, - saved_30_days_total: 2, - saved_90_days_total: 3, - }, - }; - - const result = await getStats(getMockCallCluster(enlargedMockSavedObjects)); - - expect(result).toMatchObject(expectedStats); - }); -}); diff --git a/src/plugins/visualizations/server/usage_collector/get_usage_collector.ts b/src/plugins/visualizations/server/usage_collector/get_usage_collector.ts deleted file mode 100644 index f53b4b01864c5..0000000000000 --- a/src/plugins/visualizations/server/usage_collector/get_usage_collector.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { countBy, groupBy, mapValues, max, min, values } from 'lodash'; -import type { SavedObjectsClientContract, SavedObjectsFindResult } from '@kbn/core/server'; -import { getPastDays } from './get_past_days'; - -import type { SavedVisState } from '../../common'; - -interface VisSummary { - type: string; - space: string; - past_days: number; -} - -export interface VisualizationUsage { - [x: string]: { - total: number; - spaces_min?: number; - spaces_max?: number; - spaces_avg: number; - saved_7_days_total: number; - saved_30_days_total: number; - saved_90_days_total: number; - }; -} - -/* - * Parse the response data into telemetry payload - */ -export async function getStats( - soClient: SavedObjectsClientContract -): Promise { - const finder = await soClient.createPointInTimeFinder({ - type: 'visualization', - perPage: 1000, - namespaces: ['*'], - }); - - const visSummaries: VisSummary[] = []; - - for await (const response of finder.find()) { - (response.saved_objects || []).forEach((so: SavedObjectsFindResult) => { - if (so.attributes?.visState) { - const visState: SavedVisState = JSON.parse(so.attributes.visState); - - visSummaries.push({ - type: visState.type ?? '_na_', - space: so.namespaces?.[0] ?? 'default', - past_days: getPastDays(so.updated_at!), - }); - } - }); - } - await finder.close(); - - if (visSummaries.length) { - // organize stats per type - const visTypes = groupBy(visSummaries, 'type'); - - // get the final result - return mapValues(visTypes, (curr) => { - const total = curr.length; - const spacesBreakdown = countBy(curr, 'space'); - const spaceCounts: number[] = values(spacesBreakdown); - - return { - total, - spaces_min: min(spaceCounts), - spaces_max: max(spaceCounts), - spaces_avg: total / spaceCounts.length, - saved_7_days_total: curr.filter((c) => c.past_days <= 7).length, - saved_30_days_total: curr.filter((c) => c.past_days <= 30).length, - saved_90_days_total: curr.filter((c) => c.past_days <= 90).length, - }; - }); - } -} diff --git a/src/plugins/visualizations/server/usage_collector/index.ts b/src/plugins/visualizations/server/usage_collector/index.ts deleted file mode 100644 index ca19d049b31ad..0000000000000 --- a/src/plugins/visualizations/server/usage_collector/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { registerVisualizationsCollector } from './register_visualizations_collector'; diff --git a/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts b/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts deleted file mode 100644 index 9f0fbd6571cde..0000000000000 --- a/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import { - createUsageCollectionSetupMock, - createCollectorFetchContextMock, -} from '@kbn/usage-collection-plugin/server/mocks'; -import { mockStats, mockGetStats } from './get_usage_collector.mock'; -import { registerVisualizationsCollector } from './register_visualizations_collector'; - -describe('registerVisualizationsCollector', () => { - test('makes a usage collector and registers it`', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVisualizationsCollector(mockCollectorSet); - expect(mockCollectorSet.makeUsageCollector).toBeCalledTimes(1); - expect(mockCollectorSet.registerCollector).toBeCalledTimes(1); - }); - - test('makeUsageCollector configs fit the shape', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVisualizationsCollector(mockCollectorSet); - expect(mockCollectorSet.makeUsageCollector).toHaveBeenCalledWith({ - type: 'visualization_types', - isReady: expect.any(Function), - fetch: expect.any(Function), - schema: expect.any(Object), - }); - const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; - expect(usageCollectorConfig.isReady()).toBe(true); - }); - - test('makeUsageCollector config.isReady returns true', () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVisualizationsCollector(mockCollectorSet); - const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; - expect(usageCollectorConfig.isReady()).toBe(true); - }); - - test('makeUsageCollector config.fetch calls getStats', async () => { - const mockCollectorSet = createUsageCollectionSetupMock(); - registerVisualizationsCollector(mockCollectorSet); - const usageCollector = mockCollectorSet.makeUsageCollector.mock.results[0].value; - const mockCollectorFetchContext = createCollectorFetchContextMock(); - const fetchResult = await usageCollector.fetch(mockCollectorFetchContext); - expect(mockGetStats).toBeCalledTimes(1); - expect(mockGetStats).toBeCalledWith(mockCollectorFetchContext.soClient); - expect(fetchResult).toBe(mockStats); - }); -}); diff --git a/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.ts b/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.ts deleted file mode 100644 index bf00e83be4b87..0000000000000 --- a/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import { getStats, VisualizationUsage } from './get_usage_collector'; - -export function registerVisualizationsCollector(collectorSet: UsageCollectionSetup) { - const collector = collectorSet.makeUsageCollector({ - type: 'visualization_types', - isReady: () => true, - schema: { - DYNAMIC_KEY: { - total: { type: 'long' }, - spaces_min: { type: 'long' }, - spaces_max: { type: 'long' }, - spaces_avg: { type: 'long' }, - saved_7_days_total: { type: 'long' }, - saved_30_days_total: { type: 'long' }, - saved_90_days_total: { type: 'long' }, - }, - }, - fetch: async ({ soClient }) => await getStats(soClient), - }); - collectorSet.registerCollector(collector); -} diff --git a/src/plugins/visualizations/tsconfig.json b/src/plugins/visualizations/tsconfig.json index 9a9cb97d63764..e44374e23f623 100644 --- a/src/plugins/visualizations/tsconfig.json +++ b/src/plugins/visualizations/tsconfig.json @@ -22,7 +22,6 @@ { "path": "../inspector/tsconfig.json" }, { "path": "../saved_objects/tsconfig.json" }, { "path": "../saved_objects_tagging_oss/tsconfig.json" }, - { "path": "../usage_collection/tsconfig.json" }, { "path": "../kibana_utils/tsconfig.json" }, { "path": "../kibana_react/tsconfig.json" }, { "path": "../discover/tsconfig.json" },