From daea5a8519dafccdab851f7436941ef58a974ba7 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Wed, 23 Mar 2022 12:18:50 +0300 Subject: [PATCH] [RAC][UPTIME] -126229 - Add view in app url as an action variable in 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 --- .../uptime/common/utils/get_monitor_url.ts | 40 +++++++++++++++ .../uptime/public/lib/alert_types/common.ts | 34 ------------- .../lib/alert_types/duration_anomaly.tsx | 2 +- .../public/lib/alert_types/monitor_status.tsx | 2 +- .../lib/adapters/framework/adapter_types.ts | 8 ++- .../server/lib/alerts/action_variables.ts | 11 +++++ .../uptime/server/lib/alerts/common.ts | 5 ++ .../lib/alerts/duration_anomaly.test.ts | 4 +- .../server/lib/alerts/duration_anomaly.ts | 25 +++++++--- .../server/lib/alerts/status_check.test.ts | 6 +++ .../uptime/server/lib/alerts/status_check.ts | 49 +++++++++++++++---- .../server/lib/alerts/test_utils/index.ts | 12 ++++- .../plugins/uptime/server/lib/alerts/types.ts | 1 + x-pack/plugins/uptime/server/plugin.ts | 1 + 14 files changed, 145 insertions(+), 55 deletions(-) create mode 100644 x-pack/plugins/uptime/common/utils/get_monitor_url.ts diff --git a/x-pack/plugins/uptime/common/utils/get_monitor_url.ts b/x-pack/plugins/uptime/common/utils/get_monitor_url.ts new file mode 100644 index 0000000000000..09b02150957d0 --- /dev/null +++ b/x-pack/plugins/uptime/common/utils/get_monitor_url.ts @@ -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 => { + return `${pathname}?${stringify(query)}`; +}; + +export const getMonitorRouteFromMonitorId = ({ + monitorId, + dateRangeStart, + dateRangeEnd, + filters = {}, +}: { + monitorId: string; + dateRangeStart: string; + dateRangeEnd: string; + filters?: Record; +}) => + 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]])) } + : {}), + }, + }); diff --git a/x-pack/plugins/uptime/public/lib/alert_types/common.ts b/x-pack/plugins/uptime/public/lib/alert_types/common.ts index 6a45f73357597..0835cc4b5202c 100644 --- a/x-pack/plugins/uptime/public/lib/alert_types/common.ts +++ b/x-pack/plugins/uptime/public/lib/alert_types/common.ts @@ -5,40 +5,6 @@ * 2.0. */ -import { stringify } from 'querystring'; - -export const format = ({ - pathname, - query, -}: { - pathname: string; - query: Record; -}): string => { - return `${pathname}?${stringify(query)}`; -}; - -export const getMonitorRouteFromMonitorId = ({ - monitorId, - dateRangeStart, - dateRangeEnd, - filters = {}, -}: { - monitorId: string; - dateRangeStart: string; - dateRangeEnd: string; - filters?: Record; -}) => - 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; }; diff --git a/x-pack/plugins/uptime/public/lib/alert_types/duration_anomaly.tsx b/x-pack/plugins/uptime/public/lib/alert_types/duration_anomaly.tsx index cdd0441575b33..d6498015e41ce 100644 --- a/x-pack/plugins/uptime/public/lib/alert_types/duration_anomaly.tsx +++ b/x-pack/plugins/uptime/public/lib/alert_types/duration_anomaly.tsx @@ -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'; diff --git a/x-pack/plugins/uptime/public/lib/alert_types/monitor_status.tsx b/x-pack/plugins/uptime/public/lib/alert_types/monitor_status.tsx index 9737753df0225..5d6f8f3fea333 100644 --- a/x-pack/plugins/uptime/public/lib/alert_types/monitor_status.tsx +++ b/x-pack/plugins/uptime/public/lib/alert_types/monitor_status.tsx @@ -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'; diff --git a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts index 9efb7e36ebab9..d9dadc81397ce 100644 --- a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts @@ -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 { @@ -56,6 +61,7 @@ export interface UptimeServerSetup { logger: Logger; telemetry: TelemetryEventsSender; uptimeEsClient: UptimeESClient; + basePath: IBasePath; } export interface UptimeCorePluginsSetup { diff --git a/x-pack/plugins/uptime/server/lib/alerts/action_variables.ts b/x-pack/plugins/uptime/server/lib/alerts/action_variables.ts index 48fa6e45f19a8..763cccb404e51 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/action_variables.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/action_variables.ts @@ -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]: { @@ -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', + } + ), + }, }; diff --git a/x-pack/plugins/uptime/server/lib/alerts/common.ts b/x-pack/plugins/uptime/server/lib/alerts/common.ts index 6bf9d28c2da9e..542aaa27819a3 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/common.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/common.ts @@ -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 = ( @@ -60,3 +61,7 @@ export const updateState: UpdateUptimeAlertState = (state, isTriggeredNow) => { export const generateAlertMessage = (messageTemplate: string, fields: Record) => { return Mustache.render(messageTemplate, { state: { ...fields } }); }; +export const getViewInAppUrl = (relativeViewInAppUrl: string, basePath: IBasePath) => + basePath.publicBaseUrl + ? new URL(basePath.prepend(relativeViewInAppUrl), basePath.publicBaseUrl).toString() + : relativeViewInAppUrl; diff --git a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.test.ts b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.test.ts index 208f19354a0f3..2848df14776b5 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.test.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.test.ts @@ -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']; @@ -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", }, ] `); @@ -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", }, ] `); diff --git a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts index 1dcb91b9e5270..d1e83c917d6f7 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/duration_anomaly.ts @@ -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'; @@ -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; @@ -72,7 +73,7 @@ const getAnomalies = async ( }; export const durationAnomalyAlertFactory: UptimeAlertTypeFactory = ( - _server, + server, libs, plugins ) => ({ @@ -93,20 +94,23 @@ export const durationAnomalyAlertFactory: UptimeAlertTypeFactory }, ], 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)) ?? {}; @@ -128,8 +132,16 @@ export const durationAnomalyAlertFactory: UptimeAlertTypeFactory 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, @@ -147,6 +159,7 @@ export const durationAnomalyAlertFactory: UptimeAlertTypeFactory }); alertInstance.scheduleActions(DURATION_ANOMALY.id, { [ALERT_REASON_MSG]: alertReasonMessage, + [VIEW_IN_APP_URL]: getViewInAppUrl(relativeViewInAppUrl, basePath), }); }); } diff --git a/x-pack/plugins/uptime/server/lib/alerts/status_check.test.ts b/x-pack/plugins/uptime/server/lib/alerts/status_check.test.ts index d2e4a8dbc044e..84e7c0d68400c 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/status_check.test.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.test.ts @@ -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", }, ] `); @@ -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", }, ] `); @@ -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", }, ], ] diff --git a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts index fe93928cb7e02..6d9a0d23d9d32 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts @@ -5,6 +5,7 @@ * 2.0. */ import { min } from 'lodash'; + import datemath from '@elastic/datemath'; import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; @@ -18,7 +19,7 @@ import { GetMonitorAvailabilityParams, } from '../../../common/runtime_types'; import { MONITOR_STATUS } from '../../../common/constants/alerts'; -import { updateState } from './common'; +import { updateState, getViewInAppUrl } from './common'; import { commonMonitorStateI18, commonStateTranslations, @@ -36,7 +37,14 @@ import { getUptimeIndexPattern, IndexPatternTitleAndFields } from '../requests/g import { UMServerLibs, UptimeESClient, createUptimeESClient } from '../lib'; import { ActionGroupIdsOf } from '../../../../alerting/common'; import { formatDurationFromTimeUnitChar, TimeUnitChar } from '../../../../observability/common'; -import { ALERT_REASON_MSG, MESSAGE, MONITOR_WITH_GEO, ACTION_VARIABLES } from './action_variables'; +import { + ALERT_REASON_MSG, + MESSAGE, + MONITOR_WITH_GEO, + ACTION_VARIABLES, + VIEW_IN_APP_URL, +} from './action_variables'; +import { getMonitorRouteFromMonitorId } from '../../../common/utils/get_monitor_url'; export type ActionGroupIds = ActionGroupIdsOf; /** @@ -214,7 +222,7 @@ export const getInstanceId = (monitorInfo: Ping, monIdByLoc: string) => { return `${urlText}_${monIdByLoc}`; }; -export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) => ({ +export const statusCheckAlertFactory: UptimeAlertTypeFactory = (server, libs) => ({ id: 'xpack.uptime.alerts.monitorStatus', producer: 'uptime', name: i18n.translate('xpack.uptime.alerts.monitorStatus', { @@ -272,6 +280,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( ACTION_VARIABLES[MESSAGE], ACTION_VARIABLES[MONITOR_WITH_GEO], ACTION_VARIABLES[ALERT_REASON_MSG], + ACTION_VARIABLES[VIEW_IN_APP_URL], ], state: [...commonMonitorStateI18, ...commonStateTranslations], }, @@ -280,10 +289,11 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( async executor({ params: rawParams, state, - services: { savedObjectsClient, scopedClusterClient, alertWithLifecycle }, + services: { savedObjectsClient, scopedClusterClient, alertWithLifecycle, getAlertStartedDate }, rule: { schedule: { interval }, }, + startedAt, }) { const { filters, @@ -297,7 +307,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( isAutoGenerated, timerange: oldVersionTimeRange, } = rawParams; - + const { basePath } = server; const uptimeEsClient = createUptimeESClient({ esClient: scopedClusterClient.asCurrentUser, savedObjectsClient, @@ -336,7 +346,6 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( if (isAutoGenerated) { for (const monitorLoc of downMonitorsByLocation) { const monitorInfo = monitorLoc.monitorInfo; - const monitorStatusMessageParams = getMonitorDownStatusMessageParams( monitorInfo, monitorLoc.count, @@ -348,8 +357,10 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( const statusMessage = getStatusMessage(monitorStatusMessageParams); const monitorSummary = getMonitorSummary(monitorInfo, statusMessage); + const alertId = getInstanceId(monitorInfo, monitorLoc.location); + const indexedStartedAt = getAlertStartedDate(alertId) ?? startedAt.toISOString(); const alert = alertWithLifecycle({ - id: getInstanceId(monitorInfo, monitorLoc.location), + id: alertId, fields: getMonitorAlertDocument(monitorSummary), }); @@ -360,8 +371,18 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( ...updateState(state, true), }); + const relativeViewInAppUrl = getMonitorRouteFromMonitorId({ + monitorId: monitorSummary.monitorId, + dateRangeEnd: 'now', + dateRangeStart: indexedStartedAt, + filters: { + 'observer.geo.name': [monitorSummary.observerLocation], + }, + }); + alert.scheduleActions(MONITOR_STATUS.id, { [ALERT_REASON_MSG]: monitorSummary.reason, + [VIEW_IN_APP_URL]: getViewInAppUrl(relativeViewInAppUrl, basePath), }); } return updateState(state, downMonitorsByLocation.length > 0); @@ -408,8 +429,10 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( availability ); const monitorSummary = getMonitorSummary(monitorInfo, statusMessage); + const alertId = getInstanceId(monitorInfo, monIdByLoc); + const indexedStartedAt = getAlertStartedDate(alertId) ?? startedAt.toISOString(); const alert = alertWithLifecycle({ - id: getInstanceId(monitorInfo, monIdByLoc), + id: alertId, fields: getMonitorAlertDocument(monitorSummary), }); @@ -418,12 +441,20 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( ...monitorSummary, statusMessage, }); + const relativeViewInAppUrl = getMonitorRouteFromMonitorId({ + monitorId: monitorSummary.monitorId, + dateRangeEnd: 'now', + dateRangeStart: indexedStartedAt, + filters: { + 'observer.geo.name': [monitorSummary.observerLocation], + }, + }); alert.scheduleActions(MONITOR_STATUS.id, { [ALERT_REASON_MSG]: monitorSummary.reason, + [VIEW_IN_APP_URL]: getViewInAppUrl(relativeViewInAppUrl, basePath), }); }); - return updateState(state, downMonitorsByLocation.length > 0); }, }); diff --git a/x-pack/plugins/uptime/server/lib/alerts/test_utils/index.ts b/x-pack/plugins/uptime/server/lib/alerts/test_utils/index.ts index 826259cfa1405..374719172405f 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/test_utils/index.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/test_utils/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Logger } from 'kibana/server'; +import { IBasePath, Logger } from 'kibana/server'; import { UMServerLibs } from '../../lib'; import { UptimeCorePluginsSetup, UptimeServerSetup } from '../../adapters'; import type { UptimeRouter } from '../../../types'; @@ -25,9 +25,16 @@ import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../common/constants'; */ export const bootstrapDependencies = (customRequests?: any, customPlugins: any = {}) => { const router = {} as UptimeRouter; + const basePath = { + prepend: (url: string) => { + return `/hfe${url}`; + }, + publicBaseUrl: 'http://localhost:5601/hfe', + serverBasePath: '/hfe', + } as IBasePath; // these server/libs parameters don't have any functionality, which is fine // because we aren't testing them here - const server = { router, config: {} } as UptimeServerSetup; + const server = { router, config: {}, basePath } as UptimeServerSetup; const plugins: UptimeCorePluginsSetup = customPlugins as any; const libs: UMServerLibs = { requests: {} } as UMServerLibs; libs.requests = { ...libs.requests, ...customRequests }; @@ -56,6 +63,7 @@ export const createRuleTypeMocks = ( ...getUptimeESMockClient(), ...alertsMock.createAlertServices(), alertWithLifecycle: jest.fn().mockReturnValue({ scheduleActions, replaceState }), + getAlertStartedDate: jest.fn().mockReturnValue('2022-03-17T13:13:33.755Z'), logger: loggerMock, }; diff --git a/x-pack/plugins/uptime/server/lib/alerts/types.ts b/x-pack/plugins/uptime/server/lib/alerts/types.ts index e8e496cba997e..5275cddae9d24 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/types.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/types.ts @@ -26,6 +26,7 @@ export type DefaultUptimeAlertInstance = AlertTy AlertInstanceContext, TActionGroupIds >; + getAlertStartedDate: (alertId: string) => string | null; } >; diff --git a/x-pack/plugins/uptime/server/plugin.ts b/x-pack/plugins/uptime/server/plugin.ts index d2afb3f16fb6a..2f329aa83a5c4 100644 --- a/x-pack/plugins/uptime/server/plugin.ts +++ b/x-pack/plugins/uptime/server/plugin.ts @@ -78,6 +78,7 @@ export class Plugin implements PluginType { router: core.http.createRouter(), cloud: plugins.cloud, kibanaVersion: this.initContext.env.packageInfo.version, + basePath: core.http.basePath, logger: this.logger, telemetry: this.telemetryEventsSender, } as UptimeServerSetup;