From a1eb6cebd0194ff39969774ffe87efba8db1e9fe Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Tue, 6 Aug 2024 11:42:36 +0200 Subject: [PATCH 01/14] Add alert grouping functionality to the alerts page --- .../src/components/alerts_grouping.tsx | 23 +++--- .../src/components/alerts_grouping_level.tsx | 3 +- .../get_alerts_page_table_configuration.tsx | 27 ++++++- .../alerts/get_peristent_controls.ts | 68 ++++++++++++++++ .../register_alerts_table_configuration.tsx | 13 ++- .../public/components/alerts_table/types.ts | 36 +++++++++ .../observability/public/components/tags.tsx | 47 +++++++---- .../observability/public/constants.ts | 1 + .../public/pages/alerts/alerts.tsx | 79 ++++++++++++++----- .../public/pages/alerts/grouping/constants.ts | 32 ++++++++ .../get_aggregations_by_grouping_field.ts | 69 ++++++++++++++++ .../pages/alerts/grouping/get_group_stats.tsx | 55 +++++++++++++ .../alerts/grouping/render_group_panel.tsx | 74 +++++++++++++++++ .../alerts/helpers/merge_bool_queries.ts | 25 ++++++ .../observability/public/plugin.ts | 10 ++- .../observability/tsconfig.json | 2 + .../translations/translations/ja-JP.json | 1 - 17 files changed, 509 insertions(+), 56 deletions(-) create mode 100644 x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts create mode 100644 x-pack/plugins/observability_solution/observability/public/components/alerts_table/types.ts create mode 100644 x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/constants.ts create mode 100644 x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_aggregations_by_grouping_field.ts create mode 100644 x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx create mode 100644 x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx create mode 100644 x-pack/plugins/observability_solution/observability/public/pages/alerts/helpers/merge_bool_queries.ts diff --git a/packages/kbn-alerts-grouping/src/components/alerts_grouping.tsx b/packages/kbn-alerts-grouping/src/components/alerts_grouping.tsx index 130997dd393ce6..ba087b84754b08 100644 --- a/packages/kbn-alerts-grouping/src/components/alerts_grouping.tsx +++ b/packages/kbn-alerts-grouping/src/components/alerts_grouping.tsx @@ -56,7 +56,9 @@ const NextLevel = ({ return children(nextGroupingFilters)!; }; -const AlertsGroupingInternal = (props: AlertsGroupingProps) => { +const AlertsGroupingInternal = >( + props: AlertsGroupingProps +) => { const { groupingId, services, @@ -195,7 +197,7 @@ const AlertsGroupingInternal = (props: AlertsGroupingProps) => { }; return ( - {...props} getGrouping={getGrouping} groupingLevel={level} @@ -276,10 +278,13 @@ const AlertsGroupingInternal = (props: AlertsGroupingProps) => { * ); * ``` */ -export const AlertsGrouping = memo((props: AlertsGroupingProps) => { - return ( - - - - ); -}); +const typedMemo: (c: T) => T = memo; +export const AlertsGrouping = typedMemo( + >(props: AlertsGroupingProps) => { + return ( + + + + ); + } +); diff --git a/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx b/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx index e4511e8dea774e..ed4c7c503b4c18 100644 --- a/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx +++ b/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx @@ -40,7 +40,8 @@ const DEFAULT_FILTERS: Filter[] = []; /** * Renders an alerts grouping level */ -export const AlertsGroupingLevel = memo( +const typedMemo: (c: T) => T = memo; +export const AlertsGroupingLevel = typedMemo( = {}>({ featureIds, defaultFilters = DEFAULT_FILTERS, diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx index cabf1d6d6f34e6..9a0c478b0383cc 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx @@ -12,17 +12,29 @@ import { AlertsTableConfigurationRegistry, RenderCustomActionsRowArgs, } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { casesFeatureId, observabilityFeatureId } from '../../../../common'; +import { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types'; +import { HttpSetup } from '@kbn/core-http-browser'; +import { NotificationsStart } from '@kbn/core-notifications-browser'; +import { + casesFeatureId, + observabilityAlertFeatureIds, + observabilityFeatureId, +} from '../../../../common'; import { AlertActions } from '../../../pages/alerts/components/alert_actions'; import { useGetAlertFlyoutComponents } from '../../alerts_flyout/use_get_alert_flyout_components'; import type { ObservabilityRuleTypeRegistry } from '../../../rules/create_observability_rule_type_registry'; +import { ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID } from '../../../constants'; import type { ConfigSchema } from '../../../plugin'; import { getRenderCellValue } from '../common/render_cell_value'; import { getColumns } from '../common/get_columns'; +import { getPersistentControlsHook } from './get_peristent_controls'; export const getAlertsPageTableConfiguration = ( observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry, - config: ConfigSchema + config: ConfigSchema, + dataViews: DataViewsServicePublic, + http: HttpSetup, + notifications: NotificationsStart ): AlertsTableConfigurationRegistry => { const renderCustomActionsRow = (props: RenderCustomActionsRowArgs) => { return ( @@ -34,7 +46,7 @@ export const getAlertsPageTableConfiguration = ( ); }; return { - id: observabilityFeatureId, + id: ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID, cases: { featureId: casesFeatureId, owner: [observabilityFeatureId] }, columns: getColumns({ showRuleName: true }), getRenderCellValue, @@ -53,6 +65,15 @@ export const getAlertsPageTableConfiguration = ( return { header, body, footer }; }, ruleTypeIds: observabilityRuleTypeRegistry.list(), + usePersistentControls: getPersistentControlsHook({ + groupingId: ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID, + featureIds: observabilityAlertFeatureIds, + services: { + dataViews, + http, + notifications, + }, + }), showInspectButton: true, }; }; diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts new file mode 100644 index 00000000000000..648e3ed387f8c5 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts @@ -0,0 +1,68 @@ +/* + * 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 { useMemo, useCallback } from 'react'; +import { type AlertsGroupingProps, useAlertsGroupingState } from '@kbn/alerts-grouping'; +import { useAlertDataView } from '@kbn/alerts-ui-shared'; +import { useGetGroupSelectorStateless } from '@kbn/grouping/src/hooks/use_get_group_selector'; +import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertsByGroupingAgg } from '../types'; + +interface GetPersistentControlsParams { + groupingId: string; + featureIds: AlertConsumers[]; + maxGroupingLevels?: number; + services: Pick< + AlertsGroupingProps['services'], + 'dataViews' | 'http' | 'notifications' + >; +} + +export const getPersistentControlsHook = + ({ + groupingId, + featureIds, + maxGroupingLevels = 3, + services: { dataViews, http, notifications }, + }: GetPersistentControlsParams) => + () => { + const { grouping, updateGrouping } = useAlertsGroupingState(groupingId); + + const onGroupChange = useCallback( + (selectedGroups: string[]) => { + updateGrouping({ + activeGroups: grouping.activeGroups.filter((g) => g !== 'none').concat(selectedGroups), + }); + }, + [grouping, updateGrouping] + ); + + const { dataViews: alertDataViews } = useAlertDataView({ + featureIds, + dataViewsService: dataViews, + http, + toasts: notifications.toasts, + }); + + const dataView = useMemo(() => alertDataViews?.[0], [alertDataViews]); + + const groupSelector = useGetGroupSelectorStateless({ + groupingId, + onGroupChange, + fields: dataView?.fields ?? [], + defaultGroupingOptions: grouping.options.filter( + (option) => !grouping.activeGroups.includes(option.key) + ), + maxGroupingLevels, + }); + + return useMemo(() => { + return { + right: groupSelector, + }; + }, [groupSelector]); + }; diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/register_alerts_table_configuration.tsx b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/register_alerts_table_configuration.tsx index 1fa574d1dd4026..4ed421e37defe6 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/register_alerts_table_configuration.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/register_alerts_table_configuration.tsx @@ -6,6 +6,9 @@ */ import { AlertTableConfigRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/alert_table_config_registry'; +import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types'; +import { HttpSetup } from '@kbn/core-http-browser'; +import { NotificationsStart } from '@kbn/core-notifications-browser'; import type { ConfigSchema } from '../../plugin'; import { ObservabilityRuleTypeRegistry } from '../..'; import { getAlertsPageTableConfiguration } from './alerts/get_alerts_page_table_configuration'; @@ -15,12 +18,18 @@ import { getSloAlertsTableConfiguration } from './slo/get_slo_alerts_table_confi export const registerAlertsTableConfiguration = ( alertTableConfigRegistry: AlertTableConfigRegistry, observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry, - config: ConfigSchema + config: ConfigSchema, + dataViews: DataViewsServicePublic, + http: HttpSetup, + notifications: NotificationsStart ) => { // Alert page const alertsPageAlertsTableConfig = getAlertsPageTableConfiguration( observabilityRuleTypeRegistry, - config + config, + dataViews, + http, + notifications ); alertTableConfigRegistry.register(alertsPageAlertsTableConfig); diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/types.ts b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/types.ts new file mode 100644 index 00000000000000..477117999a8ca2 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/types.ts @@ -0,0 +1,36 @@ +/* + * 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. + */ + +export interface BucketItem { + key: string; + doc_count: number; +} + +export interface AlertsByGroupingAgg extends Record { + groupByFields: { + doc_count_error_upper_bound: number; + sum_other_doc_count: number; + buckets: BucketItem[]; + }; + ruleTags: { + doc_count_error_upper_bound: number; + sum_other_doc_count: number; + buckets: BucketItem[]; + }; + rulesCountAggregation?: { + value: number; + }; + sourceCountAggregation?: { + value: number; + }; + groupsCount: { + value: number; + }; + unitsCount: { + value: number; + }; +} diff --git a/x-pack/plugins/observability_solution/observability/public/components/tags.tsx b/x-pack/plugins/observability_solution/observability/public/components/tags.tsx index e7059463ef7bd7..015e911c535be5 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/tags.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/tags.tsx @@ -10,38 +10,53 @@ import React, { useState } from 'react'; import { EuiBadge, EuiPopover } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -export function Tags({ tags }: { tags: string[] }) { +export function Tags({ + tags, + color, + size = 3, + oneLine = false, +}: { + tags: string[]; + color?: string; + size?: number; + oneLine?: boolean; +}) { const [isMoreTagsOpen, setIsMoreTagsOpen] = useState(false); - const onMoreTagsClick = () => setIsMoreTagsOpen((isPopoverOpen) => !isPopoverOpen); + const onMoreTagsClick = (e: any) => { + e.stopPropagation(); + setIsMoreTagsOpen((isPopoverOpen) => !isPopoverOpen); + }; const closePopover = () => setIsMoreTagsOpen(false); - const moreTags = tags.length > 3 && ( + const moreTags = tags.length > size && ( ); return ( <> - {tags.slice(0, 3).map((tag) => ( - {tag} + {tags.slice(0, size).map((tag) => ( + + {tag} + ))} -
+ {oneLine ? ' ' :
} - {tags.slice(3).map((tag) => ( - {tag} + {tags.slice(size).map((tag) => ( + + {tag} + ))} diff --git a/x-pack/plugins/observability_solution/observability/public/constants.ts b/x-pack/plugins/observability_solution/observability/public/constants.ts index 2da72ff858283a..768094ec8a66b7 100644 --- a/x-pack/plugins/observability_solution/observability/public/constants.ts +++ b/x-pack/plugins/observability_solution/observability/public/constants.ts @@ -8,4 +8,5 @@ export const DEFAULT_INTERVAL = '60s'; export const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH:mm'; +export const ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID = `alerts-page-alerts-table`; export const RULE_DETAILS_ALERTS_TABLE_CONFIG_ID = `rule-details-alerts-table`; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx index def57b3b4bd1b7..ba31e95c2076f0 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx @@ -11,20 +11,21 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { BoolQuery } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { loadRuleAggregations } from '@kbn/triggers-actions-ui-plugin/public'; -import { AlertConsumers } from '@kbn/rule-data-utils'; import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public'; import { MaintenanceWindowCallout } from '@kbn/alerts-ui-shared'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; +import { AlertsGrouping } from '@kbn/alerts-grouping'; +import { renderGroupPanel } from './grouping/render_group_panel'; import { rulesLocatorID } from '../../../common'; -import { RulesParams } from '../../locators/rules'; -import { useKibana } from '../../utils/kibana_react'; +import { AlertsByGroupingAgg } from '../../components/alerts_table/types'; +import { ObservabilityAlertSearchBar } from '../../components/alert_search_bar/alert_search_bar'; +import { useGetFilteredRuleTypes } from '../../hooks/use_get_filtered_rule_types'; import { usePluginContext } from '../../hooks/use_plugin_context'; import { useTimeBuckets } from '../../hooks/use_time_buckets'; -import { useGetFilteredRuleTypes } from '../../hooks/use_get_filtered_rule_types'; import { useToasts } from '../../hooks/use_toast'; -import { renderRuleStats, RuleStatsState } from './components/rule_stats'; -import { ObservabilityAlertSearchBar } from '../../components/alert_search_bar/alert_search_bar'; +import { RulesParams } from '../../locators/rules'; +import { useKibana } from '../../utils/kibana_react'; import { alertSearchBarStateContainer, Provider, @@ -34,8 +35,15 @@ import { calculateTimeRangeBucketSize } from '../overview/helpers/calculate_buck import { getAlertSummaryTimeRange } from '../../utils/alert_summary_widget'; import { observabilityAlertFeatureIds } from '../../../common/constants'; import { ALERTS_URL_STORAGE_KEY } from '../../../common/constants'; +import { ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID } from '../../constants'; import { HeaderMenu } from '../overview/components/header_menu/header_menu'; import { useGetAvailableRulesWithDescriptions } from '../../hooks/use_get_available_rules_with_descriptions'; +import { buildEsQuery } from '../../utils/build_es_query'; +import { renderRuleStats, RuleStatsState } from './components/rule_stats'; +import { getGroupStats } from './grouping/get_group_stats'; +import { getAggregationsByGroupingField } from './grouping/get_aggregations_by_grouping_field'; +import { DEFAULT_GROUPING_OPTIONS } from './grouping/constants'; +import { mergeBoolQueries } from './helpers/merge_bool_queries'; const ALERTS_SEARCH_BAR_ID = 'alerts-search-bar-o11y'; const ALERTS_PER_PAGE = 50; @@ -48,13 +56,10 @@ function InternalAlertsPage() { const kibanaServices = useKibana().services; const { charts, - data: { - query: { - timefilter: { timefilter: timeFilterService }, - }, - }, + data, http, - notifications: { toasts }, + notifications, + dataViews, observabilityAIAssistant, share: { url: { locators }, @@ -67,6 +72,12 @@ function InternalAlertsPage() { }, uiSettings, } = kibanaServices; + const { toasts } = notifications; + const { + query: { + timefilter: { timefilter: timeFilterService }, + }, + } = data; const { ObservabilityPageTemplate, observabilityRuleTypeRegistry } = usePluginContext(); const alertSearchBarStateProps = useAlertSearchBarStateContainer(ALERTS_URL_STORAGE_KEY, { replace: false, @@ -241,16 +252,42 @@ function InternalAlertsPage() { {esQuery && ( - featureIds={observabilityAlertFeatureIds} - query={esQuery} - showAlertStatusWithFlapping - pageSize={ALERTS_PER_PAGE} - cellContext={{ observabilityRuleTypeRegistry }} - /> + defaultFilters={[]} + from={alertSearchBarStateProps.rangeFrom} + to={alertSearchBarStateProps.rangeTo} + globalFilters={alertSearchBarStateProps.filters} + globalQuery={{ query: alertSearchBarStateProps.kuery, language: 'kql' }} + groupingId={ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID} + defaultGroupingOptions={DEFAULT_GROUPING_OPTIONS} + getAggregationsByGroupingField={getAggregationsByGroupingField} + renderGroupPanel={renderGroupPanel} + getGroupStats={getGroupStats} + services={{ + notifications, + dataViews, + http, + }} + > + {(groupingFilters) => { + const groupQuery = buildEsQuery({ + filters: groupingFilters, + }); + return ( + + ); + }} + )} diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/constants.ts b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/constants.ts new file mode 100644 index 00000000000000..31e461e34926c4 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/constants.ts @@ -0,0 +1,32 @@ +/* + * 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'; +import { ALERT_RULE_NAME, ALERT_INSTANCE_ID } from '@kbn/rule-data-utils'; + +export const unknown = i18n.translate('xpack.observability.alert.grouping.unknown.label', { + defaultMessage: 'Unknown', +}); + +export const ruleName = i18n.translate('xpack.observability.alert.grouping.ruleName.label', { + defaultMessage: 'Rule name', +}); + +export const source = i18n.translate('xpack.observability.alert.grouping.source.label', { + defaultMessage: 'Source', +}); + +export const DEFAULT_GROUPING_OPTIONS = [ + { + label: ruleName, + key: ALERT_RULE_NAME, + }, + { + label: source, + key: ALERT_INSTANCE_ID, + }, +]; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_aggregations_by_grouping_field.ts b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_aggregations_by_grouping_field.ts new file mode 100644 index 00000000000000..7762d06468bd4e --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_aggregations_by_grouping_field.ts @@ -0,0 +1,69 @@ +/* + * 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 { + ALERT_INSTANCE_ID, + ALERT_RULE_NAME, + ALERT_RULE_UUID, + ALERT_UUID, +} from '@kbn/rule-data-utils'; + +export const getAggregationsByGroupingField = (field: string): any[] => { + const aggMetrics: any[] = [ + { + unitsCount: { + cardinality: { + field: ALERT_UUID, + }, + }, + }, + ]; + switch (field) { + case ALERT_RULE_NAME: + aggMetrics.push( + ...[ + { + sourceCountAggregation: { + cardinality: { + field: ALERT_INSTANCE_ID, + }, + }, + }, + { + ruleTags: { + terms: { + field: 'tags', + }, + }, + }, + ] + ); + break; + case ALERT_INSTANCE_ID: + aggMetrics.push( + ...[ + { + rulesCountAggregation: { + cardinality: { + field: ALERT_RULE_UUID, + }, + }, + }, + ] + ); + break; + default: + aggMetrics.push({ + rulesCountAggregation: { + cardinality: { + field: ALERT_RULE_UUID, + }, + }, + }); + } + return aggMetrics; +}; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx new file mode 100644 index 00000000000000..4dac663ba17d06 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx @@ -0,0 +1,55 @@ +/* + * 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 { GetGroupStats } from '@kbn/grouping/src'; +import { ALERT_INSTANCE_ID, ALERT_RULE_NAME } from '@kbn/rule-data-utils'; +import { AlertsByGroupingAgg } from '../../../components/alerts_table/types'; + +export const getGroupStats: GetGroupStats = (selectedGroup, bucket) => { + const defaultBadges = [ + { + title: 'Alerts:', + badge: { + value: bucket.doc_count, + width: 50, + color: '#a83632', + }, + }, + ]; + + switch (selectedGroup) { + case ALERT_RULE_NAME: + return [ + { + title: 'Sources:', + badge: { + value: bucket.sourceCountAggregation?.value ?? 0, + }, + }, + ...defaultBadges, + ]; + case ALERT_INSTANCE_ID: + return [ + { + title: 'Rules:', + badge: { + value: bucket.rulesCountAggregation?.value ?? 0, + }, + }, + ...defaultBadges, + ]; + } + return [ + { + title: 'Rules:', + badge: { + value: bucket.rulesCountAggregation?.value ?? 0, + }, + }, + ...defaultBadges, + ]; +}; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx new file mode 100644 index 00000000000000..f102721b963297 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx @@ -0,0 +1,74 @@ +/* + * 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 { isArray } from 'lodash/fp'; +import { firstNonNullValue, GroupPanelRenderer } from '@kbn/grouping/src'; +import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui'; +import { AlertsByGroupingAgg } from '../../../components/alerts_table/types'; +import { Tags } from '../../../components/tags'; +import { unknown } from './constants'; + +export const renderGroupPanel: GroupPanelRenderer = ( + selectedGroup, + bucket +) => { + switch (selectedGroup) { + case 'kibana.alert.rule.name': + return isArray(bucket.key) ? ( + tag.key)} + /> + ) : undefined; + case 'kibana.alert.instance.id': + return ; + } +}; + +const RuleNameGroupContent = React.memo<{ + ruleName: string; + tags?: string[] | undefined; +}>(({ ruleName, tags }) => { + return ( +
+ + + +
{ruleName}
+
+
+
+ + {!!tags && tags.length > 0 && ( + + + + )} +
+ ); +}); +RuleNameGroupContent.displayName = 'RuleNameGroup'; + +const InstanceIdGroupContent = React.memo<{ + instanceId?: string; +}>(({ instanceId }) => { + return ( +
+ + + +
+ {instanceId === '*' ? unknown : instanceId ?? '--'} +
+
+
+
+
+ ); +}); +InstanceIdGroupContent.displayName = 'InstanceIdGroupContent'; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/helpers/merge_bool_queries.ts b/x-pack/plugins/observability_solution/observability/public/pages/alerts/helpers/merge_bool_queries.ts new file mode 100644 index 00000000000000..bd748f4e5b9283 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/helpers/merge_bool_queries.ts @@ -0,0 +1,25 @@ +/* + * 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 { BoolQuery } from '@kbn/es-query'; + +export const mergeBoolQueries = ( + firstQuery: { bool: BoolQuery }, + secondQuery: { bool: BoolQuery } +): { bool: BoolQuery } => { + const first = firstQuery.bool; + const second = secondQuery.bool; + + return { + bool: { + must: [...first.must, ...second.must], + must_not: [...first.must_not, ...second.must_not], + filter: [...first.filter, ...second.filter], + should: [...first.should, ...second.should], + }, + }; +}; diff --git a/x-pack/plugins/observability_solution/observability/public/plugin.ts b/x-pack/plugins/observability_solution/observability/public/plugin.ts index a97085f0c036d9..676dbe7059d854 100644 --- a/x-pack/plugins/observability_solution/observability/public/plugin.ts +++ b/x-pack/plugins/observability_solution/observability/public/plugin.ts @@ -443,14 +443,18 @@ export class Plugin } public start(coreStart: CoreStart, pluginsStart: ObservabilityPublicPluginsStart) { - const { application } = coreStart; + const { application, http, notifications } = coreStart; + const { dataViews, triggersActionsUi } = pluginsStart; const config = this.initContext.config.get(); - const { alertsTableConfigurationRegistry } = pluginsStart.triggersActionsUi; + const { alertsTableConfigurationRegistry } = triggersActionsUi; this.lazyRegisterAlertsTableConfiguration().then(({ registerAlertsTableConfiguration }) => { return registerAlertsTableConfiguration( alertsTableConfigurationRegistry, this.observabilityRuleTypeRegistry, - config + config, + dataViews, + http, + notifications ); }); diff --git a/x-pack/plugins/observability_solution/observability/tsconfig.json b/x-pack/plugins/observability_solution/observability/tsconfig.json index 7432602b54c43f..8274d14c1ed590 100644 --- a/x-pack/plugins/observability_solution/observability/tsconfig.json +++ b/x-pack/plugins/observability_solution/observability/tsconfig.json @@ -108,6 +108,8 @@ "@kbn/event-annotation-components", "@kbn/slo-schema", "@kbn/license-management-plugin", + "@kbn/grouping", + "@kbn/alerts-grouping" ], "exclude": [ "target/**/*" diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b73e2d2a97d245..8216325d747770 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6629,7 +6629,6 @@ "textBasedEditor.query.textBasedLanguagesEditor.runQuery": "クエリを実行", "textBasedEditor.query.textBasedLanguagesEditor.sourceCommands": "ソースコマンド", "textBasedEditor.query.textBasedLanguagesEditor.submitFeedback": "フィードバックを送信", - "": "@timestampが見つかりました", "textBasedEditor.query.textBasedLanguagesEditor.timestampNotDetected": "@timestampが見つかりません", "textBasedEditor.query.textBasedLanguagesEditor.warningCount": "{count} {count, plural, other {件の警告}}", "textBasedEditor.query.textBasedLanguagesEditor.warningsTitle": "警告", From b788b66fecb530a6d301e829aa6b170f9f98b680 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Tue, 6 Aug 2024 12:37:45 +0200 Subject: [PATCH 02/14] Add ungrouped tooltip. --- .../public/pages/alerts/grouping/constants.ts | 4 ++-- .../alerts/grouping/render_group_panel.tsx | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/constants.ts b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/constants.ts index 31e461e34926c4..6bfe2f0febdd53 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/constants.ts +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/constants.ts @@ -8,8 +8,8 @@ import { i18n } from '@kbn/i18n'; import { ALERT_RULE_NAME, ALERT_INSTANCE_ID } from '@kbn/rule-data-utils'; -export const unknown = i18n.translate('xpack.observability.alert.grouping.unknown.label', { - defaultMessage: 'Unknown', +export const ungrouped = i18n.translate('xpack.observability.alert.grouping.ungrouped.label', { + defaultMessage: 'Ungrouped', }); export const ruleName = i18n.translate('xpack.observability.alert.grouping.ruleName.label', { diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx index f102721b963297..462e7322cff538 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx @@ -7,11 +7,12 @@ import React from 'react'; import { isArray } from 'lodash/fp'; +import { EuiFlexGroup, EuiIconTip, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui'; import { firstNonNullValue, GroupPanelRenderer } from '@kbn/grouping/src'; -import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; import { AlertsByGroupingAgg } from '../../../components/alerts_table/types'; import { Tags } from '../../../components/tags'; -import { unknown } from './constants'; +import { ungrouped } from './constants'; export const renderGroupPanel: GroupPanelRenderer = ( selectedGroup, @@ -57,13 +58,25 @@ RuleNameGroupContent.displayName = 'RuleNameGroup'; const InstanceIdGroupContent = React.memo<{ instanceId?: string; }>(({ instanceId }) => { + const isUngrouped = instanceId === '*'; return (
- {instanceId === '*' ? unknown : instanceId ?? '--'} + {isUngrouped ? ungrouped : instanceId ?? '--'} +   + {isUngrouped && ( + + } + /> + )}
From 2bba4c99d49f7271bbb9ce8e33bd350bf6c8be10 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 6 Aug 2024 10:50:01 +0000 Subject: [PATCH 03/14] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- .../plugins/observability_solution/observability/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/observability_solution/observability/tsconfig.json b/x-pack/plugins/observability_solution/observability/tsconfig.json index fa5e0a12edef8b..7861d686584773 100644 --- a/x-pack/plugins/observability_solution/observability/tsconfig.json +++ b/x-pack/plugins/observability_solution/observability/tsconfig.json @@ -112,6 +112,7 @@ "@kbn/core-ui-settings-server-mocks", "@kbn/grouping", "@kbn/alerts-grouping", + "@kbn/core-http-browser", ], "exclude": [ "target/**/*" From d26fe4eef2040a8124b967bdaa4cb94c22dcc4c9 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Wed, 7 Aug 2024 09:00:49 +0200 Subject: [PATCH 04/14] Update ungrouped message Co-authored-by: DeDe Morton --- .../public/pages/alerts/grouping/render_group_panel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx index 462e7322cff538..17e674eb0a44e5 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/render_group_panel.tsx @@ -72,7 +72,7 @@ const InstanceIdGroupContent = React.memo<{ content={ } /> From 48596ee24bded58aa4d47a8342792df1f76ab55c Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Wed, 7 Aug 2024 10:18:24 +0200 Subject: [PATCH 05/14] Register a separate alerts table for the alerts page with grouping --- .../get_alerts_page_table_configuration.tsx | 58 +++++++++++++++++++ .../register_alerts_table_configuration.tsx | 10 +++- 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/observability_solution/observability/public/components/alerts_table/observability/get_alerts_page_table_configuration.tsx diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/observability/get_alerts_page_table_configuration.tsx b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/observability/get_alerts_page_table_configuration.tsx new file mode 100644 index 00000000000000..9d761aa87f4cdc --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/observability/get_alerts_page_table_configuration.tsx @@ -0,0 +1,58 @@ +/* + * 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 { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { ALERT_START, AlertConsumers } from '@kbn/rule-data-utils'; +import { + AlertsTableConfigurationRegistry, + RenderCustomActionsRowArgs, +} from '@kbn/triggers-actions-ui-plugin/public/types'; +import { casesFeatureId, observabilityFeatureId } from '../../../../common'; +import { AlertActions } from '../../../pages/alerts/components/alert_actions'; +import { useGetAlertFlyoutComponents } from '../../alerts_flyout/use_get_alert_flyout_components'; +import type { ObservabilityRuleTypeRegistry } from '../../../rules/create_observability_rule_type_registry'; +import type { ConfigSchema } from '../../../plugin'; +import { getRenderCellValue } from '../common/render_cell_value'; +import { getColumns } from '../common/get_columns'; + +export const getObservabilityTableConfiguration = ( + observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry, + config: ConfigSchema +): AlertsTableConfigurationRegistry => { + const renderCustomActionsRow = (props: RenderCustomActionsRowArgs) => { + return ( + + ); + }; + return { + id: AlertConsumers.OBSERVABILITY, + cases: { featureId: casesFeatureId, owner: [observabilityFeatureId] }, + columns: getColumns({ showRuleName: true }), + getRenderCellValue, + sort: [ + { + [ALERT_START]: { + order: 'desc' as SortOrder, + }, + }, + ], + useActionsColumn: () => ({ + renderCustomActionsRow, + }), + useInternalFlyout: () => { + const { header, body, footer } = useGetAlertFlyoutComponents(observabilityRuleTypeRegistry); + return { header, body, footer }; + }, + ruleTypeIds: observabilityRuleTypeRegistry.list(), + showInspectButton: true, + }; +}; diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/register_alerts_table_configuration.tsx b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/register_alerts_table_configuration.tsx index 4ed421e37defe6..de687c4dd7944c 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/register_alerts_table_configuration.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/register_alerts_table_configuration.tsx @@ -14,6 +14,7 @@ import { ObservabilityRuleTypeRegistry } from '../..'; import { getAlertsPageTableConfiguration } from './alerts/get_alerts_page_table_configuration'; import { getRuleDetailsTableConfiguration } from './rule_details/get_rule_details_table_configuration'; import { getSloAlertsTableConfiguration } from './slo/get_slo_alerts_table_configuration'; +import { getObservabilityTableConfiguration } from './observability/get_alerts_page_table_configuration'; export const registerAlertsTableConfiguration = ( alertTableConfigRegistry: AlertTableConfigRegistry, @@ -23,7 +24,14 @@ export const registerAlertsTableConfiguration = ( http: HttpSetup, notifications: NotificationsStart ) => { - // Alert page + // Observability table + const observabilityAlertsTableConfig = getObservabilityTableConfiguration( + observabilityRuleTypeRegistry, + config + ); + alertTableConfigRegistry.register(observabilityAlertsTableConfig); + + // Alerts page const alertsPageAlertsTableConfig = getAlertsPageTableConfiguration( observabilityRuleTypeRegistry, config, From 288ce39aff74971821c3bf13957cf5b4bdc931d8 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Fri, 9 Aug 2024 17:15:35 +0200 Subject: [PATCH 06/14] Fix import --- .../components/alerts_table/alerts/get_peristent_controls.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts index 648e3ed387f8c5..8986f1fb693523 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts @@ -7,7 +7,7 @@ import { useMemo, useCallback } from 'react'; import { type AlertsGroupingProps, useAlertsGroupingState } from '@kbn/alerts-grouping'; -import { useAlertDataView } from '@kbn/alerts-ui-shared'; +import { useAlertsDataView } from '@kbn/alerts-ui-shared/src/common/hooks/use_alerts_data_view'; import { useGetGroupSelectorStateless } from '@kbn/grouping/src/hooks/use_get_group_selector'; import { AlertConsumers } from '@kbn/rule-data-utils'; import { AlertsByGroupingAgg } from '../types'; @@ -41,7 +41,7 @@ export const getPersistentControlsHook = [grouping, updateGrouping] ); - const { dataViews: alertDataViews } = useAlertDataView({ + const { dataViews: alertDataViews } = useAlertsDataView({ featureIds, dataViewsService: dataViews, http, From f19cf455cfa7c8d47d08709e1a5e615ffc44342d Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Mon, 12 Aug 2024 14:20:54 +0200 Subject: [PATCH 07/14] Fix using data view --- .../alerts/get_alerts_page_table_configuration.tsx | 2 +- ...et_peristent_controls.ts => get_persistent_controls.ts} | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) rename x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/{get_peristent_controls.ts => get_persistent_controls.ts} (88%) diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx index 9a0c478b0383cc..30c912b5107436 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_alerts_page_table_configuration.tsx @@ -27,7 +27,7 @@ import { ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID } from '../../../constants'; import type { ConfigSchema } from '../../../plugin'; import { getRenderCellValue } from '../common/render_cell_value'; import { getColumns } from '../common/get_columns'; -import { getPersistentControlsHook } from './get_peristent_controls'; +import { getPersistentControlsHook } from './get_persistent_controls'; export const getAlertsPageTableConfiguration = ( observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry, diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts similarity index 88% rename from x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts rename to x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts index 8986f1fb693523..2fbc2df3d104d4 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_peristent_controls.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts @@ -35,21 +35,20 @@ export const getPersistentControlsHook = const onGroupChange = useCallback( (selectedGroups: string[]) => { updateGrouping({ - activeGroups: grouping.activeGroups.filter((g) => g !== 'none').concat(selectedGroups), + activeGroups: + grouping.activeGroups?.filter((g) => g !== 'none').concat(selectedGroups) ?? [], }); }, [grouping, updateGrouping] ); - const { dataViews: alertDataViews } = useAlertsDataView({ + const { dataView } = useAlertsDataView({ featureIds, dataViewsService: dataViews, http, toasts: notifications.toasts, }); - const dataView = useMemo(() => alertDataViews?.[0], [alertDataViews]); - const groupSelector = useGetGroupSelectorStateless({ groupingId, onGroupChange, From 38ab838c66a808f22b369bcd91a2f54a26568a20 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Tue, 13 Aug 2024 17:02:10 +0200 Subject: [PATCH 08/14] Fix applying alert status filter --- .../observability/common/typings.ts | 2 + .../components/alert_search_bar/constants.ts | 37 +++++++++++++++++++ .../public/pages/alerts/alerts.tsx | 5 ++- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/observability/common/typings.ts b/x-pack/plugins/observability_solution/observability/common/typings.ts index bfdcd6d5209dc0..03981f5941dc24 100644 --- a/x-pack/plugins/observability_solution/observability/common/typings.ts +++ b/x-pack/plugins/observability_solution/observability/common/typings.ts @@ -11,6 +11,7 @@ import { ALERT_STATUS_RECOVERED, ALERT_STATUS_UNTRACKED, } from '@kbn/rule-data-utils'; +import { Filter } from '@kbn/es-query'; import { ALERT_STATUS_ALL } from './constants'; export type Maybe = T | null | undefined; @@ -39,6 +40,7 @@ export type AlertStatus = export interface AlertStatusFilter { status: AlertStatus; query: string; + filter: Filter[]; label: string; } diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/constants.ts b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/constants.ts index 85ea6464d5ac0e..dc6af6316c41c0 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/constants.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/constants.ts @@ -22,6 +22,7 @@ export const DEFAULT_QUERY_STRING = ''; export const ALL_ALERTS: AlertStatusFilter = { status: ALERT_STATUS_ALL, query: '', + filter: [], label: i18n.translate('xpack.observability.alerts.alertStatusFilter.showAll', { defaultMessage: 'Show all', }), @@ -30,6 +31,16 @@ export const ALL_ALERTS: AlertStatusFilter = { export const ACTIVE_ALERTS: AlertStatusFilter = { status: ALERT_STATUS_ACTIVE, query: `${ALERT_STATUS}: "${ALERT_STATUS_ACTIVE}"`, + filter: [ + { + query: { + match_phrase: { + [ALERT_STATUS]: ALERT_STATUS_ACTIVE, + }, + }, + meta: {}, + }, + ], label: i18n.translate('xpack.observability.alerts.alertStatusFilter.active', { defaultMessage: 'Active', }), @@ -38,6 +49,16 @@ export const ACTIVE_ALERTS: AlertStatusFilter = { export const RECOVERED_ALERTS: AlertStatusFilter = { status: ALERT_STATUS_RECOVERED, query: `${ALERT_STATUS}: "${ALERT_STATUS_RECOVERED}"`, + filter: [ + { + query: { + match_phrase: { + [ALERT_STATUS]: ALERT_STATUS_RECOVERED, + }, + }, + meta: {}, + }, + ], label: i18n.translate('xpack.observability.alerts.alertStatusFilter.recovered', { defaultMessage: 'Recovered', }), @@ -46,6 +67,16 @@ export const RECOVERED_ALERTS: AlertStatusFilter = { export const UNTRACKED_ALERTS: AlertStatusFilter = { status: ALERT_STATUS_UNTRACKED, query: `${ALERT_STATUS}: "${ALERT_STATUS_UNTRACKED}"`, + filter: [ + { + query: { + match_phrase: { + [ALERT_STATUS]: ALERT_STATUS_UNTRACKED, + }, + }, + meta: {}, + }, + ], label: i18n.translate('xpack.observability.alerts.alertStatusFilter.untracked', { defaultMessage: 'Untracked', }), @@ -56,3 +87,9 @@ export const ALERT_STATUS_QUERY = { [RECOVERED_ALERTS.status]: RECOVERED_ALERTS.query, [UNTRACKED_ALERTS.status]: UNTRACKED_ALERTS.query, }; + +export const ALERT_STATUS_FILTER = { + [ACTIVE_ALERTS.status]: ACTIVE_ALERTS.filter, + [RECOVERED_ALERTS.status]: RECOVERED_ALERTS.filter, + [UNTRACKED_ALERTS.status]: UNTRACKED_ALERTS.filter, +}; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx index 860973b15387e0..0f604bca02944f 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx @@ -14,10 +14,11 @@ import { loadRuleAggregations } from '@kbn/triggers-actions-ui-plugin/public'; import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public'; import { MaintenanceWindowCallout } from '@kbn/alerts-ui-shared'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; - import { AlertsGrouping } from '@kbn/alerts-grouping'; + import { renderGroupPanel } from './grouping/render_group_panel'; import { rulesLocatorID } from '../../../common'; +import { ALERT_STATUS_FILTER } from '../../components/alert_search_bar/constants'; import { AlertsByGroupingAgg } from '../../components/alerts_table/types'; import { ObservabilityAlertSearchBar } from '../../components/alert_search_bar/alert_search_bar'; import { useGetFilteredRuleTypes } from '../../hooks/use_get_filtered_rule_types'; @@ -254,7 +255,7 @@ function InternalAlertsPage() { {esQuery && ( featureIds={observabilityAlertFeatureIds} - defaultFilters={[]} + defaultFilters={ALERT_STATUS_FILTER[alertSearchBarStateProps.status] ?? []} from={alertSearchBarStateProps.rangeFrom} to={alertSearchBarStateProps.rangeTo} globalFilters={alertSearchBarStateProps.filters} From a4d5dd0570bbb063d85d99888c6ad8d9cca0d3cf Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Tue, 20 Aug 2024 18:25:57 +0200 Subject: [PATCH 09/14] Fix KQL kuery and translation --- packages/kbn-alerts-grouping/src/types.ts | 2 +- .../alerts_table/alerts/get_persistent_controls.ts | 2 +- .../observability/public/pages/alerts/alerts.tsx | 2 +- x-pack/plugins/translations/translations/fr-FR.json | 12 +++++------- x-pack/plugins/translations/translations/ja-JP.json | 12 +++++------- x-pack/plugins/translations/translations/zh-CN.json | 12 +++++------- 6 files changed, 18 insertions(+), 24 deletions(-) diff --git a/packages/kbn-alerts-grouping/src/types.ts b/packages/kbn-alerts-grouping/src/types.ts index 835941e8db95d5..24239364bb6c2e 100644 --- a/packages/kbn-alerts-grouping/src/types.ts +++ b/packages/kbn-alerts-grouping/src/types.ts @@ -22,7 +22,7 @@ import { ReactElement } from 'react'; export interface GroupModel { activeGroups: string[]; - options: Array<{ key: string; label: string }>; + options?: Array<{ key: string; label: string }>; } export interface AlertsGroupingState { diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts index 2fbc2df3d104d4..e17b963422b901 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts @@ -53,7 +53,7 @@ export const getPersistentControlsHook = groupingId, onGroupChange, fields: dataView?.fields ?? [], - defaultGroupingOptions: grouping.options.filter( + defaultGroupingOptions: grouping.options?.filter( (option) => !grouping.activeGroups.includes(option.key) ), maxGroupingLevels, diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx index 0f604bca02944f..c1d14165f5f6e4 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/alerts.tsx @@ -259,7 +259,7 @@ function InternalAlertsPage() { from={alertSearchBarStateProps.rangeFrom} to={alertSearchBarStateProps.rangeTo} globalFilters={alertSearchBarStateProps.filters} - globalQuery={{ query: alertSearchBarStateProps.kuery, language: 'kql' }} + globalQuery={{ query: alertSearchBarStateProps.kuery, language: 'kuery' }} groupingId={ALERTS_PAGE_ALERTS_TABLE_CONFIG_ID} defaultGroupingOptions={DEFAULT_GROUPING_OPTIONS} getAggregationsByGroupingField={getAggregationsByGroupingField} diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 43b621fff0144e..d663462c0ce66d 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -11131,8 +11131,8 @@ "xpack.apm.serviceIcons.service": "Service", "xpack.apm.serviceIcons.serviceDetails.cloud.architecture": "Architecture", "xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, =0 {Zone de disponibilité} one {Zone de disponibilité} other {Zones de disponibilité}} ", - "xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, =0 {Nom de fonction} one {Nom de fonction} other {Noms de fonction}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, =0 {Type de déclencheur} one {Type de déclencheur} other {Types de déclencheurs}} ", + "xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, =0 {Nom de fonction} one {Nom de fonction} other {Noms de fonction}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, =0{Type de machine} one {Type de machine} other {Types de machines}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "ID de projet", "xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "Fournisseur cloud", @@ -27088,8 +27088,8 @@ "xpack.maps.source.esSearch.descendingLabel": "décroissant", "xpack.maps.source.esSearch.extentFilterLabel": "Filtre dynamique pour les données de la zone de carte visible", "xpack.maps.source.esSearch.fieldNotFoundMsg": "Impossible de trouver \"{fieldName}\" dans le modèle d'indexation \"{indexPatternName}\".", - "xpack.maps.source.esSearch.geoFieldLabel": "Champ géospatial", "xpack.maps.source.esSearch.geofieldLabel": "Champ géospatial", + "xpack.maps.source.esSearch.geoFieldLabel": "Champ géospatial", "xpack.maps.source.esSearch.geoFieldTypeLabel": "Type de champ géospatial", "xpack.maps.source.esSearch.indexOverOneLengthEditError": "Votre vue de données pointe vers plusieurs index. Un seul index est autorisé par vue de données.", "xpack.maps.source.esSearch.indexZeroLengthEditError": "Votre vue de données ne pointe vers aucun index.", @@ -32452,8 +32452,6 @@ "xpack.observability.alertDetailContextualInsights.InsightButtonLabel": "Aidez moi à comprendre cette alerte", "xpack.observability.alertDetails.actionsButtonLabel": "Actions", "xpack.observability.alertDetails.addToCase": "Ajouter au cas", - "xpack.observability.alertDetails.alertSummaryField.moreTags": "+{number} de plus", - "xpack.observability.alertDetails.alertSummaryField.moreTags.ariaLabel": "badge plus de balises", "xpack.observability.alertDetails.alertSummaryField.rule": "Règle", "xpack.observability.alertDetails.alertSummaryField.source": "Source", "xpack.observability.alertDetails.alertSummaryField.tags": "Balises", @@ -36554,8 +36552,8 @@ "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "Kibana ne permet qu'un maximum de {maxNumber} {maxNumber, plural, =1 {alerte} other {alertes}} par exécution de règle.", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "Nom obligatoire.", "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "Ajouter un guide d'investigation sur les règles...", - "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "Fournissez des instructions sur les conditions préalables à la règle, telles que les intégrations requises, les étapes de configuration et tout ce qui est nécessaire au bon fonctionnement de la règle.", "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "Ajouter le guide de configuration de règle...", + "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "Fournissez des instructions sur les conditions préalables à la règle, telles que les intégrations requises, les étapes de configuration et tout ce qui est nécessaire au bon fonctionnement de la règle.", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "Guide de configuration", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "Une balise ne doit pas être vide", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError": "Le remplacement du préfixe d'indicateur ne peut pas être vide.", @@ -42193,8 +42191,8 @@ "xpack.slo.sloEmbeddable.config.sloSelector.placeholder": "Sélectionner un SLO", "xpack.slo.sloEmbeddable.displayName": "Aperçu du SLO", "xpack.slo.sloEmbeddable.overview.sloNotFoundText": "Le SLO a été supprimé. Vous pouvez supprimer sans risque le widget du tableau de bord.", - "xpack.slo.sLOGridItem.targetFlexItemLabel": "Cible {target}", "xpack.slo.sloGridItem.targetFlexItemLabel": "Cible {target}", + "xpack.slo.sLOGridItem.targetFlexItemLabel": "Cible {target}", "xpack.slo.sloGroupConfiguration.customFiltersLabel": "Personnaliser le filtre", "xpack.slo.sloGroupConfiguration.customFiltersOptional": "Facultatif", "xpack.slo.sloGroupConfiguration.customFilterText": "Personnaliser le filtre", @@ -43640,8 +43638,8 @@ "xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webhook - Données de gestion des cas", "xpack.stackConnectors.components.d3security.bodyCodeEditorAriaLabel": "Éditeur de code", "xpack.stackConnectors.components.d3security.bodyFieldLabel": "Corps", - "xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3 Security", "xpack.stackConnectors.components.d3security.connectorTypeTitle": "Données D3", + "xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3 Security", "xpack.stackConnectors.components.d3security.eventTypeFieldLabel": "Type d'événement", "xpack.stackConnectors.components.d3security.invalidActionText": "Nom d'action non valide.", "xpack.stackConnectors.components.d3security.requiredActionText": "L'action est requise.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 05a2e7a22a01c5..473717e01a6329 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -11120,8 +11120,8 @@ "xpack.apm.serviceIcons.service": "サービス", "xpack.apm.serviceIcons.serviceDetails.cloud.architecture": "アーキテクチャー", "xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, other {可用性ゾーン}} ", - "xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, other {関数名}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {トリガータイプ}} ", + "xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, other {関数名}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, other {コンピュータータイプ} }\n ", "xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "プロジェクト ID", "xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "クラウドプロバイダー", @@ -27076,8 +27076,8 @@ "xpack.maps.source.esSearch.descendingLabel": "降順", "xpack.maps.source.esSearch.extentFilterLabel": "マップの表示範囲でデータを動的にフィルタリング", "xpack.maps.source.esSearch.fieldNotFoundMsg": "インデックスパターン''{indexPatternName}''に''{fieldName}''が見つかりません。", - "xpack.maps.source.esSearch.geoFieldLabel": "地理空間フィールド", "xpack.maps.source.esSearch.geofieldLabel": "地理空間フィールド", + "xpack.maps.source.esSearch.geoFieldLabel": "地理空間フィールド", "xpack.maps.source.esSearch.geoFieldTypeLabel": "地理空間フィールドタイプ", "xpack.maps.source.esSearch.indexOverOneLengthEditError": "データビューは複数のインデックスを参照しています。データビューごとに1つのインデックスのみが許可されています。", "xpack.maps.source.esSearch.indexZeroLengthEditError": "データビューはどのインデックスも参照していません。", @@ -32436,8 +32436,6 @@ "xpack.observability.alertDetailContextualInsights.InsightButtonLabel": "このアラートを理解できるように支援してください", "xpack.observability.alertDetails.actionsButtonLabel": "アクション", "xpack.observability.alertDetails.addToCase": "ケースに追加", - "xpack.observability.alertDetails.alertSummaryField.moreTags": "その他{number}", - "xpack.observability.alertDetails.alertSummaryField.moreTags.ariaLabel": "その他のタグバッジ", "xpack.observability.alertDetails.alertSummaryField.rule": "ルール", "xpack.observability.alertDetails.alertSummaryField.source": "送信元", "xpack.observability.alertDetails.alertSummaryField.tags": "タグ", @@ -36537,8 +36535,8 @@ "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "Kibanaで許可される最大数は、1回の実行につき、{maxNumber} {maxNumber, plural, other {アラート}}です。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "名前が必要です。", "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "ルール調査ガイドを追加...", - "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "必要な統合、構成ステップ、ルールが正常に動作するために必要な他のすべての項目といった、ルール前提条件に関する指示を入力します。", "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "ルールセットアップガイドを追加...", + "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "必要な統合、構成ステップ、ルールが正常に動作するために必要な他のすべての項目といった、ルール前提条件に関する指示を入力します。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "セットアップガイド", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "タグを空にすることはできません", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError": "インジケータープレフィックスの無効化を空にすることはできません", @@ -42176,8 +42174,8 @@ "xpack.slo.sloEmbeddable.config.sloSelector.placeholder": "SLOを選択", "xpack.slo.sloEmbeddable.displayName": "SLO概要", "xpack.slo.sloEmbeddable.overview.sloNotFoundText": "SLOが削除されました。ウィジェットをダッシュボードから安全に削除できます。", - "xpack.slo.sLOGridItem.targetFlexItemLabel": "目標{target}", "xpack.slo.sloGridItem.targetFlexItemLabel": "目標{target}", + "xpack.slo.sLOGridItem.targetFlexItemLabel": "目標{target}", "xpack.slo.sloGroupConfiguration.customFiltersLabel": "カスタムフィルター", "xpack.slo.sloGroupConfiguration.customFiltersOptional": "オプション", "xpack.slo.sloGroupConfiguration.customFilterText": "カスタムフィルター", @@ -43619,8 +43617,8 @@ "xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webフック - ケース管理データ", "xpack.stackConnectors.components.d3security.bodyCodeEditorAriaLabel": "コードエディター", "xpack.stackConnectors.components.d3security.bodyFieldLabel": "本文", - "xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3セキュリティ", "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3データ", + "xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3セキュリティ", "xpack.stackConnectors.components.d3security.eventTypeFieldLabel": "イベントタイプ", "xpack.stackConnectors.components.d3security.invalidActionText": "無効なアクション名です。", "xpack.stackConnectors.components.d3security.requiredActionText": "アクションが必要です。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index ab9ce8edafe35a..278e2cb469880d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -11139,8 +11139,8 @@ "xpack.apm.serviceIcons.service": "服务", "xpack.apm.serviceIcons.serviceDetails.cloud.architecture": "架构", "xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, other {可用性区域}} ", - "xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, other {功能名称}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {触发类型}} ", + "xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, other {功能名称}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, other {机器类型}} ", "xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "项目 ID", "xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "云服务提供商", @@ -27108,8 +27108,8 @@ "xpack.maps.source.esSearch.descendingLabel": "降序", "xpack.maps.source.esSearch.extentFilterLabel": "在可见地图区域中动态筛留数据", "xpack.maps.source.esSearch.fieldNotFoundMsg": "在索引模式“{indexPatternName}”中找不到“{fieldName}”。", - "xpack.maps.source.esSearch.geoFieldLabel": "地理空间字段", "xpack.maps.source.esSearch.geofieldLabel": "地理空间字段", + "xpack.maps.source.esSearch.geoFieldLabel": "地理空间字段", "xpack.maps.source.esSearch.geoFieldTypeLabel": "地理空间字段类型", "xpack.maps.source.esSearch.indexOverOneLengthEditError": "您的数据视图指向多个索引。每个数据视图只允许一个索引。", "xpack.maps.source.esSearch.indexZeroLengthEditError": "您的数据视图未指向任何索引。", @@ -32476,8 +32476,6 @@ "xpack.observability.alertDetailContextualInsights.InsightButtonLabel": "帮助我了解此告警", "xpack.observability.alertDetails.actionsButtonLabel": "操作", "xpack.observability.alertDetails.addToCase": "添加到案例", - "xpack.observability.alertDetails.alertSummaryField.moreTags": "+ 另外 {number} 个", - "xpack.observability.alertDetails.alertSummaryField.moreTags.ariaLabel": "更多标签徽章", "xpack.observability.alertDetails.alertSummaryField.rule": "规则", "xpack.observability.alertDetails.alertSummaryField.source": "源", "xpack.observability.alertDetails.alertSummaryField.tags": "标签", @@ -36579,8 +36577,8 @@ "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "每次规则运行时,Kibana 最多只允许 {maxNumber} 个{maxNumber, plural, other {告警}}。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "名称必填。", "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "添加规则调查指南......", - "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "提供有关规则先决条件的说明,如所需集成、配置步骤,以及规则正常运行所需的任何其他内容。", "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "添加规则设置指南......", + "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "提供有关规则先决条件的说明,如所需集成、配置步骤,以及规则正常运行所需的任何其他内容。", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "设置指南", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "标签不得为空", "xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError": "指标前缀覆盖不得为空", @@ -42220,8 +42218,8 @@ "xpack.slo.sloEmbeddable.config.sloSelector.placeholder": "选择 SLO", "xpack.slo.sloEmbeddable.displayName": "SLO 概览", "xpack.slo.sloEmbeddable.overview.sloNotFoundText": "SLO 已删除。您可以放心从仪表板中删除小组件。", - "xpack.slo.sLOGridItem.targetFlexItemLabel": "目标 {target}", "xpack.slo.sloGridItem.targetFlexItemLabel": "目标 {target}", + "xpack.slo.sLOGridItem.targetFlexItemLabel": "目标 {target}", "xpack.slo.sloGroupConfiguration.customFiltersLabel": "定制筛选", "xpack.slo.sloGroupConfiguration.customFiltersOptional": "可选", "xpack.slo.sloGroupConfiguration.customFilterText": "定制筛选", @@ -43667,8 +43665,8 @@ "xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webhook - 案例管理数据", "xpack.stackConnectors.components.d3security.bodyCodeEditorAriaLabel": "代码编辑器", "xpack.stackConnectors.components.d3security.bodyFieldLabel": "正文", - "xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3 Security", "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3 数据", + "xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3 Security", "xpack.stackConnectors.components.d3security.eventTypeFieldLabel": "事件类型", "xpack.stackConnectors.components.d3security.invalidActionText": "操作名称无效。", "xpack.stackConnectors.components.d3security.requiredActionText": "“操作”必填。", From a13dccfab4ef4e7747d2c48d4c4c84cc52ffa5c9 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Wed, 21 Aug 2024 11:02:08 +0200 Subject: [PATCH 10/14] Fix timestamp and type --- .../src/components/alerts_grouping_level.tsx | 3 ++- .../src/contexts/alerts_grouping_context.tsx | 1 - .../alerts_table/alerts/get_persistent_controls.ts | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx b/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx index a82818215cbf4d..c0ebf0e6fa2342 100644 --- a/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx +++ b/packages/kbn-alerts-grouping/src/components/alerts_grouping_level.tsx @@ -14,6 +14,7 @@ import { type GroupingAggregation } from '@kbn/grouping'; import { isNoneGroup } from '@kbn/grouping'; import type { DynamicGroupingProps } from '@kbn/grouping/src'; import { parseGroupingQuery } from '@kbn/grouping/src'; +import { ALERT_TIME_RANGE } from '@kbn/rule-data-utils'; import { useGetAlertsGroupAggregationsQuery, UseGetAlertsGroupAggregationsQueryProps, @@ -94,7 +95,7 @@ export const AlertsGroupingLevel = typedMemo( ...filters, { range: { - '@timestamp': { + [ALERT_TIME_RANGE]: { gte: from, lte: to, }, diff --git a/packages/kbn-alerts-grouping/src/contexts/alerts_grouping_context.tsx b/packages/kbn-alerts-grouping/src/contexts/alerts_grouping_context.tsx index cc5e06e652cd46..2d1315e3ece6d4 100644 --- a/packages/kbn-alerts-grouping/src/contexts/alerts_grouping_context.tsx +++ b/packages/kbn-alerts-grouping/src/contexts/alerts_grouping_context.tsx @@ -54,7 +54,6 @@ export const useAlertsGroupingState = (groupingId: string) => { setGroupingState((prevState) => ({ ...prevState, [groupingId]: { - // @ts-expect-error options might not be defined options: [], // @ts-expect-error activeGroups might not be defined activeGroups: initialActiveGroups, diff --git a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts index e17b963422b901..2141e0fb68d66b 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/alerts_table/alerts/get_persistent_controls.ts @@ -53,9 +53,8 @@ export const getPersistentControlsHook = groupingId, onGroupChange, fields: dataView?.fields ?? [], - defaultGroupingOptions: grouping.options?.filter( - (option) => !grouping.activeGroups.includes(option.key) - ), + defaultGroupingOptions: + grouping.options?.filter((option) => !grouping.activeGroups.includes(option.key)) ?? [], maxGroupingLevels, }); From d83aecb5f13fa0b1cc1d3311ceb0ff0f4f7d092d Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Wed, 21 Aug 2024 12:54:17 +0200 Subject: [PATCH 11/14] Fix test --- .../kbn-alerts-grouping/src/components/alerts_grouping.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx b/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx index 87517def778cd9..47e2d5c1b40821 100644 --- a/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx +++ b/packages/kbn-alerts-grouping/src/components/alerts_grouping.test.tsx @@ -158,7 +158,7 @@ describe('AlertsGrouping', () => { }, { range: { - '@timestamp': { + 'kibana.alert.time_range': { gte: mockDate.from, lte: mockDate.to, }, From d06e0d96fbdfc32afaf0a00ba41b9e762df4f49b Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Wed, 21 Aug 2024 15:01:31 +0200 Subject: [PATCH 12/14] Fix mismatch in number of alerts without the mapping for the grouped field --- .../get_aggregations_by_grouping_field.ts | 74 ++++++++----------- .../pages/alerts/grouping/get_group_stats.tsx | 2 +- .../server/alert_data_client/alerts_client.ts | 2 +- 3 files changed, 31 insertions(+), 47 deletions(-) diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_aggregations_by_grouping_field.ts b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_aggregations_by_grouping_field.ts index 7762d06468bd4e..e4c8b27225ea54 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_aggregations_by_grouping_field.ts +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_aggregations_by_grouping_field.ts @@ -5,65 +5,49 @@ * 2.0. */ -import { - ALERT_INSTANCE_ID, - ALERT_RULE_NAME, - ALERT_RULE_UUID, - ALERT_UUID, -} from '@kbn/rule-data-utils'; +import { NamedAggregation } from '@kbn/grouping'; +import { ALERT_INSTANCE_ID, ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; -export const getAggregationsByGroupingField = (field: string): any[] => { - const aggMetrics: any[] = [ - { - unitsCount: { - cardinality: { - field: ALERT_UUID, - }, - }, - }, - ]; +export const getAggregationsByGroupingField = (field: string): NamedAggregation[] => { switch (field) { case ALERT_RULE_NAME: - aggMetrics.push( - ...[ - { - sourceCountAggregation: { - cardinality: { - field: ALERT_INSTANCE_ID, - }, + return [ + { + sourceCountAggregation: { + cardinality: { + field: ALERT_INSTANCE_ID, }, }, - { - ruleTags: { - terms: { - field: 'tags', - }, + }, + { + ruleTags: { + terms: { + field: 'tags', }, }, - ] - ); + }, + ]; break; case ALERT_INSTANCE_ID: - aggMetrics.push( - ...[ - { - rulesCountAggregation: { - cardinality: { - field: ALERT_RULE_UUID, - }, + return [ + { + rulesCountAggregation: { + cardinality: { + field: ALERT_RULE_UUID, }, }, - ] - ); + }, + ]; break; default: - aggMetrics.push({ - rulesCountAggregation: { - cardinality: { - field: ALERT_RULE_UUID, + return [ + { + rulesCountAggregation: { + cardinality: { + field: ALERT_RULE_UUID, + }, }, }, - }); + ]; } - return aggMetrics; }; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx index 4dac663ba17d06..cd54860dad12c1 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx @@ -16,7 +16,7 @@ export const getGroupStats: GetGroupStats = (selectedGroup, badge: { value: bucket.doc_count, width: 50, - color: '#a83632', + color: 'primary', }, }, ]; diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 76a39737190ce1..8d61b2b4e5609e 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -1133,7 +1133,7 @@ export class AlertsClient { script: { source: // When size()==0, emits a uniqueValue as the value to represent this group else join by uniqueValue. - "if (doc[params['selectedGroup']].size()==0) { emit(params['uniqueValue']) }" + + "if (!doc.containsKey(params['selectedGroup']) || doc[params['selectedGroup']].size()==0) { emit(params['uniqueValue']) }" + // Else, join the values with uniqueValue. We cannot simply emit the value like doc[params['selectedGroup']].value, // the runtime field will only return the first value in an array. // The docs advise that if the field has multiple values, "Scripts can call the emit method multiple times to emit multiple values." From 4e354b2528adb5a0aa8acf1a8037f76cdc5df1c6 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Wed, 21 Aug 2024 15:41:17 +0200 Subject: [PATCH 13/14] Remove badge color --- .../public/pages/alerts/grouping/get_group_stats.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx index cd54860dad12c1..3bcc37c267d01e 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx @@ -16,7 +16,6 @@ export const getGroupStats: GetGroupStats = (selectedGroup, badge: { value: bucket.doc_count, width: 50, - color: 'primary', }, }, ]; From e8165da81a866d36edae06aad341009c618f1445 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Thu, 22 Aug 2024 09:56:19 +0200 Subject: [PATCH 14/14] fix test --- .../public/pages/alerts/grouping/get_group_stats.tsx | 3 +++ .../tests/get_alerts_group_aggregations.test.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx index 3bcc37c267d01e..3fe0a6d0068258 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/grouping/get_group_stats.tsx @@ -27,6 +27,7 @@ export const getGroupStats: GetGroupStats = (selectedGroup, title: 'Sources:', badge: { value: bucket.sourceCountAggregation?.value ?? 0, + width: 50, }, }, ...defaultBadges, @@ -37,6 +38,7 @@ export const getGroupStats: GetGroupStats = (selectedGroup, title: 'Rules:', badge: { value: bucket.rulesCountAggregation?.value ?? 0, + width: 50, }, }, ...defaultBadges, @@ -47,6 +49,7 @@ export const getGroupStats: GetGroupStats = (selectedGroup, title: 'Rules:', badge: { value: bucket.rulesCountAggregation?.value ?? 0, + width: 50, }, }, ...defaultBadges, diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts index af10edf3723838..c351de1283c2b0 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/tests/get_alerts_group_aggregations.test.ts @@ -127,7 +127,7 @@ describe('getGroupAggregations()', () => { type: 'keyword', script: { source: - "if (doc[params['selectedGroup']].size()==0) { emit(params['uniqueValue']) }" + + "if (!doc.containsKey(params['selectedGroup']) || doc[params['selectedGroup']].size()==0) { emit(params['uniqueValue']) }" + " else { emit(doc[params['selectedGroup']].join(params['uniqueValue']))}", params: { selectedGroup: groupByField,