mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
return error message when usage collector failed (#136507)
* return error message when usage collector is failed
This commit is contained in:
parent
3aa0599305
commit
e59c7958de
17 changed files with 264 additions and 58 deletions
|
@ -112,6 +112,7 @@ Object {
|
|||
"some.type": 1,
|
||||
},
|
||||
"countTotal": 4,
|
||||
"hasErrors": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -130,6 +131,8 @@ Object {
|
|||
Object {
|
||||
"countByType": Object {},
|
||||
"countTotal": 0,
|
||||
"errorMessage": "oh no",
|
||||
"hasErrors": true,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -194,6 +197,7 @@ Object {
|
|||
"countEmailByService": Object {},
|
||||
"countNamespaces": 1,
|
||||
"countTotal": 2,
|
||||
"hasErrors": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -295,6 +299,7 @@ Object {
|
|||
"countEmailByService": Object {},
|
||||
"countNamespaces": 1,
|
||||
"countTotal": 4,
|
||||
"hasErrors": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -316,6 +321,8 @@ Object {
|
|||
"countEmailByService": Object {},
|
||||
"countNamespaces": 0,
|
||||
"countTotal": 0,
|
||||
"errorMessage": "oh no",
|
||||
"hasErrors": true,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -438,6 +445,7 @@ Object {
|
|||
"some.type": 1,
|
||||
},
|
||||
"countTotal": 6,
|
||||
"hasErrors": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -546,6 +554,7 @@ Object {
|
|||
},
|
||||
"countNamespaces": 1,
|
||||
"countTotal": 6,
|
||||
"hasErrors": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -645,6 +654,7 @@ Object {
|
|||
},
|
||||
"countNamespaces": 3,
|
||||
"countTotal": 6,
|
||||
"hasErrors": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -744,6 +754,7 @@ Object {
|
|||
__slack: 7,
|
||||
},
|
||||
countTotal: 120,
|
||||
hasErrors: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -765,6 +776,8 @@ Object {
|
|||
"countFailed": 0,
|
||||
"countFailedByType": Object {},
|
||||
"countTotal": 0,
|
||||
"errorMessage": "oh no",
|
||||
"hasErrors": true,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
|
|
@ -43,7 +43,6 @@ export async function getTotalCount(
|
|||
`,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const searchResult = await esClient.search({
|
||||
index: kibanaIndex,
|
||||
|
@ -78,6 +77,7 @@ export async function getTotalCount(
|
|||
}
|
||||
}
|
||||
return {
|
||||
hasErrors: false,
|
||||
countTotal:
|
||||
Object.keys(aggs).reduce(
|
||||
(total: number, key: string) => parseInt(aggs[key], 10) + total,
|
||||
|
@ -86,8 +86,13 @@ export async function getTotalCount(
|
|||
countByType,
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err && err.message ? err.message : err.toString();
|
||||
|
||||
logger.warn(`Error executing actions telemetry task: getTotalCount - ${JSON.stringify(err)}`);
|
||||
|
||||
return {
|
||||
hasErrors: true,
|
||||
errorMessage,
|
||||
countTotal: 0,
|
||||
countByType: {},
|
||||
};
|
||||
|
@ -101,6 +106,8 @@ export async function getInUseTotalCount(
|
|||
referenceType?: string,
|
||||
preconfiguredActions?: PreConfiguredAction[]
|
||||
): Promise<{
|
||||
hasErrors: boolean;
|
||||
errorMessage?: string;
|
||||
countTotal: number;
|
||||
countByType: Record<string, number>;
|
||||
countByAlertHistoryConnectorType: number;
|
||||
|
@ -363,6 +370,7 @@ export async function getInUseTotalCount(
|
|||
}
|
||||
|
||||
return {
|
||||
hasErrors: false,
|
||||
countTotal: aggs.total + (preconfiguredActionsAggs?.total ?? 0),
|
||||
countByType: countByActionTypeId,
|
||||
countByAlertHistoryConnectorType: preconfiguredAlertHistoryConnectors,
|
||||
|
@ -370,10 +378,14 @@ export async function getInUseTotalCount(
|
|||
countNamespaces: namespacesList.size,
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err && err.message ? err.message : err.toString();
|
||||
|
||||
logger.warn(
|
||||
`Error executing actions telemetry task: getInUseTotalCount - ${JSON.stringify(err)}`
|
||||
);
|
||||
return {
|
||||
hasErrors: true,
|
||||
errorMessage,
|
||||
countTotal: 0,
|
||||
countByType: {},
|
||||
countByAlertHistoryConnectorType: 0,
|
||||
|
@ -383,21 +395,6 @@ export async function getInUseTotalCount(
|
|||
}
|
||||
}
|
||||
|
||||
export async function getInUseByAlertingTotalCounts(
|
||||
esClient: ElasticsearchClient,
|
||||
kibanaIndex: string,
|
||||
logger: Logger,
|
||||
preconfiguredActions?: PreConfiguredAction[]
|
||||
): Promise<{
|
||||
countTotal: number;
|
||||
countByType: Record<string, number>;
|
||||
countByAlertHistoryConnectorType: number;
|
||||
countEmailByService: Record<string, number>;
|
||||
countNamespaces: number;
|
||||
}> {
|
||||
return await getInUseTotalCount(esClient, kibanaIndex, logger, 'alert', preconfiguredActions);
|
||||
}
|
||||
|
||||
function replaceFirstAndLastDotSymbols(strToReplace: string) {
|
||||
const hasFirstSymbolDot = strToReplace.startsWith('.');
|
||||
const appliedString = hasFirstSymbolDot ? strToReplace.replace('.', '__') : strToReplace;
|
||||
|
@ -410,6 +407,8 @@ export async function getExecutionsPerDayCount(
|
|||
eventLogIndex: string,
|
||||
logger: Logger
|
||||
): Promise<{
|
||||
hasErrors: boolean;
|
||||
errorMessage?: string;
|
||||
countTotal: number;
|
||||
countByType: Record<string, number>;
|
||||
countFailed: number;
|
||||
|
@ -566,6 +565,7 @@ export async function getExecutionsPerDayCount(
|
|||
);
|
||||
|
||||
return {
|
||||
hasErrors: false,
|
||||
countTotal: aggsExecutions.total,
|
||||
countByType: Object.entries(aggsExecutions.connectorTypes).reduce(
|
||||
(res: Record<string, number>, [key, value]) => {
|
||||
|
@ -588,10 +588,13 @@ export async function getExecutionsPerDayCount(
|
|||
avgExecutionTimeByType,
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err && err.message ? err.message : err.toString();
|
||||
logger.warn(
|
||||
`Error executing actions telemetry task: getExecutionsPerDayCount - ${JSON.stringify(err)}`
|
||||
);
|
||||
return {
|
||||
hasErrors: true,
|
||||
errorMessage,
|
||||
countTotal: 0,
|
||||
countByType: {},
|
||||
countFailed: 0,
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
*/
|
||||
|
||||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
|
||||
|
||||
import { registerActionsUsageCollector } from './actions_usage_collector';
|
||||
import { configSchema, ActionsConfig } from '../config';
|
||||
import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks';
|
||||
import { ConcreteTaskInstance, TaskManagerStartContract } from '@kbn/task-manager-plugin/server';
|
||||
|
||||
const mockTaskManagerStart = taskManagerMock.createStart();
|
||||
|
||||
|
@ -43,4 +45,50 @@ describe('registerActionsUsageCollector', () => {
|
|||
expect(usageCollectionMock.makeUsageCollector).toHaveBeenCalledTimes(1);
|
||||
expect(usageCollectionMock.makeUsageCollector.mock.calls[0][0].type).toBe('actions');
|
||||
});
|
||||
|
||||
it('should return an error message if fetching data fails', async () => {
|
||||
mockTaskManagerStart.get.mockRejectedValueOnce(new Error('error message'));
|
||||
const taskManagerPromise = new Promise<TaskManagerStartContract>((resolve) => {
|
||||
resolve(mockTaskManagerStart);
|
||||
});
|
||||
registerActionsUsageCollector(
|
||||
usageCollectionMock as UsageCollectionSetup,
|
||||
config,
|
||||
taskManagerPromise
|
||||
);
|
||||
// @ts-ignore
|
||||
expect(await usageCollectionMock.makeUsageCollector.mock.calls[0][0].fetch()).toEqual(
|
||||
expect.objectContaining({
|
||||
has_errors: true,
|
||||
error_messages: ['error message'],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should return the task state including error messages', async () => {
|
||||
const mockStats = {
|
||||
has_errors: true,
|
||||
error_messages: ['an error message'],
|
||||
count_active_total: 1,
|
||||
count_disabled_total: 10,
|
||||
};
|
||||
mockTaskManagerStart.get.mockResolvedValue({
|
||||
id: '1',
|
||||
state: mockStats,
|
||||
} as unknown as ConcreteTaskInstance);
|
||||
|
||||
const taskManagerPromise = new Promise<TaskManagerStartContract>((resolve) => {
|
||||
resolve(mockTaskManagerStart);
|
||||
});
|
||||
registerActionsUsageCollector(
|
||||
usageCollectionMock as UsageCollectionSetup,
|
||||
config,
|
||||
taskManagerPromise
|
||||
);
|
||||
// @ts-ignore
|
||||
expect(await usageCollectionMock.makeUsageCollector.mock.calls[0][0].fetch()).toEqual({
|
||||
alert_history_connector_enabled: false,
|
||||
...mockStats,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,6 +23,8 @@ export function createActionsUsageCollector(
|
|||
return true;
|
||||
},
|
||||
schema: {
|
||||
has_errors: { type: 'boolean' },
|
||||
error_messages: { type: 'array', items: { type: 'text' } },
|
||||
alert_history_connector_enabled: {
|
||||
type: 'boolean',
|
||||
_meta: { description: 'Indicates if preconfigured alert history connector is enabled.' },
|
||||
|
@ -51,13 +53,16 @@ export function createActionsUsageCollector(
|
|||
const doc = await getLatestTaskState(await taskManager);
|
||||
// get the accumulated state from the recurring task
|
||||
const { runs, ...state } = get(doc, 'state') as ActionsUsage & { runs: number };
|
||||
|
||||
return {
|
||||
...state,
|
||||
alert_history_connector_enabled: config.preconfiguredAlertHistoryEsIndex,
|
||||
};
|
||||
} catch (err) {
|
||||
const errMessage = err && err.message ? err.message : err.toString();
|
||||
|
||||
return {
|
||||
has_errors: true,
|
||||
error_messages: [errMessage],
|
||||
alert_history_connector_enabled: false,
|
||||
count_total: 0,
|
||||
count_by_type: {},
|
||||
|
|
|
@ -101,36 +101,39 @@ export function telemetryTaskRunner(
|
|||
getTotalCount(esClient, kibanaIndex, logger, preconfiguredActions),
|
||||
getInUseTotalCount(esClient, kibanaIndex, logger, undefined, preconfiguredActions),
|
||||
getExecutionsPerDayCount(esClient, eventLogIndex, logger),
|
||||
])
|
||||
.then(([totalAggegations, totalInUse, totalExecutionsPerDay]) => {
|
||||
return {
|
||||
state: {
|
||||
runs: (state.runs || 0) + 1,
|
||||
count_total: totalAggegations.countTotal,
|
||||
count_by_type: totalAggegations.countByType,
|
||||
count_active_total: totalInUse.countTotal,
|
||||
count_active_by_type: totalInUse.countByType,
|
||||
count_active_alert_history_connectors: totalInUse.countByAlertHistoryConnectorType,
|
||||
count_active_email_connectors_by_service_type: totalInUse.countEmailByService,
|
||||
count_actions_namespaces: totalInUse.countNamespaces,
|
||||
count_actions_executions_per_day: totalExecutionsPerDay.countTotal,
|
||||
count_actions_executions_by_type_per_day: totalExecutionsPerDay.countByType,
|
||||
count_actions_executions_failed_per_day: totalExecutionsPerDay.countFailed,
|
||||
count_actions_executions_failed_by_type_per_day:
|
||||
totalExecutionsPerDay.countFailedByType,
|
||||
avg_execution_time_per_day: totalExecutionsPerDay.avgExecutionTime,
|
||||
avg_execution_time_by_type_per_day: totalExecutionsPerDay.avgExecutionTimeByType,
|
||||
},
|
||||
runAt: getNextMidnight(),
|
||||
};
|
||||
})
|
||||
.catch((errMsg) => {
|
||||
logger.warn(`Error executing actions telemetry task: ${errMsg}`);
|
||||
return {
|
||||
state: {},
|
||||
runAt: getNextMidnight(),
|
||||
};
|
||||
});
|
||||
]).then(([totalAggegations, totalInUse, totalExecutionsPerDay]) => {
|
||||
const hasErrors =
|
||||
totalAggegations.hasErrors || totalInUse.hasErrors || totalExecutionsPerDay.hasErrors;
|
||||
|
||||
const errorMessages = [
|
||||
totalAggegations.errorMessage,
|
||||
totalInUse.errorMessage,
|
||||
totalExecutionsPerDay.errorMessage,
|
||||
].filter((message) => message !== undefined);
|
||||
|
||||
return {
|
||||
state: {
|
||||
has_errors: hasErrors,
|
||||
...(errorMessages.length > 0 && { error_messages: errorMessages }),
|
||||
runs: (state.runs || 0) + 1,
|
||||
count_total: totalAggegations.countTotal,
|
||||
count_by_type: totalAggegations.countByType,
|
||||
count_active_total: totalInUse.countTotal,
|
||||
count_active_by_type: totalInUse.countByType,
|
||||
count_active_alert_history_connectors: totalInUse.countByAlertHistoryConnectorType,
|
||||
count_active_email_connectors_by_service_type: totalInUse.countEmailByService,
|
||||
count_actions_namespaces: totalInUse.countNamespaces,
|
||||
count_actions_executions_per_day: totalExecutionsPerDay.countTotal,
|
||||
count_actions_executions_by_type_per_day: totalExecutionsPerDay.countByType,
|
||||
count_actions_executions_failed_per_day: totalExecutionsPerDay.countFailed,
|
||||
count_actions_executions_failed_by_type_per_day:
|
||||
totalExecutionsPerDay.countFailedByType,
|
||||
avg_execution_time_per_day: totalExecutionsPerDay.avgExecutionTime,
|
||||
avg_execution_time_by_type_per_day: totalExecutionsPerDay.avgExecutionTimeByType,
|
||||
},
|
||||
runAt: getNextMidnight(),
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
import { MakeSchemaFrom } from '@kbn/usage-collection-plugin/server';
|
||||
|
||||
export interface ActionsUsage {
|
||||
has_errors: boolean;
|
||||
error_messages?: string[];
|
||||
alert_history_connector_enabled: boolean;
|
||||
count_total: number;
|
||||
count_by_type: Record<string, number>;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
|
||||
import { registerAlertingUsageCollector } from './alerting_usage_collector';
|
||||
import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks';
|
||||
import { ConcreteTaskInstance, TaskManagerStartContract } from '@kbn/task-manager-plugin/server';
|
||||
const taskManagerStart = taskManagerMock.createStart();
|
||||
|
||||
beforeEach(() => jest.resetAllMocks());
|
||||
|
@ -38,4 +39,41 @@ describe('registerAlertingUsageCollector', () => {
|
|||
expect(usageCollectionMock.makeUsageCollector).toHaveBeenCalledTimes(1);
|
||||
expect(usageCollectionMock.makeUsageCollector.mock.calls[0][0].type).toBe('alerts');
|
||||
});
|
||||
|
||||
it('should return an error message if fetching data fails', async () => {
|
||||
taskManagerStart.get.mockRejectedValueOnce(new Error('error message'));
|
||||
const taskManagerPromise = new Promise<TaskManagerStartContract>((resolve) => {
|
||||
resolve(taskManagerStart);
|
||||
});
|
||||
registerAlertingUsageCollector(usageCollectionMock as UsageCollectionSetup, taskManagerPromise);
|
||||
// @ts-ignore
|
||||
expect(await usageCollectionMock.makeUsageCollector.mock.calls[0][0].fetch()).toEqual(
|
||||
expect.objectContaining({
|
||||
has_errors: true,
|
||||
error_messages: ['error message'],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should return the task state including error messages', async () => {
|
||||
const mockStats = {
|
||||
has_errors: true,
|
||||
error_messages: ['an error message'],
|
||||
count_active_total: 1,
|
||||
count_disabled_total: 10,
|
||||
};
|
||||
taskManagerStart.get.mockResolvedValue({
|
||||
id: '1',
|
||||
state: mockStats,
|
||||
} as unknown as ConcreteTaskInstance);
|
||||
|
||||
const taskManagerPromise = new Promise<TaskManagerStartContract>((resolve) => {
|
||||
resolve(taskManagerStart);
|
||||
});
|
||||
registerAlertingUsageCollector(usageCollectionMock as UsageCollectionSetup, taskManagerPromise);
|
||||
// @ts-ignore
|
||||
expect(await usageCollectionMock.makeUsageCollector.mock.calls[0][0].fetch()).toEqual(
|
||||
mockStats
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -126,11 +126,12 @@ export function createAlertingUsageCollector(
|
|||
// get the accumulated state from the recurring task
|
||||
const { runs, ...state } = get(doc, 'state') as AlertingUsage & { runs: number };
|
||||
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
return state;
|
||||
} catch (err) {
|
||||
const errMessage = err && err.message ? err.message : err.toString();
|
||||
return {
|
||||
has_errors: true,
|
||||
error_messages: [errMessage],
|
||||
count_total: 0,
|
||||
count_active_total: 0,
|
||||
count_disabled_total: 0,
|
||||
|
@ -202,6 +203,11 @@ export function createAlertingUsageCollector(
|
|||
}
|
||||
},
|
||||
schema: {
|
||||
has_errors: { type: 'boolean' },
|
||||
error_messages: {
|
||||
type: 'array',
|
||||
items: { type: 'text' },
|
||||
},
|
||||
count_total: { type: 'long' },
|
||||
count_active_total: { type: 'long' },
|
||||
count_disabled_total: { type: 'long' },
|
||||
|
|
|
@ -1398,6 +1398,7 @@ describe('event log telemetry', () => {
|
|||
logs__alert__document__count: 0,
|
||||
},
|
||||
},
|
||||
hasErrors: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1419,6 +1420,8 @@ describe('event log telemetry', () => {
|
|||
expect(loggerMeta?.tags).toEqual(['alerting', 'telemetry-failed']);
|
||||
expect(loggerMeta?.error?.stack_trace).toBeDefined();
|
||||
expect(telemetry).toStrictEqual({
|
||||
hasErrors: true,
|
||||
errorMessage: 'oh no',
|
||||
countTotalRuleExecutions: 0,
|
||||
countRuleExecutionsByType: {},
|
||||
countTotalFailedExecutions: 0,
|
||||
|
@ -1495,6 +1498,7 @@ describe('event log telemetry', () => {
|
|||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
logs__alert__document__count: 1,
|
||||
},
|
||||
hasErrors: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1518,6 +1522,8 @@ describe('event log telemetry', () => {
|
|||
expect(telemetry).toStrictEqual({
|
||||
countExecutionTimeouts: 0,
|
||||
countExecutionTimeoutsByType: {},
|
||||
errorMessage: 'oh no',
|
||||
hasErrors: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -37,6 +37,8 @@ interface Opts {
|
|||
}
|
||||
|
||||
interface GetExecutionsPerDayCountResults {
|
||||
hasErrors: boolean;
|
||||
errorMessage?: string;
|
||||
countTotalRuleExecutions: number;
|
||||
countRuleExecutionsByType: Record<string, number>;
|
||||
countTotalFailedExecutions: number;
|
||||
|
@ -55,6 +57,8 @@ interface GetExecutionsPerDayCountResults {
|
|||
}
|
||||
|
||||
interface GetExecutionTimeoutsPerDayCountResults {
|
||||
hasErrors: boolean;
|
||||
errorMessage?: string;
|
||||
countExecutionTimeouts: number;
|
||||
countExecutionTimeoutsByType: Record<string, number>;
|
||||
}
|
||||
|
@ -167,12 +171,14 @@ export async function getExecutionsPerDayCount({
|
|||
aggregations.by_rule_type_id.buckets as GetExecutionCountsAggregationBucket[];
|
||||
|
||||
return {
|
||||
hasErrors: false,
|
||||
...parseRuleTypeBucket(aggregationsByRuleTypeId),
|
||||
...parseExecutionFailureByRuleType(aggregationsByRuleTypeId),
|
||||
...parseExecutionCountAggregationResults(aggregations),
|
||||
countTotalRuleExecutions: totalRuleExecutions ?? 0,
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err && err.message ? err.message : err.toString();
|
||||
logger.warn(
|
||||
`Error executing alerting telemetry task: getExecutionsPerDayCount - ${JSON.stringify(err)}`,
|
||||
{
|
||||
|
@ -181,6 +187,8 @@ export async function getExecutionsPerDayCount({
|
|||
}
|
||||
);
|
||||
return {
|
||||
hasErrors: true,
|
||||
errorMessage,
|
||||
countTotalRuleExecutions: 0,
|
||||
countRuleExecutionsByType: {},
|
||||
countTotalFailedExecutions: 0,
|
||||
|
@ -235,10 +243,13 @@ export async function getExecutionTimeoutsPerDayCount({
|
|||
typeof results.hits.total === 'number' ? results.hits.total : results.hits.total?.value;
|
||||
|
||||
return {
|
||||
hasErrors: false,
|
||||
countExecutionTimeouts: totalTimedoutExecutionsCount ?? 0,
|
||||
countExecutionTimeoutsByType: parseSimpleRuleTypeBucket(aggregations.by_rule_type_id.buckets),
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err && err.message ? err.message : err.toString();
|
||||
|
||||
logger.warn(
|
||||
`Error executing alerting telemetry task: getExecutionsTimeoutsPerDayCount - ${JSON.stringify(
|
||||
err
|
||||
|
@ -249,6 +260,8 @@ export async function getExecutionTimeoutsPerDayCount({
|
|||
}
|
||||
);
|
||||
return {
|
||||
hasErrors: true,
|
||||
errorMessage,
|
||||
countExecutionTimeouts: 0,
|
||||
countExecutionTimeoutsByType: {},
|
||||
};
|
||||
|
|
|
@ -88,6 +88,7 @@ describe('kibana index telemetry', () => {
|
|||
logs__alert__document__count: 1,
|
||||
},
|
||||
count_total: 4,
|
||||
hasErrors: false,
|
||||
schedule_time: {
|
||||
avg: '4.5s',
|
||||
max: '10s',
|
||||
|
@ -129,6 +130,8 @@ describe('kibana index telemetry', () => {
|
|||
expect(loggerMeta?.tags).toEqual(['alerting', 'telemetry-failed']);
|
||||
expect(loggerMeta?.error?.stack_trace).toBeDefined();
|
||||
expect(telemetry).toEqual({
|
||||
errorMessage: 'oh no',
|
||||
hasErrors: true,
|
||||
connectors_per_alert: {
|
||||
avg: 0,
|
||||
max: 0,
|
||||
|
@ -219,6 +222,7 @@ describe('kibana index telemetry', () => {
|
|||
},
|
||||
countNamespaces: 1,
|
||||
countTotal: 4,
|
||||
hasErrors: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -243,6 +247,8 @@ describe('kibana index telemetry', () => {
|
|||
countByType: {},
|
||||
countNamespaces: 0,
|
||||
countTotal: 0,
|
||||
errorMessage: 'oh no',
|
||||
hasErrors: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -31,12 +31,14 @@ type GetTotalCountsResults = Pick<
|
|||
| 'throttle_time_number_s'
|
||||
| 'schedule_time_number_s'
|
||||
| 'connectors_per_alert'
|
||||
>;
|
||||
> & { errorMessage?: string; hasErrors: boolean };
|
||||
|
||||
interface GetTotalCountInUseResults {
|
||||
countTotal: number;
|
||||
countByType: Record<string, number>;
|
||||
countNamespaces: number;
|
||||
errorMessage?: string;
|
||||
hasErrors: boolean;
|
||||
}
|
||||
|
||||
export async function getTotalCountAggregations({
|
||||
|
@ -79,17 +81,17 @@ export async function getTotalCountAggregations({
|
|||
int parsed = 0;
|
||||
if (doc['alert.schedule.interval'].size() > 0) {
|
||||
def interval = doc['alert.schedule.interval'].value;
|
||||
|
||||
|
||||
if (interval.length() > 1) {
|
||||
// get last char
|
||||
String timeChar = interval.substring(interval.length() - 1);
|
||||
// remove last char
|
||||
interval = interval.substring(0, interval.length() - 1);
|
||||
|
||||
|
||||
if (interval.chars().allMatch(Character::isDigit)) {
|
||||
// using of regex is not allowed in painless language
|
||||
parsed = Integer.parseInt(interval);
|
||||
|
||||
|
||||
if (timeChar.equals("s")) {
|
||||
parsed = parsed;
|
||||
} else if (timeChar.equals("m")) {
|
||||
|
@ -115,17 +117,17 @@ export async function getTotalCountAggregations({
|
|||
int parsed = 0;
|
||||
if (doc['alert.throttle'].size() > 0) {
|
||||
def throttle = doc['alert.throttle'].value;
|
||||
|
||||
|
||||
if (throttle.length() > 1) {
|
||||
// get last char
|
||||
String timeChar = throttle.substring(throttle.length() - 1);
|
||||
// remove last char
|
||||
throttle = throttle.substring(0, throttle.length() - 1);
|
||||
|
||||
|
||||
if (throttle.chars().allMatch(Character::isDigit)) {
|
||||
// using of regex is not allowed in painless language
|
||||
parsed = Integer.parseInt(throttle);
|
||||
|
||||
|
||||
if (timeChar.equals("s")) {
|
||||
parsed = parsed;
|
||||
} else if (timeChar.equals("m")) {
|
||||
|
@ -186,6 +188,7 @@ export async function getTotalCountAggregations({
|
|||
typeof results.hits.total === 'number' ? results.hits.total : results.hits.total?.value;
|
||||
|
||||
return {
|
||||
hasErrors: false,
|
||||
count_total: totalRulesCount ?? 0,
|
||||
count_by_type: parseSimpleRuleTypeBucket(aggregations.by_rule_type_id.buckets),
|
||||
throttle_time: {
|
||||
|
@ -215,6 +218,8 @@ export async function getTotalCountAggregations({
|
|||
},
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err && err.message ? err.message : err.toString();
|
||||
|
||||
logger.warn(
|
||||
`Error executing alerting telemetry task: getTotalCountAggregations - ${JSON.stringify(err)}`,
|
||||
{
|
||||
|
@ -223,6 +228,8 @@ export async function getTotalCountAggregations({
|
|||
}
|
||||
);
|
||||
return {
|
||||
hasErrors: true,
|
||||
errorMessage,
|
||||
count_total: 0,
|
||||
count_by_type: {},
|
||||
throttle_time: {
|
||||
|
@ -296,11 +303,13 @@ export async function getTotalCountInUse({
|
|||
typeof results.hits.total === 'number' ? results.hits.total : results.hits.total?.value;
|
||||
|
||||
return {
|
||||
hasErrors: false,
|
||||
countTotal: totalEnabledRulesCount ?? 0,
|
||||
countByType: parseSimpleRuleTypeBucket(aggregations.by_rule_type_id.buckets),
|
||||
countNamespaces: aggregations.namespaces_count.value ?? 0,
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err && err.message ? err.message : err.toString();
|
||||
logger.warn(
|
||||
`Error executing alerting telemetry task: getTotalCountInUse - ${JSON.stringify(err)}`,
|
||||
{
|
||||
|
@ -309,6 +318,8 @@ export async function getTotalCountInUse({
|
|||
}
|
||||
);
|
||||
return {
|
||||
hasErrors: true,
|
||||
errorMessage,
|
||||
countTotal: 0,
|
||||
countByType: {},
|
||||
countNamespaces: 0,
|
||||
|
|
|
@ -225,6 +225,7 @@ describe('task manager telemetry', () => {
|
|||
logs__alert__document__count: 4,
|
||||
},
|
||||
},
|
||||
hasErrors: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -247,6 +248,8 @@ describe('task manager telemetry', () => {
|
|||
expect(loggerMeta?.tags).toEqual(['alerting', 'telemetry-failed']);
|
||||
expect(loggerMeta?.error?.stack_trace).toBeDefined();
|
||||
expect(telemetry).toStrictEqual({
|
||||
errorMessage: 'oh no',
|
||||
hasErrors: true,
|
||||
countFailedAndUnrecognizedTasks: 0,
|
||||
countFailedAndUnrecognizedTasksByStatus: {},
|
||||
countFailedAndUnrecognizedTasksByStatusByType: {},
|
||||
|
|
|
@ -26,6 +26,8 @@ interface GetFailedAndUnrecognizedTasksAggregationBucket extends AggregationsStr
|
|||
}
|
||||
|
||||
interface GetFailedAndUnrecognizedTasksResults {
|
||||
hasErrors: boolean;
|
||||
errorMessage?: string;
|
||||
countFailedAndUnrecognizedTasks: number;
|
||||
countFailedAndUnrecognizedTasksByStatus: Record<string, number>;
|
||||
countFailedAndUnrecognizedTasksByStatusByType: Record<string, Record<string, number>>;
|
||||
|
@ -115,10 +117,12 @@ export async function getFailedAndUnrecognizedTasksPerDay({
|
|||
aggregations.by_status.buckets as GetFailedAndUnrecognizedTasksAggregationBucket[];
|
||||
|
||||
return {
|
||||
hasErrors: false,
|
||||
...parseBucket(aggregationsByStatus),
|
||||
countFailedAndUnrecognizedTasks: totalFailedAndUnrecognizedTasks ?? 0,
|
||||
};
|
||||
} catch (err) {
|
||||
const errorMessage = err && err.message ? err.message : err.toString();
|
||||
logger.warn(
|
||||
`Error executing alerting telemetry task: getFailedAndUnrecognizedTasksPerDay - ${JSON.stringify(
|
||||
err
|
||||
|
@ -129,6 +133,8 @@ export async function getFailedAndUnrecognizedTasksPerDay({
|
|||
}
|
||||
);
|
||||
return {
|
||||
hasErrors: true,
|
||||
errorMessage,
|
||||
countFailedAndUnrecognizedTasks: 0,
|
||||
countFailedAndUnrecognizedTasksByStatus: {},
|
||||
countFailedAndUnrecognizedTasksByStatusByType: {},
|
||||
|
|
|
@ -111,10 +111,33 @@ export function telemetryTaskRunner(
|
|||
dailyExecutionTimeoutCounts,
|
||||
dailyFailedAndUnrecognizedTasks,
|
||||
]) => {
|
||||
const hasErrors =
|
||||
totalCountAggregations.hasErrors ||
|
||||
totalInUse.hasErrors ||
|
||||
dailyExecutionCounts.hasErrors ||
|
||||
dailyExecutionTimeoutCounts.hasErrors ||
|
||||
dailyFailedAndUnrecognizedTasks.hasErrors;
|
||||
|
||||
const errorMessages = [
|
||||
totalCountAggregations.errorMessage,
|
||||
totalInUse.errorMessage,
|
||||
dailyExecutionCounts.errorMessage,
|
||||
dailyExecutionTimeoutCounts.errorMessage,
|
||||
dailyFailedAndUnrecognizedTasks.errorMessage,
|
||||
].filter((message) => message !== undefined);
|
||||
|
||||
return {
|
||||
state: {
|
||||
has_errors: hasErrors,
|
||||
...(errorMessages.length > 0 && { error_messages: errorMessages }),
|
||||
runs: (state.runs || 0) + 1,
|
||||
...totalCountAggregations,
|
||||
count_total: totalCountAggregations.count_total,
|
||||
count_by_type: totalCountAggregations.count_by_type,
|
||||
throttle_time: totalCountAggregations.throttle_time,
|
||||
schedule_time: totalCountAggregations.schedule_time,
|
||||
throttle_time_number_s: totalCountAggregations.throttle_time_number_s,
|
||||
schedule_time_number_s: totalCountAggregations.schedule_time_number_s,
|
||||
connectors_per_alert: totalCountAggregations.connectors_per_alert,
|
||||
count_active_by_type: totalInUse.countByType,
|
||||
count_active_total: totalInUse.countTotal,
|
||||
count_disabled_total: totalCountAggregations.count_total - totalInUse.countTotal,
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
|
||||
export interface AlertingUsage {
|
||||
has_errors: boolean;
|
||||
error_messages?: string[];
|
||||
count_total: number;
|
||||
count_active_total: number;
|
||||
count_disabled_total: number;
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
"properties": {
|
||||
"actions": {
|
||||
"properties": {
|
||||
"has_errors": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"error_messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
"alert_history_connector_enabled": {
|
||||
"type": "boolean",
|
||||
"_meta": {
|
||||
|
@ -261,6 +270,15 @@
|
|||
},
|
||||
"alerts": {
|
||||
"properties": {
|
||||
"has_errors": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"error_messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
"count_total": {
|
||||
"type": "long"
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue