Skip to content

Commit

Permalink
[RAC][UPTIME] -126229 - Add view in app url as an action variable in …
Browse files Browse the repository at this point in the history
…the alert message for uptime app (#127478)

* Expose getMonitorRouteFromMonitorId in the common folder

* Remove unused import

* WIP

* Fix some issues

* Add 5 min before when the alert is raised

* Update status

* Cover the autogenerated use case

* Update tests

* Updated tests

* Use indexedStartedAt and full URL

* Take into consideration the kibanaBase path

* Fix URL

* LINT

* Fix tests

* Use IBasePath for clarity and update related tests

* Optim - use getViewInAppUrl

* Add duration anomaly and fix tests

* Fix tests

* Rename server var

* Remove join
  • Loading branch information
fkanout authored Mar 23, 2022
1 parent d3d36cf commit daea5a8
Show file tree
Hide file tree
Showing 14 changed files with 145 additions and 55 deletions.
40 changes: 40 additions & 0 deletions x-pack/plugins/uptime/common/utils/get_monitor_url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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 { stringify } from 'querystring';

export const format = ({
pathname,
query,
}: {
pathname: string;
query: Record<string, any>;
}): string => {
return `${pathname}?${stringify(query)}`;
};

export const getMonitorRouteFromMonitorId = ({
monitorId,
dateRangeStart,
dateRangeEnd,
filters = {},
}: {
monitorId: string;
dateRangeStart: string;
dateRangeEnd: string;
filters?: Record<string, string[]>;
}) =>
format({
pathname: `/app/uptime/monitor/${btoa(monitorId)}`,
query: {
dateRangeEnd,
dateRangeStart,
...(Object.keys(filters).length
? { filters: JSON.stringify(Object.keys(filters).map((key) => [key, filters[key]])) }
: {}),
},
});
34 changes: 0 additions & 34 deletions x-pack/plugins/uptime/public/lib/alert_types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,6 @@
* 2.0.
*/

import { stringify } from 'querystring';

export const format = ({
pathname,
query,
}: {
pathname: string;
query: Record<string, any>;
}): string => {
return `${pathname}?${stringify(query)}`;
};

export const getMonitorRouteFromMonitorId = ({
monitorId,
dateRangeStart,
dateRangeEnd,
filters = {},
}: {
monitorId: string;
dateRangeStart: string;
dateRangeEnd: string;
filters?: Record<string, string[]>;
}) =>
format({
pathname: `/app/uptime/monitor/${btoa(monitorId)}`,
query: {
dateRangeEnd,
dateRangeStart,
...(Object.keys(filters).length
? { filters: JSON.stringify(Object.keys(filters).map((key) => [key, filters[key]])) }
: {}),
},
});

export const getUrlForAlert = (id: string, basePath: string) => {
return basePath + '/app/management/insightsAndAlerting/triggersActions/alert/' + id;
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import moment from 'moment';
import { ALERT_END, ALERT_STATUS, ALERT_STATUS_ACTIVE, ALERT_REASON } from '@kbn/rule-data-utils';

import { AlertTypeInitializer } from '.';
import { getMonitorRouteFromMonitorId } from './common';
import { getMonitorRouteFromMonitorId } from '../../../common/utils/get_monitor_url';
import { CLIENT_ALERT_TYPES } from '../../../common/constants/alerts';
import { DurationAnomalyTranslations } from '../../../common/translations';
import { ObservabilityRuleTypeModel } from '../../../../observability/public';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from '@kbn/rule-data-utils';

import { AlertTypeInitializer } from '.';
import { getMonitorRouteFromMonitorId } from './common';
import { getMonitorRouteFromMonitorId } from '../../../common/utils/get_monitor_url';
import { MonitorStatusTranslations } from '../../../common/translations';
import { CLIENT_ALERT_TYPES } from '../../../common/constants/alerts';
import { ObservabilityRuleTypeModel } from '../../../../observability/public';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
*/

import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import type { SavedObjectsClientContract, IScopedClusterClient, Logger } from 'src/core/server';
import type {
SavedObjectsClientContract,
IScopedClusterClient,
Logger,
IBasePath,
} from 'src/core/server';
import type { TelemetryPluginSetup, TelemetryPluginStart } from 'src/plugins/telemetry/server';
import { ObservabilityPluginSetup } from '../../../../../observability/server';
import {
Expand Down Expand Up @@ -56,6 +61,7 @@ export interface UptimeServerSetup {
logger: Logger;
telemetry: TelemetryEventsSender;
uptimeEsClient: UptimeESClient;
basePath: IBasePath;
}

export interface UptimeCorePluginsSetup {
Expand Down
11 changes: 11 additions & 0 deletions x-pack/plugins/uptime/server/lib/alerts/action_variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n';
export const MESSAGE = 'message';
export const MONITOR_WITH_GEO = 'downMonitorsWithGeo';
export const ALERT_REASON_MSG = 'reason';
export const VIEW_IN_APP_URL = 'viewInAppUrl';

export const ACTION_VARIABLES = {
[MESSAGE]: {
Expand Down Expand Up @@ -40,4 +41,14 @@ export const ACTION_VARIABLES = {
}
),
},
[VIEW_IN_APP_URL]: {
name: VIEW_IN_APP_URL,
description: i18n.translate(
'xpack.uptime.alerts.monitorStatus.actionVariables.context.viewInAppUrl.description',
{
defaultMessage:
'Link to the view or feature within Elastic that can be used to investigate the alert and its context further',
}
),
},
};
5 changes: 5 additions & 0 deletions x-pack/plugins/uptime/server/lib/alerts/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { isRight } from 'fp-ts/lib/Either';
import Mustache from 'mustache';
import { IBasePath } from 'kibana/server';
import { UptimeCommonState, UptimeCommonStateType } from '../../../common/runtime_types';

export type UpdateUptimeAlertState = (
Expand Down Expand Up @@ -60,3 +61,7 @@ export const updateState: UpdateUptimeAlertState = (state, isTriggeredNow) => {
export const generateAlertMessage = (messageTemplate: string, fields: Record<string, any>) => {
return Mustache.render(messageTemplate, { state: { ...fields } });
};
export const getViewInAppUrl = (relativeViewInAppUrl: string, basePath: IBasePath) =>
basePath.publicBaseUrl
? new URL(basePath.prepend(relativeViewInAppUrl), basePath.publicBaseUrl).toString()
: relativeViewInAppUrl;
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { DynamicSettings } from '../../../common/runtime_types';
import { createRuleTypeMocks, bootstrapDependencies } from './test_utils';
import { getSeverityType } from '../../../../ml/common/util/anomaly_utils';
import { Ping } from '../../../common/runtime_types/ping';
import { ALERT_REASON_MSG } from './action_variables';
import { ALERT_REASON_MSG, VIEW_IN_APP_URL } from './action_variables';

interface MockAnomaly {
severity: AnomaliesTableRecord['severity'];
Expand Down Expand Up @@ -219,6 +219,7 @@ Response times as high as ${slowestResponse} ms have been detected from location
"xpack.uptime.alerts.actionGroups.durationAnomaly",
Object {
"${ALERT_REASON_MSG}": "${reasonMessages[0]}",
"${VIEW_IN_APP_URL}": "http://localhost:5601/hfe/app/uptime/monitor/eHBhY2sudXB0aW1lLmFsZXJ0cy5hY3Rpb25Hcm91cHMuZHVyYXRpb25Bbm9tYWx5MA==?dateRangeEnd=now&dateRangeStart=2022-03-17T13%3A13%3A33.755Z",
},
]
`);
Expand All @@ -227,6 +228,7 @@ Response times as high as ${slowestResponse} ms have been detected from location
"xpack.uptime.alerts.actionGroups.durationAnomaly",
Object {
"${ALERT_REASON_MSG}": "${reasonMessages[1]}",
"${VIEW_IN_APP_URL}": "http://localhost:5601/hfe/app/uptime/monitor/eHBhY2sudXB0aW1lLmFsZXJ0cy5hY3Rpb25Hcm91cHMuZHVyYXRpb25Bbm9tYWx5MQ==?dateRangeEnd=now&dateRangeStart=2022-03-17T13%3A13%3A33.755Z",
},
]
`);
Expand Down
25 changes: 19 additions & 6 deletions x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
ALERT_REASON,
} from '@kbn/rule-data-utils';
import { ActionGroupIdsOf } from '../../../../alerting/common';
import { updateState, generateAlertMessage } from './common';
import { updateState, generateAlertMessage, getViewInAppUrl } from './common';
import { DURATION_ANOMALY } from '../../../common/constants/alerts';
import { commonStateTranslations, durationAnomalyTranslations } from './translations';
import { AnomaliesTableRecord } from '../../../../ml/common/types/anomalies';
Expand All @@ -24,9 +24,10 @@ import { Ping } from '../../../common/runtime_types/ping';
import { getMLJobId } from '../../../common/lib';

import { DurationAnomalyTranslations as CommonDurationAnomalyTranslations } from '../../../common/translations';
import { getMonitorRouteFromMonitorId } from '../../../common/utils/get_monitor_url';

import { createUptimeESClient } from '../lib';
import { ALERT_REASON_MSG, ACTION_VARIABLES } from './action_variables';
import { ALERT_REASON_MSG, ACTION_VARIABLES, VIEW_IN_APP_URL } from './action_variables';

export type ActionGroupIds = ActionGroupIdsOf<typeof DURATION_ANOMALY>;

Expand Down Expand Up @@ -72,7 +73,7 @@ const getAnomalies = async (
};

export const durationAnomalyAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (
_server,
server,
libs,
plugins
) => ({
Expand All @@ -93,20 +94,23 @@ export const durationAnomalyAlertFactory: UptimeAlertTypeFactory<ActionGroupIds>
},
],
actionVariables: {
context: [ACTION_VARIABLES[ALERT_REASON_MSG]],
context: [ACTION_VARIABLES[ALERT_REASON_MSG], ACTION_VARIABLES[VIEW_IN_APP_URL]],
state: [...durationAnomalyTranslations.actionVariables, ...commonStateTranslations],
},
isExportable: true,
minimumLicenseRequired: 'platinum',
async executor({
params,
services: { alertWithLifecycle, scopedClusterClient, savedObjectsClient },
services: { alertWithLifecycle, scopedClusterClient, savedObjectsClient, getAlertStartedDate },
state,
startedAt,
}) {
const uptimeEsClient = createUptimeESClient({
esClient: scopedClusterClient.asCurrentUser,
savedObjectsClient,
});
const { basePath } = server;

const { anomalies } =
(await getAnomalies(plugins, savedObjectsClient, params, state.lastCheckedAt as string)) ??
{};
Expand All @@ -128,8 +132,16 @@ export const durationAnomalyAlertFactory: UptimeAlertTypeFactory<ActionGroupIds>
summary
);

const alertId = DURATION_ANOMALY.id + index;
const indexedStartedAt = getAlertStartedDate(alertId) ?? startedAt.toISOString();
const relativeViewInAppUrl = getMonitorRouteFromMonitorId({
monitorId: DURATION_ANOMALY.id + index,
dateRangeEnd: 'now',
dateRangeStart: indexedStartedAt,
});

const alertInstance = alertWithLifecycle({
id: DURATION_ANOMALY.id + index,
id: alertId,
fields: {
'monitor.id': params.monitorId,
'url.full': summary.monitorUrl,
Expand All @@ -147,6 +159,7 @@ export const durationAnomalyAlertFactory: UptimeAlertTypeFactory<ActionGroupIds>
});
alertInstance.scheduleActions(DURATION_ANOMALY.id, {
[ALERT_REASON_MSG]: alertReasonMessage,
[VIEW_IN_APP_URL]: getViewInAppUrl(relativeViewInAppUrl, basePath),
});
});
}
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/uptime/server/lib/alerts/status_check.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ describe('status check alert', () => {
"xpack.uptime.alerts.actionGroups.monitorStatus",
Object {
"reason": "First from harrisburg failed 234 times in the last 15 mins. Alert when > 5.",
"viewInAppUrl": "http://localhost:5601/hfe/app/uptime/monitor/Zmlyc3Q=?dateRangeEnd=now&dateRangeStart=2022-03-17T13%3A13%3A33.755Z&filters=%5B%5B%22observer.geo.name%22%2C%5B%22harrisburg%22%5D%5D%5D",
},
]
`);
Expand Down Expand Up @@ -313,6 +314,7 @@ describe('status check alert', () => {
"xpack.uptime.alerts.actionGroups.monitorStatus",
Object {
"reason": "First from harrisburg failed 234 times in the last 15m. Alert when > 5.",
"viewInAppUrl": "http://localhost:5601/hfe/app/uptime/monitor/Zmlyc3Q=?dateRangeEnd=now&dateRangeStart=2022-03-17T13%3A13%3A33.755Z&filters=%5B%5B%22observer.geo.name%22%2C%5B%22harrisburg%22%5D%5D%5D",
},
]
`);
Expand Down Expand Up @@ -784,24 +786,28 @@ describe('status check alert', () => {
"xpack.uptime.alerts.actionGroups.monitorStatus",
Object {
"reason": "Foo from harrisburg 35 days availability is 99.28%. Alert when < 99.34%.",
"viewInAppUrl": "http://localhost:5601/hfe/app/uptime/monitor/Zm9v?dateRangeEnd=now&dateRangeStart=2022-03-17T13%3A13%3A33.755Z&filters=%5B%5B%22observer.geo.name%22%2C%5B%22harrisburg%22%5D%5D%5D",
},
],
Array [
"xpack.uptime.alerts.actionGroups.monitorStatus",
Object {
"reason": "Foo from fairbanks 35 days availability is 98.03%. Alert when < 99.34%.",
"viewInAppUrl": "http://localhost:5601/hfe/app/uptime/monitor/Zm9v?dateRangeEnd=now&dateRangeStart=2022-03-17T13%3A13%3A33.755Z&filters=%5B%5B%22observer.geo.name%22%2C%5B%22fairbanks%22%5D%5D%5D",
},
],
Array [
"xpack.uptime.alerts.actionGroups.monitorStatus",
Object {
"reason": "Unreliable from fairbanks 35 days availability is 90.92%. Alert when < 99.34%.",
"viewInAppUrl": "http://localhost:5601/hfe/app/uptime/monitor/dW5yZWxpYWJsZQ==?dateRangeEnd=now&dateRangeStart=2022-03-17T13%3A13%3A33.755Z&filters=%5B%5B%22observer.geo.name%22%2C%5B%22fairbanks%22%5D%5D%5D",
},
],
Array [
"xpack.uptime.alerts.actionGroups.monitorStatus",
Object {
"reason": "no-name from fairbanks 35 days availability is 90.92%. Alert when < 99.34%.",
"viewInAppUrl": "http://localhost:5601/hfe/app/uptime/monitor/bm8tbmFtZQ==?dateRangeEnd=now&dateRangeStart=2022-03-17T13%3A13%3A33.755Z&filters=%5B%5B%22observer.geo.name%22%2C%5B%22fairbanks%22%5D%5D%5D",
},
],
]
Expand Down
Loading

0 comments on commit daea5a8

Please sign in to comment.