@oneuptime/common 8.0.5516 → 8.0.5547
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/Models/DatabaseModels/AcmeChallenge.ts +3 -0
- package/Models/DatabaseModels/Domain.ts +6 -1
- package/Server/API/AcmeChallengeAPI.ts +64 -0
- package/Server/EnvironmentConfig.ts +54 -0
- package/Server/Infrastructure/Queue.ts +12 -16
- package/Server/Infrastructure/QueueWorker.ts +2 -6
- package/Server/Services/DomainService.ts +48 -40
- package/Server/Utils/AnalyticsDatabase/Statement.ts +8 -4
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +47 -15
- package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +13 -12
- package/Server/Utils/Monitor/MonitorAlert.ts +46 -1
- package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +208 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +439 -0
- package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +141 -0
- package/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.ts +88 -0
- package/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.ts +196 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +1123 -0
- package/Server/Utils/Monitor/MonitorIncident.ts +46 -1
- package/Server/Utils/Monitor/MonitorLogUtil.ts +44 -0
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +482 -0
- package/Server/Utils/Monitor/MonitorResource.ts +185 -914
- package/Server/Utils/StartServer.ts +14 -6
- package/Types/Email.ts +3 -7
- package/Types/Monitor/IncomingMonitor/IncomingMonitorRequest.ts +2 -0
- package/Types/Monitor/LogMonitor/LogMonitorResponse.ts +2 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +2 -0
- package/Types/Monitor/MonitorEvaluationSummary.ts +48 -0
- package/Types/Monitor/ServerMonitor/ServerMonitorResponse.ts +2 -0
- package/Types/Monitor/TraceMonitor/TraceMonitorResponse.ts +2 -0
- package/Types/Probe/ProbeApiIngestResponse.ts +2 -0
- package/Types/Probe/ProbeMonitorResponse.ts +2 -0
- package/build/dist/Models/DatabaseModels/AcmeChallenge.js +3 -0
- package/build/dist/Models/DatabaseModels/AcmeChallenge.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Domain.js +6 -1
- package/build/dist/Models/DatabaseModels/Domain.js.map +1 -1
- package/build/dist/Server/API/AcmeChallengeAPI.js +39 -0
- package/build/dist/Server/API/AcmeChallengeAPI.js.map +1 -0
- package/build/dist/Server/EnvironmentConfig.js +44 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Queue.js +8 -11
- package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
- package/build/dist/Server/Infrastructure/QueueWorker.js +2 -6
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Services/DomainService.js +31 -29
- package/build/dist/Server/Services/DomainService.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +2 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +34 -16
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +12 -12
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +42 -4
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +119 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +312 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +109 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js +45 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js +132 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +583 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +42 -4
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorLogUtil.js +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorLogUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +361 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +134 -666
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +7 -4
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Types/Email.js +2 -5
- package/build/dist/Types/Email.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorEvaluationSummary.js +2 -0
- package/build/dist/Types/Monitor/MonitorEvaluationSummary.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,1123 @@
|
|
|
1
|
+
import logger from "../Logger";
|
|
2
|
+
import OneUptimeDate from "../../../Types/Date";
|
|
3
|
+
import Monitor from "../../../Models/DatabaseModels/Monitor";
|
|
4
|
+
import MonitorStep from "../../../Types/Monitor/MonitorStep";
|
|
5
|
+
import DataToProcess from "./DataToProcess";
|
|
6
|
+
import { CheckOn, CriteriaFilter } from "../../../Types/Monitor/CriteriaFilter";
|
|
7
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
8
|
+
import ProbeMonitorResponse from "../../../Types/Probe/ProbeMonitorResponse";
|
|
9
|
+
import ServerMonitorResponse, {
|
|
10
|
+
ServerProcess,
|
|
11
|
+
} from "../../../Types/Monitor/ServerMonitor/ServerMonitorResponse";
|
|
12
|
+
import IncomingMonitorRequest from "../../../Types/Monitor/IncomingMonitor/IncomingMonitorRequest";
|
|
13
|
+
import BasicInfrastructureMetrics, {
|
|
14
|
+
BasicDiskMetrics,
|
|
15
|
+
} from "../../../Types/Infrastructure/BasicMetrics";
|
|
16
|
+
import Typeof from "../../../Types/Typeof";
|
|
17
|
+
import SslMonitorResponse from "../../../Types/Monitor/SSLMonitor/SslMonitorResponse";
|
|
18
|
+
import SyntheticMonitorResponse from "../../../Types/Monitor/SyntheticMonitors/SyntheticMonitorResponse";
|
|
19
|
+
import CustomCodeMonitorResponse from "../../../Types/Monitor/CustomCodeMonitor/CustomCodeMonitorResponse";
|
|
20
|
+
import LogMonitorResponse from "../../../Types/Monitor/LogMonitor/LogMonitorResponse";
|
|
21
|
+
import TraceMonitorResponse from "../../../Types/Monitor/TraceMonitor/TraceMonitorResponse";
|
|
22
|
+
import MonitorCriteriaMessageFormatter from "./MonitorCriteriaMessageFormatter";
|
|
23
|
+
import MonitorCriteriaDataExtractor from "./MonitorCriteriaDataExtractor";
|
|
24
|
+
import MonitorCriteriaExpectationBuilder from "./MonitorCriteriaExpectationBuilder";
|
|
25
|
+
|
|
26
|
+
export default class MonitorCriteriaObservationBuilder {
|
|
27
|
+
public static describeFilterObservation(input: {
|
|
28
|
+
monitor: Monitor;
|
|
29
|
+
criteriaFilter: CriteriaFilter;
|
|
30
|
+
dataToProcess: DataToProcess;
|
|
31
|
+
monitorStep: MonitorStep;
|
|
32
|
+
}): string | null {
|
|
33
|
+
const { criteriaFilter } = input;
|
|
34
|
+
|
|
35
|
+
switch (criteriaFilter.checkOn) {
|
|
36
|
+
case CheckOn.ResponseTime:
|
|
37
|
+
return MonitorCriteriaObservationBuilder.describeResponseTimeObservation(
|
|
38
|
+
input,
|
|
39
|
+
);
|
|
40
|
+
case CheckOn.ResponseStatusCode:
|
|
41
|
+
return MonitorCriteriaObservationBuilder.describeResponseStatusCodeObservation(
|
|
42
|
+
input,
|
|
43
|
+
);
|
|
44
|
+
case CheckOn.ResponseHeader:
|
|
45
|
+
return MonitorCriteriaObservationBuilder.describeResponseHeaderObservation(
|
|
46
|
+
input,
|
|
47
|
+
);
|
|
48
|
+
case CheckOn.ResponseHeaderValue:
|
|
49
|
+
return MonitorCriteriaObservationBuilder.describeResponseHeaderValueObservation(
|
|
50
|
+
input,
|
|
51
|
+
);
|
|
52
|
+
case CheckOn.ResponseBody:
|
|
53
|
+
return MonitorCriteriaObservationBuilder.describeResponseBodyObservation(
|
|
54
|
+
input,
|
|
55
|
+
);
|
|
56
|
+
case CheckOn.IsOnline:
|
|
57
|
+
return MonitorCriteriaObservationBuilder.describeIsOnlineObservation(
|
|
58
|
+
input,
|
|
59
|
+
);
|
|
60
|
+
case CheckOn.IsRequestTimeout:
|
|
61
|
+
return MonitorCriteriaObservationBuilder.describeIsTimeoutObservation(
|
|
62
|
+
input,
|
|
63
|
+
);
|
|
64
|
+
case CheckOn.IncomingRequest:
|
|
65
|
+
return MonitorCriteriaObservationBuilder.describeIncomingRequestObservation(
|
|
66
|
+
input,
|
|
67
|
+
);
|
|
68
|
+
case CheckOn.RequestBody:
|
|
69
|
+
return MonitorCriteriaObservationBuilder.describeRequestBodyObservation(
|
|
70
|
+
input,
|
|
71
|
+
);
|
|
72
|
+
case CheckOn.RequestHeader:
|
|
73
|
+
return MonitorCriteriaObservationBuilder.describeRequestHeaderObservation(
|
|
74
|
+
input,
|
|
75
|
+
);
|
|
76
|
+
case CheckOn.RequestHeaderValue:
|
|
77
|
+
return MonitorCriteriaObservationBuilder.describeRequestHeaderValueObservation(
|
|
78
|
+
input,
|
|
79
|
+
);
|
|
80
|
+
case CheckOn.JavaScriptExpression:
|
|
81
|
+
return MonitorCriteriaObservationBuilder.describeJavaScriptExpressionObservation(
|
|
82
|
+
input,
|
|
83
|
+
);
|
|
84
|
+
case CheckOn.CPUUsagePercent:
|
|
85
|
+
return MonitorCriteriaObservationBuilder.describeCpuUsageObservation(
|
|
86
|
+
input,
|
|
87
|
+
);
|
|
88
|
+
case CheckOn.MemoryUsagePercent:
|
|
89
|
+
return MonitorCriteriaObservationBuilder.describeMemoryUsageObservation(
|
|
90
|
+
input,
|
|
91
|
+
);
|
|
92
|
+
case CheckOn.DiskUsagePercent:
|
|
93
|
+
return MonitorCriteriaObservationBuilder.describeDiskUsageObservation(
|
|
94
|
+
input,
|
|
95
|
+
);
|
|
96
|
+
case CheckOn.ServerProcessName:
|
|
97
|
+
return MonitorCriteriaObservationBuilder.describeServerProcessNameObservation(
|
|
98
|
+
input,
|
|
99
|
+
);
|
|
100
|
+
case CheckOn.ServerProcessPID:
|
|
101
|
+
return MonitorCriteriaObservationBuilder.describeServerProcessPidObservation(
|
|
102
|
+
input,
|
|
103
|
+
);
|
|
104
|
+
case CheckOn.ServerProcessCommand:
|
|
105
|
+
return MonitorCriteriaObservationBuilder.describeServerProcessCommandObservation(
|
|
106
|
+
input,
|
|
107
|
+
);
|
|
108
|
+
case CheckOn.ExpiresInHours:
|
|
109
|
+
return MonitorCriteriaObservationBuilder.describeCertificateExpiresInHoursObservation(
|
|
110
|
+
input,
|
|
111
|
+
);
|
|
112
|
+
case CheckOn.ExpiresInDays:
|
|
113
|
+
return MonitorCriteriaObservationBuilder.describeCertificateExpiresInDaysObservation(
|
|
114
|
+
input,
|
|
115
|
+
);
|
|
116
|
+
case CheckOn.IsSelfSignedCertificate:
|
|
117
|
+
return MonitorCriteriaObservationBuilder.describeIsSelfSignedObservation(
|
|
118
|
+
input,
|
|
119
|
+
);
|
|
120
|
+
case CheckOn.IsExpiredCertificate:
|
|
121
|
+
return MonitorCriteriaObservationBuilder.describeIsExpiredObservation(
|
|
122
|
+
input,
|
|
123
|
+
);
|
|
124
|
+
case CheckOn.IsValidCertificate:
|
|
125
|
+
return MonitorCriteriaObservationBuilder.describeIsValidObservation(
|
|
126
|
+
input,
|
|
127
|
+
);
|
|
128
|
+
case CheckOn.IsNotAValidCertificate:
|
|
129
|
+
return MonitorCriteriaObservationBuilder.describeIsInvalidObservation(
|
|
130
|
+
input,
|
|
131
|
+
);
|
|
132
|
+
case CheckOn.ResultValue:
|
|
133
|
+
return MonitorCriteriaObservationBuilder.describeResultValueObservation(
|
|
134
|
+
input,
|
|
135
|
+
);
|
|
136
|
+
case CheckOn.Error:
|
|
137
|
+
return MonitorCriteriaObservationBuilder.describeErrorObservation(
|
|
138
|
+
input,
|
|
139
|
+
);
|
|
140
|
+
case CheckOn.ExecutionTime:
|
|
141
|
+
return MonitorCriteriaObservationBuilder.describeExecutionTimeObservation(
|
|
142
|
+
input,
|
|
143
|
+
);
|
|
144
|
+
case CheckOn.ScreenSizeType:
|
|
145
|
+
return MonitorCriteriaObservationBuilder.describeScreenSizeObservation(
|
|
146
|
+
input,
|
|
147
|
+
);
|
|
148
|
+
case CheckOn.BrowserType:
|
|
149
|
+
return MonitorCriteriaObservationBuilder.describeBrowserObservation(
|
|
150
|
+
input,
|
|
151
|
+
);
|
|
152
|
+
case CheckOn.LogCount:
|
|
153
|
+
return MonitorCriteriaObservationBuilder.describeLogCountObservation(
|
|
154
|
+
input,
|
|
155
|
+
);
|
|
156
|
+
case CheckOn.SpanCount:
|
|
157
|
+
return MonitorCriteriaObservationBuilder.describeSpanCountObservation(
|
|
158
|
+
input,
|
|
159
|
+
);
|
|
160
|
+
case CheckOn.MetricValue:
|
|
161
|
+
return MonitorCriteriaObservationBuilder.describeMetricValueObservation(
|
|
162
|
+
input,
|
|
163
|
+
);
|
|
164
|
+
default:
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private static describeResponseTimeObservation(input: {
|
|
170
|
+
criteriaFilter: CriteriaFilter;
|
|
171
|
+
dataToProcess: DataToProcess;
|
|
172
|
+
}): string | null {
|
|
173
|
+
const probeResponse: ProbeMonitorResponse | null =
|
|
174
|
+
MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
|
|
175
|
+
|
|
176
|
+
if (!probeResponse) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const responseTime: number | undefined =
|
|
181
|
+
probeResponse.responseTimeInMs ?? undefined;
|
|
182
|
+
|
|
183
|
+
if (responseTime === undefined || responseTime === null) {
|
|
184
|
+
return "Response time metric was not recorded";
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const formatted: string | null =
|
|
188
|
+
MonitorCriteriaMessageFormatter.formatNumber(responseTime, {
|
|
189
|
+
maximumFractionDigits: 2,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const evaluationWindow: string | null =
|
|
193
|
+
MonitorCriteriaExpectationBuilder.getEvaluationWindowDescription(
|
|
194
|
+
input.criteriaFilter,
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
let message: string = `Response Time (in ms) was ${formatted ?? responseTime} ms`;
|
|
198
|
+
|
|
199
|
+
if (evaluationWindow) {
|
|
200
|
+
message += ` ${evaluationWindow}`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return message;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private static describeResponseStatusCodeObservation(input: {
|
|
207
|
+
dataToProcess: DataToProcess;
|
|
208
|
+
}): string | null {
|
|
209
|
+
const probeResponse: ProbeMonitorResponse | null =
|
|
210
|
+
MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
|
|
211
|
+
|
|
212
|
+
if (!probeResponse) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (probeResponse.responseCode === undefined) {
|
|
217
|
+
return "Response status code was not recorded";
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return `Response Status Code was ${probeResponse.responseCode}.`;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private static describeResponseHeaderObservation(input: {
|
|
224
|
+
dataToProcess: DataToProcess;
|
|
225
|
+
}): string | null {
|
|
226
|
+
const probeResponse: ProbeMonitorResponse | null =
|
|
227
|
+
MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
|
|
228
|
+
|
|
229
|
+
if (!probeResponse) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const headers: Array<string> = Object.keys(
|
|
234
|
+
probeResponse.responseHeaders || {},
|
|
235
|
+
).map((header: string) => {
|
|
236
|
+
return header.toLowerCase();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
if (!headers.length) {
|
|
240
|
+
return "Response headers were empty.";
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return `Response headers present: ${MonitorCriteriaMessageFormatter.formatList(headers)}.`;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private static describeResponseHeaderValueObservation(input: {
|
|
247
|
+
dataToProcess: DataToProcess;
|
|
248
|
+
}): string | null {
|
|
249
|
+
const probeResponse: ProbeMonitorResponse | null =
|
|
250
|
+
MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
|
|
251
|
+
|
|
252
|
+
if (!probeResponse) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const headerValues: Array<string> = Object.values(
|
|
257
|
+
probeResponse.responseHeaders || {},
|
|
258
|
+
).map((value: string) => {
|
|
259
|
+
return value.toLowerCase();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
if (!headerValues.length) {
|
|
263
|
+
return "Response header values were empty.";
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return `Response header values: ${MonitorCriteriaMessageFormatter.formatList(headerValues)}.`;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private static describeResponseBodyObservation(input: {
|
|
270
|
+
dataToProcess: DataToProcess;
|
|
271
|
+
}): string | null {
|
|
272
|
+
const probeResponse: ProbeMonitorResponse | null =
|
|
273
|
+
MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
|
|
274
|
+
|
|
275
|
+
if (!probeResponse) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (!probeResponse.responseBody) {
|
|
280
|
+
return "Response body was empty.";
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
let bodyAsString: string;
|
|
284
|
+
|
|
285
|
+
if (typeof probeResponse.responseBody === Typeof.Object) {
|
|
286
|
+
try {
|
|
287
|
+
bodyAsString = JSON.stringify(probeResponse.responseBody);
|
|
288
|
+
} catch (err) {
|
|
289
|
+
logger.error(err);
|
|
290
|
+
bodyAsString = "[object]";
|
|
291
|
+
}
|
|
292
|
+
} else {
|
|
293
|
+
bodyAsString = probeResponse.responseBody as string;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return `Response body sample: ${MonitorCriteriaMessageFormatter.formatSnippet(bodyAsString)}.`;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private static describeIsOnlineObservation(input: {
|
|
300
|
+
criteriaFilter: CriteriaFilter;
|
|
301
|
+
dataToProcess: DataToProcess;
|
|
302
|
+
}): string | null {
|
|
303
|
+
const probeResponse: ProbeMonitorResponse | null =
|
|
304
|
+
MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
|
|
305
|
+
|
|
306
|
+
if (probeResponse && probeResponse.isOnline !== undefined) {
|
|
307
|
+
return `Monitor reported ${
|
|
308
|
+
probeResponse.isOnline ? "online" : "offline"
|
|
309
|
+
} status at ${OneUptimeDate.getDateAsLocalFormattedString(
|
|
310
|
+
probeResponse.monitoredAt,
|
|
311
|
+
)}.`;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const serverResponse: ServerMonitorResponse | null =
|
|
315
|
+
MonitorCriteriaDataExtractor.getServerMonitorResponse(
|
|
316
|
+
input.dataToProcess,
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
if (serverResponse) {
|
|
320
|
+
const lastHeartbeat: Date = serverResponse.requestReceivedAt;
|
|
321
|
+
const timeNow: Date =
|
|
322
|
+
serverResponse.timeNow || OneUptimeDate.getCurrentDate();
|
|
323
|
+
const minutesSinceHeartbeat: number =
|
|
324
|
+
OneUptimeDate.getDifferenceInMinutes(lastHeartbeat, timeNow);
|
|
325
|
+
|
|
326
|
+
const formattedMinutes: string | null =
|
|
327
|
+
MonitorCriteriaMessageFormatter.formatNumber(minutesSinceHeartbeat, {
|
|
328
|
+
maximumFractionDigits: 2,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
return `Server heartbeat last received ${
|
|
332
|
+
formattedMinutes ?? minutesSinceHeartbeat
|
|
333
|
+
} minutes ago.`;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
private static describeIsTimeoutObservation(input: {
|
|
340
|
+
dataToProcess: DataToProcess;
|
|
341
|
+
}): string | null {
|
|
342
|
+
const probeResponse: ProbeMonitorResponse | null =
|
|
343
|
+
MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
|
|
344
|
+
|
|
345
|
+
if (probeResponse && probeResponse.isTimeout !== undefined) {
|
|
346
|
+
return probeResponse.isTimeout
|
|
347
|
+
? "Request timed out."
|
|
348
|
+
: "Request completed before timeout.";
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return "Timeout information was unavailable.";
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private static describeIncomingRequestObservation(input: {
|
|
355
|
+
criteriaFilter: CriteriaFilter;
|
|
356
|
+
dataToProcess: DataToProcess;
|
|
357
|
+
}): string | null {
|
|
358
|
+
const incomingRequest: IncomingMonitorRequest | null =
|
|
359
|
+
MonitorCriteriaDataExtractor.getIncomingMonitorRequest(
|
|
360
|
+
input.dataToProcess,
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
if (!incomingRequest) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const lastHeartbeat: Date = incomingRequest.incomingRequestReceivedAt;
|
|
368
|
+
const checkedAt: Date =
|
|
369
|
+
incomingRequest.checkedAt || OneUptimeDate.getCurrentDate();
|
|
370
|
+
|
|
371
|
+
const minutesSinceHeartbeat: number = OneUptimeDate.getDifferenceInMinutes(
|
|
372
|
+
lastHeartbeat,
|
|
373
|
+
checkedAt,
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
const formattedMinutes: string | null =
|
|
377
|
+
MonitorCriteriaMessageFormatter.formatNumber(minutesSinceHeartbeat, {
|
|
378
|
+
maximumFractionDigits: 2,
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
return `Last incoming request was ${
|
|
382
|
+
formattedMinutes ?? minutesSinceHeartbeat
|
|
383
|
+
} minutes ago (checked at ${OneUptimeDate.getDateAsLocalFormattedString(
|
|
384
|
+
checkedAt,
|
|
385
|
+
)}).`;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
private static describeRequestBodyObservation(input: {
|
|
389
|
+
dataToProcess: DataToProcess;
|
|
390
|
+
}): string | null {
|
|
391
|
+
const incomingRequest: IncomingMonitorRequest | null =
|
|
392
|
+
MonitorCriteriaDataExtractor.getIncomingMonitorRequest(
|
|
393
|
+
input.dataToProcess,
|
|
394
|
+
);
|
|
395
|
+
|
|
396
|
+
if (!incomingRequest) {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const requestBody: string | JSONObject | undefined =
|
|
401
|
+
incomingRequest.requestBody;
|
|
402
|
+
|
|
403
|
+
if (!requestBody) {
|
|
404
|
+
return "Request body was empty.";
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
let requestBodyAsString: string;
|
|
408
|
+
|
|
409
|
+
if (typeof requestBody === Typeof.Object) {
|
|
410
|
+
try {
|
|
411
|
+
requestBodyAsString = JSON.stringify(requestBody);
|
|
412
|
+
} catch (err) {
|
|
413
|
+
logger.error(err);
|
|
414
|
+
requestBodyAsString = "[object]";
|
|
415
|
+
}
|
|
416
|
+
} else {
|
|
417
|
+
requestBodyAsString = requestBody as string;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return `Request body sample: ${MonitorCriteriaMessageFormatter.formatSnippet(requestBodyAsString)}.`;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
private static describeRequestHeaderObservation(input: {
|
|
424
|
+
dataToProcess: DataToProcess;
|
|
425
|
+
}): string | null {
|
|
426
|
+
const incomingRequest: IncomingMonitorRequest | null =
|
|
427
|
+
MonitorCriteriaDataExtractor.getIncomingMonitorRequest(
|
|
428
|
+
input.dataToProcess,
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
if (!incomingRequest) {
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const headers: Array<string> = Object.keys(
|
|
436
|
+
incomingRequest.requestHeaders || {},
|
|
437
|
+
).map((header: string) => {
|
|
438
|
+
return header.toLowerCase();
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
if (!headers.length) {
|
|
442
|
+
return "Request headers were empty.";
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return `Request headers present: ${MonitorCriteriaMessageFormatter.formatList(headers)}.`;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private static describeRequestHeaderValueObservation(input: {
|
|
449
|
+
dataToProcess: DataToProcess;
|
|
450
|
+
}): string | null {
|
|
451
|
+
const incomingRequest: IncomingMonitorRequest | null =
|
|
452
|
+
MonitorCriteriaDataExtractor.getIncomingMonitorRequest(
|
|
453
|
+
input.dataToProcess,
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
if (!incomingRequest) {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const headerValues: Array<string> = Object.values(
|
|
461
|
+
incomingRequest.requestHeaders || {},
|
|
462
|
+
).map((value: string) => {
|
|
463
|
+
return value.toLowerCase();
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
if (!headerValues.length) {
|
|
467
|
+
return "Request header values were empty.";
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
return `Request header values: ${MonitorCriteriaMessageFormatter.formatList(headerValues)}.`;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
private static describeJavaScriptExpressionObservation(input: {
|
|
474
|
+
criteriaFilter: CriteriaFilter;
|
|
475
|
+
}): string | null {
|
|
476
|
+
if (!input.criteriaFilter.value) {
|
|
477
|
+
return "JavaScript expression evaluated to false.";
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return `JavaScript expression "${input.criteriaFilter.value}" evaluated to false.`;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
private static describeCpuUsageObservation(input: {
|
|
484
|
+
dataToProcess: DataToProcess;
|
|
485
|
+
}): string | null {
|
|
486
|
+
const serverResponse: ServerMonitorResponse | null =
|
|
487
|
+
MonitorCriteriaDataExtractor.getServerMonitorResponse(
|
|
488
|
+
input.dataToProcess,
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
if (!serverResponse) {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const cpuMetrics: BasicInfrastructureMetrics | undefined =
|
|
496
|
+
serverResponse.basicInfrastructureMetrics;
|
|
497
|
+
|
|
498
|
+
if (!cpuMetrics || !cpuMetrics.cpuMetrics) {
|
|
499
|
+
return "CPU usage metrics were unavailable.";
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
const cpuPercent: string | null =
|
|
503
|
+
MonitorCriteriaMessageFormatter.formatPercentage(
|
|
504
|
+
cpuMetrics.cpuMetrics.percentUsed,
|
|
505
|
+
);
|
|
506
|
+
|
|
507
|
+
const coreInfo: string = cpuMetrics.cpuMetrics.cores
|
|
508
|
+
? ` across ${cpuMetrics.cpuMetrics.cores} core${
|
|
509
|
+
cpuMetrics.cpuMetrics.cores > 1 ? "s" : ""
|
|
510
|
+
}`
|
|
511
|
+
: "";
|
|
512
|
+
|
|
513
|
+
return `CPU Usage (in %) was ${cpuPercent ?? "unavailable"}${coreInfo}.`;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
private static describeMemoryUsageObservation(input: {
|
|
517
|
+
dataToProcess: DataToProcess;
|
|
518
|
+
}): string | null {
|
|
519
|
+
const serverResponse: ServerMonitorResponse | null =
|
|
520
|
+
MonitorCriteriaDataExtractor.getServerMonitorResponse(
|
|
521
|
+
input.dataToProcess,
|
|
522
|
+
);
|
|
523
|
+
|
|
524
|
+
if (!serverResponse) {
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const memoryMetrics: BasicInfrastructureMetrics | undefined =
|
|
529
|
+
serverResponse.basicInfrastructureMetrics;
|
|
530
|
+
|
|
531
|
+
if (!memoryMetrics || !memoryMetrics.memoryMetrics) {
|
|
532
|
+
return "Memory usage metrics were unavailable.";
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const percentUsed: string | null =
|
|
536
|
+
MonitorCriteriaMessageFormatter.formatPercentage(
|
|
537
|
+
memoryMetrics.memoryMetrics.percentUsed,
|
|
538
|
+
);
|
|
539
|
+
|
|
540
|
+
const used: string | null = MonitorCriteriaMessageFormatter.formatBytes(
|
|
541
|
+
memoryMetrics.memoryMetrics.used,
|
|
542
|
+
);
|
|
543
|
+
const total: string | null = MonitorCriteriaMessageFormatter.formatBytes(
|
|
544
|
+
memoryMetrics.memoryMetrics.total,
|
|
545
|
+
);
|
|
546
|
+
|
|
547
|
+
return `Memory Usage (in %) was ${percentUsed ?? "unavailable"} (${used ?? "?"} used of ${total ?? "?"}).`;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
private static describeDiskUsageObservation(input: {
|
|
551
|
+
criteriaFilter: CriteriaFilter;
|
|
552
|
+
dataToProcess: DataToProcess;
|
|
553
|
+
}): string | null {
|
|
554
|
+
const serverResponse: ServerMonitorResponse | null =
|
|
555
|
+
MonitorCriteriaDataExtractor.getServerMonitorResponse(
|
|
556
|
+
input.dataToProcess,
|
|
557
|
+
);
|
|
558
|
+
|
|
559
|
+
if (!serverResponse) {
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const diskPath: string =
|
|
564
|
+
input.criteriaFilter.serverMonitorOptions?.diskPath || "/";
|
|
565
|
+
|
|
566
|
+
const diskMetric: BasicInfrastructureMetrics | undefined =
|
|
567
|
+
serverResponse.basicInfrastructureMetrics;
|
|
568
|
+
|
|
569
|
+
if (!diskMetric || !diskMetric.diskMetrics?.length) {
|
|
570
|
+
return `Disk metrics for path ${diskPath} were unavailable.`;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const matchedDisk: BasicDiskMetrics | undefined =
|
|
574
|
+
diskMetric.diskMetrics.find((disk: BasicDiskMetrics) => {
|
|
575
|
+
return (
|
|
576
|
+
disk.diskPath.trim().toLowerCase() === diskPath.trim().toLowerCase()
|
|
577
|
+
);
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
if (!matchedDisk) {
|
|
581
|
+
return `Disk metrics did not include path ${diskPath}.`;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const percentUsedValue: number | null =
|
|
585
|
+
MonitorCriteriaMessageFormatter.computeDiskUsagePercent(matchedDisk);
|
|
586
|
+
const percentUsed: string | null =
|
|
587
|
+
MonitorCriteriaMessageFormatter.formatPercentage(
|
|
588
|
+
percentUsedValue ?? undefined,
|
|
589
|
+
);
|
|
590
|
+
|
|
591
|
+
const used: string | null = MonitorCriteriaMessageFormatter.formatBytes(
|
|
592
|
+
matchedDisk.used,
|
|
593
|
+
);
|
|
594
|
+
const total: string | null = MonitorCriteriaMessageFormatter.formatBytes(
|
|
595
|
+
matchedDisk.total,
|
|
596
|
+
);
|
|
597
|
+
const free: string | null = MonitorCriteriaMessageFormatter.formatBytes(
|
|
598
|
+
matchedDisk.free,
|
|
599
|
+
);
|
|
600
|
+
|
|
601
|
+
return `Disk Usage (in %) on disk ${diskPath} was ${
|
|
602
|
+
percentUsed ?? "unavailable"
|
|
603
|
+
} (${used ?? "?"} used of ${total ?? "?"}, free ${free ?? "?"}).`;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
private static describeServerProcessNameObservation(input: {
|
|
607
|
+
criteriaFilter: CriteriaFilter;
|
|
608
|
+
dataToProcess: DataToProcess;
|
|
609
|
+
}): string | null {
|
|
610
|
+
const serverResponse: ServerMonitorResponse | null =
|
|
611
|
+
MonitorCriteriaDataExtractor.getServerMonitorResponse(
|
|
612
|
+
input.dataToProcess,
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
if (!serverResponse) {
|
|
616
|
+
return null;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const thresholdName: string = (input.criteriaFilter.value ?? "")
|
|
620
|
+
.toString()
|
|
621
|
+
.trim()
|
|
622
|
+
.toLowerCase();
|
|
623
|
+
|
|
624
|
+
const processes: Array<ServerProcess> = serverResponse.processes || [];
|
|
625
|
+
|
|
626
|
+
const matchingProcesses: Array<ServerProcess> = processes.filter(
|
|
627
|
+
(process: ServerProcess) => {
|
|
628
|
+
return process.name.trim().toLowerCase() === thresholdName;
|
|
629
|
+
},
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
if (matchingProcesses.length > 0) {
|
|
633
|
+
const summary: string = matchingProcesses
|
|
634
|
+
.map((process: ServerProcess) => {
|
|
635
|
+
return `${process.name} (pid ${process.pid})`;
|
|
636
|
+
})
|
|
637
|
+
.join(", ");
|
|
638
|
+
|
|
639
|
+
return `Process ${input.criteriaFilter.value} is running (${summary}).`;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
const processSummary: string | null =
|
|
643
|
+
MonitorCriteriaMessageFormatter.describeProcesses(processes);
|
|
644
|
+
|
|
645
|
+
if (processSummary) {
|
|
646
|
+
return `Process ${input.criteriaFilter.value} was not running. Active processes: ${processSummary}.`;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
return `Process ${input.criteriaFilter.value} was not running.`;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
private static describeServerProcessPidObservation(input: {
|
|
653
|
+
criteriaFilter: CriteriaFilter;
|
|
654
|
+
dataToProcess: DataToProcess;
|
|
655
|
+
}): string | null {
|
|
656
|
+
const serverResponse: ServerMonitorResponse | null =
|
|
657
|
+
MonitorCriteriaDataExtractor.getServerMonitorResponse(
|
|
658
|
+
input.dataToProcess,
|
|
659
|
+
);
|
|
660
|
+
|
|
661
|
+
if (!serverResponse) {
|
|
662
|
+
return null;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
const thresholdPid: string = (input.criteriaFilter.value ?? "")
|
|
666
|
+
.toString()
|
|
667
|
+
.trim()
|
|
668
|
+
.toLowerCase();
|
|
669
|
+
|
|
670
|
+
const processes: Array<ServerProcess> = serverResponse.processes || [];
|
|
671
|
+
|
|
672
|
+
const matchingProcesses: Array<ServerProcess> = processes.filter(
|
|
673
|
+
(process: ServerProcess) => {
|
|
674
|
+
return process.pid.toString().trim().toLowerCase() === thresholdPid;
|
|
675
|
+
},
|
|
676
|
+
);
|
|
677
|
+
|
|
678
|
+
if (matchingProcesses.length > 0) {
|
|
679
|
+
const summary: string = matchingProcesses
|
|
680
|
+
.map((process: ServerProcess) => {
|
|
681
|
+
return `${process.name} (pid ${process.pid})`;
|
|
682
|
+
})
|
|
683
|
+
.join(", ");
|
|
684
|
+
|
|
685
|
+
return `Process with PID ${input.criteriaFilter.value} is running (${summary}).`;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
const processSummary: string | null =
|
|
689
|
+
MonitorCriteriaMessageFormatter.describeProcesses(processes);
|
|
690
|
+
|
|
691
|
+
if (processSummary) {
|
|
692
|
+
return `Process with PID ${input.criteriaFilter.value} was not running. Active processes: ${processSummary}.`;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
return `Process with PID ${input.criteriaFilter.value} was not running.`;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
private static describeServerProcessCommandObservation(input: {
|
|
699
|
+
criteriaFilter: CriteriaFilter;
|
|
700
|
+
dataToProcess: DataToProcess;
|
|
701
|
+
}): string | null {
|
|
702
|
+
const serverResponse: ServerMonitorResponse | null =
|
|
703
|
+
MonitorCriteriaDataExtractor.getServerMonitorResponse(
|
|
704
|
+
input.dataToProcess,
|
|
705
|
+
);
|
|
706
|
+
|
|
707
|
+
if (!serverResponse) {
|
|
708
|
+
return null;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
const thresholdCommand: string = (input.criteriaFilter.value ?? "")
|
|
712
|
+
.toString()
|
|
713
|
+
.trim()
|
|
714
|
+
.toLowerCase();
|
|
715
|
+
|
|
716
|
+
const processes: Array<ServerProcess> = serverResponse.processes || [];
|
|
717
|
+
|
|
718
|
+
const matchingProcesses: Array<ServerProcess> = processes.filter(
|
|
719
|
+
(process: ServerProcess) => {
|
|
720
|
+
return process.command.trim().toLowerCase() === thresholdCommand;
|
|
721
|
+
},
|
|
722
|
+
);
|
|
723
|
+
|
|
724
|
+
if (matchingProcesses.length > 0) {
|
|
725
|
+
const summary: string = matchingProcesses
|
|
726
|
+
.map((process: ServerProcess) => {
|
|
727
|
+
return `${process.command} (pid ${process.pid})`;
|
|
728
|
+
})
|
|
729
|
+
.join(", ");
|
|
730
|
+
|
|
731
|
+
return `Process with command ${input.criteriaFilter.value} is running (${summary}).`;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
const processSummary: string | null =
|
|
735
|
+
MonitorCriteriaMessageFormatter.describeProcesses(processes);
|
|
736
|
+
|
|
737
|
+
if (processSummary) {
|
|
738
|
+
return `Process with command ${input.criteriaFilter.value} was not running. Active processes: ${processSummary}.`;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
return `Process with command ${input.criteriaFilter.value} was not running.`;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
private static describeCertificateExpiresInHoursObservation(input: {
|
|
745
|
+
dataToProcess: DataToProcess;
|
|
746
|
+
}): string | null {
|
|
747
|
+
const sslResponse: SslMonitorResponse | null =
|
|
748
|
+
MonitorCriteriaDataExtractor.getSslResponse(input.dataToProcess);
|
|
749
|
+
|
|
750
|
+
if (!sslResponse || !sslResponse.expiresAt) {
|
|
751
|
+
return "SSL certificate expiration time was unavailable.";
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
const hoursRemaining: number = OneUptimeDate.getHoursBetweenTwoDates(
|
|
755
|
+
OneUptimeDate.getCurrentDate(),
|
|
756
|
+
sslResponse.expiresAt,
|
|
757
|
+
);
|
|
758
|
+
|
|
759
|
+
const formattedHours: string | null =
|
|
760
|
+
MonitorCriteriaMessageFormatter.formatNumber(hoursRemaining, {
|
|
761
|
+
maximumFractionDigits: 2,
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
return `SSL certificate expires at ${OneUptimeDate.getDateAsLocalFormattedString(
|
|
765
|
+
sslResponse.expiresAt,
|
|
766
|
+
)} (${formattedHours ?? hoursRemaining} hours remaining).`;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
private static describeCertificateExpiresInDaysObservation(input: {
|
|
770
|
+
dataToProcess: DataToProcess;
|
|
771
|
+
}): string | null {
|
|
772
|
+
const sslResponse: SslMonitorResponse | null =
|
|
773
|
+
MonitorCriteriaDataExtractor.getSslResponse(input.dataToProcess);
|
|
774
|
+
|
|
775
|
+
if (!sslResponse || !sslResponse.expiresAt) {
|
|
776
|
+
return "SSL certificate expiration time was unavailable.";
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
const daysRemaining: number = OneUptimeDate.getDaysBetweenTwoDates(
|
|
780
|
+
OneUptimeDate.getCurrentDate(),
|
|
781
|
+
sslResponse.expiresAt,
|
|
782
|
+
);
|
|
783
|
+
|
|
784
|
+
const formattedDays: string | null =
|
|
785
|
+
MonitorCriteriaMessageFormatter.formatNumber(daysRemaining, {
|
|
786
|
+
maximumFractionDigits: 2,
|
|
787
|
+
});
|
|
788
|
+
|
|
789
|
+
return `SSL certificate expires at ${OneUptimeDate.getDateAsLocalFormattedString(
|
|
790
|
+
sslResponse.expiresAt,
|
|
791
|
+
)} (${formattedDays ?? daysRemaining} days remaining).`;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
private static describeIsSelfSignedObservation(input: {
|
|
795
|
+
dataToProcess: DataToProcess;
|
|
796
|
+
}): string | null {
|
|
797
|
+
const sslResponse: SslMonitorResponse | null =
|
|
798
|
+
MonitorCriteriaDataExtractor.getSslResponse(input.dataToProcess);
|
|
799
|
+
|
|
800
|
+
if (!sslResponse || sslResponse.isSelfSigned === undefined) {
|
|
801
|
+
return "SSL certificate self-signed status was unavailable.";
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
return sslResponse.isSelfSigned
|
|
805
|
+
? "SSL certificate is self signed."
|
|
806
|
+
: "SSL certificate is not self signed.";
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
private static describeIsExpiredObservation(input: {
|
|
810
|
+
dataToProcess: DataToProcess;
|
|
811
|
+
}): string | null {
|
|
812
|
+
const sslResponse: SslMonitorResponse | null =
|
|
813
|
+
MonitorCriteriaDataExtractor.getSslResponse(input.dataToProcess);
|
|
814
|
+
|
|
815
|
+
if (!sslResponse || !sslResponse.expiresAt) {
|
|
816
|
+
return "SSL certificate expiration time was unavailable.";
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
const isExpired: boolean = OneUptimeDate.isBefore(
|
|
820
|
+
sslResponse.expiresAt,
|
|
821
|
+
OneUptimeDate.getCurrentDate(),
|
|
822
|
+
);
|
|
823
|
+
|
|
824
|
+
return isExpired
|
|
825
|
+
? "SSL certificate is expired."
|
|
826
|
+
: "SSL certificate is not expired.";
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
private static describeIsValidObservation(input: {
|
|
830
|
+
dataToProcess: DataToProcess;
|
|
831
|
+
}): string | null {
|
|
832
|
+
const probeResponse: ProbeMonitorResponse | null =
|
|
833
|
+
MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
|
|
834
|
+
|
|
835
|
+
const sslResponse: SslMonitorResponse | undefined =
|
|
836
|
+
probeResponse?.sslResponse;
|
|
837
|
+
|
|
838
|
+
const isValid: boolean = Boolean(
|
|
839
|
+
sslResponse &&
|
|
840
|
+
probeResponse?.isOnline &&
|
|
841
|
+
sslResponse.expiresAt &&
|
|
842
|
+
!sslResponse.isSelfSigned &&
|
|
843
|
+
OneUptimeDate.isAfter(
|
|
844
|
+
sslResponse.expiresAt,
|
|
845
|
+
OneUptimeDate.getCurrentDate(),
|
|
846
|
+
),
|
|
847
|
+
);
|
|
848
|
+
|
|
849
|
+
if (!sslResponse) {
|
|
850
|
+
return "SSL certificate details were unavailable.";
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
return isValid
|
|
854
|
+
? "SSL certificate is valid."
|
|
855
|
+
: "SSL certificate is not valid.";
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
private static describeIsInvalidObservation(input: {
|
|
859
|
+
dataToProcess: DataToProcess;
|
|
860
|
+
}): string | null {
|
|
861
|
+
const probeResponse: ProbeMonitorResponse | null =
|
|
862
|
+
MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
|
|
863
|
+
|
|
864
|
+
const sslResponse: SslMonitorResponse | undefined =
|
|
865
|
+
probeResponse?.sslResponse;
|
|
866
|
+
|
|
867
|
+
const isInvalid: boolean =
|
|
868
|
+
!sslResponse ||
|
|
869
|
+
!probeResponse?.isOnline ||
|
|
870
|
+
Boolean(
|
|
871
|
+
sslResponse &&
|
|
872
|
+
sslResponse.expiresAt &&
|
|
873
|
+
(sslResponse.isSelfSigned ||
|
|
874
|
+
OneUptimeDate.isBefore(
|
|
875
|
+
sslResponse.expiresAt,
|
|
876
|
+
OneUptimeDate.getCurrentDate(),
|
|
877
|
+
)),
|
|
878
|
+
);
|
|
879
|
+
|
|
880
|
+
if (!sslResponse) {
|
|
881
|
+
return "SSL certificate details were unavailable.";
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
return isInvalid
|
|
885
|
+
? "SSL certificate is not valid."
|
|
886
|
+
: "SSL certificate is valid.";
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
private static describeExecutionTimeObservation(input: {
|
|
890
|
+
dataToProcess: DataToProcess;
|
|
891
|
+
}): string | null {
|
|
892
|
+
const syntheticResponses: Array<SyntheticMonitorResponse> =
|
|
893
|
+
MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(
|
|
894
|
+
input.dataToProcess,
|
|
895
|
+
);
|
|
896
|
+
|
|
897
|
+
const executionTimes: Array<number> = syntheticResponses
|
|
898
|
+
.map((response: SyntheticMonitorResponse) => {
|
|
899
|
+
return response.executionTimeInMS;
|
|
900
|
+
})
|
|
901
|
+
.filter((value: number) => {
|
|
902
|
+
return typeof value === "number" && !isNaN(value);
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
if (executionTimes.length > 0) {
|
|
906
|
+
const summary: string | null =
|
|
907
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries(executionTimes);
|
|
908
|
+
|
|
909
|
+
if (summary) {
|
|
910
|
+
return `Execution Time (in ms) recorded ${summary}.`;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
const customCodeResponse: CustomCodeMonitorResponse | null =
|
|
915
|
+
MonitorCriteriaDataExtractor.getCustomCodeMonitorResponse(
|
|
916
|
+
input.dataToProcess,
|
|
917
|
+
);
|
|
918
|
+
|
|
919
|
+
if (customCodeResponse) {
|
|
920
|
+
const formatted: string | null =
|
|
921
|
+
MonitorCriteriaMessageFormatter.formatNumber(
|
|
922
|
+
customCodeResponse.executionTimeInMS,
|
|
923
|
+
{ maximumFractionDigits: 2 },
|
|
924
|
+
);
|
|
925
|
+
|
|
926
|
+
return `Execution Time (in ms) was ${
|
|
927
|
+
formatted ?? customCodeResponse.executionTimeInMS
|
|
928
|
+
} ms.`;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
return "Execution time was unavailable.";
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
private static describeResultValueObservation(input: {
|
|
935
|
+
dataToProcess: DataToProcess;
|
|
936
|
+
}): string | null {
|
|
937
|
+
const syntheticResponses: Array<SyntheticMonitorResponse> =
|
|
938
|
+
MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(
|
|
939
|
+
input.dataToProcess,
|
|
940
|
+
);
|
|
941
|
+
|
|
942
|
+
const resultValues: Array<string> = syntheticResponses
|
|
943
|
+
.map((response: SyntheticMonitorResponse) => {
|
|
944
|
+
return MonitorCriteriaMessageFormatter.formatResultValue(
|
|
945
|
+
response.result,
|
|
946
|
+
);
|
|
947
|
+
})
|
|
948
|
+
.filter((value: string) => {
|
|
949
|
+
return value !== "undefined";
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
if (resultValues.length > 0) {
|
|
953
|
+
const uniqueResults: Array<string> = Array.from(new Set(resultValues));
|
|
954
|
+
|
|
955
|
+
return `Result Value samples: ${MonitorCriteriaMessageFormatter.formatList(uniqueResults)}.`;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
const customCodeResponse: CustomCodeMonitorResponse | null =
|
|
959
|
+
MonitorCriteriaDataExtractor.getCustomCodeMonitorResponse(
|
|
960
|
+
input.dataToProcess,
|
|
961
|
+
);
|
|
962
|
+
|
|
963
|
+
if (customCodeResponse && customCodeResponse.result !== undefined) {
|
|
964
|
+
const formatted: string =
|
|
965
|
+
MonitorCriteriaMessageFormatter.formatResultValue(
|
|
966
|
+
customCodeResponse.result,
|
|
967
|
+
);
|
|
968
|
+
|
|
969
|
+
return `Result Value was ${MonitorCriteriaMessageFormatter.formatSnippet(formatted)}.`;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
return "Result value was unavailable.";
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
private static describeErrorObservation(input: {
|
|
976
|
+
dataToProcess: DataToProcess;
|
|
977
|
+
}): string | null {
|
|
978
|
+
const syntheticResponses: Array<SyntheticMonitorResponse> =
|
|
979
|
+
MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(
|
|
980
|
+
input.dataToProcess,
|
|
981
|
+
);
|
|
982
|
+
|
|
983
|
+
const errors: Array<string> = syntheticResponses
|
|
984
|
+
.map((response: SyntheticMonitorResponse) => {
|
|
985
|
+
return response.scriptError;
|
|
986
|
+
})
|
|
987
|
+
.filter((value: string | undefined): value is string => {
|
|
988
|
+
return Boolean(value);
|
|
989
|
+
})
|
|
990
|
+
.map((error: string) => {
|
|
991
|
+
return MonitorCriteriaMessageFormatter.formatSnippet(error, 80);
|
|
992
|
+
});
|
|
993
|
+
|
|
994
|
+
if (errors.length > 0) {
|
|
995
|
+
return `Script errors: ${MonitorCriteriaMessageFormatter.formatList(errors)}.`;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
const customCodeResponse: CustomCodeMonitorResponse | null =
|
|
999
|
+
MonitorCriteriaDataExtractor.getCustomCodeMonitorResponse(
|
|
1000
|
+
input.dataToProcess,
|
|
1001
|
+
);
|
|
1002
|
+
|
|
1003
|
+
if (customCodeResponse?.scriptError) {
|
|
1004
|
+
return `Script error: ${MonitorCriteriaMessageFormatter.formatSnippet(customCodeResponse.scriptError, 80)}.`;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
if (customCodeResponse?.logMessages?.length) {
|
|
1008
|
+
return `Script log messages: ${MonitorCriteriaMessageFormatter.formatList(customCodeResponse.logMessages)}.`;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
return "No script errors were reported.";
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
private static describeScreenSizeObservation(input: {
|
|
1015
|
+
dataToProcess: DataToProcess;
|
|
1016
|
+
}): string | null {
|
|
1017
|
+
const syntheticResponses: Array<SyntheticMonitorResponse> =
|
|
1018
|
+
MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(
|
|
1019
|
+
input.dataToProcess,
|
|
1020
|
+
);
|
|
1021
|
+
|
|
1022
|
+
if (!syntheticResponses.length) {
|
|
1023
|
+
return "Synthetic monitor results were unavailable.";
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
const screenSizes: Array<string> = Array.from(
|
|
1027
|
+
new Set(
|
|
1028
|
+
syntheticResponses.map((response: SyntheticMonitorResponse) => {
|
|
1029
|
+
return response.screenSizeType;
|
|
1030
|
+
}),
|
|
1031
|
+
),
|
|
1032
|
+
);
|
|
1033
|
+
|
|
1034
|
+
return `Synthetic monitor screen sizes: ${MonitorCriteriaMessageFormatter.formatList(screenSizes)}.`;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
private static describeBrowserObservation(input: {
|
|
1038
|
+
dataToProcess: DataToProcess;
|
|
1039
|
+
}): string | null {
|
|
1040
|
+
const syntheticResponses: Array<SyntheticMonitorResponse> =
|
|
1041
|
+
MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(
|
|
1042
|
+
input.dataToProcess,
|
|
1043
|
+
);
|
|
1044
|
+
|
|
1045
|
+
if (!syntheticResponses.length) {
|
|
1046
|
+
return "Synthetic monitor results were unavailable.";
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
const browsers: Array<string> = Array.from(
|
|
1050
|
+
new Set(
|
|
1051
|
+
syntheticResponses.map((response: SyntheticMonitorResponse) => {
|
|
1052
|
+
return response.browserType;
|
|
1053
|
+
}),
|
|
1054
|
+
),
|
|
1055
|
+
);
|
|
1056
|
+
|
|
1057
|
+
return `Synthetic monitor browsers: ${MonitorCriteriaMessageFormatter.formatList(browsers)}.`;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
private static describeLogCountObservation(input: {
|
|
1061
|
+
dataToProcess: DataToProcess;
|
|
1062
|
+
}): string | null {
|
|
1063
|
+
const logResponse: LogMonitorResponse | null =
|
|
1064
|
+
MonitorCriteriaDataExtractor.getLogMonitorResponse(input.dataToProcess);
|
|
1065
|
+
|
|
1066
|
+
if (!logResponse) {
|
|
1067
|
+
return null;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
return `Log count was ${logResponse.logCount}.`;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
private static describeSpanCountObservation(input: {
|
|
1074
|
+
dataToProcess: DataToProcess;
|
|
1075
|
+
}): string | null {
|
|
1076
|
+
const traceResponse: TraceMonitorResponse | null =
|
|
1077
|
+
MonitorCriteriaDataExtractor.getTraceMonitorResponse(input.dataToProcess);
|
|
1078
|
+
|
|
1079
|
+
if (!traceResponse) {
|
|
1080
|
+
return null;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
return `Span count was ${traceResponse.spanCount}.`;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
private static describeMetricValueObservation(input: {
|
|
1087
|
+
criteriaFilter: CriteriaFilter;
|
|
1088
|
+
dataToProcess: DataToProcess;
|
|
1089
|
+
monitorStep: MonitorStep;
|
|
1090
|
+
}): string | null {
|
|
1091
|
+
const metricValues: {
|
|
1092
|
+
alias: string | null;
|
|
1093
|
+
values: Array<number>;
|
|
1094
|
+
} | null = MonitorCriteriaDataExtractor.extractMetricValues({
|
|
1095
|
+
criteriaFilter: input.criteriaFilter,
|
|
1096
|
+
dataToProcess: input.dataToProcess,
|
|
1097
|
+
monitorStep: input.monitorStep,
|
|
1098
|
+
});
|
|
1099
|
+
|
|
1100
|
+
if (!metricValues) {
|
|
1101
|
+
return null;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
if (!metricValues.values.length) {
|
|
1105
|
+
return `Metric Value${
|
|
1106
|
+
metricValues.alias ? ` (${metricValues.alias})` : ""
|
|
1107
|
+
} returned no data points.`;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
const summary: string | null =
|
|
1111
|
+
MonitorCriteriaMessageFormatter.summarizeNumericSeries(
|
|
1112
|
+
metricValues.values,
|
|
1113
|
+
);
|
|
1114
|
+
|
|
1115
|
+
if (!summary) {
|
|
1116
|
+
return null;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
return `Metric Value${
|
|
1120
|
+
metricValues.alias ? ` (${metricValues.alias})` : ""
|
|
1121
|
+
} recorded ${summary}.`;
|
|
1122
|
+
}
|
|
1123
|
+
}
|