From b7bcf32a5431df09a97d0b03730a351fd5b33bdf Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 19 Apr 2023 14:45:55 -0600 Subject: [PATCH 1/5] Fix the charts and group by section Log Threshold's alert detail page --- .../src/field_maps/alert_field_map.ts | 6 ++++++ .../src/default_alerts_as_data.ts | 5 +++++ .../src/technical_field_names.ts | 2 ++ .../alert_details_app_section/index.tsx | 16 +++++++++++++--- .../log_threshold/log_threshold_executor.ts | 13 ++++++++++--- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts b/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts index 72fe68fa9cf59..a4b251dc17e61 100644 --- a/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts +++ b/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts @@ -16,6 +16,7 @@ import { ALERT_INSTANCE_ID, ALERT_LAST_DETECTED, ALERT_REASON, + ALERT_CONTEXT, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, ALERT_RULE_EXECUTION_UUID, @@ -82,6 +83,11 @@ export const alertFieldMap = { array: false, required: false, }, + [ALERT_CONTEXT]: { + type: 'object', + array: false, + required: false, + }, [ALERT_RULE_CATEGORY]: { type: 'keyword', array: false, diff --git a/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts b/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts index e996acbd9fb6c..ce8bfa0d00eb6 100644 --- a/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts +++ b/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts @@ -49,6 +49,9 @@ const ALERT_LAST_DETECTED = `${ALERT_NAMESPACE}.last_detected` as const; // kibana.alert.reason - human readable reason that this alert is active const ALERT_REASON = `${ALERT_NAMESPACE}.reason` as const; +// kibana.alert.context - human readable reason that this alert is active +const ALERT_CONTEXT = `${ALERT_NAMESPACE}.context` as const; + // kibana.alert.start - timestamp when the alert is first active const ALERT_START = `${ALERT_NAMESPACE}.start` as const; @@ -110,6 +113,7 @@ const fields = { ALERT_INSTANCE_ID, ALERT_LAST_DETECTED, ALERT_REASON, + ALERT_CONTEXT, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, ALERT_RULE_EXECUTION_UUID, @@ -146,6 +150,7 @@ export { ALERT_INSTANCE_ID, ALERT_LAST_DETECTED, ALERT_REASON, + ALERT_CONTEXT, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, ALERT_RULE_EXECUTION_UUID, diff --git a/packages/kbn-rule-data-utils/src/technical_field_names.ts b/packages/kbn-rule-data-utils/src/technical_field_names.ts index cf45162b20853..4867e79c89ec0 100644 --- a/packages/kbn-rule-data-utils/src/technical_field_names.ts +++ b/packages/kbn-rule-data-utils/src/technical_field_names.ts @@ -18,6 +18,7 @@ import { ALERT_FLAPPING, ALERT_INSTANCE_ID, ALERT_REASON, + ALERT_CONTEXT, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, ALERT_RULE_EXECUTION_UUID, @@ -129,6 +130,7 @@ const fields = { ALERT_RULE_CONSUMER, ALERT_RULE_PRODUCER, ALERT_REASON, + ALERT_CONTEXT, ALERT_RISK_SCORE, ALERT_CASE_IDS, ALERT_RULE_AUTHOR, diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx index fa2e3668bc957..dc065ff8d17c8 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/index.tsx @@ -8,7 +8,12 @@ import React, { useEffect, useState } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { LIGHT_THEME } from '@elastic/charts'; import { EuiPanel } from '@elastic/eui'; -import { ALERT_END, ALERT_EVALUATION_VALUE, ALERT_START } from '@kbn/rule-data-utils'; +import { + ALERT_CONTEXT, + ALERT_END, + ALERT_EVALUATION_VALUE, + ALERT_START, +} from '@kbn/rule-data-utils'; import moment from 'moment'; import { useTheme } from '@emotion/react'; import { EuiTitle } from '@elastic/eui'; @@ -20,6 +25,7 @@ import { } from '@kbn/observability-alert-details'; import { useEuiTheme } from '@elastic/eui'; import { UI_SETTINGS } from '@kbn/data-plugin/public'; +import { get } from 'lodash'; import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana'; import { getChartGroupNames } from '../../../../../common/utils/get_chart_group_names'; import { @@ -61,7 +67,9 @@ const AlertDetailsAppSection = ({ rule.params.groupBy?.reduce( (selectedFields: Record, field) => ({ ...selectedFields, - ...{ [field]: alert.fields[field] }, + ...{ + [field]: get(alert.fields[ALERT_CONTEXT], ['groupByKeys', ...field.split('.')], null), + }, }), {} ) || {}; @@ -232,7 +240,9 @@ const AlertDetailsAppSection = ({ rule && rule.params.criteria.length === 1 && ( - + ) ); diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts index 856575370dce5..cca3b24b24c9a 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts @@ -8,6 +8,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import { + ALERT_CONTEXT, ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, ALERT_REASON, @@ -86,7 +87,7 @@ export type LogThresholdAlertFactory = ( value: number, threshold: number, actions?: Array<{ actionGroup: LogThresholdActionGroups; context: AlertContext }>, - additionalContext?: AdditionalContext + rootLevelContext?: AdditionalContext ) => LogThresholdAlert; export type LogThresholdAlertLimit = RuleExecutorServices< LogThresholdAlertState, @@ -134,15 +135,21 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => value, threshold, actions, - additionalContext + rootLevelContext ) => { + const alertContext = + actions != null + ? actions.reduce((next, action) => ({ ...next, ...action.context }), {}) + : {}; + const alert = alertWithLifecycle({ id, fields: { [ALERT_EVALUATION_THRESHOLD]: threshold, [ALERT_EVALUATION_VALUE]: value, [ALERT_REASON]: reason, - ...flattenAdditionalContext(additionalContext), + [ALERT_CONTEXT]: alertContext, + ...flattenAdditionalContext(rootLevelContext), }, }); From c0fe697de0a1f61e6400b5bba34a75e58f5cd2e8 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 19 Apr 2023 16:18:03 -0600 Subject: [PATCH 2/5] Fixing assumption that groupBy is always an array --- .../alert_details_app_section/components/logs_ratio_chart.tsx | 1 + .../expression_editor/hooks/use_chart_preview_data.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/logs_ratio_chart.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/logs_ratio_chart.tsx index 82f511cb8403b..d09c942f4038a 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/logs_ratio_chart.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/logs_ratio_chart.tsx @@ -131,6 +131,7 @@ const LogsRatioChart: React.FC = ({ const barSeries = useMemo(() => { return series.flatMap(({ points, id }) => points.map((point) => ({ ...point, groupBy: id }))); }, [series]); + if (isLoading) { return ; } else if (hasError) { diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/hooks/use_chart_preview_data.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/hooks/use_chart_preview_data.tsx index 62d18138880b1..1b15a7e2c6eed 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/hooks/use_chart_preview_data.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/hooks/use_chart_preview_data.tsx @@ -68,7 +68,7 @@ export const useChartPreviewData = ({ let seriesQueryB = ratio[1].data.series[0].points; let seriesId = 'ratio'; // When groupBy and a filter is applied, return the ratio only for the filtered grouped-by - if (ruleParams.groupBy.length && filterSeriesByGroupName) { + if (ruleParams.groupBy?.length && filterSeriesByGroupName) { seriesId = filterSeriesByGroupName; seriesQueryA = ratio[0].data.series.find((series) => series.id === filterSeriesByGroupName) From 3659f3c87ccca0e7f232a140c977bfbc300762d0 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 20 Apr 2023 06:52:32 -0600 Subject: [PATCH 3/5] Update packages/kbn-rule-data-utils/src/default_alerts_as_data.ts Co-authored-by: Kevin Delemme --- packages/kbn-rule-data-utils/src/default_alerts_as_data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts b/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts index ce8bfa0d00eb6..cbcbb84601ffc 100644 --- a/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts +++ b/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts @@ -49,7 +49,7 @@ const ALERT_LAST_DETECTED = `${ALERT_NAMESPACE}.last_detected` as const; // kibana.alert.reason - human readable reason that this alert is active const ALERT_REASON = `${ALERT_NAMESPACE}.reason` as const; -// kibana.alert.context - human readable reason that this alert is active +// kibana.alert.context - alert context const ALERT_CONTEXT = `${ALERT_NAMESPACE}.context` as const; // kibana.alert.start - timestamp when the alert is first active From 0bf2f95bc2a0f46b04fc79709f4b60736e5666ed Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 20 Apr 2023 06:58:11 -0600 Subject: [PATCH 4/5] Updated unit tests --- .../alert_schema/field_maps/mapping_from_field_map.test.ts | 3 +++ .../assets/field_maps/technical_rule_field_map.test.ts | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts b/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts index 4456bd363a016..522aba705c2fa 100644 --- a/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts +++ b/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts @@ -200,6 +200,9 @@ describe('mappingFromFieldMap', () => { case_ids: { type: 'keyword', }, + context: { + type: 'object', + }, duration: { properties: { us: { diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts index 581c77670a153..65e1405d4a299 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts @@ -42,6 +42,11 @@ it('matches snapshot', () => { "required": false, "type": "keyword", }, + "kibana.alert.context": Object { + "array": false, + "required": false, + "type": "object", + }, "kibana.alert.duration.us": Object { "array": false, "required": false, From def678764dd73a14ddb01791070692004b3536d4 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 20 Apr 2023 14:28:09 -0600 Subject: [PATCH 5/5] Moving ALERT_CONTEXT to legacy experimental fields --- .../src/field_maps/alert_field_map.ts | 6 ------ .../src/field_maps/legacy_experimental_field_map.ts | 7 ++++++- packages/kbn-rule-data-utils/src/default_alerts_as_data.ts | 5 ----- packages/kbn-rule-data-utils/src/technical_field_names.ts | 3 ++- .../alert_schema/field_maps/mapping_from_field_map.test.ts | 3 --- .../assets/field_maps/technical_rule_field_map.test.ts | 5 ----- 6 files changed, 8 insertions(+), 21 deletions(-) diff --git a/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts b/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts index a4b251dc17e61..72fe68fa9cf59 100644 --- a/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts +++ b/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts @@ -16,7 +16,6 @@ import { ALERT_INSTANCE_ID, ALERT_LAST_DETECTED, ALERT_REASON, - ALERT_CONTEXT, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, ALERT_RULE_EXECUTION_UUID, @@ -83,11 +82,6 @@ export const alertFieldMap = { array: false, required: false, }, - [ALERT_CONTEXT]: { - type: 'object', - array: false, - required: false, - }, [ALERT_RULE_CATEGORY]: { type: 'keyword', array: false, diff --git a/packages/kbn-alerts-as-data-utils/src/field_maps/legacy_experimental_field_map.ts b/packages/kbn-alerts-as-data-utils/src/field_maps/legacy_experimental_field_map.ts index 8c8445ad6761a..55cd0b467e0ff 100644 --- a/packages/kbn-alerts-as-data-utils/src/field_maps/legacy_experimental_field_map.ts +++ b/packages/kbn-alerts-as-data-utils/src/field_maps/legacy_experimental_field_map.ts @@ -6,7 +6,11 @@ * Side Public License, v 1. */ -import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE } from '@kbn/rule-data-utils'; +import { + ALERT_CONTEXT, + ALERT_EVALUATION_THRESHOLD, + ALERT_EVALUATION_VALUE, +} from '@kbn/rule-data-utils'; export const legacyExperimentalFieldMap = { [ALERT_EVALUATION_THRESHOLD]: { @@ -15,6 +19,7 @@ export const legacyExperimentalFieldMap = { required: false, }, [ALERT_EVALUATION_VALUE]: { type: 'scaled_float', scaling_factor: 100, required: false }, + [ALERT_CONTEXT]: { type: 'object', array: false, required: false }, } as const; export type ExperimentalRuleFieldMap = typeof legacyExperimentalFieldMap; diff --git a/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts b/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts index cbcbb84601ffc..e996acbd9fb6c 100644 --- a/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts +++ b/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts @@ -49,9 +49,6 @@ const ALERT_LAST_DETECTED = `${ALERT_NAMESPACE}.last_detected` as const; // kibana.alert.reason - human readable reason that this alert is active const ALERT_REASON = `${ALERT_NAMESPACE}.reason` as const; -// kibana.alert.context - alert context -const ALERT_CONTEXT = `${ALERT_NAMESPACE}.context` as const; - // kibana.alert.start - timestamp when the alert is first active const ALERT_START = `${ALERT_NAMESPACE}.start` as const; @@ -113,7 +110,6 @@ const fields = { ALERT_INSTANCE_ID, ALERT_LAST_DETECTED, ALERT_REASON, - ALERT_CONTEXT, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, ALERT_RULE_EXECUTION_UUID, @@ -150,7 +146,6 @@ export { ALERT_INSTANCE_ID, ALERT_LAST_DETECTED, ALERT_REASON, - ALERT_CONTEXT, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, ALERT_RULE_EXECUTION_UUID, diff --git a/packages/kbn-rule-data-utils/src/technical_field_names.ts b/packages/kbn-rule-data-utils/src/technical_field_names.ts index 4867e79c89ec0..efe3dcfd46815 100644 --- a/packages/kbn-rule-data-utils/src/technical_field_names.ts +++ b/packages/kbn-rule-data-utils/src/technical_field_names.ts @@ -18,7 +18,6 @@ import { ALERT_FLAPPING, ALERT_INSTANCE_ID, ALERT_REASON, - ALERT_CONTEXT, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, ALERT_RULE_EXECUTION_UUID, @@ -85,6 +84,7 @@ const EVENT_MODULE = 'event.module' as const; const ALERT_BUILDING_BLOCK_TYPE = `${ALERT_NAMESPACE}.building_block_type` as const; const ALERT_EVALUATION_THRESHOLD = `${ALERT_NAMESPACE}.evaluation.threshold` as const; const ALERT_EVALUATION_VALUE = `${ALERT_NAMESPACE}.evaluation.value` as const; +const ALERT_CONTEXT = `${ALERT_NAMESPACE}.context` as const; // Fields pertaining to the rule associated with the alert const ALERT_RULE_EXCEPTIONS_LIST = `${ALERT_RULE_NAMESPACE}.exceptions_list` as const; @@ -192,6 +192,7 @@ export { ALERT_BUILDING_BLOCK_TYPE, ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, + ALERT_CONTEXT, ALERT_RULE_EXCEPTIONS_LIST, ALERT_RULE_NAMESPACE_FIELD, ALERT_THREAT_FRAMEWORK, diff --git a/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts b/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts index 522aba705c2fa..4456bd363a016 100644 --- a/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts +++ b/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts @@ -200,9 +200,6 @@ describe('mappingFromFieldMap', () => { case_ids: { type: 'keyword', }, - context: { - type: 'object', - }, duration: { properties: { us: { diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts index 65e1405d4a299..581c77670a153 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts @@ -42,11 +42,6 @@ it('matches snapshot', () => { "required": false, "type": "keyword", }, - "kibana.alert.context": Object { - "array": false, - "required": false, - "type": "object", - }, "kibana.alert.duration.us": Object { "array": false, "required": false,