From 032ec682acdcdba7de2067c73d3f37869e25d723 Mon Sep 17 00:00:00 2001 From: Nikita Khristinin Date: Mon, 3 Mar 2025 15:14:27 +0100 Subject: [PATCH 1/2] Add gaps callout --- .../components/rule_gaps_callout/index.tsx | 35 +++++++++++++++++++ .../rule_gaps_callout/translations.tsx | 23 ++++++++++++ .../components/rules_table/index.tsx | 2 ++ .../components/rules_table/rules_tables.tsx | 1 - 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/index.tsx create mode 100644 x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/translations.tsx diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/index.tsx new file mode 100644 index 0000000000000..50c3adef28f0b --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/index.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { EuiCallOut, EuiSpacer } from '@elastic/eui'; +import { gapStatus } from '@kbn/alerting-plugin/common'; +import { useGetRuleIdsWithGaps } from '../../api/hooks/use_get_rule_ids_with_gaps'; +import { GapRangeValue } from '../../constants'; +import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; +import * as i18n from './translations'; + +export const RuleGapsCallout = () => { + const storeGapsInEventLogEnabled = useIsExperimentalFeatureEnabled('storeGapsInEventLogEnabled'); + + const { data } = useGetRuleIdsWithGaps({ + gapRange: GapRangeValue.LAST_24_H, + statuses: [gapStatus.UNFILLED, gapStatus.PARTIALLY_FILLED], + }); + + if (!data || data?.total === 0 || !storeGapsInEventLogEnabled) { + return null; + } + + return ( + <> + +

{i18n.RULE_GAPS_CALLOUT_MESSAGE}

+
+ + + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/translations.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/translations.tsx new file mode 100644 index 0000000000000..880fc39fdbc24 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/translations.tsx @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const RULE_GAPS_CALLOUT_TITLE = i18n.translate( + 'xpack.securitySolution.ruleGaps.callout.title', + { + defaultMessage: 'Some alerts may have been missed', + } +); + +export const RULE_GAPS_CALLOUT_MESSAGE = i18n.translate( + 'xpack.securitySolution.ruleGaps.callout.message', + { + defaultMessage: + 'Some alerts may have been missed in past 24h due to rule execution gaps. For more details visit Rule monitoring tab.', + } +); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/index.tsx index b4456715abd4b..20d13513287a2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/index.tsx @@ -14,6 +14,7 @@ import { RulesTables } from './rules_tables'; import { AllRulesTabs, RulesTableToolbar } from './rules_table_toolbar'; import { UpgradePrebuiltRulesTable } from './upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table'; import { UpgradePrebuiltRulesTableContextProvider } from './upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context'; +import { RuleGapsCallout } from '../../../rule_gaps/components/rule_gaps_callout'; /** * Table Component for displaying all Rules for a given cluster. Provides the ability to filter @@ -31,6 +32,7 @@ export const AllRules = React.memo(() => { return ( <> + {tabName !== AllRulesTabs.monitoring && } diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_tables.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_tables.tsx index 4742d3d57831c..de5450db8bf7c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_tables.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_tables.tsx @@ -325,7 +325,6 @@ export const RulesTables = React.memo(({ selectedTab }) => { <> {selectedTab === AllRulesTabs.monitoring && storeGapsInEventLogEnabled && ( <> - From 2db97fd31265adee50256693e008b6545feb08d9 Mon Sep 17 00:00:00 2001 From: Nikita Khristinin Date: Tue, 4 Mar 2025 13:18:29 +0100 Subject: [PATCH 2/2] Change copy --- .../rule_gaps/components/rule_gaps_callout/index.tsx | 2 +- .../rule_gaps/components/rule_gaps_callout/translations.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/index.tsx index 50c3adef28f0b..dea8ec48da0b0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/index.tsx @@ -26,7 +26,7 @@ export const RuleGapsCallout = () => { return ( <> - +

{i18n.RULE_GAPS_CALLOUT_MESSAGE}

diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/translations.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/translations.tsx index 880fc39fdbc24..af97bce64ef6b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/translations.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_gaps_callout/translations.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; export const RULE_GAPS_CALLOUT_TITLE = i18n.translate( 'xpack.securitySolution.ruleGaps.callout.title', { - defaultMessage: 'Some alerts may have been missed', + defaultMessage: 'Rule execution gaps detected', } ); @@ -18,6 +18,6 @@ export const RULE_GAPS_CALLOUT_MESSAGE = i18n.translate( 'xpack.securitySolution.ruleGaps.callout.message', { defaultMessage: - 'Some alerts may have been missed in past 24h due to rule execution gaps. For more details visit Rule monitoring tab.', + 'Gaps in rule coverage were detected over the past 24 hours. Check the Rule Monitoring tab to learn which rules are affected and to begin remediating gaps.', } );