Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Alerting] More telemetry for 8.0 based on Event Log data #115318

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b1683b3
[Alerting] More telemetry for 8.0 based on Event Log data
YulNaumenko Oct 18, 2021
34eb761
fixed event log index mapping
YulNaumenko Oct 18, 2021
30c9ae7
fixed typecheck
YulNaumenko Oct 18, 2021
91e9b09
fixed tests
YulNaumenko Oct 18, 2021
216bc96
added avg aggs
YulNaumenko Oct 19, 2021
bb21d80
Merge branch 'master' into alerting-actions-more-8-0-telemetry
kibanamachine Oct 19, 2021
d657f25
Merge branch 'master' into alerting-actions-more-8-0-telemetry
kibanamachine Oct 19, 2021
6005cd4
set size to 0
YulNaumenko Oct 21, 2021
76fad13
Merged upstream/master
YulNaumenko Oct 22, 2021
ffde2fc
Merge branch 'master' into alerting-actions-more-8-0-telemetry
kibanamachine Oct 25, 2021
6b5bc61
fixed due to comments
YulNaumenko Oct 26, 2021
79f5e7a
Merge remote-tracking branch upstream
YulNaumenko Oct 27, 2021
86d3cf5
fixed telemetry schema
YulNaumenko Oct 27, 2021
899a624
fixed query
YulNaumenko Oct 28, 2021
26efb80
removed test data
YulNaumenko Oct 28, 2021
712d84c
added tests
YulNaumenko Oct 28, 2021
d486697
fixed test
YulNaumenko Oct 28, 2021
04a5eea
fixed query
YulNaumenko Oct 28, 2021
f43d3a9
Merge branch 'master' into alerting-actions-more-8-0-telemetry
kibanamachine Oct 28, 2021
e4cde26
Merge branch 'main' into alerting-actions-more-8-0-telemetry
kibanamachine Nov 1, 2021
1b90e4a
Merge branch 'main' into alerting-actions-more-8-0-telemetry
kibanamachine Nov 1, 2021
6920190
added exection detalization by day
YulNaumenko Nov 2, 2021
92f84df
fixed test
YulNaumenko Nov 2, 2021
20672e4
fixed for rules
YulNaumenko Nov 2, 2021
5c6a53e
fixed schema
YulNaumenko Nov 2, 2021
04717dd
fixed schema
YulNaumenko Nov 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion x-pack/plugins/actions/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
plugins.taskManager,
core,
this.kibanaIndexConfig.kibana.index,
this.preconfiguredActions
this.preconfiguredActions,
plugins.eventLog
);
}

Expand Down
189 changes: 188 additions & 1 deletion x-pack/plugins/actions/server/usage/actions_telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,4 +314,191 @@ function replaceFirstAndLastDotSymbols(strToReplace: string) {
return hasLastSymbolDot ? `${appliedString.slice(0, -1)}__` : appliedString;
}

// TODO: Implement executions count telemetry with eventLog, when it will write to index
export async function getExecutionsTotalCount(
esClient: ElasticsearchClient,
eventLogIndex: string
): Promise<{
countTotal: number;
countByType: Record<string, number>;
countFailures: number;
countFailuresByType: Record<string, number>;
avgExecutionTime: number;
avgExecutionTimeByType: Record<string, number>;
}> {
const scriptedMetric = {
scripted_metric: {
init_script: 'state.connectorTypes = [:]; state.total = 0;',
map_script: `
if (doc['kibana.saved_objects.type'].value == 'action') {
String connectorType = doc['kibana.saved_objects.type_id'].value;
state.connectorTypes.put(connectorType, state.connectorTypes.containsKey(connectorType) ? state.connectorTypes.get(connectorType) + 1 : 1);
state.total++;
}
`,
// Combine script is executed per cluster, but we already have a key-value pair per cluster.
// Despite docs that say this is optional, this script can't be blank.
combine_script: 'return state',
// Reduce script is executed across all clusters, so we need to add up all the total from each cluster
// This also needs to account for having no data
reduce_script: `
Map connectorTypes = [:];
long total = 0;
for (state in states) {
chrisronline marked this conversation as resolved.
Show resolved Hide resolved
if (state !== null) {
total += state.total;
for (String k : state.connectorTypes.keySet()) {
connectorTypes.put(k, connectorTypes.containsKey(k) ? connectorTypes.get(k) + state.connectorTypes.get(k) : state.connectorTypes.get(k));
}
}
}
Map result = new HashMap();
result.total = total;
result.connectorTypes = connectorTypes;
return result;
`,
},
};

const { body: actionResults } = await esClient.search({
index: eventLogIndex,
body: {
YulNaumenko marked this conversation as resolved.
Show resolved Hide resolved
query: {
YulNaumenko marked this conversation as resolved.
Show resolved Hide resolved
bool: {
filter: {
bool: {
must: [
{
term: { 'event.action': 'execute' },
},
{
nested: {
path: 'kibana.saved_objects',
query: {
bool: {
must: [
{
term: {
'kibana.saved_objects.type': {
value: 'action',
},
},
},
],
},
YulNaumenko marked this conversation as resolved.
Show resolved Hide resolved
},
},
},
],
},
},
},
},
aggs: {
totalExecutions: {
nested: {
path: 'kibana.saved_objects',
},
aggs: {
byConnectorTypeId: scriptedMetric,
},
},
failuresExecutions: {
filter: {
bool: {
filter: [
{
term: {
'event.outcome': 'failure',
},
},
],
},
},
aggs: {
refs: {
nested: {
path: 'kibana.saved_objects',
},
aggs: {
byConnectorTypeId: scriptedMetric,
},
},
},
},
avgDuration: { avg: { field: 'event.duration' } },
},
},
});

// @ts-expect-error aggegation type is not specified
const aggsExecutions = actionResults.aggregations.totalExecutions?.byConnectorTypeId.value;
const aggsAvgExecutionTime = Math.round(
// @ts-expect-error aggegation type is not specified
actionResults.aggregations.avgDuration.value / (1000 * 1000)
); // nano seconds
YulNaumenko marked this conversation as resolved.
Show resolved Hide resolved
const aggsFailureExecutions =
// @ts-expect-error aggegation type is not specified
actionResults.aggregations.failuresExecutions?.refs?.byConnectorTypeId.value;

const avgExecutionTimeByType: Record<string, number> = {};
for (const [key] of Object.entries(aggsExecutions.connectorTypes)) {
const { body: connectorTypeResults } = await esClient.search({
YulNaumenko marked this conversation as resolved.
Show resolved Hide resolved
index: eventLogIndex,
body: {
query: {
bool: {
filter: {
bool: {
must: [
{
term: { 'event.action': 'execute' },
},
{
nested: {
path: 'kibana.saved_objects',
query: {
bool: {
must: [
{
term: {
'kibana.saved_objects.type': {
value: 'action',
},
},
},
{
term: {
'kibana.saved_objects.type_id': {
value: key,
},
},
},
],
},
},
},
},
],
},
},
},
},
aggs: {
avgDuration: { avg: { field: 'event.duration' } },
},
},
});
avgExecutionTimeByType[key] =
// @ts-expect-error aggegation type is not specified
Math.round(connectorTypeResults.aggregations?.avgDuration.value / (1000 * 1000));
}

return {
countTotal: aggsExecutions.total,
countByType: aggsExecutions.connectorTypes,
countFailures: aggsFailureExecutions.total,
countFailuresByType: aggsFailureExecutions.connectorTypes,
avgExecutionTime: aggsAvgExecutionTime,
avgExecutionTimeByType,
};
}
12 changes: 12 additions & 0 deletions x-pack/plugins/actions/server/usage/actions_usage_collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ export function createActionsUsageCollector(
},
count_by_type: byTypeSchema,
count_active_by_type: byTypeSchema,
count_actions_executions: { type: 'long' },
count_actions_executions_by_type: byTypeSchema,
count_actions_executions_failured: { type: 'long' },
YulNaumenko marked this conversation as resolved.
Show resolved Hide resolved
count_actions_executions_failured_by_type: byTypeSchema,
avg_execution_time: { type: 'long' },
avg_execution_time_by_type: byTypeSchema,
},
fetch: async () => {
try {
Expand All @@ -73,6 +79,12 @@ export function createActionsUsageCollector(
count_active_alert_history_connectors: 0,
count_active_by_type: {},
count_by_type: {},
count_actions_executions: 0,
count_actions_executions_by_type: {},
count_actions_executions_failured: 0,
count_actions_executions_failured_by_type: {},
avg_execution_time: 0,
avg_execution_time_by_type: {},
};
}
},
Expand Down
43 changes: 34 additions & 9 deletions x-pack/plugins/actions/server/usage/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@

import { Logger, CoreSetup } from 'kibana/server';
import moment from 'moment';
import { IEventLogService } from '../../../event_log/server';
import {
RunContext,
TaskManagerSetupContract,
TaskManagerStartContract,
} from '../../../task_manager/server';
import { PreConfiguredAction } from '../types';
import { getTotalCount, getInUseTotalCount } from './actions_telemetry';
import { getTotalCount, getInUseTotalCount, getExecutionsTotalCount } from './actions_telemetry';

export const TELEMETRY_TASK_TYPE = 'actions_telemetry';

Expand All @@ -24,9 +25,17 @@ export function initializeActionsTelemetry(
taskManager: TaskManagerSetupContract,
core: CoreSetup,
kibanaIndex: string,
preconfiguredActions: PreConfiguredAction[]
preconfiguredActions: PreConfiguredAction[],
eventLog: IEventLogService
) {
registerActionsTelemetryTask(logger, taskManager, core, kibanaIndex, preconfiguredActions);
registerActionsTelemetryTask(
logger,
taskManager,
core,
kibanaIndex,
preconfiguredActions,
eventLog
);
}

export function scheduleActionsTelemetry(logger: Logger, taskManager: TaskManagerStartContract) {
Expand All @@ -38,13 +47,20 @@ function registerActionsTelemetryTask(
taskManager: TaskManagerSetupContract,
core: CoreSetup,
kibanaIndex: string,
preconfiguredActions: PreConfiguredAction[]
preconfiguredActions: PreConfiguredAction[],
eventLog: IEventLogService
) {
taskManager.registerTaskDefinitions({
[TELEMETRY_TASK_TYPE]: {
title: 'Actions usage fetch task',
timeout: '5m',
createTaskRunner: telemetryTaskRunner(logger, core, kibanaIndex, preconfiguredActions),
timeout: '5s',
createTaskRunner: telemetryTaskRunner(
logger,
core,
kibanaIndex,
preconfiguredActions,
eventLog
),
},
});
}
Expand All @@ -66,10 +82,12 @@ export function telemetryTaskRunner(
logger: Logger,
core: CoreSetup,
kibanaIndex: string,
preconfiguredActions: PreConfiguredAction[]
preconfiguredActions: PreConfiguredAction[],
eventLog: IEventLogService
) {
return ({ taskInstance }: RunContext) => {
const { state } = taskInstance;
const eventLogIndex = eventLog.getIndexPatterns();
const getEsClient = () =>
core.getStartServices().then(
([
Expand All @@ -84,8 +102,9 @@ export function telemetryTaskRunner(
return Promise.all([
getTotalCount(esClient, kibanaIndex, preconfiguredActions),
getInUseTotalCount(esClient, kibanaIndex),
getExecutionsTotalCount(esClient, eventLogIndex),
])
.then(([totalAggegations, totalInUse]) => {
.then(([totalAggegations, totalInUse, totalExecutions]) => {
return {
state: {
runs: (state.runs || 0) + 1,
Expand All @@ -94,6 +113,12 @@ export function telemetryTaskRunner(
count_active_total: totalInUse.countTotal,
count_active_by_type: totalInUse.countByType,
count_active_alert_history_connectors: totalInUse.countByAlertHistoryConnectorType,
count_actions_executions: totalExecutions.countTotal,
count_actions_executions_by_type: totalExecutions.countByType,
count_actions_executions_failured: totalExecutions.countFailures,
count_actions_executions_failured_by_type: totalExecutions.countFailuresByType,
avg_execution_time: totalExecutions.avgExecutionTime,
avg_execution_time_by_type: totalExecutions.avgExecutionTimeByType,
},
runAt: getNextMidnight(),
};
Expand All @@ -111,5 +136,5 @@ export function telemetryTaskRunner(
}

function getNextMidnight() {
return moment().add(1, 'd').startOf('d').toDate();
return moment().add(1, 'm').startOf('m').toDate();
YulNaumenko marked this conversation as resolved.
Show resolved Hide resolved
}
9 changes: 6 additions & 3 deletions x-pack/plugins/actions/server/usage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ export interface ActionsUsage {
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
// executions_by_type: Record<string, number>;
// executions_total: number;
count_actions_executions: number;
count_actions_executions_by_type: Record<string, number>;
count_actions_executions_failured: number;
count_actions_executions_failured_by_type: Record<string, number>;
avg_execution_time: number;
avg_execution_time_by_type: Record<string, number>;
}
3 changes: 2 additions & 1 deletion x-pack/plugins/alerting/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ export class AlertingPlugin {
this.telemetryLogger,
core,
plugins.taskManager,
config.kibana.index
config.kibana.index,
plugins.eventLog
);
});
}
Expand Down
Loading