Skip to content

Commit

Permalink
Add new telemetry data from event-log index. (#140943)
Browse files Browse the repository at this point in the history
* Add new telemetry data from eventLog index.
count_rules_by_execution_status_per_day,
count_connector_types_by_action_run_outcome_per_day,
  • Loading branch information
ersin-erdal authored Sep 20, 2022
1 parent 50b3381 commit 17a25b8
Show file tree
Hide file tree
Showing 14 changed files with 300 additions and 4 deletions.
41 changes: 41 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 @@ -721,6 +721,36 @@ Object {
},
},
},
count_connector_types_by_action_run_outcome_per_day: {
actionSavedObjects: {
connector_types: {
buckets: [
{
key: '.slack',
outcome: {
count: {
buckets: [
{ key: 'success', doc_count: 12 },
{ key: 'failure', doc_count: 1 },
],
},
},
},
{
key: '.email',
outcome: {
count: {
buckets: [
{ key: 'success', doc_count: 13 },
{ key: 'failure', doc_count: 2 },
],
},
},
},
],
},
},
},
},
}
);
Expand Down Expand Up @@ -754,6 +784,16 @@ Object {
__slack: 7,
},
countTotal: 120,
countRunOutcomeByConnectorType: {
__email: {
failure: 2,
success: 13,
},
__slack: {
failure: 1,
success: 12,
},
},
hasErrors: false,
});
});
Expand All @@ -775,6 +815,7 @@ Object {
"countByType": Object {},
"countFailed": 0,
"countFailedByType": Object {},
"countRunOutcomeByConnectorType": Object {},
"countTotal": 0,
"errorMessage": "oh no",
"hasErrors": true,
Expand Down
50 changes: 49 additions & 1 deletion x-pack/plugins/actions/server/usage/actions_telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types';
import { ElasticsearchClient, Logger } from '@kbn/core/server';
import { AggregationsTermsAggregateBase } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import {
AvgActionRunOutcomeByConnectorTypeBucket,
parseActionRunOutcomeByConnectorTypesBucket,
} from './lib/parse_connector_type_bucket';
import { AlertHistoryEsIndexConnectorId } from '../../common';
import { ActionResult, PreConfiguredAction } from '../types';

Expand Down Expand Up @@ -395,7 +400,7 @@ export async function getInUseTotalCount(
}
}

function replaceFirstAndLastDotSymbols(strToReplace: string) {
export function replaceFirstAndLastDotSymbols(strToReplace: string) {
const hasFirstSymbolDot = strToReplace.startsWith('.');
const appliedString = hasFirstSymbolDot ? strToReplace.replace('.', '__') : strToReplace;
const hasLastSymbolDot = strToReplace.endsWith('.');
Expand All @@ -415,6 +420,7 @@ export async function getExecutionsPerDayCount(
countFailedByType: Record<string, number>;
avgExecutionTime: number;
avgExecutionTimeByType: Record<string, number>;
countRunOutcomeByConnectorType: Record<string, number>;
}> {
const scriptedMetric = {
scripted_metric: {
Expand Down Expand Up @@ -536,6 +542,35 @@ export async function getExecutionsPerDayCount(
},
},
},
count_connector_types_by_action_run_outcome_per_day: {
nested: {
path: 'kibana.saved_objects',
},
aggs: {
actionSavedObjects: {
filter: { term: { 'kibana.saved_objects.type': 'action' } },
aggs: {
connector_types: {
terms: {
field: 'kibana.saved_objects.type_id',
},
aggs: {
outcome: {
reverse_nested: {},
aggs: {
count: {
terms: {
field: 'event.outcome',
},
},
},
},
},
},
},
},
},
},
},
},
});
Expand Down Expand Up @@ -564,6 +599,14 @@ export async function getExecutionsPerDayCount(
{}
);

const aggsCountConnectorTypeByActionRun = actionResults.aggregations as {
count_connector_types_by_action_run_outcome_per_day: {
actionSavedObjects: {
connector_types: AggregationsTermsAggregateBase<AvgActionRunOutcomeByConnectorTypeBucket>;
};
};
};

return {
hasErrors: false,
countTotal: aggsExecutions.total,
Expand All @@ -586,6 +629,10 @@ export async function getExecutionsPerDayCount(
),
avgExecutionTime: aggsAvgExecutionTime,
avgExecutionTimeByType,
countRunOutcomeByConnectorType: parseActionRunOutcomeByConnectorTypesBucket(
aggsCountConnectorTypeByActionRun.count_connector_types_by_action_run_outcome_per_day
.actionSavedObjects.connector_types.buckets
),
};
} catch (err) {
const errorMessage = err && err.message ? err.message : err.toString();
Expand All @@ -601,6 +648,7 @@ export async function getExecutionsPerDayCount(
countFailedByType: {},
avgExecutionTime: 0,
avgExecutionTimeByType: {},
countRunOutcomeByConnectorType: {},
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ export function createActionsUsageCollector(
count_actions_executions_failed_by_type_per_day: byTypeSchema,
avg_execution_time_per_day: { type: 'long' },
avg_execution_time_by_type_per_day: byTypeSchema,
count_connector_types_by_action_run_outcome_per_day: {
DYNAMIC_KEY: {
success: { type: 'long' },
failure: { type: 'long' },
unknown: { type: 'long' },
},
},
},
fetch: async () => {
try {
Expand Down Expand Up @@ -77,6 +84,7 @@ export function createActionsUsageCollector(
count_actions_executions_failed_by_type_per_day: {},
avg_execution_time_per_day: 0,
avg_execution_time_by_type_per_day: {},
count_connector_types_by_action_run_outcome_per_day: {},
};
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { parseActionRunOutcomeByConnectorTypesBucket } from './parse_connector_type_bucket';

describe('parseActionRunOutcomeByConnectorTypesBucket', () => {
test('should correctly parse connector type bucket results', () => {
expect(
parseActionRunOutcomeByConnectorTypesBucket([
{
key: '.server-log',
doc_count: 78,
outcome: {
count: {
buckets: [
{ key: 'success', doc_count: 2 },
{ key: 'failure', doc_count: 1 },
],
},
},
},
{
key: '.index',
doc_count: 42,
outcome: {
count: {
buckets: [
{ key: 'success', doc_count: 3 },
{ key: 'failure', doc_count: 4 },
],
},
},
},
])
).toEqual({
__index: {
failure: 4,
success: 3,
},
'__server-log': {
failure: 1,
success: 2,
},
});
});

test('should handle missing values', () => {
expect(
parseActionRunOutcomeByConnectorTypesBucket([
{
key: '.server-log',
doc_count: 78,
outcome: {
count: {
// @ts-expect-error
buckets: [{ key: 'success', doc_count: 2 }, { key: 'failure' }],
},
},
},
{
key: '.index',
outcome: {
// @ts-expect-error
count: {},
},
},
])
).toEqual({
'__server-log': {
failure: 0,
success: 2,
},
__index: {},
});
});

test('should handle empty input', () => {
expect(parseActionRunOutcomeByConnectorTypesBucket([])).toEqual({});
});
//
test('should handle undefined input', () => {
expect(parseActionRunOutcomeByConnectorTypesBucket(undefined)).toEqual({});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { AggregationsBuckets } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { replaceFirstAndLastDotSymbols } from '../actions_telemetry';

export interface AvgActionRunOutcomeByConnectorTypeBucket {
key: string;
doc_count: number; // Not used for duration telemetry but can be helpful later.
outcome: { count: { buckets: Array<{ key: string; doc_count: number }> } };
}

export function parseActionRunOutcomeByConnectorTypesBucket(
connectorTypeBuckets: AggregationsBuckets<AvgActionRunOutcomeByConnectorTypeBucket> = []
) {
const connectorTypes = connectorTypeBuckets as AvgActionRunOutcomeByConnectorTypeBucket[];
return connectorTypes.reduce((acc, connectorType) => {
const outcomes = connectorType.outcome?.count?.buckets ?? [];
return {
...acc,
[replaceFirstAndLastDotSymbols(connectorType.key)]: outcomes.reduce((accBucket, bucket) => {
return { ...accBucket, [replaceFirstAndLastDotSymbols(bucket.key)]: bucket.doc_count || 0 };
}, {}),
};
}, {});
}
2 changes: 2 additions & 0 deletions x-pack/plugins/actions/server/usage/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ export function telemetryTaskRunner(
totalExecutionsPerDay.countFailedByType,
avg_execution_time_per_day: totalExecutionsPerDay.avgExecutionTime,
avg_execution_time_by_type_per_day: totalExecutionsPerDay.avgExecutionTimeByType,
count_connector_types_by_action_run_outcome_per_day:
totalExecutionsPerDay.countRunOutcomeByConnectorType,
},
runAt: getNextMidnight(),
};
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/actions/server/usage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface ActionsUsage {
count_actions_executions_by_type_per_day: Record<string, number>;
count_actions_executions_failed_per_day: number;
count_actions_executions_failed_by_type_per_day: Record<string, number>;
count_connector_types_by_action_run_outcome_per_day: Record<string, Record<string, number>>;
avg_execution_time_per_day: number;
avg_execution_time_by_type_per_day: Record<string, number>;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ const byStatusSchema: MakeSchemaFrom<AlertingUsage>['count_rules_by_execution_st
warning: { type: 'long' },
};

const byStatusPerDaySchema: MakeSchemaFrom<AlertingUsage>['count_rules_by_execution_status_per_day'] =
{
success: { type: 'long' },
failure: { type: 'long' },
unknown: { type: 'long' },
};

const byNotifyWhenSchema: MakeSchemaFrom<AlertingUsage>['count_rules_by_notify_when'] = {
on_action_group_change: { type: 'long' },
on_active_alert: { type: 'long' },
Expand Down Expand Up @@ -200,6 +207,7 @@ export function createAlertingUsageCollector(
count_rules_muted: 0,
count_rules_with_muted_alerts: 0,
count_connector_types_by_consumers: {},
count_rules_by_execution_status_per_day: {},
avg_execution_time_per_day: 0,
avg_execution_time_by_type_per_day: {},
avg_es_search_duration_per_day: 0,
Expand Down Expand Up @@ -283,6 +291,7 @@ export function createAlertingUsageCollector(
count_rules_muted: { type: 'long' },
count_rules_with_muted_alerts: { type: 'long' },
count_connector_types_by_consumers: { DYNAMIC_KEY: { DYNAMIC_KEY: { type: 'long' } } },
count_rules_by_execution_status_per_day: byStatusPerDaySchema,
avg_execution_time_per_day: { type: 'long' },
avg_execution_time_by_type_per_day: byTypeSchema,
avg_es_search_duration_per_day: { type: 'long' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,14 @@ describe('event log telemetry', () => {
avg_total_search_duration: {
value: 28.630434782608695,
},
by_execution_status: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 'success', doc_count: 21 },
{ key: 'failure', doc_count: 22 },
],
},
},
});

Expand Down Expand Up @@ -1377,7 +1385,6 @@ describe('event log telemetry', () => {
logs__alert__document__count: 0,
},
},

alertsPercentilesByType: {
p50: {
'__index-threshold': 1,
Expand All @@ -1398,6 +1405,10 @@ describe('event log telemetry', () => {
logs__alert__document__count: 0,
},
},
countRulesByExecutionStatus: {
failure: 22,
success: 21,
},
hasErrors: false,
});
});
Expand Down Expand Up @@ -1437,6 +1448,7 @@ describe('event log telemetry', () => {
generatedActionsPercentilesByType: {},
alertsPercentiles: {},
alertsPercentilesByType: {},
countRulesByExecutionStatus: {},
});
});
});
Expand Down
Loading

0 comments on commit 17a25b8

Please sign in to comment.