Skip to content

Commit

Permalink
[Actions][Telemetry] Counting number of alert history connectors in u…
Browse files Browse the repository at this point in the history
…se (#97063) (#97300)

* Counting number of alert history connectors in use

* Telemetry for preconfigured alert history config enabled

* Updating telemetry mappings

* Updating tests

* Adding descriptions to new telemetry fields

Co-authored-by: Kibana Machine <[email protected]>

Co-authored-by: ymao1 <[email protected]>
  • Loading branch information
kibanamachine and ymao1 authored Apr 15, 2021
1 parent 0a2799d commit 249818d
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 4 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/actions/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
if (usageCollection) {
registerActionsUsageCollector(
usageCollection,
this.actionsConfig,
core.getStartServices().then(([_, { taskManager }]) => taskManager)
);
}
Expand Down
67 changes: 67 additions & 0 deletions x-pack/plugins/actions/server/usage/actions_telemetry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
`);
});
});
26 changes: 23 additions & 3 deletions x-pack/plugins/actions/server/usage/actions_telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -79,7 +80,11 @@ export async function getInUseTotalCount(
options?: SavedObjectsBaseOptions | undefined
) => Promise<SavedObjectsBulkResponse<ActionResult<Record<string, unknown>>>>,
kibanaIndex: string
): Promise<{ countTotal: number; countByType: Record<string, number> }> {
): Promise<{
countTotal: number;
countByType: Record<string, number>;
countByAlertHistoryConnectorType: number;
}> {
const scriptedMetric = {
scripted_metric: {
init_script: 'state.connectorIds = new HashMap(); state.total = 0;',
Expand Down Expand Up @@ -167,7 +172,13 @@ 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 and return
// an error in the bulk response
const actionsWithActionTypeId = actions.saved_objects.filter(
(action) => action?.attributes?.actionTypeId != null
);
const countByActionTypeId = actionsWithActionTypeId.reduce(
(actionTypeCount: Record<string, number>, action) => {
const alertTypeId = replaceFirstAndLastDotSymbols(action.attributes.actionTypeId);
const currentCount =
Expand All @@ -177,7 +188,16 @@ export async function getInUseTotalCount(
},
{}
);
return { countTotal: aggs.total, countByType };

const preconfiguredAlertHistoryConnector = actions.saved_objects.filter(
(action) => action.id === AlertHistoryEsIndexConnectorId
);

return {
countTotal: aggs.total,
countByType: countByActionTypeId,
countByAlertHistoryConnectorType: preconfiguredAlertHistoryConnector.length,
};
}

function replaceFirstAndLastDotSymbols(strToReplace: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@

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();

beforeEach(() => jest.resetAllMocks());

describe('registerActionsUsageCollector', () => {
let config: ActionsConfig;
let usageCollectionMock: jest.Mocked<UsageCollectionSetup>;
beforeEach(() => {
config = configSchema.validate({});
usageCollectionMock = ({
makeUsageCollector: jest.fn(),
registerCollector: jest.fn(),
Expand All @@ -25,6 +28,7 @@ describe('registerActionsUsageCollector', () => {
it('should call registerCollector', () => {
registerActionsUsageCollector(
usageCollectionMock as UsageCollectionSetup,
config,
new Promise(() => mockTaskManagerStart)
);
expect(usageCollectionMock.registerCollector).toHaveBeenCalledTimes(1);
Expand All @@ -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);
Expand Down
18 changes: 17 additions & 1 deletion x-pack/plugins/actions/server/usage/actions_usage_collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<ActionsUsage>['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)
Expand All @@ -28,6 +29,7 @@ const byTypeSchema: MakeSchemaFrom<ActionsUsage>['count_by_type'] = {

export function createActionsUsageCollector(
usageCollection: UsageCollectionSetup,
config: ActionsConfig,
taskManager: Promise<TaskManagerStartContract>
) {
return usageCollection.makeUsageCollector<ActionsUsage>({
Expand All @@ -37,8 +39,18 @@ export function createActionsUsageCollector(
return true;
},
schema: {
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',
_meta: {
description: 'The total number of preconfigured alert history connectors used by rules.',
},
},
count_by_type: byTypeSchema,
count_active_by_type: byTypeSchema,
},
Expand All @@ -50,11 +62,14 @@ 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,
count_active_by_type: {},
count_by_type: {},
};
Expand Down Expand Up @@ -84,8 +99,9 @@ async function getLatestTaskState(taskManager: TaskManagerStartContract) {

export function registerActionsUsageCollector(
usageCollection: UsageCollectionSetup,
config: ActionsConfig,
taskManager: Promise<TaskManagerStartContract>
) {
const collector = createActionsUsageCollector(usageCollection, taskManager);
const collector = createActionsUsageCollector(usageCollection, config, taskManager);
usageCollection.registerCollector(collector);
}
1 change: 1 addition & 0 deletions x-pack/plugins/actions/server/usage/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
};
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/actions/server/usage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
*/

export interface ActionsUsage {
alert_history_connector_enabled: boolean;
count_total: number;
count_active_total: number;
count_active_alert_history_connectors: number;
count_by_type: Record<string, number>;
count_active_by_type: Record<string, number>;
// TODO: Implement executions count telemetry with eventLog, when it will write to index
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@
"properties": {
"actions": {
"properties": {
"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",
"_meta": {
"description": "The total number of preconfigured alert history connectors used by rules."
}
},
"count_by_type": {
"properties": {
"DYNAMIC_KEY": {
Expand Down

0 comments on commit 249818d

Please sign in to comment.