@oneuptime/common 10.0.6 → 10.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Server/Middleware/UserAuthorization.ts +36 -0
- package/Server/Services/MonitorService.ts +9 -0
- package/Server/Services/UserNotificationRuleService.ts +83 -0
- package/Server/Types/Markdown.ts +17 -4
- package/Server/Utils/Browser.ts +3 -3
- package/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.ts +158 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +15 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +32 -0
- package/Server/Utils/VM/VMRunner.ts +273 -52
- package/Server/Views/Partials/Head.ejs +3 -1
- package/Tests/Server/Middleware/UserAuthorization.test.ts +1 -0
- package/Types/Monitor/CriteriaFilter.ts +12 -2
- package/Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse.ts +16 -0
- package/Types/Monitor/ExternalStatusPageProviderType.ts +8 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
- package/Types/Monitor/MonitorStep.ts +34 -0
- package/Types/Monitor/MonitorStepExternalStatusPageMonitor.ts +48 -0
- package/Types/Monitor/MonitorType.ts +16 -2
- package/Types/Probe/ProbeMonitorResponse.ts +2 -0
- package/Utils/Monitor/MonitorMetricType.ts +3 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +30 -1
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +7 -1
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +58 -5
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +16 -4
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Utils/Browser.js +3 -3
- package/build/dist/Server/Utils/Browser.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js +119 -0
- package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +10 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +22 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +243 -49
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Tests/Server/Middleware/UserAuthorization.test.js +1 -0
- package/build/dist/Tests/Server/Middleware/UserAuthorization.test.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +11 -2
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse.js +2 -0
- package/build/dist/Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse.js.map +1 -0
- package/build/dist/Types/Monitor/ExternalStatusPageProviderType.js +9 -0
- package/build/dist/Types/Monitor/ExternalStatusPageProviderType.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +22 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js +32 -0
- package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorType.js +14 -2
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +3 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/package.json +1 -1
|
@@ -116,6 +116,42 @@ export default class UserMiddleware {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
/*
|
|
120
|
+
* Also check x-sso-tokens header (mobile app flow).
|
|
121
|
+
* The header value is a JSON-encoded map of { projectId: ssoToken }.
|
|
122
|
+
*/
|
|
123
|
+
const ssoTokensHeader: string | undefined = req.headers["x-sso-tokens"] as
|
|
124
|
+
| string
|
|
125
|
+
| undefined;
|
|
126
|
+
|
|
127
|
+
if (ssoTokensHeader) {
|
|
128
|
+
try {
|
|
129
|
+
const headerTokens: Record<string, string> =
|
|
130
|
+
JSON.parse(ssoTokensHeader);
|
|
131
|
+
|
|
132
|
+
for (const projectId of Object.keys(headerTokens)) {
|
|
133
|
+
const token: string | undefined = headerTokens[projectId];
|
|
134
|
+
|
|
135
|
+
if (!token || typeof token !== "string") {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const decoded: JSONWebTokenData = JSONWebToken.decode(token);
|
|
141
|
+
|
|
142
|
+
if (decoded.projectId?.toString() === projectId) {
|
|
143
|
+
ssoTokens[projectId] = token;
|
|
144
|
+
}
|
|
145
|
+
} catch (err) {
|
|
146
|
+
logger.error(err);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} catch (err) {
|
|
151
|
+
logger.error(err);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
119
155
|
return ssoTokens;
|
|
120
156
|
}
|
|
121
157
|
|
|
@@ -135,6 +135,15 @@ export class Service extends DatabaseService<Model> {
|
|
|
135
135
|
monitorDestination = `${monitorDestination} @${firstStep.data.dnsMonitor.hostname}`;
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
+
|
|
139
|
+
// For External Status Page monitors, use the statusPageUrl
|
|
140
|
+
if (
|
|
141
|
+
monitorType === MonitorType.ExternalStatusPage &&
|
|
142
|
+
firstStep?.data?.externalStatusPageMonitor
|
|
143
|
+
) {
|
|
144
|
+
monitorDestination =
|
|
145
|
+
firstStep.data.externalStatusPageMonitor.statusPageUrl || "";
|
|
146
|
+
}
|
|
138
147
|
}
|
|
139
148
|
}
|
|
140
149
|
|
|
@@ -1110,6 +1110,9 @@ export class Service extends DatabaseService<Model> {
|
|
|
1110
1110
|
...(alert.alertNumber !== undefined && {
|
|
1111
1111
|
alertNumber: alert.alertNumber,
|
|
1112
1112
|
}),
|
|
1113
|
+
...(alert.alertNumberWithPrefix && {
|
|
1114
|
+
alertNumberWithPrefix: alert.alertNumberWithPrefix,
|
|
1115
|
+
}),
|
|
1113
1116
|
alertId: alert.id!.toString(),
|
|
1114
1117
|
projectId: alert.projectId!.toString(),
|
|
1115
1118
|
});
|
|
@@ -1187,6 +1190,9 @@ export class Service extends DatabaseService<Model> {
|
|
|
1187
1190
|
...(incident.incidentNumber !== undefined && {
|
|
1188
1191
|
incidentNumber: incident.incidentNumber,
|
|
1189
1192
|
}),
|
|
1193
|
+
...(incident.incidentNumberWithPrefix && {
|
|
1194
|
+
incidentNumberWithPrefix: incident.incidentNumberWithPrefix,
|
|
1195
|
+
}),
|
|
1190
1196
|
incidentId: incident.id!.toString(),
|
|
1191
1197
|
projectId: incident.projectId!.toString(),
|
|
1192
1198
|
});
|
|
@@ -1309,6 +1315,83 @@ export class Service extends DatabaseService<Model> {
|
|
|
1309
1315
|
});
|
|
1310
1316
|
});
|
|
1311
1317
|
}
|
|
1318
|
+
|
|
1319
|
+
// send push notification for incident episode
|
|
1320
|
+
if (
|
|
1321
|
+
options.userNotificationEventType ===
|
|
1322
|
+
UserNotificationEventType.IncidentEpisodeCreated &&
|
|
1323
|
+
incidentEpisode
|
|
1324
|
+
) {
|
|
1325
|
+
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
1326
|
+
logTimelineItem.statusMessage = `Sending push notification to device.`;
|
|
1327
|
+
logTimelineItem.userPushId = notificationRuleItem.userPush.id!;
|
|
1328
|
+
|
|
1329
|
+
const updatedLog: UserOnCallLogTimeline =
|
|
1330
|
+
await UserOnCallLogTimelineService.create({
|
|
1331
|
+
data: logTimelineItem,
|
|
1332
|
+
props: {
|
|
1333
|
+
isRoot: true,
|
|
1334
|
+
},
|
|
1335
|
+
});
|
|
1336
|
+
|
|
1337
|
+
const pushMessage: PushNotificationMessage =
|
|
1338
|
+
PushNotificationUtil.createIncidentEpisodeCreatedNotification({
|
|
1339
|
+
incidentEpisodeTitle: incidentEpisode.title!,
|
|
1340
|
+
projectName: incidentEpisode.project?.name || "OneUptime",
|
|
1341
|
+
incidentEpisodeViewLink: (
|
|
1342
|
+
await IncidentEpisodeService.getEpisodeLinkInDashboard(
|
|
1343
|
+
incidentEpisode.projectId!,
|
|
1344
|
+
incidentEpisode.id!,
|
|
1345
|
+
)
|
|
1346
|
+
).toString(),
|
|
1347
|
+
...(incidentEpisode.episodeNumber !== undefined && {
|
|
1348
|
+
episodeNumber: incidentEpisode.episodeNumber,
|
|
1349
|
+
}),
|
|
1350
|
+
...(incidentEpisode.episodeNumberWithPrefix && {
|
|
1351
|
+
episodeNumberWithPrefix: incidentEpisode.episodeNumberWithPrefix,
|
|
1352
|
+
}),
|
|
1353
|
+
incidentEpisodeId: incidentEpisode.id!.toString(),
|
|
1354
|
+
projectId: incidentEpisode.projectId!.toString(),
|
|
1355
|
+
});
|
|
1356
|
+
|
|
1357
|
+
PushNotificationService.sendPushNotification(
|
|
1358
|
+
{
|
|
1359
|
+
devices: [
|
|
1360
|
+
{
|
|
1361
|
+
token: notificationRuleItem.userPush.deviceToken!,
|
|
1362
|
+
...(notificationRuleItem.userPush.deviceName && {
|
|
1363
|
+
name: notificationRuleItem.userPush.deviceName,
|
|
1364
|
+
}),
|
|
1365
|
+
},
|
|
1366
|
+
],
|
|
1367
|
+
message: pushMessage,
|
|
1368
|
+
deviceType: notificationRuleItem.userPush
|
|
1369
|
+
.deviceType! as PushDeviceType,
|
|
1370
|
+
},
|
|
1371
|
+
{
|
|
1372
|
+
projectId: options.projectId,
|
|
1373
|
+
userOnCallLogTimelineId: updatedLog.id!,
|
|
1374
|
+
userId: notificationRuleItem.userId!,
|
|
1375
|
+
onCallPolicyId: options.onCallPolicyId,
|
|
1376
|
+
onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
|
|
1377
|
+
teamId: options.userBelongsToTeamId,
|
|
1378
|
+
onCallDutyPolicyExecutionLogTimelineId:
|
|
1379
|
+
options.onCallDutyPolicyExecutionLogTimelineId,
|
|
1380
|
+
onCallScheduleId: options.onCallScheduleId,
|
|
1381
|
+
},
|
|
1382
|
+
).catch(async (err: Error) => {
|
|
1383
|
+
await UserOnCallLogTimelineService.updateOneById({
|
|
1384
|
+
id: updatedLog.id!,
|
|
1385
|
+
data: {
|
|
1386
|
+
status: UserNotificationStatus.Error,
|
|
1387
|
+
statusMessage: err.message || "Error sending push notification.",
|
|
1388
|
+
},
|
|
1389
|
+
props: {
|
|
1390
|
+
isRoot: true,
|
|
1391
|
+
},
|
|
1392
|
+
});
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1312
1395
|
}
|
|
1313
1396
|
|
|
1314
1397
|
if (
|
package/Server/Types/Markdown.ts
CHANGED
|
@@ -103,6 +103,15 @@ export default class Markdown {
|
|
|
103
103
|
return htmlBody;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
private static escapeHtml(text: string): string {
|
|
107
|
+
return text
|
|
108
|
+
.replace(/&/g, "&")
|
|
109
|
+
.replace(/</g, "<")
|
|
110
|
+
.replace(/>/g, ">")
|
|
111
|
+
.replace(/"/g, """)
|
|
112
|
+
.replace(/'/g, "'");
|
|
113
|
+
}
|
|
114
|
+
|
|
106
115
|
private static getEmailRenderer(): Renderer {
|
|
107
116
|
if (this.emailRenderer !== null) {
|
|
108
117
|
return this.emailRenderer;
|
|
@@ -140,7 +149,8 @@ export default class Markdown {
|
|
|
140
149
|
if (language === "mermaid") {
|
|
141
150
|
return `<div class="mermaid">${code}</div>`;
|
|
142
151
|
}
|
|
143
|
-
|
|
152
|
+
const escaped: string = Markdown.escapeHtml(code);
|
|
153
|
+
return `<pre><code class="language-${language}">${escaped}</code></pre>`;
|
|
144
154
|
};
|
|
145
155
|
|
|
146
156
|
renderer.heading = function (text, level) {
|
|
@@ -160,7 +170,8 @@ export default class Markdown {
|
|
|
160
170
|
|
|
161
171
|
// Inline code
|
|
162
172
|
renderer.codespan = function (code) {
|
|
163
|
-
|
|
173
|
+
const escaped: string = Markdown.escapeHtml(code);
|
|
174
|
+
return `<code class="rounded-md bg-slate-100 px-1.5 py-0.5 text-sm text-slate-700 font-mono">${escaped}</code>`;
|
|
164
175
|
};
|
|
165
176
|
|
|
166
177
|
this.docsRenderer = renderer;
|
|
@@ -186,7 +197,8 @@ export default class Markdown {
|
|
|
186
197
|
};
|
|
187
198
|
|
|
188
199
|
renderer.code = function (code, language) {
|
|
189
|
-
|
|
200
|
+
const escaped: string = Markdown.escapeHtml(code);
|
|
201
|
+
return `<pre class="language-${language} rounded-md"><code class="language-${language} rounded-md">${escaped}</code></pre>`;
|
|
190
202
|
};
|
|
191
203
|
|
|
192
204
|
renderer.heading = function (text, level) {
|
|
@@ -237,7 +249,8 @@ export default class Markdown {
|
|
|
237
249
|
|
|
238
250
|
// Inline code
|
|
239
251
|
renderer.codespan = function (code) {
|
|
240
|
-
|
|
252
|
+
const escaped: string = Markdown.escapeHtml(code);
|
|
253
|
+
return `<code class="rounded-md bg-gray-100 px-1.5 py-0.5 text-sm text-pink-600">${escaped}</code>`;
|
|
241
254
|
};
|
|
242
255
|
|
|
243
256
|
// Horizontal rule
|
package/Server/Utils/Browser.ts
CHANGED
|
@@ -23,7 +23,9 @@ export default class BrowserUtil {
|
|
|
23
23
|
"--disable-dev-shm-usage",
|
|
24
24
|
"--disable-gpu",
|
|
25
25
|
"--disable-software-rasterizer",
|
|
26
|
-
"--
|
|
26
|
+
"--disable-dbus", // no D-Bus daemon in containers
|
|
27
|
+
"--disable-features=dbus", // additional D-Bus feature gate
|
|
28
|
+
"--no-zygote", // skip zygote process that fails OOM score adjustments in containers
|
|
27
29
|
];
|
|
28
30
|
|
|
29
31
|
// Firefox preferences for stability in containerized environments
|
|
@@ -31,8 +33,6 @@ export default class BrowserUtil {
|
|
|
31
33
|
string,
|
|
32
34
|
string | number | boolean
|
|
33
35
|
> = {
|
|
34
|
-
"browser.tabs.remote.autostart": false, // disable multi-process (electrolysis)
|
|
35
|
-
"dom.ipc.processCount": 1, // single content process
|
|
36
36
|
"gfx.webrender.all": false, // disable GPU-based WebRender
|
|
37
37
|
"media.hardware-video-decoding.enabled": false, // disable hardware video decoding
|
|
38
38
|
"layers.acceleration.disabled": true, // disable GPU-accelerated layers
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import DataToProcess from "../DataToProcess";
|
|
2
|
+
import CompareCriteria from "./CompareCriteria";
|
|
3
|
+
import {
|
|
4
|
+
CheckOn,
|
|
5
|
+
CriteriaFilter,
|
|
6
|
+
} from "../../../../Types/Monitor/CriteriaFilter";
|
|
7
|
+
import ExternalStatusPageMonitorResponse from "../../../../Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse";
|
|
8
|
+
import ProbeMonitorResponse from "../../../../Types/Probe/ProbeMonitorResponse";
|
|
9
|
+
import EvaluateOverTime from "./EvaluateOverTime";
|
|
10
|
+
import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
11
|
+
import logger from "../../Logger";
|
|
12
|
+
|
|
13
|
+
export default class ExternalStatusPageMonitorCriteria {
|
|
14
|
+
@CaptureSpan()
|
|
15
|
+
public static async isMonitorInstanceCriteriaFilterMet(input: {
|
|
16
|
+
dataToProcess: DataToProcess;
|
|
17
|
+
criteriaFilter: CriteriaFilter;
|
|
18
|
+
}): Promise<string | null> {
|
|
19
|
+
let threshold: number | string | undefined | null =
|
|
20
|
+
input.criteriaFilter.value;
|
|
21
|
+
|
|
22
|
+
const dataToProcess: ProbeMonitorResponse =
|
|
23
|
+
input.dataToProcess as ProbeMonitorResponse;
|
|
24
|
+
|
|
25
|
+
const externalStatusPageResponse:
|
|
26
|
+
| ExternalStatusPageMonitorResponse
|
|
27
|
+
| undefined = dataToProcess.externalStatusPageResponse;
|
|
28
|
+
|
|
29
|
+
let overTimeValue: Array<number | boolean> | number | boolean | undefined =
|
|
30
|
+
undefined;
|
|
31
|
+
|
|
32
|
+
if (
|
|
33
|
+
input.criteriaFilter.evaluateOverTime &&
|
|
34
|
+
input.criteriaFilter.evaluateOverTimeOptions
|
|
35
|
+
) {
|
|
36
|
+
try {
|
|
37
|
+
overTimeValue = await EvaluateOverTime.getValueOverTime({
|
|
38
|
+
projectId: (input.dataToProcess as ProbeMonitorResponse).projectId,
|
|
39
|
+
monitorId: input.dataToProcess.monitorId!,
|
|
40
|
+
evaluateOverTimeOptions: input.criteriaFilter.evaluateOverTimeOptions,
|
|
41
|
+
metricType: input.criteriaFilter.checkOn,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (Array.isArray(overTimeValue) && overTimeValue.length === 0) {
|
|
45
|
+
overTimeValue = undefined;
|
|
46
|
+
}
|
|
47
|
+
} catch (err) {
|
|
48
|
+
logger.error(
|
|
49
|
+
`Error in getting over time value for ${input.criteriaFilter.checkOn}`,
|
|
50
|
+
);
|
|
51
|
+
logger.error(err);
|
|
52
|
+
overTimeValue = undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check if external status page is online
|
|
57
|
+
if (input.criteriaFilter.checkOn === CheckOn.ExternalStatusPageIsOnline) {
|
|
58
|
+
const currentIsOnline: boolean | Array<boolean> =
|
|
59
|
+
(overTimeValue as Array<boolean>) ||
|
|
60
|
+
(input.dataToProcess as ProbeMonitorResponse).isOnline;
|
|
61
|
+
|
|
62
|
+
return CompareCriteria.compareCriteriaBoolean({
|
|
63
|
+
value: currentIsOnline,
|
|
64
|
+
criteriaFilter: input.criteriaFilter,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Check external status page response time
|
|
69
|
+
if (
|
|
70
|
+
input.criteriaFilter.checkOn === CheckOn.ExternalStatusPageResponseTime
|
|
71
|
+
) {
|
|
72
|
+
threshold = CompareCriteria.convertToNumber(threshold);
|
|
73
|
+
|
|
74
|
+
if (threshold === null || threshold === undefined) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const currentResponseTime: number | Array<number> =
|
|
79
|
+
(overTimeValue as Array<number>) ||
|
|
80
|
+
externalStatusPageResponse?.responseTimeInMs ||
|
|
81
|
+
(input.dataToProcess as ProbeMonitorResponse).responseTimeInMs;
|
|
82
|
+
|
|
83
|
+
if (currentResponseTime === null || currentResponseTime === undefined) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return CompareCriteria.compareCriteriaNumbers({
|
|
88
|
+
value: currentResponseTime,
|
|
89
|
+
threshold: threshold as number,
|
|
90
|
+
criteriaFilter: input.criteriaFilter,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Check overall status
|
|
95
|
+
if (
|
|
96
|
+
input.criteriaFilter.checkOn === CheckOn.ExternalStatusPageOverallStatus
|
|
97
|
+
) {
|
|
98
|
+
if (!externalStatusPageResponse?.overallStatus) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return CompareCriteria.compareCriteriaStrings({
|
|
103
|
+
value: externalStatusPageResponse.overallStatus,
|
|
104
|
+
threshold: String(threshold),
|
|
105
|
+
criteriaFilter: input.criteriaFilter,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Check component status
|
|
110
|
+
if (
|
|
111
|
+
input.criteriaFilter.checkOn === CheckOn.ExternalStatusPageComponentStatus
|
|
112
|
+
) {
|
|
113
|
+
if (
|
|
114
|
+
!externalStatusPageResponse?.componentStatuses ||
|
|
115
|
+
externalStatusPageResponse.componentStatuses.length === 0
|
|
116
|
+
) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Check if any component status matches the criteria
|
|
121
|
+
for (const component of externalStatusPageResponse.componentStatuses) {
|
|
122
|
+
const result: string | null = CompareCriteria.compareCriteriaStrings({
|
|
123
|
+
value: component.status,
|
|
124
|
+
threshold: String(threshold),
|
|
125
|
+
criteriaFilter: input.criteriaFilter,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
if (result) {
|
|
129
|
+
return `Component "${component.name}": ${result}`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Check active incidents count
|
|
137
|
+
if (
|
|
138
|
+
input.criteriaFilter.checkOn === CheckOn.ExternalStatusPageActiveIncidents
|
|
139
|
+
) {
|
|
140
|
+
threshold = CompareCriteria.convertToNumber(threshold);
|
|
141
|
+
|
|
142
|
+
if (threshold === null || threshold === undefined) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const activeIncidents: number =
|
|
147
|
+
externalStatusPageResponse?.activeIncidentCount || 0;
|
|
148
|
+
|
|
149
|
+
return CompareCriteria.compareCriteriaNumbers({
|
|
150
|
+
value: activeIncidents,
|
|
151
|
+
threshold: threshold as number,
|
|
152
|
+
criteriaFilter: input.criteriaFilter,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -14,6 +14,7 @@ import ExceptionMonitorCriteria from "./Criteria/ExceptionMonitorCriteria";
|
|
|
14
14
|
import SnmpMonitorCriteria from "./Criteria/SnmpMonitorCriteria";
|
|
15
15
|
import DnsMonitorCriteria from "./Criteria/DnsMonitorCriteria";
|
|
16
16
|
import DomainMonitorCriteria from "./Criteria/DomainMonitorCriteria";
|
|
17
|
+
import ExternalStatusPageMonitorCriteria from "./Criteria/ExternalStatusPageMonitorCriteria";
|
|
17
18
|
import MonitorCriteriaMessageBuilder from "./MonitorCriteriaMessageBuilder";
|
|
18
19
|
import MonitorCriteriaDataExtractor from "./MonitorCriteriaDataExtractor";
|
|
19
20
|
import MonitorCriteriaMessageFormatter from "./MonitorCriteriaMessageFormatter";
|
|
@@ -519,6 +520,20 @@ ${contextBlock}
|
|
|
519
520
|
}
|
|
520
521
|
}
|
|
521
522
|
|
|
523
|
+
if (input.monitor.monitorType === MonitorType.ExternalStatusPage) {
|
|
524
|
+
const externalStatusPageResult: string | null =
|
|
525
|
+
await ExternalStatusPageMonitorCriteria.isMonitorInstanceCriteriaFilterMet(
|
|
526
|
+
{
|
|
527
|
+
dataToProcess: input.dataToProcess,
|
|
528
|
+
criteriaFilter: input.criteriaFilter,
|
|
529
|
+
},
|
|
530
|
+
);
|
|
531
|
+
|
|
532
|
+
if (externalStatusPageResult) {
|
|
533
|
+
return externalStatusPageResult;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
522
537
|
return null;
|
|
523
538
|
}
|
|
524
539
|
|
|
@@ -18,6 +18,9 @@ import DnsMonitorResponse, {
|
|
|
18
18
|
DnsRecordResponse,
|
|
19
19
|
} from "../../../Types/Monitor/DnsMonitor/DnsMonitorResponse";
|
|
20
20
|
import DomainMonitorResponse from "../../../Types/Monitor/DomainMonitor/DomainMonitorResponse";
|
|
21
|
+
import ExternalStatusPageMonitorResponse, {
|
|
22
|
+
ExternalStatusPageComponentStatus,
|
|
23
|
+
} from "../../../Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse";
|
|
21
24
|
import Typeof from "../../../Types/Typeof";
|
|
22
25
|
import VMUtil from "../VM/VMAPI";
|
|
23
26
|
import DataToProcess from "./DataToProcess";
|
|
@@ -298,6 +301,35 @@ export default class MonitorTemplateUtil {
|
|
|
298
301
|
dnssec: domainResponse?.dnssec,
|
|
299
302
|
} as JSONObject;
|
|
300
303
|
}
|
|
304
|
+
|
|
305
|
+
if (data.monitorType === MonitorType.ExternalStatusPage) {
|
|
306
|
+
const externalStatusPageResponse:
|
|
307
|
+
| ExternalStatusPageMonitorResponse
|
|
308
|
+
| undefined = (data.dataToProcess as ProbeMonitorResponse)
|
|
309
|
+
.externalStatusPageResponse;
|
|
310
|
+
|
|
311
|
+
storageMap = {
|
|
312
|
+
isOnline: (data.dataToProcess as ProbeMonitorResponse).isOnline,
|
|
313
|
+
responseTimeInMs: externalStatusPageResponse?.responseTimeInMs,
|
|
314
|
+
failureCause: externalStatusPageResponse?.failureCause,
|
|
315
|
+
overallStatus: externalStatusPageResponse?.overallStatus,
|
|
316
|
+
activeIncidentCount: externalStatusPageResponse?.activeIncidentCount,
|
|
317
|
+
} as JSONObject;
|
|
318
|
+
|
|
319
|
+
// Add component statuses
|
|
320
|
+
if (externalStatusPageResponse?.componentStatuses) {
|
|
321
|
+
storageMap["componentStatuses"] =
|
|
322
|
+
externalStatusPageResponse.componentStatuses.map(
|
|
323
|
+
(component: ExternalStatusPageComponentStatus) => {
|
|
324
|
+
return {
|
|
325
|
+
name: component.name,
|
|
326
|
+
status: component.status,
|
|
327
|
+
description: component.description,
|
|
328
|
+
};
|
|
329
|
+
},
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
301
333
|
} catch (err) {
|
|
302
334
|
logger.error(err);
|
|
303
335
|
}
|