mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Custom threshold] Add viewInApp URL to the custom threshold rule type (#171985)
Closes #171613 ## Summary This PR adds the viewInApp URL to the custom threshold rule type. This URL will send the user to the log explorer with the selected data view and the rule's query filter. If there is only one document aggregation, then the filter related to this aggregation will be added as shown below: |Rule|Discover with pre-fill data| |---|---| || For the ad-hoc data view, you should be able to see the selected index pattern in discover similar to this: <img src="046493ae
-ba59-46b7-a40f-68d1836d43f1" width=400 /> ### 🧪 How to test - Check the viewInApp URL both in action variables and the alert table for the following scenarios: - A rule with a persisted data view - A rule with an ad-hoc data view - A rule with count aggregation and filter - A rule with an optional query filter - A rule with non-count aggregation In all the above scenarios, the starting time in the Discover should be before the alert's start time. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
d83955dcdd
commit
59982bfa5c
42 changed files with 307 additions and 89 deletions
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -555,6 +555,7 @@ x-pack/plugins/observability_ai_assistant @elastic/obs-knowledge-team
|
|||
x-pack/packages/observability/alert_details @elastic/obs-ux-management-team
|
||||
x-pack/packages/observability/alerting_test_data @elastic/obs-ux-management-team
|
||||
x-pack/test/cases_api_integration/common/plugins/observability @elastic/response-ops
|
||||
x-pack/packages/observability/get_padded_alert_time_range_util @elastic/obs-ux-management-team
|
||||
x-pack/plugins/observability_log_explorer @elastic/obs-ux-logs-team
|
||||
x-pack/plugins/observability_onboarding @elastic/obs-ux-logs-team
|
||||
x-pack/plugins/observability @elastic/obs-ux-management-team
|
||||
|
|
|
@ -573,6 +573,7 @@
|
|||
"@kbn/observability-alert-details": "link:x-pack/packages/observability/alert_details",
|
||||
"@kbn/observability-alerting-test-data": "link:x-pack/packages/observability/alerting_test_data",
|
||||
"@kbn/observability-fixtures-plugin": "link:x-pack/test/cases_api_integration/common/plugins/observability",
|
||||
"@kbn/observability-get-padded-alert-time-range-util": "link:x-pack/packages/observability/get_padded_alert_time_range_util",
|
||||
"@kbn/observability-log-explorer-plugin": "link:x-pack/plugins/observability_log_explorer",
|
||||
"@kbn/observability-onboarding-plugin": "link:x-pack/plugins/observability_onboarding",
|
||||
"@kbn/observability-plugin": "link:x-pack/plugins/observability",
|
||||
|
|
|
@ -1104,6 +1104,8 @@
|
|||
"@kbn/observability-alerting-test-data/*": ["x-pack/packages/observability/alerting_test_data/*"],
|
||||
"@kbn/observability-fixtures-plugin": ["x-pack/test/cases_api_integration/common/plugins/observability"],
|
||||
"@kbn/observability-fixtures-plugin/*": ["x-pack/test/cases_api_integration/common/plugins/observability/*"],
|
||||
"@kbn/observability-get-padded-alert-time-range-util": ["x-pack/packages/observability/get_padded_alert_time_range_util"],
|
||||
"@kbn/observability-get-padded-alert-time-range-util/*": ["x-pack/packages/observability/get_padded_alert_time_range_util/*"],
|
||||
"@kbn/observability-log-explorer-plugin": ["x-pack/plugins/observability_log_explorer"],
|
||||
"@kbn/observability-log-explorer-plugin/*": ["x-pack/plugins/observability_log_explorer/*"],
|
||||
"@kbn/observability-onboarding-plugin": ["x-pack/plugins/observability_onboarding"],
|
||||
|
|
|
@ -9,5 +9,4 @@ export { AlertAnnotation } from './src/components/alert_annotation';
|
|||
export { AlertActiveTimeRangeAnnotation } from './src/components/alert_active_time_range_annotation';
|
||||
export { AlertThresholdTimeRangeRect } from './src/components/alert_threshold_time_range_rect';
|
||||
export { AlertThresholdAnnotation } from './src/components/alert_threshold_annotation';
|
||||
export { getPaddedAlertTimeRange } from './src/helpers/get_padded_alert_time_range';
|
||||
export { useAlertsHistory } from './src/hooks/use_alerts_history';
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"name": "@kbn/observability-alert-details",
|
||||
"descriptio": "Helper and components related to alert details",
|
||||
"author": "Actionable Observability",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"license": "Elastic License 2.0"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# @kbn/get-padded-alert-time-range-util
|
||||
|
||||
A utility to get padded alert time range based on alert's start and end time
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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 { getPaddedAlertTimeRange } from './src/get_padded_alert_time_range';
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../../..',
|
||||
roots: ['<rootDir>/x-pack/packages/observability/get_padded_alert_time_range_util'],
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type": "shared-common",
|
||||
"id": "@kbn/observability-get-padded-alert-time-range-util",
|
||||
"owner": "@elastic/obs-ux-management-team"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "@kbn/observability-get-padded-alert-time-range-util",
|
||||
"descriptio": "An util to get padded alert time range",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"license": "Elastic License 2.0"
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types",
|
||||
"types": [
|
||||
"jest",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*"
|
||||
],
|
||||
"kbn_references": []
|
||||
}
|
|
@ -19,7 +19,7 @@ import {
|
|||
import moment from 'moment';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { getPaddedAlertTimeRange } from '@kbn/observability-alert-details';
|
||||
import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util';
|
||||
import { EuiCallOut } from '@elastic/eui';
|
||||
import { SERVICE_ENVIRONMENT } from '../../../../../common/es_fields/apm';
|
||||
import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context';
|
||||
|
|
|
@ -105,7 +105,8 @@
|
|||
"@kbn/deeplinks-observability",
|
||||
"@kbn/custom-icons",
|
||||
"@kbn/elastic-agent-utils",
|
||||
"@kbn/shared-ux-link-redirect-app"
|
||||
"@kbn/shared-ux-link-redirect-app",
|
||||
"@kbn/observability-get-padded-alert-time-range-util"
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import moment from 'moment';
|
|||
import { useTheme } from '@emotion/react';
|
||||
import { EuiTitle } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { getPaddedAlertTimeRange } from '@kbn/observability-alert-details';
|
||||
import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util';
|
||||
import { get, identity } from 'lodash';
|
||||
import { ObservabilityAIAssistantProvider } from '@kbn/observability-ai-assistant-plugin/public';
|
||||
import { useLogView } from '@kbn/logs-shared-plugin/public';
|
||||
|
|
|
@ -24,6 +24,9 @@ const mockedChartStartContract = chartPluginMock.createStartContract();
|
|||
jest.mock('@kbn/observability-alert-details', () => ({
|
||||
AlertAnnotation: () => {},
|
||||
AlertActiveTimeRangeAnnotation: () => {},
|
||||
}));
|
||||
|
||||
jest.mock('@kbn/observability-get-padded-alert-time-range-util', () => ({
|
||||
getPaddedAlertTimeRange: () => ({
|
||||
from: '2023-03-28T10:43:13.802Z',
|
||||
to: '2023-03-29T13:14:09.581Z',
|
||||
|
|
|
@ -22,11 +22,8 @@ import {
|
|||
import { AlertSummaryField, TopAlert } from '@kbn/observability-plugin/public';
|
||||
import { ALERT_END, ALERT_START, ALERT_EVALUATION_VALUES } from '@kbn/rule-data-utils';
|
||||
import { Rule } from '@kbn/alerting-plugin/common';
|
||||
import {
|
||||
AlertAnnotation,
|
||||
getPaddedAlertTimeRange,
|
||||
AlertActiveTimeRangeAnnotation,
|
||||
} from '@kbn/observability-alert-details';
|
||||
import { AlertAnnotation, AlertActiveTimeRangeAnnotation } from '@kbn/observability-alert-details';
|
||||
import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util';
|
||||
import { metricValueFormatter } from '../../../../common/alerting/metrics/metric_value_formatter';
|
||||
import { TIME_LABELS } from '../../common/criterion_preview_chart/criterion_preview_chart';
|
||||
import { Threshold } from '../../common/components/threshold';
|
||||
|
|
|
@ -78,7 +78,8 @@
|
|||
"@kbn/custom-icons",
|
||||
"@kbn/profiling-utils",
|
||||
"@kbn/profiling-data-access-plugin",
|
||||
"@kbn/core-http-request-handler-context-server"
|
||||
"@kbn/core-http-request-handler-context-server",
|
||||
"@kbn/observability-get-padded-alert-time-range-util"
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
|
@ -10,16 +10,14 @@ import { LogExplorerLocatorDefinition } from './log_explorer_locator';
|
|||
import { LogExplorerLocatorDependencies } from './types';
|
||||
|
||||
const setup = async () => {
|
||||
const discoverSetupContract: LogExplorerLocatorDependencies = {
|
||||
discover: {
|
||||
locator: sharePluginMock.createLocator(),
|
||||
},
|
||||
const logExplorerLocatorDependencies: LogExplorerLocatorDependencies = {
|
||||
discoverAppLocator: sharePluginMock.createLocator(),
|
||||
};
|
||||
const logExplorerLocator = new LogExplorerLocatorDefinition(discoverSetupContract);
|
||||
const logExplorerLocator = new LogExplorerLocatorDefinition(logExplorerLocatorDependencies);
|
||||
|
||||
return {
|
||||
logExplorerLocator,
|
||||
discoverGetLocation: discoverSetupContract.discover.locator?.getLocation,
|
||||
discoverGetLocation: logExplorerLocatorDependencies.discoverAppLocator?.getLocation,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ export class LogExplorerLocatorDefinition implements LocatorDefinition<LogExplor
|
|||
}
|
||||
: undefined;
|
||||
|
||||
return this.deps.discover.locator?.getLocation({
|
||||
return this.deps.discoverAppLocator?.getLocation({
|
||||
...params,
|
||||
dataViewId: dataset,
|
||||
dataViewSpec,
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { DiscoverSetup } from '@kbn/discover-plugin/public';
|
||||
import { DiscoverAppLocatorParams } from '@kbn/discover-plugin/common';
|
||||
import { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
|
||||
export interface LogExplorerLocatorDependencies {
|
||||
discover: DiscoverSetup;
|
||||
discoverAppLocator?: LocatorPublic<DiscoverAppLocatorParams>;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public';
|
||||
import { DISCOVER_APP_LOCATOR, DiscoverAppLocatorParams } from '@kbn/discover-plugin/common';
|
||||
import { LogExplorerLocatorDefinition, LogExplorerLocators } from '../common/locators';
|
||||
import { createLogExplorer } from './components/log_explorer';
|
||||
import {
|
||||
|
@ -21,12 +22,14 @@ export class LogExplorerPlugin implements Plugin<LogExplorerPluginSetup, LogExpl
|
|||
constructor(context: PluginInitializerContext) {}
|
||||
|
||||
public setup(core: CoreSetup, plugins: LogExplorerSetupDeps) {
|
||||
const { share, discover } = plugins;
|
||||
const { share } = plugins;
|
||||
const discoverAppLocator =
|
||||
share.url.locators.get<DiscoverAppLocatorParams>(DISCOVER_APP_LOCATOR);
|
||||
|
||||
// Register Locators
|
||||
const logExplorerLocator = share.url.locators.create(
|
||||
new LogExplorerLocatorDefinition({
|
||||
discover,
|
||||
discoverAppLocator,
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
@ -5,10 +5,34 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Plugin } from '@kbn/core/server';
|
||||
import { Plugin, CoreSetup } from '@kbn/core/server';
|
||||
import { DISCOVER_APP_LOCATOR, DiscoverAppLocatorParams } from '@kbn/discover-plugin/common';
|
||||
import { LogExplorerLocatorDefinition, LogExplorerLocators } from '../common/locators';
|
||||
import type { LogExplorerSetupDeps } from './types';
|
||||
|
||||
export class LogExplorerServerPlugin implements Plugin {
|
||||
setup() {}
|
||||
private locators?: LogExplorerLocators;
|
||||
|
||||
setup(core: CoreSetup, plugins: LogExplorerSetupDeps) {
|
||||
const { share } = plugins;
|
||||
const discoverAppLocator =
|
||||
share.url.locators.get<DiscoverAppLocatorParams>(DISCOVER_APP_LOCATOR);
|
||||
|
||||
// Register Locators
|
||||
const logExplorerLocator = share.url.locators.create(
|
||||
new LogExplorerLocatorDefinition({
|
||||
discoverAppLocator,
|
||||
})
|
||||
);
|
||||
|
||||
this.locators = {
|
||||
logExplorerLocator,
|
||||
};
|
||||
|
||||
return {
|
||||
locators: this.locators,
|
||||
};
|
||||
}
|
||||
|
||||
start() {}
|
||||
}
|
||||
|
|
12
x-pack/plugins/log_explorer/server/types.ts
Normal file
12
x-pack/plugins/log_explorer/server/types.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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 type { SharePluginSetup } from '@kbn/share-plugin/server';
|
||||
|
||||
export interface LogExplorerSetupDeps {
|
||||
share: SharePluginSetup;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util';
|
||||
import type { DiscoverAppLocatorParams } from '@kbn/discover-plugin/common';
|
||||
import type { TimeRange } from '@kbn/es-query';
|
||||
import type { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
import type { CustomThresholdExpressionMetric } from './types';
|
||||
|
||||
export const getViewInAppUrl = (
|
||||
metrics: CustomThresholdExpressionMetric[],
|
||||
startedAt?: string,
|
||||
logExplorerLocator?: LocatorPublic<DiscoverAppLocatorParams>,
|
||||
filter?: string,
|
||||
dataViewId?: string,
|
||||
endedAt?: string
|
||||
) => {
|
||||
if (!logExplorerLocator) return '';
|
||||
|
||||
let timeRange: TimeRange | undefined;
|
||||
if (startedAt) {
|
||||
timeRange = getPaddedAlertTimeRange(startedAt, endedAt);
|
||||
timeRange.to = endedAt ? timeRange.to : 'now';
|
||||
}
|
||||
|
||||
const query = {
|
||||
query: '',
|
||||
language: 'kuery',
|
||||
};
|
||||
const isOneCountConditionWithFilter =
|
||||
metrics.length === 1 && metrics[0].aggType === 'count' && metrics[0].filter;
|
||||
if (filter && isOneCountConditionWithFilter) {
|
||||
query.query = `${filter} and ${metrics[0].filter}`;
|
||||
} else if (isOneCountConditionWithFilter) {
|
||||
query.query = metrics[0].filter!;
|
||||
} else if (filter) {
|
||||
query.query = filter;
|
||||
}
|
||||
|
||||
return logExplorerLocator?.getRedirectUrl({
|
||||
dataset: dataViewId,
|
||||
timeRange,
|
||||
query,
|
||||
});
|
||||
};
|
|
@ -35,6 +35,7 @@
|
|||
"visualizations",
|
||||
"dashboard",
|
||||
"expressions",
|
||||
"logExplorer",
|
||||
"licensing"
|
||||
],
|
||||
"optionalPlugins": [
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { EuiFlyoutFooter, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useKibana } from '../../utils/kibana_react';
|
||||
|
@ -25,17 +26,22 @@ export function AlertsFlyoutFooter({ alert, isInApp }: FlyoutProps & { isInApp:
|
|||
},
|
||||
} = useKibana().services;
|
||||
const { config } = usePluginContext();
|
||||
const [viewInAppUrl, setViewInAppUrl] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!alert.hasBasePath) {
|
||||
setViewInAppUrl(prepend(alert.link ?? ''));
|
||||
} else {
|
||||
setViewInAppUrl(alert.link);
|
||||
}
|
||||
}, [alert.hasBasePath, alert.link, prepend]);
|
||||
|
||||
return (
|
||||
<EuiFlyoutFooter>
|
||||
<EuiFlexGroup justifyContent="flexEnd">
|
||||
{!alert.link || isInApp ? null : (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
data-test-subj="alertsFlyoutViewInAppButton"
|
||||
fill
|
||||
href={prepend && prepend(alert.link)}
|
||||
>
|
||||
<EuiButton data-test-subj="alertsFlyoutViewInAppButton" fill href={viewInAppUrl}>
|
||||
{i18n.translate('xpack.observability.alertsFlyout.viewInAppButtonText', {
|
||||
defaultMessage: 'View in app',
|
||||
})}
|
||||
|
|
|
@ -24,6 +24,9 @@ const mockedChartStartContract = chartPluginMock.createStartContract();
|
|||
jest.mock('@kbn/observability-alert-details', () => ({
|
||||
AlertAnnotation: () => {},
|
||||
AlertActiveTimeRangeAnnotation: () => {},
|
||||
}));
|
||||
|
||||
jest.mock('@kbn/observability-get-padded-alert-time-range-util', () => ({
|
||||
getPaddedAlertTimeRange: () => ({
|
||||
from: '2023-03-28T10:43:13.802Z',
|
||||
to: '2023-03-29T13:14:09.581Z',
|
||||
|
|
|
@ -22,11 +22,8 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { ALERT_END, ALERT_START, ALERT_EVALUATION_VALUES } from '@kbn/rule-data-utils';
|
||||
import { Rule, RuleTypeParams } from '@kbn/alerting-plugin/common';
|
||||
import {
|
||||
AlertAnnotation,
|
||||
getPaddedAlertTimeRange,
|
||||
AlertActiveTimeRangeAnnotation,
|
||||
} from '@kbn/observability-alert-details';
|
||||
import { AlertAnnotation, AlertActiveTimeRangeAnnotation } from '@kbn/observability-alert-details';
|
||||
import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util';
|
||||
import { DataView } from '@kbn/data-views-plugin/common';
|
||||
import { MetricsExplorerChartType } from '../../../../common/custom_threshold_rule/types';
|
||||
import { useKibana } from '../../../utils/kibana_react';
|
||||
|
|
|
@ -14,19 +14,17 @@ import {
|
|||
EuiToolTip,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import React, { useMemo, useState, useCallback } from 'react';
|
||||
import React, { useMemo, useState, useCallback, useEffect } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { CaseAttachmentsWithoutOwner } from '@kbn/cases-plugin/public';
|
||||
import { AttachmentType } from '@kbn/cases-plugin/common';
|
||||
import { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
|
||||
import { TimelineNonEcsData } from '@kbn/timelines-plugin/common';
|
||||
import {
|
||||
ALERT_RULE_TYPE_ID,
|
||||
ALERT_RULE_UUID,
|
||||
ALERT_STATUS,
|
||||
ALERT_STATUS_ACTIVE,
|
||||
ALERT_UUID,
|
||||
OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
|
||||
} from '@kbn/rule-data-utils';
|
||||
import { useBulkUntrackAlerts } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { useKibana } from '../../../utils/kibana_react';
|
||||
|
@ -70,6 +68,7 @@ export function AlertActions({
|
|||
} = useKibana().services;
|
||||
const { mutateAsync: untrackAlerts } = useBulkUntrackAlerts();
|
||||
const userCasesPermissions = canUseCases([observabilityFeatureId]);
|
||||
const [viewInAppUrl, setViewInAppUrl] = useState<string>();
|
||||
|
||||
const parseObservabilityAlert = useMemo(
|
||||
() => parseAlert(observabilityRuleTypeRegistry),
|
||||
|
@ -79,6 +78,14 @@ export function AlertActions({
|
|||
const dataFieldEs = data.reduce((acc, d) => ({ ...acc, [d.field]: d.value }), {});
|
||||
const alert = parseObservabilityAlert(dataFieldEs);
|
||||
|
||||
useEffect(() => {
|
||||
if (!alert.hasBasePath) {
|
||||
setViewInAppUrl(prepend(alert.link ?? ''));
|
||||
} else {
|
||||
setViewInAppUrl(alert.link);
|
||||
}
|
||||
}, [alert.hasBasePath, alert.link, prepend]);
|
||||
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
|
||||
|
||||
const ruleId = alert.fields[ALERT_RULE_UUID] ?? null;
|
||||
|
@ -236,10 +243,7 @@ export function AlertActions({
|
|||
|
||||
return (
|
||||
<>
|
||||
{/* Hide the View In App for the Threshold alerts, temporarily https://github.com/elastic/kibana/pull/159915 */}
|
||||
{alert.fields[ALERT_RULE_TYPE_ID] === OBSERVABILITY_THRESHOLD_RULE_TYPE_ID ? (
|
||||
<EuiFlexItem style={{ width: 32 }} />
|
||||
) : (
|
||||
{viewInAppUrl ? (
|
||||
<EuiFlexItem>
|
||||
<EuiToolTip
|
||||
content={i18n.translate('xpack.observability.alertsTable.viewInAppTextLabel', {
|
||||
|
@ -252,12 +256,14 @@ export function AlertActions({
|
|||
defaultMessage: 'View in app',
|
||||
})}
|
||||
color="text"
|
||||
href={prepend(alert.link ?? '')}
|
||||
href={viewInAppUrl}
|
||||
iconType="eye"
|
||||
size="s"
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
) : (
|
||||
<EuiFlexItem style={{ width: 32 }} />
|
||||
)}
|
||||
|
||||
<EuiFlexItem>
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
|
||||
import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import { LOG_EXPLORER_LOCATOR_ID, LogExplorerLocatorParams } from '@kbn/deeplinks-observability';
|
||||
import type { DiscoverStart } from '@kbn/discover-plugin/public';
|
||||
import type { EmbeddableStart } from '@kbn/embeddable-plugin/public';
|
||||
import type { HomePublicPluginSetup, HomePublicPluginStart } from '@kbn/home-plugin/public';
|
||||
|
@ -82,6 +83,7 @@ import {
|
|||
ObservabilityRuleTypeRegistry,
|
||||
} from './rules/create_observability_rule_type_registry';
|
||||
import { registerObservabilityRuleTypes } from './rules/register_observability_rule_types';
|
||||
|
||||
export interface ConfigSchema {
|
||||
unsafe: {
|
||||
alertDetails: {
|
||||
|
@ -103,9 +105,7 @@ export interface ConfigSchema {
|
|||
};
|
||||
};
|
||||
}
|
||||
|
||||
export type ObservabilityPublicSetup = ReturnType<Plugin['setup']>;
|
||||
|
||||
export interface ObservabilityPublicPluginsSetup {
|
||||
data: DataPublicPluginSetup;
|
||||
observabilityShared: ObservabilitySharedPluginSetup;
|
||||
|
@ -117,7 +117,6 @@ export interface ObservabilityPublicPluginsSetup {
|
|||
embeddable: EmbeddableSetup;
|
||||
licensing: LicensingPluginSetup;
|
||||
}
|
||||
|
||||
export interface ObservabilityPublicPluginsStart {
|
||||
actionTypeRegistry: ActionTypeRegistryContract;
|
||||
cases: CasesUiStart;
|
||||
|
@ -146,7 +145,6 @@ export interface ObservabilityPublicPluginsStart {
|
|||
aiops: AiopsPluginStart;
|
||||
serverless?: ServerlessPluginStart;
|
||||
}
|
||||
|
||||
export type ObservabilityPublicStart = ReturnType<Plugin['start']>;
|
||||
|
||||
export class Plugin
|
||||
|
@ -239,6 +237,9 @@ export class Plugin
|
|||
const sloEditLocator = pluginsSetup.share.url.locators.create(new SloEditLocatorDefinition());
|
||||
const sloListLocator = pluginsSetup.share.url.locators.create(new SloListLocatorDefinition());
|
||||
|
||||
const logExplorerLocator =
|
||||
pluginsSetup.share.url.locators.get<LogExplorerLocatorParams>(LOG_EXPLORER_LOCATOR_ID);
|
||||
|
||||
const mount = async (params: AppMountParameters<unknown>) => {
|
||||
// Load application bundle
|
||||
const { renderApp } = await import('./application');
|
||||
|
@ -292,7 +293,7 @@ export class Plugin
|
|||
|
||||
coreSetup.application.register(app);
|
||||
|
||||
registerObservabilityRuleTypes(config, this.observabilityRuleTypeRegistry);
|
||||
registerObservabilityRuleTypes(config, this.observabilityRuleTypeRegistry, logExplorerLocator);
|
||||
|
||||
const assertPlatinumLicense = async () => {
|
||||
const licensing = await pluginsSetup.licensing;
|
||||
|
|
|
@ -16,7 +16,7 @@ import { AsDuration, AsPercent } from '../../common/utils/formatters';
|
|||
export type ObservabilityRuleTypeFormatter = (options: {
|
||||
fields: ParsedTechnicalFields & Record<string, any>;
|
||||
formatters: { asDuration: AsDuration; asPercent: AsPercent };
|
||||
}) => { reason: string; link?: string };
|
||||
}) => { reason: string; link?: string; hasBasePath?: boolean };
|
||||
|
||||
export interface ObservabilityRuleTypeModel<Params extends RuleTypeParams = RuleTypeParams>
|
||||
extends RuleTypeModel<Params> {
|
||||
|
|
|
@ -7,15 +7,24 @@
|
|||
|
||||
import { lazy } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ALERT_REASON, OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils';
|
||||
|
||||
import type { SerializedSearchSourceFields } from '@kbn/data-plugin/common';
|
||||
import {
|
||||
ALERT_REASON,
|
||||
ALERT_RULE_PARAMETERS,
|
||||
ALERT_START,
|
||||
OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
|
||||
} from '@kbn/rule-data-utils';
|
||||
import type { DiscoverAppLocatorParams } from '@kbn/discover-plugin/common';
|
||||
import type { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
import type { MetricExpression } from '../components/custom_threshold/types';
|
||||
import type { CustomThresholdExpressionMetric } from '../../common/custom_threshold_rule/types';
|
||||
import { getViewInAppUrl } from '../../common/custom_threshold_rule/get_view_in_app_url';
|
||||
import { SLO_ID_FIELD, SLO_INSTANCE_ID_FIELD } from '../../common/field_names/slo';
|
||||
import { ConfigSchema } from '../plugin';
|
||||
import { ObservabilityRuleTypeRegistry } from './create_observability_rule_type_registry';
|
||||
import { SLO_BURN_RATE_RULE_TYPE_ID } from '../../common/constants';
|
||||
import { validateBurnRateRule } from '../components/burn_rate_rule_editor/validation';
|
||||
import { validateCustomThreshold } from '../components/custom_threshold/components/validation';
|
||||
import { formatReason } from '../components/custom_threshold/rule_data_formatters';
|
||||
|
||||
const sloBurnRateDefaultActionMessage = i18n.translate(
|
||||
'xpack.observability.slo.rules.burnRate.defaultActionMessage',
|
||||
|
@ -71,9 +80,15 @@ const thresholdDefaultRecoveryMessage = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const registerObservabilityRuleTypes = (
|
||||
const getDataViewId = (searchConfiguration?: SerializedSearchSourceFields) =>
|
||||
typeof searchConfiguration?.index === 'string'
|
||||
? searchConfiguration.index
|
||||
: searchConfiguration?.index?.title;
|
||||
|
||||
export const registerObservabilityRuleTypes = async (
|
||||
config: ConfigSchema,
|
||||
observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry
|
||||
observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry,
|
||||
logExplorerLocator?: LocatorPublic<DiscoverAppLocatorParams>
|
||||
) => {
|
||||
observabilityRuleTypeRegistry.register({
|
||||
id: SLO_BURN_RATE_RULE_TYPE_ID,
|
||||
|
@ -121,7 +136,27 @@ export const registerObservabilityRuleTypes = (
|
|||
defaultActionMessage: thresholdDefaultActionMessage,
|
||||
defaultRecoveryMessage: thresholdDefaultRecoveryMessage,
|
||||
requiresAppContext: false,
|
||||
format: formatReason,
|
||||
format: ({ fields }) => {
|
||||
const searchConfiguration = fields[ALERT_RULE_PARAMETERS]?.searchConfiguration as
|
||||
| SerializedSearchSourceFields
|
||||
| undefined;
|
||||
const criteria = fields[ALERT_RULE_PARAMETERS]?.criteria as MetricExpression[];
|
||||
const metrics: CustomThresholdExpressionMetric[] =
|
||||
criteria.length === 1 ? criteria[0].metrics : [];
|
||||
|
||||
const dataViewId = getDataViewId(searchConfiguration);
|
||||
return {
|
||||
reason: fields[ALERT_REASON] ?? '-',
|
||||
link: getViewInAppUrl(
|
||||
metrics,
|
||||
fields[ALERT_START],
|
||||
logExplorerLocator,
|
||||
(searchConfiguration?.query as { query: string }).query,
|
||||
dataViewId
|
||||
),
|
||||
hasBasePath: true,
|
||||
};
|
||||
},
|
||||
alertDetailsAppSection: lazy(
|
||||
() => import('../components/custom_threshold/components/alert_details_app_section')
|
||||
),
|
||||
|
|
|
@ -15,4 +15,5 @@ export interface TopAlert<TAdditionalMetaFields extends Record<string, any> = {}
|
|||
reason: string;
|
||||
link?: string;
|
||||
active: boolean;
|
||||
hasBasePath?: boolean;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ import {
|
|||
} from '../../../../common/custom_threshold_rule/types';
|
||||
|
||||
jest.mock('./lib/evaluate_rule', () => ({ evaluateRule: jest.fn() }));
|
||||
jest.mock('../../../../common/custom_threshold_rule/get_view_in_app_url', () => ({
|
||||
getViewInAppUrl: () => 'mockedViewInApp',
|
||||
}));
|
||||
|
||||
interface AlertTestInstance {
|
||||
instance: AlertInstanceMock;
|
||||
|
@ -134,7 +137,7 @@ const setEvaluationResults = (response: Array<Record<string, Evaluation>>) => {
|
|||
jest.requireMock('./lib/evaluate_rule').evaluateRule.mockImplementation(() => response);
|
||||
};
|
||||
|
||||
describe('The metric threshold alert type', () => {
|
||||
describe('The custom threshold alert type', () => {
|
||||
describe('querying the entire infrastructure', () => {
|
||||
afterAll(() => clearInstances());
|
||||
const instanceID = '*';
|
||||
|
@ -1339,6 +1342,7 @@ describe('The metric threshold alert type', () => {
|
|||
timestamp: STARTED_AT_MOCK_DATE.toISOString(),
|
||||
value: ['[NO DATA]', null],
|
||||
tags: [],
|
||||
viewInAppUrl: 'mockedViewInApp',
|
||||
});
|
||||
expect(recentAction).toBeNoDataAction();
|
||||
});
|
||||
|
@ -1765,6 +1769,7 @@ const mockLibs: any = {
|
|||
groupByPageSize: 10_000,
|
||||
},
|
||||
},
|
||||
locators: {},
|
||||
};
|
||||
|
||||
const executor = createCustomThresholdExecutor(mockLibs);
|
||||
|
@ -1780,6 +1785,7 @@ const mockedIndex = {
|
|||
};
|
||||
const mockedDataView = {
|
||||
getIndexPattern: () => 'mockedIndexPattern',
|
||||
getName: () => 'mockedDataViewName',
|
||||
...mockedIndex,
|
||||
};
|
||||
const mockedSearchSource = {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { isEqual } from 'lodash';
|
||||
import { LogExplorerLocatorParams } from '@kbn/deeplinks-observability';
|
||||
import {
|
||||
ALERT_ACTION_GROUP,
|
||||
ALERT_EVALUATION_VALUES,
|
||||
|
@ -17,6 +18,7 @@ import { RecoveredActionGroup } from '@kbn/alerting-plugin/common';
|
|||
import { IBasePath, Logger } from '@kbn/core/server';
|
||||
import { LifecycleRuleExecutor } from '@kbn/rule-registry-plugin/server';
|
||||
import { AlertsLocatorParams, getAlertUrl } from '../../../../common';
|
||||
import { getViewInAppUrl } from '../../../../common/custom_threshold_rule/get_view_in_app_url';
|
||||
import { ObservabilityConfig } from '../../..';
|
||||
import { FIRED_ACTIONS_ID, NO_DATA_ACTIONS_ID, UNGROUPED_FACTORY_KEY } from './constants';
|
||||
import {
|
||||
|
@ -48,16 +50,21 @@ import { EvaluatedRuleParams, evaluateRule } from './lib/evaluate_rule';
|
|||
import { MissingGroupsRecord } from './lib/check_missing_group';
|
||||
import { convertStringsToMissingGroupsRecord } from './lib/convert_strings_to_missing_groups_record';
|
||||
|
||||
export interface CustomThresholdLocators {
|
||||
alertsLocator?: LocatorPublic<AlertsLocatorParams>;
|
||||
logExplorerLocator?: LocatorPublic<LogExplorerLocatorParams>;
|
||||
}
|
||||
|
||||
export const createCustomThresholdExecutor = ({
|
||||
alertsLocator,
|
||||
basePath,
|
||||
logger,
|
||||
config,
|
||||
locators: { alertsLocator, logExplorerLocator },
|
||||
}: {
|
||||
basePath: IBasePath;
|
||||
logger: Logger;
|
||||
config: ObservabilityConfig;
|
||||
alertsLocator?: LocatorPublic<AlertsLocatorParams>;
|
||||
locators: CustomThresholdLocators;
|
||||
}): LifecycleRuleExecutor<
|
||||
CustomThresholdRuleParams,
|
||||
CustomThresholdRuleTypeState,
|
||||
|
@ -132,21 +139,22 @@ export const createCustomThresholdExecutor = ({
|
|||
: [];
|
||||
|
||||
const initialSearchSource = await searchSourceClient.create(params.searchConfiguration!);
|
||||
const dataView = initialSearchSource.getField('index')!.getIndexPattern();
|
||||
const dataViewName = initialSearchSource.getField('index')!.name;
|
||||
const timeFieldName = initialSearchSource.getField('index')?.timeFieldName;
|
||||
if (!dataView) {
|
||||
const dataView = initialSearchSource.getField('index')!;
|
||||
const { id: dataViewId, timeFieldName } = dataView;
|
||||
const dataViewIndexPattern = dataView.getIndexPattern();
|
||||
const dataViewName = dataView.getName();
|
||||
if (!dataViewIndexPattern) {
|
||||
throw new Error('No matched data view');
|
||||
} else if (!timeFieldName) {
|
||||
throw new Error('The selected data view does not have a timestamp field');
|
||||
}
|
||||
|
||||
// Calculate initial start and end date with no time window, as each criteria has it's own time window
|
||||
// Calculate initial start and end date with no time window, as each criterion has its own time window
|
||||
const { dateStart, dateEnd } = getTimeRange();
|
||||
const alertResults = await evaluateRule(
|
||||
services.scopedClusterClient.asCurrentUser,
|
||||
params as EvaluatedRuleParams,
|
||||
dataView,
|
||||
dataViewIndexPattern,
|
||||
timeFieldName,
|
||||
compositeSize,
|
||||
alertOnGroupDisappear,
|
||||
|
@ -270,13 +278,20 @@ export const createCustomThresholdExecutor = ({
|
|||
group: groupByKeysObjectMapping[group],
|
||||
reason,
|
||||
timestamp,
|
||||
value: alertResults.map((result, index) => {
|
||||
value: alertResults.map((result) => {
|
||||
const evaluation = result[group];
|
||||
if (!evaluation) {
|
||||
return null;
|
||||
}
|
||||
return formatAlertResult(evaluation).currentValue;
|
||||
}),
|
||||
viewInAppUrl: getViewInAppUrl(
|
||||
alertResults.length === 1 ? alertResults[0][group].metrics : [],
|
||||
indexedStartedAt,
|
||||
logExplorerLocator,
|
||||
params.searchConfiguration.query.query,
|
||||
params.searchConfiguration?.index?.title ?? dataViewId
|
||||
),
|
||||
...additionalContext,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,13 +16,8 @@ import { legacyExperimentalFieldMap } from '@kbn/alerts-as-data-utils';
|
|||
import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils';
|
||||
import { createLifecycleExecutor, IRuleDataClient } from '@kbn/rule-registry-plugin/server';
|
||||
import { LicenseType } from '@kbn/licensing-plugin/server';
|
||||
import { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
import { EsQueryRuleParamsExtractedParams } from '@kbn/stack-alerts-plugin/server/rule_types/es_query/rule_type_params';
|
||||
import {
|
||||
AlertsLocatorParams,
|
||||
observabilityFeatureId,
|
||||
observabilityPaths,
|
||||
} from '../../../../common';
|
||||
import { observabilityFeatureId, observabilityPaths } from '../../../../common';
|
||||
import { Comparator } from '../../../../common/custom_threshold_rule/types';
|
||||
import { THRESHOLD_RULE_REGISTRATION_CONTEXT } from '../../../common/constants';
|
||||
|
||||
|
@ -38,9 +33,13 @@ import {
|
|||
tagsActionVariableDescription,
|
||||
timestampActionVariableDescription,
|
||||
valueActionVariableDescription,
|
||||
viewInAppUrlActionVariableDescription,
|
||||
} from './translations';
|
||||
import { oneOfLiterals, validateKQLStringFilter } from './utils';
|
||||
import { createCustomThresholdExecutor } from './custom_threshold_executor';
|
||||
import {
|
||||
createCustomThresholdExecutor,
|
||||
CustomThresholdLocators,
|
||||
} from './custom_threshold_executor';
|
||||
import { FIRED_ACTION, NO_DATA_ACTION } from './constants';
|
||||
import { ObservabilityConfig } from '../../..';
|
||||
|
||||
|
@ -69,7 +68,7 @@ export function thresholdRuleType(
|
|||
config: ObservabilityConfig,
|
||||
logger: Logger,
|
||||
ruleDataClient: IRuleDataClient,
|
||||
alertsLocator?: LocatorPublic<AlertsLocatorParams>
|
||||
locators: CustomThresholdLocators
|
||||
) {
|
||||
const baseCriterion = {
|
||||
threshold: schema.arrayOf(schema.number()),
|
||||
|
@ -128,7 +127,7 @@ export function thresholdRuleType(
|
|||
minimumLicenseRequired: 'basic' as LicenseType,
|
||||
isExportable: true,
|
||||
executor: createLifecycleRuleExecutor(
|
||||
createCustomThresholdExecutor({ alertsLocator, basePath, logger, config })
|
||||
createCustomThresholdExecutor({ basePath, logger, config, locators })
|
||||
),
|
||||
doesSetRecoveryContext: true,
|
||||
actionVariables: {
|
||||
|
@ -148,6 +147,7 @@ export function thresholdRuleType(
|
|||
{ name: 'orchestrator', description: orchestratorActionVariableDescription },
|
||||
{ name: 'labels', description: labelsActionVariableDescription },
|
||||
{ name: 'tags', description: tagsActionVariableDescription },
|
||||
{ name: 'viewInAppUrl', description: viewInAppUrlActionVariableDescription },
|
||||
],
|
||||
},
|
||||
useSavedObjectReferences: {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import { PluginSetupContract } from '@kbn/alerting-plugin/server';
|
||||
import { IBasePath, Logger } from '@kbn/core/server';
|
||||
import { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
import {
|
||||
createLifecycleExecutor,
|
||||
Dataset,
|
||||
|
@ -15,7 +14,8 @@ import {
|
|||
} from '@kbn/rule-registry-plugin/server';
|
||||
import { mappingFromFieldMap } from '@kbn/alerting-plugin/common';
|
||||
import { legacyExperimentalFieldMap } from '@kbn/alerts-as-data-utils';
|
||||
import { sloFeatureId, AlertsLocatorParams, observabilityFeatureId } from '../../../common';
|
||||
import { CustomThresholdLocators } from './custom_threshold/custom_threshold_executor';
|
||||
import { sloFeatureId, observabilityFeatureId } from '../../../common';
|
||||
import { ObservabilityConfig } from '../..';
|
||||
import {
|
||||
SLO_RULE_REGISTRATION_CONTEXT,
|
||||
|
@ -27,11 +27,11 @@ import { sloRuleFieldMap } from './slo_burn_rate/field_map';
|
|||
|
||||
export function registerRuleTypes(
|
||||
alertingPlugin: PluginSetupContract,
|
||||
logger: Logger,
|
||||
ruleDataService: IRuleDataService,
|
||||
basePath: IBasePath,
|
||||
config: ObservabilityConfig,
|
||||
alertsLocator?: LocatorPublic<AlertsLocatorParams>
|
||||
logger: Logger,
|
||||
ruleDataService: IRuleDataService,
|
||||
locators: CustomThresholdLocators
|
||||
) {
|
||||
// SLO RULE
|
||||
const ruleDataClientSLO = ruleDataService.initializeIndex({
|
||||
|
@ -55,7 +55,7 @@ export function registerRuleTypes(
|
|||
ruleDataClientSLO
|
||||
);
|
||||
alertingPlugin.registerType(
|
||||
sloBurnRateRuleType(createLifecycleRuleExecutorSLO, basePath, alertsLocator)
|
||||
sloBurnRateRuleType(createLifecycleRuleExecutorSLO, basePath, locators.alertsLocator)
|
||||
);
|
||||
|
||||
// Threshold RULE
|
||||
|
@ -85,7 +85,7 @@ export function registerRuleTypes(
|
|||
config,
|
||||
logger,
|
||||
ruleDataClientThreshold,
|
||||
alertsLocator
|
||||
locators
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
Plugin,
|
||||
PluginInitializerContext,
|
||||
} from '@kbn/core/server';
|
||||
import { LOG_EXPLORER_LOCATOR_ID, LogExplorerLocatorParams } from '@kbn/deeplinks-observability';
|
||||
import { PluginSetupContract as FeaturesSetup } from '@kbn/features-plugin/server';
|
||||
import { hiddenTypes as filesSavedObjectTypes } from '@kbn/files-plugin/server/saved_objects';
|
||||
import type { GuidedOnboardingPluginSetup } from '@kbn/guided-onboarding-plugin/server';
|
||||
|
@ -101,6 +102,8 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
|
|||
const config = this.initContext.config.get<ObservabilityConfig>();
|
||||
|
||||
const alertsLocator = plugins.share.url.locators.create(new AlertsLocatorDefinition());
|
||||
const logExplorerLocator =
|
||||
plugins.share.url.locators.get<LogExplorerLocatorParams>(LOG_EXPLORER_LOCATOR_ID);
|
||||
|
||||
plugins.features.registerKibanaFeature({
|
||||
id: casesFeatureId,
|
||||
|
@ -332,14 +335,10 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
|
|||
core.savedObjects.registerType(slo);
|
||||
core.savedObjects.registerType(threshold);
|
||||
|
||||
registerRuleTypes(
|
||||
plugins.alerting,
|
||||
this.logger,
|
||||
ruleDataService,
|
||||
core.http.basePath,
|
||||
config,
|
||||
alertsLocator
|
||||
);
|
||||
registerRuleTypes(plugins.alerting, core.http.basePath, config, this.logger, ruleDataService, {
|
||||
alertsLocator,
|
||||
logExplorerLocator,
|
||||
});
|
||||
registerSloUsageCollector(plugins.usageCollection);
|
||||
|
||||
core.getStartServices().then(([coreStart, pluginStart]) => {
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"@kbn/rison",
|
||||
"@kbn/io-ts-utils",
|
||||
"@kbn/observability-alert-details",
|
||||
"@kbn/observability-get-padded-alert-time-range-util",
|
||||
"@kbn/ui-actions-plugin",
|
||||
"@kbn/field-types",
|
||||
"@kbn/safer-lodash-set",
|
||||
|
|
|
@ -5143,6 +5143,10 @@
|
|||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/observability-get-padded-alert-time-range-util@link:x-pack/packages/observability/get_padded_alert_time_range_util":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/observability-log-explorer-plugin@link:x-pack/plugins/observability_log_explorer":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue