[RAC][Observability] preserve lifecycle alert changes for active alerts (#110124)
* preserve lifecycle changes for active alerts * fix failing tests * fix failing lifecycle executor tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
02538b6b41
commit
b7ad4268d0
|
@ -17,6 +17,7 @@ import {
|
|||
ALERT_STATUS,
|
||||
ALERT_STATUS_ACTIVE,
|
||||
ALERT_STATUS_RECOVERED,
|
||||
ALERT_WORKFLOW_STATUS,
|
||||
ALERT_UUID,
|
||||
EVENT_ACTION,
|
||||
EVENT_KIND,
|
||||
|
@ -118,7 +119,7 @@ describe('createLifecycleExecutor', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('overwrites existing documents for repeatedly firing alerts', async () => {
|
||||
it('updates existing documents for repeatedly firing alerts', async () => {
|
||||
const logger = loggerMock.create();
|
||||
const ruleDataClientMock = createRuleDataClientMock();
|
||||
ruleDataClientMock.getReader().search.mockResolvedValue({
|
||||
|
@ -126,17 +127,35 @@ describe('createLifecycleExecutor', () => {
|
|||
hits: [
|
||||
{
|
||||
fields: {
|
||||
'@timestamp': '',
|
||||
[ALERT_ID]: 'TEST_ALERT_0',
|
||||
[ALERT_UUID]: 'ALERT_0_UUID',
|
||||
[ALERT_RULE_CATEGORY]: 'RULE_TYPE_NAME',
|
||||
[ALERT_RULE_CONSUMER]: 'CONSUMER',
|
||||
[ALERT_RULE_NAME]: 'NAME',
|
||||
[ALERT_RULE_PRODUCER]: 'PRODUCER',
|
||||
[ALERT_RULE_TYPE_ID]: 'RULE_TYPE_ID',
|
||||
labels: { LABEL_0_KEY: 'LABEL_0_VALUE' }, // this must not show up in the written doc
|
||||
[ALERT_RULE_UUID]: 'RULE_UUID',
|
||||
[ALERT_STATUS]: ALERT_STATUS_ACTIVE,
|
||||
[ALERT_WORKFLOW_STATUS]: 'closed',
|
||||
[SPACE_IDS]: ['fake-space-id'],
|
||||
labels: { LABEL_0_KEY: 'LABEL_0_VALUE' }, // this must show up in the written doc
|
||||
},
|
||||
},
|
||||
{
|
||||
fields: {
|
||||
'@timestamp': '',
|
||||
[ALERT_ID]: 'TEST_ALERT_1',
|
||||
[ALERT_UUID]: 'ALERT_1_UUID',
|
||||
[ALERT_RULE_CATEGORY]: 'RULE_TYPE_NAME',
|
||||
[ALERT_RULE_CONSUMER]: 'CONSUMER',
|
||||
[ALERT_RULE_NAME]: 'NAME',
|
||||
[ALERT_RULE_PRODUCER]: 'PRODUCER',
|
||||
[ALERT_RULE_TYPE_ID]: 'RULE_TYPE_ID',
|
||||
[ALERT_RULE_UUID]: 'RULE_UUID',
|
||||
[ALERT_STATUS]: ALERT_STATUS_ACTIVE,
|
||||
[ALERT_WORKFLOW_STATUS]: 'open',
|
||||
[SPACE_IDS]: ['fake-space-id'],
|
||||
labels: { LABEL_0_KEY: 'LABEL_0_VALUE' }, // this must not show up in the written doc
|
||||
},
|
||||
},
|
||||
|
@ -188,14 +207,19 @@ describe('createLifecycleExecutor', () => {
|
|||
{ index: { _id: 'TEST_ALERT_0_UUID' } },
|
||||
expect.objectContaining({
|
||||
[ALERT_ID]: 'TEST_ALERT_0',
|
||||
[ALERT_WORKFLOW_STATUS]: 'closed',
|
||||
[ALERT_STATUS]: ALERT_STATUS_ACTIVE,
|
||||
labels: { LABEL_0_KEY: 'LABEL_0_VALUE' },
|
||||
|
||||
[EVENT_ACTION]: 'active',
|
||||
[EVENT_KIND]: 'signal',
|
||||
}),
|
||||
{ index: { _id: 'TEST_ALERT_1_UUID' } },
|
||||
expect.objectContaining({
|
||||
[ALERT_ID]: 'TEST_ALERT_1',
|
||||
[ALERT_WORKFLOW_STATUS]: 'open',
|
||||
[ALERT_STATUS]: ALERT_STATUS_ACTIVE,
|
||||
|
||||
[EVENT_ACTION]: 'active',
|
||||
[EVENT_KIND]: 'signal',
|
||||
}),
|
||||
|
@ -216,8 +240,6 @@ describe('createLifecycleExecutor', () => {
|
|||
});
|
||||
|
||||
it('updates existing documents for recovered alerts', async () => {
|
||||
// NOTE: the documents should actually also be updated for recurring,
|
||||
// active alerts (see elastic/kibana#108670)
|
||||
const logger = loggerMock.create();
|
||||
const ruleDataClientMock = createRuleDataClientMock();
|
||||
ruleDataClientMock.getReader().search.mockResolvedValue({
|
||||
|
|
|
@ -182,19 +182,17 @@ export const createLifecycleExecutor = (
|
|||
|
||||
const allAlertIds = [...new Set(currentAlertIds.concat(trackedAlertIds))];
|
||||
|
||||
const trackedAlertStatesOfRecovered = Object.values(state.trackedAlerts).filter(
|
||||
(trackedAlertState) => !currentAlerts[trackedAlertState.alertId]
|
||||
);
|
||||
const trackedAlertStates = Object.values(state.trackedAlerts);
|
||||
|
||||
logger.debug(
|
||||
`Tracking ${allAlertIds.length} alerts (${newAlertIds.length} new, ${trackedAlertStatesOfRecovered.length} recovered)`
|
||||
`Tracking ${allAlertIds.length} alerts (${newAlertIds.length} new, ${trackedAlertStates.length} previous)`
|
||||
);
|
||||
|
||||
const alertsDataMap: Record<string, Partial<ParsedTechnicalFields>> = {
|
||||
...currentAlerts,
|
||||
};
|
||||
|
||||
if (trackedAlertStatesOfRecovered.length) {
|
||||
if (trackedAlertStates.length) {
|
||||
const { hits } = await ruleDataClient.getReader().search({
|
||||
body: {
|
||||
query: {
|
||||
|
@ -207,7 +205,7 @@ export const createLifecycleExecutor = (
|
|||
},
|
||||
{
|
||||
terms: {
|
||||
[ALERT_UUID]: trackedAlertStatesOfRecovered.map(
|
||||
[ALERT_UUID]: trackedAlertStates.map(
|
||||
(trackedAlertState) => trackedAlertState.alertUuid
|
||||
),
|
||||
},
|
||||
|
@ -215,7 +213,7 @@ export const createLifecycleExecutor = (
|
|||
],
|
||||
},
|
||||
},
|
||||
size: trackedAlertStatesOfRecovered.length,
|
||||
size: trackedAlertStates.length,
|
||||
collapse: {
|
||||
field: ALERT_UUID,
|
||||
},
|
||||
|
|
|
@ -263,6 +263,36 @@ describe('createLifecycleRuleTypeFactory', () => {
|
|||
},
|
||||
]);
|
||||
|
||||
// TODO mock the resolved value before calling alertWithLifecycle again
|
||||
const lastOpbeansNodeDoc = helpers.ruleDataClientMock
|
||||
.getWriter()
|
||||
.bulk.mock.calls[0][0].body?.concat()
|
||||
.reverse()
|
||||
.find(
|
||||
(doc: any) => !('index' in doc) && doc['service.name'] === 'opbeans-node'
|
||||
) as Record<string, any>;
|
||||
|
||||
const stored = mapValues(lastOpbeansNodeDoc, (val) => {
|
||||
return castArray(val);
|
||||
});
|
||||
|
||||
helpers.ruleDataClientMock.getReader().search.mockResolvedValueOnce({
|
||||
hits: {
|
||||
hits: [{ fields: stored } as any],
|
||||
total: {
|
||||
value: 1,
|
||||
relation: 'eq',
|
||||
},
|
||||
},
|
||||
took: 0,
|
||||
timed_out: false,
|
||||
_shards: {
|
||||
failed: 0,
|
||||
successful: 1,
|
||||
total: 1,
|
||||
},
|
||||
});
|
||||
|
||||
await helpers.alertWithLifecycle([
|
||||
{
|
||||
id: 'opbeans-java',
|
||||
|
@ -274,6 +304,7 @@ describe('createLifecycleRuleTypeFactory', () => {
|
|||
id: 'opbeans-node',
|
||||
fields: {
|
||||
'service.name': 'opbeans-node',
|
||||
'kibana.alert.workflow_status': 'closed',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
@ -281,7 +312,6 @@ describe('createLifecycleRuleTypeFactory', () => {
|
|||
|
||||
it('writes the correct alerts', () => {
|
||||
expect(helpers.ruleDataClientMock.getWriter().bulk).toHaveBeenCalledTimes(2);
|
||||
|
||||
const body = helpers.ruleDataClientMock.getWriter().bulk.mock.calls[1][0].body!;
|
||||
|
||||
const documents = body.filter((op: any) => !('index' in op)) as any[];
|
||||
|
|
Loading…
Reference in a new issue