Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Custom threshold][Alert details page] Deprecate feature flag for Custom threshold rule alert details page #176666

Merged
Merged
2 changes: 2 additions & 0 deletions packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
*/

export const OBSERVABILITY_THRESHOLD_RULE_TYPE_ID = 'observability.rules.custom_threshold';
export const SLO_BURN_RATE_RULE_TYPE_ID = 'slo.rules.burnRate';

export const METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.inventory.threshold';
export const LOG_THRESHOLD_ALERT_TYPE_ID = 'logs.alert.document.count';

export enum ApmRuleType {
ErrorCount = 'apm.error_rate', // ErrorRate was renamed to ErrorCount but the key is kept as `error_rate` for backwards-compat.
Expand Down
6 changes: 0 additions & 6 deletions x-pack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ xpack.observability.unsafe.alertDetails.uptime.enabled: true

**[For Uptime rule type]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table

```yaml
xpack.observability.unsafe.alertDetails.observability.enabled: true
```

**[For Observability Threshold rule type]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table

# Development

By default, Kibana will run with X-Pack installed as mentioned in the [contributing guide](../CONTRIBUTING.md).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({
apm: { enabled: false },
metrics: { enabled: false },
uptime: { enabled: false },
observability: { enabled: false },
},
},
aiAssistant: {
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/observability/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export interface ConfigSchema {
uptime: {
enabled: boolean;
};
observability: {
observability?: {
enabled: boolean;
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,26 @@
*/

import { ALERT_RULE_TYPE_ID } from '@kbn/rule-data-utils';
import {
ApmRuleType,
LOG_THRESHOLD_ALERT_TYPE_ID,
OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
SLO_BURN_RATE_RULE_TYPE_ID,
} from '@kbn/rule-data-utils';
import type { ConfigSchema } from '../plugin';
import type { TopAlert } from '../typings/alerts';

const ALLOWED_RULE_TYPES = [
'apm.transaction_duration',
'logs.alert.document.count',
'slo.rules.burnRate',
ApmRuleType.TransactionDuration,
LOG_THRESHOLD_ALERT_TYPE_ID,
OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
SLO_BURN_RATE_RULE_TYPE_ID,
];

const isUnsafeAlertDetailsFlag = (
subject: string
): subject is keyof Omit<ConfigSchema['unsafe']['alertDetails'], 'logs'> =>
['uptime', 'metrics', 'observability'].includes(subject);
): subject is keyof Omit<ConfigSchema['unsafe']['alertDetails'], 'logs' | 'observability'> =>
['uptime', 'metrics'].includes(subject);

// We are mapping the ruleTypeId from the feature flag with the ruleTypeId from the alert
// to know whether the feature flag is enabled or not.
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/observability/public/utils/test_helper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ const defaultConfig: ConfigSchema = {
alertDetails: {
metrics: { enabled: false },
uptime: { enabled: false },
observability: { enabled: false },
},
},
};
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/observability/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export const config: PluginConfigDescriptor = {
deprecations: ({ unused }) => [
unused('unsafe.thresholdRule.enabled', { level: 'warning' }),
unused('unsafe.alertDetails.logs.enabled', { level: 'warning' }),
unused('unsafe.alertDetails.observability.enabled', { level: 'warning' }),
],
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1400,7 +1400,7 @@ describe('The custom threshold alert type', () => {
await execute(true);
const recentAction = mostRecentAction(instanceID);
expect(recentAction.action).toEqual({
alertDetailsUrl: '',
alertDetailsUrl: 'http://localhost:5601/app/observability/alerts/mock-alert-uuid',
reason: 'Average test.metric.3 reported no data in the last 1m',
timestamp: STARTED_AT_MOCK_DATE.toISOString(),
value: ['[NO DATA]', null],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { RecoveredActionGroup } from '@kbn/alerting-plugin/common';
import { IBasePath, Logger } from '@kbn/core/server';
import { LifecycleRuleExecutor } from '@kbn/rule-registry-plugin/server';
import { getEvaluationValues, getThreshold } from './lib/get_values';
import { AlertsLocatorParams, getAlertUrl } from '../../../../common';
import { AlertsLocatorParams, getAlertDetailsUrl } 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';
Expand Down Expand Up @@ -278,13 +278,7 @@ export const createCustomThresholdExecutor = ({
scheduledActionsCount++;

alert.scheduleActions(actionGroupId, {
alertDetailsUrl: await getAlertUrl(
alertUuid,
spaceId,
indexedStartedAt,
alertsLocator,
basePath.publicBaseUrl
),
alertDetailsUrl: getAlertDetailsUrl(basePath, spaceId, alertUuid),
group: groupByKeysObjectMapping[group],
reason,
timestamp,
Expand Down Expand Up @@ -327,13 +321,7 @@ export const createCustomThresholdExecutor = ({
const additionalContext = getContextForRecoveredAlerts(alertHits);

alert.setContext({
alertDetailsUrl: await getAlertUrl(
alertUuid,
spaceId,
indexedStartedAt,
alertsLocator,
basePath.publicBaseUrl
),
alertDetailsUrl: getAlertDetailsUrl(basePath, spaceId, alertUuid),
group,
timestamp: startedAt.toISOString(),
viewInAppUrl: getViewInAppUrl({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import moment from 'moment';
import { omit } from 'lodash';
import { cleanup, generate, Dataset, PartialConfig } from '@kbn/data-forge';
import {
Expand Down Expand Up @@ -232,15 +231,14 @@ export default function ({ getService }: FtrProviderContext) {
});

it('should set correct action variables', async () => {
const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString();
const resp = await waitForDocumentInIndex<ActionDocument>({
esClient,
indexName: ALERT_ACTION_INDEX,
});

expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)`
`https://localhost:5601/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`Average system.cpu.user.pct is 250%, above the threshold of 50%. (duration: 5 mins, data view: ${DATA_VIEW_NAME})`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

import { omit } from 'lodash';
import moment from 'moment';
import {
Aggregators,
Comparator,
Expand Down Expand Up @@ -200,15 +199,14 @@ export default function ({ getService }: FtrProviderContext) {
});

it('should set correct action variables', async () => {
const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString();
const resp = await waitForDocumentInIndex<ActionDocument>({
esClient,
indexName: ALERT_ACTION_INDEX,
});

expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)`
`https://localhost:5601/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
'Average system.cpu.user.pct reported no data in the last 5m'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,14 @@ export default function ({ getService }: FtrProviderContext) {
});

it('should set correct action parameter: ruleType', async () => {
const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString();
const resp = await waitForDocumentInIndex<ActionDocument>({
esClient,
indexName: ALERT_ACTION_INDEX,
});

expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)`
`https://localhost:5601/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`Average span.self_time.sum.us is 10,000,000, above the threshold of 7,500,000. (duration: 5 mins, data view: ${DATA_VIEW_NAME})`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import moment from 'moment';
import { cleanup, generate, Dataset, PartialConfig } from '@kbn/data-forge';
import {
Aggregators,
Expand Down Expand Up @@ -230,15 +229,14 @@ export default function ({ getService }: FtrProviderContext) {
});

it('should set correct action variables', async () => {
const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString();
const resp = await waitForDocumentInIndex<ActionDocument>({
esClient,
indexName: ALERT_ACTION_INDEX,
});

expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)`
`https://localhost:5601/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`Custom equation is 1, above the threshold of 0.9. (duration: 1 min, data view: ${DATA_VIEW})`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

import { omit } from 'lodash';
import moment from 'moment';
import expect from '@kbn/expect';
import { cleanup, generate, Dataset, PartialConfig } from '@kbn/data-forge';
import {
Expand Down Expand Up @@ -231,15 +230,14 @@ export default function ({ getService }: FtrProviderContext) {
});

it('should set correct action variables', async () => {
const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString();
const resp = await waitForDocumentInIndex<ActionDocument>({
esClient,
indexName: ALERT_ACTION_INDEX,
});

expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)`
`https://localhost:5601/app/observability/alerts/${alertId}`
);

expect(resp.hits.hits[0]._source?.reason).eql(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import moment from 'moment';
import { cleanup, generate, Dataset, PartialConfig } from '@kbn/data-forge';
import {
Aggregators,
Expand Down Expand Up @@ -251,15 +250,14 @@ export default function ({ getService }: FtrProviderContext) {
});

it('should set correct action variables', async () => {
const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString();
const resp = await waitForDocumentInIndex<ActionDocument>({
esClient,
indexName: ALERT_ACTION_INDEX,
});

expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)`
`https://localhost:5601/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`Average system.cpu.total.norm.pct is 80%, above or equal the threshold of 20%. (duration: 1 min, data view: ${DATA_VIEW}, group: host-0,container-0)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import moment from 'moment';
import { omit } from 'lodash';
import { cleanup, generate, Dataset, PartialConfig } from '@kbn/data-forge';
import {
Expand Down Expand Up @@ -227,15 +226,14 @@ export default function ({ getService }: FtrProviderContext) {
});

it('should set correct action variables', async () => {
const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString();
const resp = await waitForDocumentInIndex<ActionDocument>({
esClient,
indexName: ALERT_ACTION_INDEX,
});

expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)`
`https://localhost:5601/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`99th percentile of system.cpu.user.pct is 250%, above the threshold of 50%. (duration: 5 mins, data view: ${DATE_VIEW_NAME})`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import moment from 'moment';
import { cleanup, generate, Dataset, PartialConfig } from '@kbn/data-forge';
import {
Aggregators,
Expand Down Expand Up @@ -247,15 +246,14 @@ export default function ({ getService }: FtrProviderContext) {
});

it('should set correct action variables', async () => {
const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString();
const resp = await waitForDocumentInIndex<ActionDocument>({
esClient,
indexName: ALERT_ACTION_INDEX,
});

expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)`
`https://localhost:5601/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`Rate of system.network.in.bytes is 0.3 B/s, above or equal the threshold of 0.2 B/s. (duration: 1 min, data view: kbn-data-forge-fake_hosts.fake_hosts-*, group: host-0,container-0)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
*/

import { kbnTestConfig } from '@kbn/test';
import moment from 'moment';
import { cleanup, generate, Dataset, PartialConfig } from '@kbn/data-forge';
import {
Aggregators,
Expand Down Expand Up @@ -238,7 +237,6 @@ export default function ({ getService }: FtrProviderContext) {
});

it('should set correct action variables', async () => {
const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString();
const resp = await alertingApi.waitForDocumentInIndex<{
ruleType: string;
alertDetailsUrl: string;
Expand All @@ -252,7 +250,7 @@ export default function ({ getService }: FtrProviderContext) {

expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`${protocol}://${hostname}:${port}/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)`
`${protocol}://${hostname}:${port}/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`Average system.cpu.total.norm.pct is 80%, above or equal the threshold of 20%. (duration: 1 min, data view: ${DATA_VIEW}, group: host-0)`
Expand Down