Skip to content

Commit

Permalink
Improve global alerts page composition and filtering, move to correct…
Browse files Browse the repository at this point in the history
… menu
  • Loading branch information
umbopepato committed Jan 22, 2024
1 parent 5ca182e commit bc455f8
Show file tree
Hide file tree
Showing 20 changed files with 639 additions and 608 deletions.
1 change: 0 additions & 1 deletion x-pack/plugins/triggers_actions_ui/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,3 @@ export const BASE_TRIGGERS_ACTIONS_UI_API_PATH = '/internal/triggers_actions_ui'
export * from './parse_interval';
export * from './experimental_features';
export * from './normalized_field_types';
export * from './alert_config';
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { i18n } from '@kbn/i18n';
import { noop } from 'lodash';
import { ALERT_TABLE_GENERIC_CONFIG_ID } from '../../common/alert_config';
import { ALERT_TABLE_GENERIC_CONFIG_ID } from './constants';
import {
AlertsTableConfigurationRegistry,
AlertsTableConfigurationRegistryWithActions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,60 +7,20 @@

import React, { lazy } from 'react';
import { Router, Routes, Route } from '@kbn/shared-ux-router';
import { ChromeBreadcrumb, CoreStart, CoreTheme, ScopedHistory } from '@kbn/core/public';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nProvider } from '@kbn/i18n-react';
import useObservable from 'react-use/lib/useObservable';
import { Observable } from 'rxjs';
import { KibanaFeature } from '@kbn/features-plugin/common';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import { PluginStartContract as AlertingStart } from '@kbn/alerting-plugin/public';
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';

import { Storage } from '@kbn/kibana-utils-plugin/public';
import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
import { ActionsPublicPluginSetup } from '@kbn/actions-plugin/public';
import { DashboardStart } from '@kbn/dashboard-plugin/public';
import { suspendedComponentWithProps } from './lib/suspended_component_with_props';
import {
ActionTypeRegistryContract,
AlertsTableConfigurationRegistryContract,
RuleTypeRegistryContract,
} from '../types';

import { setDataViewsService } from '../common/lib/data_apis';
import { KibanaContextProvider } from '../common/lib/kibana';
import type { TriggersAndActionsUiServices } from './app';

const GlobalAlerts = lazy(() => import('./sections/global_alerts'));
const GlobalAlertsPage = lazy(() => import('./sections/global_alerts_page'));

export interface TriggersAndActionsUiServices extends CoreStart {
actions: ActionsPublicPluginSetup;
data: DataPublicPluginStart;
dataViews: DataViewsPublicPluginStart;
dataViewEditor: DataViewEditorStart;
dashboard: DashboardStart;
charts: ChartsPluginStart;
alerting?: AlertingStart;
spaces?: SpacesPluginStart;
storage?: Storage;
isCloud: boolean;
setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void;
actionTypeRegistry: ActionTypeRegistryContract;
ruleTypeRegistry: RuleTypeRegistryContract;
alertsTableConfigurationRegistry: AlertsTableConfigurationRegistryContract;
history: ScopedHistory;
kibanaFeatures: KibanaFeature[];
element: HTMLElement;
theme$: Observable<CoreTheme>;
unifiedSearch: UnifiedSearchPublicPluginStart;
}

export const renderApp = (deps: Partial<TriggersAndActionsUiServices>) => {
export const renderApp = (deps: TriggersAndActionsUiServices) => {
const { element } = deps;
render(<App deps={deps} />, element);
return () => {
Expand All @@ -69,8 +29,8 @@ export const renderApp = (deps: Partial<TriggersAndActionsUiServices>) => {
};

export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => {
const { dataViews, uiSettings, theme$ } = deps;
const isDarkMode = useObservable<boolean>(uiSettings.get$('theme:darkMode'));
const { dataViews, theme, theme$ } = deps;
const isDarkMode = theme.getTheme().darkMode;

setDataViewsService(dataViews);
return (
Expand All @@ -80,7 +40,7 @@ export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => {
<KibanaContextProvider services={{ ...deps }}>
<Router history={deps.history}>
<Routes>
<Route path={`/`} component={suspendedComponentWithProps(GlobalAlerts, 'xl')} />
<Route path={`/`} component={suspendedComponentWithProps(GlobalAlertsPage, 'xl')} />
</Routes>
</Router>
</KibanaContextProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ export const AppWithoutRouter = ({ sectionsRegex }: { sectionsRegex: string }) =
/>

<Redirect from={'/'} to="rules" />
<Redirect from={'/alerts'} to="rules" />
</Routes>
</ConnectorProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ES_QUERY_ID,
OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
ML_ANOMALY_DETECTION_RULE_TYPE_ID,
AlertConsumers,
} from '@kbn/rule-data-utils';
export {
BASE_ALERTING_API_PATH,
Expand All @@ -23,8 +24,7 @@ export const routeToHome = `/`;
export const routeToConnectors = `/connectors`;
export const routeToRules = `/rules`;
export const routeToLogs = `/logs`;
export const routeToInternalAlerts = `/alerts`;
export const legacyRouteToRules = `/alerts`;
export const routeToAlerts = `/alerts`;
export const legacyRouteToRuleDetails = `/alert/:alertId`;

export const recoveredActionGroupMessage = i18n.translate(
Expand Down Expand Up @@ -129,3 +129,7 @@ export const MULTI_CONSUMER_RULE_TYPE_IDS = [
ES_QUERY_ID,
ML_ANOMALY_DETECTION_RULE_TYPE_ID,
];

export const ALERT_TABLE_GENERIC_CONFIG_ID = `${AlertConsumers.STACK_ALERTS}-generic-alerts-table`;

export const ALERT_TABLE_GLOBAL_CONFIG_ID = `${AlertConsumers.STACK_ALERTS}-global-alerts-table`;
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { EuiSpacer, EuiPageTemplate } from '@elastic/eui';

import { getIsExperimentalFeatureEnabled } from '../common/get_experimental_features';
import { Section, routeToRules, routeToInternalAlerts, routeToLogs } from './constants';
import { Section, routeToRules, routeToAlerts, routeToLogs } from './constants';
import { getAlertingSectionBreadcrumb } from './lib/breadcrumb';
import { getCurrentDocTitle } from './lib/doc_title';

Expand Down Expand Up @@ -144,7 +144,7 @@ export const TriggersActionsUIHome: React.FunctionComponent<RouteComponentProps<
{isInternalAlertsTableEnabled ? (
<Route
exact
path={routeToInternalAlerts}
path={routeToAlerts}
component={() => (
<EuiPageTemplate.Section grow={false} paddingSize="none">
{suspendedComponentWithProps(AlertsPage, 'xl')({})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
*/

import { i18n } from '@kbn/i18n';
import { routeToHome, routeToConnectors, routeToRules, routeToLogs } from '../constants';
import {
routeToHome,
routeToConnectors,
routeToRules,
routeToLogs,
routeToAlerts,
} from '../constants';

export const getAlertingSectionBreadcrumb = (
type: string,
Expand Down Expand Up @@ -47,6 +53,17 @@ export const getAlertingSectionBreadcrumb = (
}
: {}),
};
case 'alerts':
return {
text: i18n.translate('xpack.triggersActionsUI.alerts.breadcrumbTitle', {
defaultMessage: 'Alerts',
}),
...(returnHref
? {
href: `${routeToAlerts}`,
}
: {}),
};
default:
return {
text: i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export const getCurrentDocTitle = (page: string): string => {
defaultMessage: 'Rules',
});
break;
case 'alerts':
updatedTitle = i18n.translate('xpack.triggersActionsUI.alerts.breadcrumbTitle', {
defaultMessage: 'Alerts',
});
break;
default:
updatedTitle = i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', {
defaultMessage: 'Rules',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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_RULE_PRODUCER, AlertConsumers, DefaultAlertFieldName } from '@kbn/rule-data-utils';
import { FILTERS, PhraseFilter } from '@kbn/es-query';

/**
* Creates a match_phrase filter without an index pattern
*/
export const createMatchPhraseFilter = (field: DefaultAlertFieldName, value: unknown) =>
({
meta: {
field,
type: FILTERS.PHRASE,
key: field,
alias: null,
disabled: false,
index: undefined,
negate: false,
params: { query: value },
value: undefined,
},
query: {
match_phrase: {
[field]: value,
},
},
} as PhraseFilter);

/**
* Creates a match_phrase filter targeted to filtering alerts by producer
*/
export const createRuleProducerFilter = (producer: AlertConsumers) =>
createMatchPhraseFilter(ALERT_RULE_PRODUCER, producer);
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,24 @@
import React, { useCallback, useEffect } from 'react';
import { BoolQuery, FILTERS, PhraseFilter } from '@kbn/es-query';
import { ALERT_RULE_PRODUCER, AlertConsumers } from '@kbn/rule-data-utils';
import { buildEsQuery } from '../global_alerts';
import { useKibana } from '../../..';
import { useAlertSearchBarStateContainer } from './use_alert_search_bar_state_container';
import { ALERTS_URL_STORAGE_KEY, NON_SIEM_FEATURE_IDS } from './constants';
import { ALERTS_URL_STORAGE_KEY } from './constants';
import { AlertsSearchBarProps } from './types';
import AlertsSearchBar from './alerts_search_bar';
import { buildEsQuery } from '../global_alerts_page/global_alerts_page';

export type UrlSyncedAlertsSearchBarProps = Omit<
AlertsSearchBarProps,
'query' | 'rangeFrom' | 'rangeTo' | 'filters' | 'onQuerySubmit'
> & {
onEsQueryChange: (esQuery: { bool: BoolQuery }) => void;
onFeatureIdsChange: (featureIds: AlertConsumers[]) => void;
onFilteringBySolutionChange?: (value: boolean) => void;
onActiveFeatureFiltersChange?: (value: AlertConsumers[]) => void;
};

export const UrlSyncedAlertsSearchBar = ({
onEsQueryChange,
onFeatureIdsChange,
onFilteringBySolutionChange,
onActiveFeatureFiltersChange,
...rest
}: UrlSyncedAlertsSearchBarProps) => {
const {
Expand Down Expand Up @@ -55,15 +53,17 @@ export const UrlSyncedAlertsSearchBar = ({
f.meta.key === ALERT_RULE_PRODUCER &&
(f.meta.type === FILTERS.PHRASE || f.meta.type === FILTERS.PHRASES)
);
onFilteringBySolutionChange?.(solutionFilters.length > 0);
onFeatureIdsChange(
!solutionFilters.length ||
solutionFilters.filter(
(f) => (f as PhraseFilter).meta.params?.query !== AlertConsumers.SIEM
).length > 0
? NON_SIEM_FEATURE_IDS
: [AlertConsumers.SIEM]
);
onActiveFeatureFiltersChange?.([
...new Set(
solutionFilters
.flatMap((f) =>
f.meta.type === FILTERS.PHRASES
? (f.meta.params as AlertConsumers[])
: [(f as PhraseFilter).meta.params?.query as AlertConsumers]
)
.filter(Boolean)
),
]);
const newQuery = buildEsQuery({
timeRange: {
to: rangeTo,
Expand All @@ -76,15 +76,7 @@ export const UrlSyncedAlertsSearchBar = ({
} catch (e) {
// TODO show message?
}
}, [
filters,
kuery,
onEsQueryChange,
onFeatureIdsChange,
onFilteringBySolutionChange,
rangeFrom,
rangeTo,
]);
}, [filters, kuery, onActiveFeatureFiltersChange, onEsQueryChange, rangeFrom, rangeTo]);

useEffect(() => {
syncEsQuery();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
Alert,
Alerts,
AlertsTableConfigurationRegistry,
AlertsTableConfigurationRegistryContract,
AlertsTableProps,
RowSelectionState,
TableUpdateHandlerArgs,
Expand All @@ -49,7 +50,6 @@ import { alertsTableQueryClient } from './query_client';
import { useBulkGetCases } from './hooks/use_bulk_get_cases';
import { useBulkGetMaintenanceWindows } from './hooks/use_bulk_get_maintenance_windows';
import { CasesService } from './types';
import { AlertTableConfigRegistry } from '../../alert_table_config_registry';
import { AlertsTableContext, AlertsTableQueryContext } from './contexts/alerts_table_context';

const DefaultPagination = {
Expand All @@ -58,7 +58,7 @@ const DefaultPagination = {
};

export type AlertsTableStateProps = {
alertsTableConfigurationRegistry: AlertTableConfigRegistry;
alertsTableConfigurationRegistry: AlertsTableConfigurationRegistryContract;
configurationId: string;
id: string;
featureIds: ValidFeatureId[];
Expand Down Expand Up @@ -255,8 +255,6 @@ const AlertsTableStateWithQueryProvider = ({
skip: false,
});

console.log('Alerts', alerts);

const { data: mutedAlerts } = useGetMutedAlerts([
...new Set(alerts.map((a) => a['kibana.alert.rule.uuid']![0])),
]);
Expand Down
Loading

0 comments on commit bc455f8

Please sign in to comment.