From dc652f5c46a47abddfaa1122da3fa958cbb32f23 Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Tue, 13 Apr 2021 16:08:55 -0400 Subject: [PATCH 1/5] Counting number of alert history connectors in use --- .../actions/server/usage/actions_telemetry.ts | 32 +++++++++++++++++-- .../server/usage/actions_usage_collector.ts | 2 ++ x-pack/plugins/actions/server/usage/task.ts | 6 +++- x-pack/plugins/actions/server/usage/types.ts | 1 + 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index 8d028b176a00a..07fd533f038db 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -11,6 +11,7 @@ import { SavedObjectsBulkGetObject, SavedObjectsBulkResponse, } from 'kibana/server'; +import { AlertHistoryEsIndexConnectorId } from '../../common'; import { ActionResult } from '../types'; export async function getTotalCount(esClient: ElasticsearchClient, kibanaIndex: string) { @@ -79,7 +80,11 @@ export async function getInUseTotalCount( options?: SavedObjectsBaseOptions | undefined ) => Promise>>>, kibanaIndex: string -): Promise<{ countTotal: number; countByType: Record }> { +): Promise<{ + countTotal: number; + countByType: Record; + countByAlertHistoryConnectorType: number; +}> { const scriptedMetric = { scripted_metric: { init_script: 'state.connectorIds = new HashMap(); state.total = 0;', @@ -167,7 +172,12 @@ export async function getInUseTotalCount( fields: ['id', 'actionTypeId'], })); const actions = await actionsBulkGet(bulkFilter); - const countByType = actions.saved_objects.reduce( + + // filter out preconfigured connectors, which are not saved objects + const actionsWithActionTypeId = actions.saved_objects.filter( + (action) => action?.attributes?.actionTypeId != null + ); + const countByActionTypeId = actionsWithActionTypeId.reduce( (actionTypeCount: Record, action) => { const alertTypeId = replaceFirstAndLastDotSymbols(action.attributes.actionTypeId); const currentCount = @@ -177,7 +187,23 @@ export async function getInUseTotalCount( }, {} ); - return { countTotal: aggs.total, countByType }; + + const preconfiguredAlertHistoryConnector = actions.saved_objects.filter( + (action) => action.id === AlertHistoryEsIndexConnectorId + ); + + console.log( + `actions telemetry ${JSON.stringify({ + countTotal: aggs.total, + countByType: countByActionTypeId, + countByAlertHistoryConnectorType: preconfiguredAlertHistoryConnector.length, + })}` + ); + return { + countTotal: aggs.total, + countByType: countByActionTypeId, + countByAlertHistoryConnectorType: preconfiguredAlertHistoryConnector.length, + }; } function replaceFirstAndLastDotSymbols(strToReplace: string) { diff --git a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts index c338bbc998c49..baa82a880ecaf 100644 --- a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts +++ b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts @@ -39,6 +39,7 @@ export function createActionsUsageCollector( schema: { count_total: { type: 'long' }, count_active_total: { type: 'long' }, + count_active_alert_history_connectors: { type: 'long' }, count_by_type: byTypeSchema, count_active_by_type: byTypeSchema, }, @@ -55,6 +56,7 @@ export function createActionsUsageCollector( return { count_total: 0, count_active_total: 0, + count_active_alert_history_connectors: 0, count_active_by_type: {}, count_by_type: {}, }; diff --git a/x-pack/plugins/actions/server/usage/task.ts b/x-pack/plugins/actions/server/usage/task.ts index 03c49a31ed311..ecb8a813213f3 100644 --- a/x-pack/plugins/actions/server/usage/task.ts +++ b/x-pack/plugins/actions/server/usage/task.ts @@ -101,6 +101,7 @@ export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex count_by_type: totalAggegations.countByType, count_active_total: totalInUse.countTotal, count_active_by_type: totalInUse.countByType, + count_active_alert_history_connectors: totalInUse.countByAlertHistoryConnectorType, }, runAt: getNextMidnight(), }; @@ -118,5 +119,8 @@ export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex } function getNextMidnight() { - return moment().add(1, 'd').startOf('d').toDate(); + // return moment().add(1, 'd').startOf('d').toDate(); + const runAt = new Date(); + runAt.setMilliseconds(new Date().getMilliseconds() + 15000); + return runAt; } diff --git a/x-pack/plugins/actions/server/usage/types.ts b/x-pack/plugins/actions/server/usage/types.ts index c192115bfb02a..73d93a75c399c 100644 --- a/x-pack/plugins/actions/server/usage/types.ts +++ b/x-pack/plugins/actions/server/usage/types.ts @@ -8,6 +8,7 @@ export interface ActionsUsage { count_total: number; count_active_total: number; + count_active_alert_history_connectors: number; count_by_type: Record; count_active_by_type: Record; // TODO: Implement executions count telemetry with eventLog, when it will write to index From e6965bb339858d100b96551f443a3a81b543e68e Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Tue, 13 Apr 2021 19:54:11 -0400 Subject: [PATCH 2/5] Telemetry for preconfigured alert history config enabled --- x-pack/plugins/actions/server/plugin.ts | 1 + .../actions/server/usage/actions_usage_collector.ts | 8 +++++++- x-pack/plugins/actions/server/usage/types.ts | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 3c754d90c4af5..1d941617789b7 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -224,6 +224,7 @@ export class ActionsPlugin implements Plugin taskManager) ); } diff --git a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts index baa82a880ecaf..0164c6b195f50 100644 --- a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts +++ b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts @@ -9,6 +9,7 @@ import { MakeSchemaFrom, UsageCollectionSetup } from 'src/plugins/usage_collecti import { get } from 'lodash'; import { TaskManagerStartContract } from '../../../task_manager/server'; import { ActionsUsage } from './types'; +import { ActionsConfig } from '../config'; const byTypeSchema: MakeSchemaFrom['count_by_type'] = { // TODO: Find out an automated way to populate the keys or reformat these into an array (and change the Remote Telemetry indexer accordingly) @@ -28,6 +29,7 @@ const byTypeSchema: MakeSchemaFrom['count_by_type'] = { export function createActionsUsageCollector( usageCollection: UsageCollectionSetup, + config: ActionsConfig, taskManager: Promise ) { return usageCollection.makeUsageCollector({ @@ -37,6 +39,7 @@ export function createActionsUsageCollector( return true; }, schema: { + alert_history_connector_enabled: { type: 'boolean' }, count_total: { type: 'long' }, count_active_total: { type: 'long' }, count_active_alert_history_connectors: { type: 'long' }, @@ -51,9 +54,11 @@ export function createActionsUsageCollector( return { ...state, + alert_history_connector_enabled: config.preconfiguredAlertHistoryEsIndex, }; } catch (err) { return { + alert_history_connector_enabled: false, count_total: 0, count_active_total: 0, count_active_alert_history_connectors: 0, @@ -86,8 +91,9 @@ async function getLatestTaskState(taskManager: TaskManagerStartContract) { export function registerActionsUsageCollector( usageCollection: UsageCollectionSetup, + config: ActionsConfig, taskManager: Promise ) { - const collector = createActionsUsageCollector(usageCollection, taskManager); + const collector = createActionsUsageCollector(usageCollection, config, taskManager); usageCollection.registerCollector(collector); } diff --git a/x-pack/plugins/actions/server/usage/types.ts b/x-pack/plugins/actions/server/usage/types.ts index 73d93a75c399c..9221ba8ea5688 100644 --- a/x-pack/plugins/actions/server/usage/types.ts +++ b/x-pack/plugins/actions/server/usage/types.ts @@ -6,6 +6,7 @@ */ export interface ActionsUsage { + alert_history_connector_enabled: boolean; count_total: number; count_active_total: number; count_active_alert_history_connectors: number; From c728d9dc16c3544af7b57afd88c6d603b15a4c9f Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Wed, 14 Apr 2021 07:51:41 -0400 Subject: [PATCH 3/5] Updating telemetry mappings --- src/plugins/telemetry/schema/oss_plugins.json | 12 ++++++------ .../schema/xpack_plugins.json | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 41b75824e992d..53c9c22c76500 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -8136,6 +8136,12 @@ "description": "Non-default value of setting." } }, + "observability:enableInspectEsQueries": { + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } + }, "banners:placement": { "type": "keyword", "_meta": { @@ -8160,12 +8166,6 @@ "description": "Non-default value of setting." } }, - "observability:enableInspectEsQueries": { - "type": "boolean", - "_meta": { - "description": "Non-default value of setting." - } - }, "labs:presentation:unifiedToolbar": { "type": "boolean", "_meta": { diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 3d302aa12832e..9f25e6ae7319f 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -2,12 +2,18 @@ "properties": { "actions": { "properties": { + "alert_history_connector_enabled": { + "type": "boolean" + }, "count_total": { "type": "long" }, "count_active_total": { "type": "long" }, + "count_active_alert_history_connectors": { + "type": "long" + }, "count_by_type": { "properties": { "DYNAMIC_KEY": { From bc4dbc43b60c60eb645dc64ab6a145ebfb8b5ead Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Wed, 14 Apr 2021 08:27:23 -0400 Subject: [PATCH 4/5] Updating tests --- .../server/usage/actions_telemetry.test.ts | 67 +++++++++++++++++++ .../actions/server/usage/actions_telemetry.ts | 10 +-- .../usage/actions_usage_collector.test.ts | 5 ++ x-pack/plugins/actions/server/usage/task.ts | 5 +- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts index e4611857ca279..18510ba9aa864 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts @@ -158,12 +158,79 @@ Object { expect(telemetry).toMatchInlineSnapshot(` Object { + "countByAlertHistoryConnectorType": 0, "countByType": Object { "__server-log": 1, "__slack": 1, }, "countTotal": 2, } +`); + }); + + test('getInUseTotalCount should count preconfigured alert history connector usage', async () => { + const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser; + mockEsClient.search.mockReturnValue( + // @ts-expect-error not full search response + elasticsearchClientMock.createSuccessTransportRequestPromise({ + aggregations: { + refs: { + actionRefIds: { + value: { + connectorIds: { + '1': 'action_0', + '123': 'action_1', + 'preconfigured-alert-history-es-index': 'action_2', + }, + total: 3, + }, + }, + }, + hits: { + hits: [], + }, + }, + }) + ); + const actionsBulkGet = jest.fn(); + actionsBulkGet.mockReturnValue({ + saved_objects: [ + { + id: '1', + attributes: { + actionTypeId: '.server-log', + }, + }, + { + id: '123', + attributes: { + actionTypeId: '.slack', + }, + }, + { + id: 'preconfigured-alert-history-es-index', + error: { + statusCode: 404, + error: 'Not Found', + message: 'Saved object [action/preconfigured-alert-history-es-index] not found', + }, + }, + ], + }); + const telemetry = await getInUseTotalCount(mockEsClient, actionsBulkGet, 'test'); + + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(actionsBulkGet).toHaveBeenCalledTimes(1); + + expect(telemetry).toMatchInlineSnapshot(` +Object { + "countByAlertHistoryConnectorType": 1, + "countByType": Object { + "__server-log": 1, + "__slack": 1, + }, + "countTotal": 3, +} `); }); }); diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index 07fd533f038db..71516cb4918e7 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -173,7 +173,8 @@ export async function getInUseTotalCount( })); const actions = await actionsBulkGet(bulkFilter); - // filter out preconfigured connectors, which are not saved objects + // filter out preconfigured connectors, which are not saved objects and return + // an error in the bulk response const actionsWithActionTypeId = actions.saved_objects.filter( (action) => action?.attributes?.actionTypeId != null ); @@ -192,13 +193,6 @@ export async function getInUseTotalCount( (action) => action.id === AlertHistoryEsIndexConnectorId ); - console.log( - `actions telemetry ${JSON.stringify({ - countTotal: aggs.total, - countByType: countByActionTypeId, - countByAlertHistoryConnectorType: preconfiguredAlertHistoryConnector.length, - })}` - ); return { countTotal: aggs.total, countByType: countByActionTypeId, diff --git a/x-pack/plugins/actions/server/usage/actions_usage_collector.test.ts b/x-pack/plugins/actions/server/usage/actions_usage_collector.test.ts index cf76adddc5494..df43cbd084be8 100644 --- a/x-pack/plugins/actions/server/usage/actions_usage_collector.test.ts +++ b/x-pack/plugins/actions/server/usage/actions_usage_collector.test.ts @@ -7,6 +7,7 @@ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { registerActionsUsageCollector } from './actions_usage_collector'; +import { configSchema, ActionsConfig } from '../config'; import { taskManagerMock } from '../../../task_manager/server/mocks'; const mockTaskManagerStart = taskManagerMock.createStart(); @@ -14,8 +15,10 @@ const mockTaskManagerStart = taskManagerMock.createStart(); beforeEach(() => jest.resetAllMocks()); describe('registerActionsUsageCollector', () => { + let config: ActionsConfig; let usageCollectionMock: jest.Mocked; beforeEach(() => { + config = configSchema.validate({}); usageCollectionMock = ({ makeUsageCollector: jest.fn(), registerCollector: jest.fn(), @@ -25,6 +28,7 @@ describe('registerActionsUsageCollector', () => { it('should call registerCollector', () => { registerActionsUsageCollector( usageCollectionMock as UsageCollectionSetup, + config, new Promise(() => mockTaskManagerStart) ); expect(usageCollectionMock.registerCollector).toHaveBeenCalledTimes(1); @@ -33,6 +37,7 @@ describe('registerActionsUsageCollector', () => { it('should call makeUsageCollector with type = actions', () => { registerActionsUsageCollector( usageCollectionMock as UsageCollectionSetup, + config, new Promise(() => mockTaskManagerStart) ); expect(usageCollectionMock.makeUsageCollector).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/actions/server/usage/task.ts b/x-pack/plugins/actions/server/usage/task.ts index ecb8a813213f3..3ba40d92abd7a 100644 --- a/x-pack/plugins/actions/server/usage/task.ts +++ b/x-pack/plugins/actions/server/usage/task.ts @@ -119,8 +119,5 @@ export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex } function getNextMidnight() { - // return moment().add(1, 'd').startOf('d').toDate(); - const runAt = new Date(); - runAt.setMilliseconds(new Date().getMilliseconds() + 15000); - return runAt; + return moment().add(1, 'd').startOf('d').toDate(); } From 3b41bbf14a1d0d1cbfd1963d5de3d93ac7511f0b Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Wed, 14 Apr 2021 19:17:05 -0400 Subject: [PATCH 5/5] Adding descriptions to new telemetry fields --- .../actions/server/usage/actions_usage_collector.ts | 12 ++++++++++-- .../schema/xpack_plugins.json | 10 ++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts index 0164c6b195f50..06248e1fa95a8 100644 --- a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts +++ b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts @@ -39,10 +39,18 @@ export function createActionsUsageCollector( return true; }, schema: { - alert_history_connector_enabled: { type: 'boolean' }, + alert_history_connector_enabled: { + type: 'boolean', + _meta: { description: 'Indicates if preconfigured alert history connector is enabled.' }, + }, count_total: { type: 'long' }, count_active_total: { type: 'long' }, - count_active_alert_history_connectors: { type: 'long' }, + count_active_alert_history_connectors: { + type: 'long', + _meta: { + description: 'The total number of preconfigured alert history connectors used by rules.', + }, + }, count_by_type: byTypeSchema, count_active_by_type: byTypeSchema, }, diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 9f25e6ae7319f..1d1cd8c0c7667 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -3,7 +3,10 @@ "actions": { "properties": { "alert_history_connector_enabled": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if preconfigured alert history connector is enabled." + } }, "count_total": { "type": "long" @@ -12,7 +15,10 @@ "type": "long" }, "count_active_alert_history_connectors": { - "type": "long" + "type": "long", + "_meta": { + "description": "The total number of preconfigured alert history connectors used by rules." + } }, "count_by_type": { "properties": {