[Infrastructure UI][Rules] Add context variables to recovery alerts for Inventory Threshold rule (#131199)

* [Infrastructure UI][Rule] Add context variables to recovery alerts

* Adding alert state

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Chris Cowan 2022-05-25 05:08:06 -06:00 committed by GitHub
parent a9b5881cfd
commit 5798664add
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 40 deletions

View file

@ -16,7 +16,7 @@ import { InfraSource } from '../../sources';
import { calculateFromBasedOnMetric } from './lib/calculate_from_based_on_metric';
import { getData } from './lib/get_data';
type ConditionResult = InventoryMetricConditions & {
export type ConditionResult = InventoryMetricConditions & {
shouldFire: boolean;
shouldWarn: boolean;
currentValue: number;

View file

@ -13,7 +13,6 @@ import {
ActionGroupIdsOf,
AlertInstanceContext as AlertContext,
AlertInstanceState as AlertState,
RecoveredActionGroup,
} from '@kbn/alerting-plugin/common';
import { Alert, RuleTypeState } from '@kbn/alerting-plugin/server';
import { AlertStates, InventoryMetricThresholdParams } from '../../../../common/alerting/metrics';
@ -29,11 +28,10 @@ import {
buildFiredAlertReason,
buildInvalidQueryAlertReason,
buildNoDataAlertReason,
// buildRecoveredAlertReason,
stateToAlertMessage,
} from '../common/messages';
import { createScopedLogger, getViewInAppUrlInventory } from '../common/utils';
import { evaluateCondition } from './evaluate_condition';
import { evaluateCondition, ConditionResult } from './evaluate_condition';
type InventoryMetricThresholdAllowedActionGroups = ActionGroupIdsOf<
typeof FIRED_ACTIONS | typeof WARNING_ACTIONS
@ -164,15 +162,6 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) =
)
)
.join('\n');
/*
* Custom recovery actions aren't yet available in the alerting framework
* Uncomment the code below once they've been implemented
* Reference: https://github.com/elastic/kibana/issues/87048
*/
// } else if (nextState === AlertStates.OK && prevState?.alertState === AlertStates.ALERT) {
// reason = results
// .map((result) => buildReasonWithVerboseMetricName(group, result[group], buildRecoveredAlertReason))
// .join('\n');
}
if (alertOnNoData) {
if (nextState === AlertStates.NO_DATA) {
@ -193,11 +182,7 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) =
}
if (reason) {
const actionGroupId =
nextState === AlertStates.OK
? RecoveredActionGroup.id
: nextState === AlertStates.WARNING
? WARNING_ACTIONS.id
: FIRED_ACTIONS.id;
nextState === AlertStates.WARNING ? WARNING_ACTIONS.id : FIRED_ACTIONS.id;
const alert = alertFactory(group, reason);
const indexedStartedDate = getAlertStartedDate(group) ?? startedAt.toISOString();
@ -208,32 +193,49 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) =
libs.basePath
);
scheduledActionsCount++;
alert.scheduleActions(
/**
* TODO: We're lying to the compiler here as explicitly calling `scheduleActions` on
* the RecoveredActionGroup isn't allowed
*/
actionGroupId as unknown as InventoryMetricThresholdAllowedActionGroups,
{
group,
alertState: stateToAlertMessage[nextState],
reason,
timestamp: startedAt.toISOString(),
viewInAppUrl,
value: mapToConditionsLookup(results, (result) =>
formatMetric(result[group].metric, result[group].currentValue)
),
threshold: mapToConditionsLookup(criteria, (c) => c.threshold),
metric: mapToConditionsLookup(criteria, (c) => c.metric),
}
);
const context = {
group,
alertState: stateToAlertMessage[nextState],
reason,
timestamp: startedAt.toISOString(),
viewInAppUrl,
value: mapToConditionsLookup(results, (result) =>
formatMetric(result[group].metric, result[group].currentValue)
),
threshold: mapToConditionsLookup(criteria, (c) => c.threshold),
metric: mapToConditionsLookup(criteria, (c) => c.metric),
};
alert.scheduleActions(actionGroupId, context);
}
}
const { getRecoveredAlerts } = services.alertFactory.done();
const recoveredAlerts = getRecoveredAlerts();
for (const alert of recoveredAlerts) {
const recoveredAlertId = alert.getId();
const indexedStartedDate = getAlertStartedDate(recoveredAlertId) ?? startedAt.toISOString();
const viewInAppUrl = getViewInAppUrlInventory(
criteria,
nodeType,
indexedStartedDate,
libs.basePath
);
const context = {
group: recoveredAlertId,
alertState: stateToAlertMessage[AlertStates.OK],
timestamp: startedAt.toISOString(),
viewInAppUrl,
threshold: mapToConditionsLookup(criteria, (c) => c.threshold),
metric: mapToConditionsLookup(criteria, (c) => c.metric),
};
alert.setContext(context);
}
const stopTime = Date.now();
logger.debug(`Scheduled ${scheduledActionsCount} actions in ${stopTime - startTime}ms`);
});
const formatThreshold = (metric: SnapshotMetricType, value: number) => {
const formatThreshold = (metric: SnapshotMetricType, value: number | number[]) => {
const metricFormatter = get(METRIC_FORMATTERS, metric, METRIC_FORMATTERS.count);
const formatter = createFormatter(metricFormatter.formatter, metricFormatter.template);
@ -253,7 +255,7 @@ const formatThreshold = (metric: SnapshotMetricType, value: number) => {
const buildReasonWithVerboseMetricName = (
group: string,
resultItem: any,
resultItem: ConditionResult,
buildReason: (r: any) => string,
useWarningThreshold?: boolean
) => {
@ -267,7 +269,7 @@ const buildReasonWithVerboseMetricName = (
group,
metric:
toMetricOpt(resultItem.metric)?.text ||
(resultItem.metric === 'custom'
(resultItem.metric === 'custom' && resultItem.customMetric
? getCustomMetricLabel(resultItem.customMetric)
: resultItem.metric),
currentValue: formatMetric(resultItem.metric, resultItem.currentValue),

View file

@ -86,6 +86,7 @@ export async function registerMetricInventoryThresholdRuleType(
),
},
defaultActionGroupId: FIRED_ACTIONS_ID,
doesSetRecoveryContext: true,
actionGroups: [FIRED_ACTIONS, WARNING_ACTIONS],
producer: 'infrastructure',
minimumLicenseRequired: 'basic',