Skip to content

Commit

Permalink
[RAC] Get o11y alerts in alerts table (#109346) (#109517)
Browse files Browse the repository at this point in the history
* get back index names  in o11y

* testing and integration

* fix types

* Avoid using the rule data client for field list

* Remove left-over index argument

* no needs of alert consumer anymore

Co-authored-by: Felix Stürmer <stuermer@weltenwort.de>

Co-authored-by: Xavier Mouligneau <189600+XavierM@users.noreply.github.com>
Co-authored-by: Felix Stürmer <stuermer@weltenwort.de>
  • Loading branch information
3 people committed Aug 20, 2021
1 parent 3f5f4ab commit 655f824
Show file tree
Hide file tree
Showing 20 changed files with 109 additions and 135 deletions.
5 changes: 1 addition & 4 deletions x-pack/plugins/cases/public/components/case_view/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ export const CaseComponent = React.memo<CaseComponentProps>(
const [initLoadingData, setInitLoadingData] = useState(true);
const init = useRef(true);
const timelineUi = useTimelineContext()?.ui;
const alertConsumers = useTimelineContext()?.alertConsumers;

const {
caseUserActions,
Expand Down Expand Up @@ -487,9 +486,7 @@ export const CaseComponent = React.memo<CaseComponentProps>(
</EuiFlexGroup>
</ContentWrapper>
</WhitePageWrapper>
{timelineUi?.renderTimelineDetailsPanel
? timelineUi.renderTimelineDetailsPanel({ alertConsumers })
: null}
{timelineUi?.renderTimelineDetailsPanel ? timelineUi.renderTimelineDetailsPanel() : null}
</>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import React, { useState } from 'react';
import { EuiMarkdownEditorUiPlugin, EuiMarkdownAstNodePosition } from '@elastic/eui';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { Plugin } from 'unified';
/**
* @description - manage the plugins, hooks, and ui components needed to enable timeline functionality within the cases plugin
Expand All @@ -29,7 +28,6 @@ interface TimelineProcessingPluginRendererProps {
}

export interface CasesTimelineIntegration {
alertConsumers?: AlertConsumers[];
editor_plugins: {
parsingPlugin: Plugin;
processingPluginRenderer: React.FC<
Expand All @@ -45,11 +43,7 @@ export interface CasesTimelineIntegration {
};
ui?: {
renderInvestigateInTimelineActionComponent?: (alertIds: string[]) => JSX.Element;
renderTimelineDetailsPanel?: ({
alertConsumers,
}: {
alertConsumers?: AlertConsumers[];
}) => JSX.Element;
renderTimelineDetailsPanel?: () => JSX.Element;
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@
* 2.0.
*/

import { IndexPatternBase } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import React, { useMemo, useState } from 'react';
import { IIndexPattern, SearchBar, TimeHistory } from '../../../../../../src/plugins/data/public';
import { SearchBar, TimeHistory } from '../../../../../../src/plugins/data/public';
import { Storage } from '../../../../../../src/plugins/kibana_utils/public';

export function AlertsSearchBar({
dynamicIndexPattern,
dynamicIndexPatterns,
rangeFrom,
rangeTo,
onQueryChange,
query,
}: {
dynamicIndexPattern: IIndexPattern[];
dynamicIndexPatterns: IndexPatternBase[];
rangeFrom?: string;
rangeTo?: string;
query?: string;
Expand All @@ -31,9 +32,19 @@ export function AlertsSearchBar({
}, []);
const [queryLanguage, setQueryLanguage] = useState<'lucene' | 'kuery'>('kuery');

const compatibleIndexPatterns = useMemo(
() =>
dynamicIndexPatterns.map((dynamicIndexPattern) => ({
title: dynamicIndexPattern.title ?? '',
id: dynamicIndexPattern.id ?? '',
fields: dynamicIndexPattern.fields,
})),
[dynamicIndexPatterns]
);

return (
<SearchBar
indexPatterns={dynamicIndexPattern}
indexPatterns={compatibleIndexPatterns}
placeholder={i18n.translate('xpack.observability.alerts.searchBarPlaceholder', {
defaultMessage: 'kibana.alert.evaluation.threshold > 75',
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
* This way plugins can do targeted imports to reduce the final code bundle
*/
import {
AlertConsumers as AlertConsumersTyped,
ALERT_DURATION as ALERT_DURATION_TYPED,
ALERT_REASON as ALERT_REASON_TYPED,
ALERT_RULE_CONSUMER,
Expand Down Expand Up @@ -62,14 +61,13 @@ import { LazyAlertsFlyout } from '../..';
import { parseAlert } from './parse_alert';
import { CoreStart } from '../../../../../../src/core/public';

const AlertConsumers: typeof AlertConsumersTyped = AlertConsumersNonTyped;
const ALERT_DURATION: typeof ALERT_DURATION_TYPED = ALERT_DURATION_NON_TYPED;
const ALERT_REASON: typeof ALERT_REASON_TYPED = ALERT_REASON_NON_TYPED;
const ALERT_STATUS: typeof ALERT_STATUS_TYPED = ALERT_STATUS_NON_TYPED;
const ALERT_WORKFLOW_STATUS: typeof ALERT_WORKFLOW_STATUS_TYPED = ALERT_WORKFLOW_STATUS_NON_TYPED;

interface AlertsTableTGridProps {
indexName: string;
indexNames: string[];
rangeFrom: string;
rangeTo: string;
kuery: string;
Expand Down Expand Up @@ -147,13 +145,6 @@ const NO_ROW_RENDER: RowRenderer[] = [];

const trailingControlColumns: never[] = [];

const OBSERVABILITY_ALERT_CONSUMERS = [
AlertConsumers.APM,
AlertConsumers.LOGS,
AlertConsumers.INFRASTRUCTURE,
AlertConsumers.UPTIME,
];

function ObservabilityActions({
data,
eventId,
Expand Down Expand Up @@ -290,7 +281,7 @@ function ObservabilityActions({
}

export function AlertsTableTGrid(props: AlertsTableTGridProps) {
const { indexName, rangeFrom, rangeTo, kuery, workflowStatus, setRefetch, addToQuery } = props;
const { indexNames, rangeFrom, rangeTo, kuery, workflowStatus, setRefetch, addToQuery } = props;
const { timelines } = useKibana<{ timelines: TimelinesUIStart }>().services;

const [flyoutAlert, setFlyoutAlert] = useState<TopAlert | undefined>(undefined);
Expand Down Expand Up @@ -328,7 +319,6 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
const type: TGridType = 'standalone';
const sortDirection: SortDirection = 'desc';
return {
alertConsumers: OBSERVABILITY_ALERT_CONSUMERS,
appId: observabilityFeatureId,
casePermissions,
type,
Expand All @@ -337,7 +327,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
defaultCellActions: getDefaultCellActions({ addToQuery }),
end: rangeTo,
filters: [],
indexNames: [indexName],
indexNames,
itemsPerPage: 10,
itemsPerPageOptions: [10, 25, 50],
loadingText: i18n.translate('xpack.observability.alertsTable.loadingTextLabel', {
Expand Down Expand Up @@ -372,7 +362,7 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) {
};
}, [
casePermissions,
indexName,
indexNames,
kuery,
leadingControlColumns,
rangeFrom,
Expand Down
47 changes: 38 additions & 9 deletions x-pack/plugins/observability/public/pages/alerts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

import { EuiButtonEmpty, EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useCallback, useMemo, useRef } from 'react';
import React, { useCallback, useRef } from 'react';
import { useHistory } from 'react-router-dom';
import useAsync from 'react-use/lib/useAsync';
import { IndexPatternBase } from '@kbn/es-query';
import { ParsedTechnicalFields } from '../../../../rule_registry/common/parse_technical_fields';
import type { AlertWorkflowStatus } from '../../../common/typings';
import { ExperimentalBadge } from '../../components/shared/experimental_badge';
Expand All @@ -35,7 +37,7 @@ interface AlertsPageProps {
}

export function AlertsPage({ routeParams }: AlertsPageProps) {
const { core, ObservabilityPageTemplate } = usePluginContext();
const { core, plugins, ObservabilityPageTemplate } = usePluginContext();
const { prepend } = core.http.basePath;
const history = useHistory();
const refetch = useRef<() => void>();
Expand All @@ -60,17 +62,41 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
// observability. For now link to the settings page.
const manageRulesHref = prepend('/app/management/insightsAndAlerting/triggersActions/alerts');

const { data: dynamicIndexPatternResp } = useFetcher(({ signal }) => {
const { data: indexNames = NO_INDEX_NAMES } = useFetcher(({ signal }) => {
return callObservabilityApi({
signal,
endpoint: 'GET /api/observability/rules/alerts/dynamic_index_pattern',
params: {
query: {
namespace: 'default',
registrationContexts: [
'observability.apm',
'observability.logs',
'observability.infrastructure',
'observability.metrics',
'observability.uptime',
],
},
},
});
}, []);

const dynamicIndexPattern = useMemo(
() => (dynamicIndexPatternResp ? [dynamicIndexPatternResp] : []),
[dynamicIndexPatternResp]
);
const dynamicIndexPatternsAsyncState = useAsync(async (): Promise<IndexPatternBase[]> => {
if (indexNames.length === 0) {
return [];
}

return [
{
id: 'dynamic-observability-alerts-table-index-pattern',
title: indexNames.join(','),
fields: await plugins.data.indexPatterns.getFieldsForWildcard({
pattern: indexNames.join(','),
allowNoIndex: true,
}),
},
];
}, [indexNames]);

const setWorkflowStatusFilter = useCallback(
(value: AlertWorkflowStatus) => {
Expand Down Expand Up @@ -165,7 +191,7 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
</EuiFlexItem>
<EuiFlexItem>
<AlertsSearchBar
dynamicIndexPattern={dynamicIndexPattern}
dynamicIndexPatterns={dynamicIndexPatternsAsyncState.value ?? NO_INDEX_PATTERNS}
rangeFrom={rangeFrom}
rangeTo={rangeTo}
query={kuery}
Expand All @@ -183,7 +209,7 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {

<EuiFlexItem>
<AlertsTableTGrid
indexName={dynamicIndexPattern.length > 0 ? dynamicIndexPattern[0].title : ''}
indexNames={indexNames}
rangeFrom={rangeFrom}
rangeTo={rangeTo}
kuery={kuery}
Expand All @@ -196,3 +222,6 @@ export function AlertsPage({ routeParams }: AlertsPageProps) {
</ObservabilityPageTemplate>
);
}

const NO_INDEX_NAMES: string[] = [];
const NO_INDEX_PATTERNS: IndexPatternBase[] = [];
14 changes: 2 additions & 12 deletions x-pack/plugins/observability/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
ScopedAnnotationsClientFactory,
AnnotationsAPI,
} from './lib/annotations/bootstrap_annotations';
import { Dataset, RuleRegistryPluginSetupContract } from '../../rule_registry/server';
import { RuleRegistryPluginSetupContract } from '../../rule_registry/server';
import { PluginSetupContract as FeaturesSetup } from '../../features/server';
import { uiSettings } from './ui_settings';
import { registerRoutes } from './routes/register_routes';
Expand Down Expand Up @@ -101,16 +101,6 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
const start = () => core.getStartServices().then(([coreStart]) => coreStart);

const { ruleDataService } = plugins.ruleRegistry;
const ruleDataClient = ruleDataService.initializeIndex({
feature: 'observability',
registrationContext: 'observability',
dataset: Dataset.alerts,
componentTemplateRefs: [],
componentTemplates: [],
indexTemplate: {
version: 0,
},
});

registerRoutes({
core: {
Expand All @@ -119,7 +109,7 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
},
logger: this.initContext.logger.get(),
repository: getGlobalObservabilityServerRouteRepository(),
ruleDataClient,
ruleDataService,
});

return {
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/observability/server/routes/register_routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ import {
import { CoreSetup, CoreStart, Logger, RouteRegistrar } from 'kibana/server';
import Boom from '@hapi/boom';
import { RequestAbortedError } from '@elastic/elasticsearch/lib/errors';
import { IRuleDataClient } from '../../../rule_registry/server';
import { RuleDataPluginService } from '../../../rule_registry/server';
import { ObservabilityRequestHandlerContext } from '../types';
import { AbstractObservabilityServerRouteRepository } from './types';

export function registerRoutes({
repository,
core,
logger,
ruleDataClient,
ruleDataService,
}: {
core: {
setup: CoreSetup;
start: () => Promise<CoreStart>;
};
repository: AbstractObservabilityServerRouteRepository;
logger: Logger;
ruleDataClient: IRuleDataClient;
ruleDataService: RuleDataPluginService;
}) {
const routes = repository.getRoutes();

Expand Down Expand Up @@ -62,7 +62,7 @@ export function registerRoutes({
core,
logger,
params: decodedParams,
ruleDataClient,
ruleDataService,
})) as any;

return response.ok({ body: data });
Expand Down
25 changes: 21 additions & 4 deletions x-pack/plugins/observability/server/routes/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { observabilityFeatureId } from '../../common';
import * as t from 'io-ts';
import { createObservabilityServerRoute } from './create_observability_server_route';
import { createObservabilityServerRouteRepository } from './create_observability_server_route_repository';

Expand All @@ -14,10 +14,27 @@ const alertsDynamicIndexPatternRoute = createObservabilityServerRoute({
options: {
tags: [],
},
handler: async ({ ruleDataClient }) => {
const reader = ruleDataClient.getReader({ namespace: observabilityFeatureId });
params: t.type({
query: t.type({
registrationContexts: t.array(t.string),
namespace: t.string,
}),
}),
handler: async ({ ruleDataService, params }) => {
const { namespace, registrationContexts } = params.query;
const indexNames = registrationContexts.flatMap((registrationContext) => {
const indexName = ruleDataService
.getRegisteredIndexInfo(registrationContext)
?.getPrimaryAlias(namespace);

return reader.getDynamicIndexPattern();
if (indexName != null) {
return [indexName];
} else {
return [];
}
});

return indexNames;
},
});

Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/observability/server/routes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {
ServerRouteRepository,
} from '@kbn/server-route-repository';
import { CoreSetup, CoreStart, KibanaRequest, Logger } from 'kibana/server';
import { IRuleDataClient } from '../../../rule_registry/server';
import { RuleDataPluginService } from '../../../rule_registry/server';

import { ObservabilityServerRouteRepository } from './get_global_observability_server_route_repository';
import { ObservabilityRequestHandlerContext } from '../types';
Expand All @@ -24,7 +24,7 @@ export interface ObservabilityRouteHandlerResources {
start: () => Promise<CoreStart>;
setup: CoreSetup;
};
ruleDataClient: IRuleDataClient;
ruleDataService: RuleDataPluginService;
request: KibanaRequest;
context: ObservabilityRequestHandlerContext;
logger: Logger;
Expand Down
Loading

0 comments on commit 655f824

Please sign in to comment.