@oneuptime/common 10.0.71 → 10.0.73
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/Alert.ts +55 -0
- package/Models/DatabaseModels/Incident.ts +55 -0
- package/Models/DatabaseModels/Project.ts +26 -0
- package/Models/DatabaseModels/Service.ts +2 -2
- package/Models/DatabaseModels/StatusPage.ts +80 -0
- package/Server/API/StatusPageAPI.ts +4 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776940714709-MigrationName.ts +41 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776971364783-AddStatusPageLanguageSettings.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1777018175127-AddTelemetryRetentionSettings.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Services/AnalyticsDatabaseService.ts +17 -7
- package/Server/Services/OpenTelemetryIngestService.ts +36 -5
- package/Server/Services/ServiceService.ts +27 -1
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +175 -29
- package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +71 -0
- package/Server/Utils/Monitor/MonitorAlert.ts +91 -7
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +171 -2
- package/Server/Utils/Monitor/MonitorIncident.ts +133 -8
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +423 -1
- package/Server/Utils/Monitor/MonitorResource.ts +2 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +99 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +268 -0
- package/Types/AdminDashboard/AdminDashboardLanguage.ts +33 -0
- package/Types/Infrastructure/BasicMetrics.ts +75 -0
- package/Types/Metrics/MetricQueryData.ts +11 -0
- package/Types/Monitor/CriteriaFilter.ts +10 -0
- package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +11 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +10 -0
- package/Types/Monitor/MetricMonitor/MetricSeriesResult.ts +20 -0
- package/Types/Monitor/MonitorMetricType.ts +34 -0
- package/Types/Monitor/ServerMonitor/ServerMonitorResponse.ts +8 -0
- package/Types/Probe/ProbeApiIngestResponse.ts +25 -0
- package/Types/StatusPage/StatusPageLanguage.ts +30 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +17 -12
- package/UI/Components/Charts/Bar/BarChart.tsx +16 -11
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +23 -0
- package/UI/Components/Charts/Line/LineChart.tsx +16 -11
- package/UI/Components/Filters/FiltersForm.tsx +26 -2
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +453 -0
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +229 -0
- package/Utils/Metrics/MetricSeriesFingerprint.ts +97 -0
- package/Utils/Monitor/MonitorMetricType.ts +309 -19
- package/build/dist/Models/DatabaseModels/Alert.js +57 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +57 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +27 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Service.js +1 -2
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +82 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +4 -0
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776940714709-MigrationName.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776940714709-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776971364783-AddStatusPageLanguageSettings.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776971364783-AddStatusPageLanguageSettings.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1777018175127-AddTelemetryRetentionSettings.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1777018175127-AddTelemetryRetentionSettings.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +14 -4
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +30 -4
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +22 -1
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +132 -30
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +58 -7
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +66 -12
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +112 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +91 -15
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +373 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +2 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +65 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.js +199 -0
- package/build/dist/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.js.map +1 -1
- package/build/dist/Types/AdminDashboard/AdminDashboardLanguage.js +22 -0
- package/build/dist/Types/AdminDashboard/AdminDashboardLanguage.js.map +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js +10 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MetricMonitor/MetricSeriesResult.js +2 -0
- package/build/dist/Types/Monitor/MetricMonitor/MetricSeriesResult.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js +28 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/StatusPage/StatusPageLanguage.js +22 -0
- package/build/dist/Types/StatusPage/StatusPageLanguage.js.map +1 -0
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +13 -12
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +12 -11
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +11 -3
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js +12 -11
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Filters/FiltersForm.js +6 -2
- package/build/dist/UI/Components/Filters/FiltersForm.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +383 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +109 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js.map +1 -0
- package/build/dist/Utils/Metrics/MetricSeriesFingerprint.js +81 -0
- package/build/dist/Utils/Metrics/MetricSeriesFingerprint.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js +287 -19
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/package.json +1 -1
|
@@ -10,7 +10,9 @@ import {
|
|
|
10
10
|
ServiceType,
|
|
11
11
|
} from "../../../Models/AnalyticsModels/Metric";
|
|
12
12
|
import MetricType from "../../../Models/DatabaseModels/MetricType";
|
|
13
|
-
import BasicInfrastructureMetrics
|
|
13
|
+
import BasicInfrastructureMetrics, {
|
|
14
|
+
NetworkInterfaceMetrics,
|
|
15
|
+
} from "../../../Types/Infrastructure/BasicMetrics";
|
|
14
16
|
import Dictionary from "../../../Types/Dictionary";
|
|
15
17
|
import { JSONObject } from "../../../Types/JSON";
|
|
16
18
|
import CapturedMetric from "../../../Types/Monitor/CustomCodeMonitor/CapturedMetric";
|
|
@@ -159,6 +161,73 @@ export default class MonitorMetricUtil {
|
|
|
159
161
|
} as JSONObject;
|
|
160
162
|
}
|
|
161
163
|
|
|
164
|
+
/*
|
|
165
|
+
* Helper that collapses the "build attributes → build row → push → register MetricType"
|
|
166
|
+
* pattern used repeatedly below. Silently skips emission when value is missing/non-finite
|
|
167
|
+
* so callers can pass optional agent fields directly.
|
|
168
|
+
*/
|
|
169
|
+
private static async pushMonitorMetric(data: {
|
|
170
|
+
projectId: ObjectID;
|
|
171
|
+
monitorId: ObjectID;
|
|
172
|
+
monitorName: string | undefined;
|
|
173
|
+
probeName: string | undefined;
|
|
174
|
+
metricName: string;
|
|
175
|
+
value: number | null | undefined;
|
|
176
|
+
description: string;
|
|
177
|
+
unit: string;
|
|
178
|
+
extraAttributes?: JSONObject;
|
|
179
|
+
metricPointType?: MetricPointType;
|
|
180
|
+
metricRows: Array<JSONObject>;
|
|
181
|
+
metricNameServiceNameMap: Dictionary<MetricType>;
|
|
182
|
+
}): Promise<void> {
|
|
183
|
+
if (
|
|
184
|
+
data.value === undefined ||
|
|
185
|
+
data.value === null ||
|
|
186
|
+
typeof data.value !== "number" ||
|
|
187
|
+
!isFinite(data.value)
|
|
188
|
+
) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const attributeInput: {
|
|
193
|
+
monitorId: ObjectID;
|
|
194
|
+
projectId: ObjectID;
|
|
195
|
+
monitorName?: string | undefined;
|
|
196
|
+
probeName?: string | undefined;
|
|
197
|
+
extraAttributes?: JSONObject;
|
|
198
|
+
} = {
|
|
199
|
+
monitorId: data.monitorId,
|
|
200
|
+
projectId: data.projectId,
|
|
201
|
+
monitorName: data.monitorName,
|
|
202
|
+
probeName: data.probeName,
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
if (data.extraAttributes) {
|
|
206
|
+
attributeInput.extraAttributes = data.extraAttributes;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const attributes: JSONObject =
|
|
210
|
+
this.buildMonitorMetricAttributes(attributeInput);
|
|
211
|
+
|
|
212
|
+
const metricRow: JSONObject = await this.buildMonitorMetricRow({
|
|
213
|
+
projectId: data.projectId,
|
|
214
|
+
monitorId: data.monitorId,
|
|
215
|
+
metricName: data.metricName,
|
|
216
|
+
value: data.value,
|
|
217
|
+
attributes: attributes,
|
|
218
|
+
metricPointType: data.metricPointType || MetricPointType.Sum,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
data.metricRows.push(metricRow);
|
|
222
|
+
|
|
223
|
+
const metricType: MetricType = new MetricType();
|
|
224
|
+
metricType.name = data.metricName;
|
|
225
|
+
metricType.description = data.description;
|
|
226
|
+
metricType.unit = data.unit;
|
|
227
|
+
|
|
228
|
+
data.metricNameServiceNameMap[data.metricName] = metricType;
|
|
229
|
+
}
|
|
230
|
+
|
|
162
231
|
@CaptureSpan()
|
|
163
232
|
public static async saveMonitorMetrics(data: {
|
|
164
233
|
monitorId: ObjectID;
|
|
@@ -333,6 +402,359 @@ export default class MonitorMetricUtil {
|
|
|
333
402
|
metricNameServiceNameMap[MonitorMetricType.DiskUsagePercent] =
|
|
334
403
|
metricType;
|
|
335
404
|
}
|
|
405
|
+
|
|
406
|
+
// Per-disk I/O counters (cumulative since boot).
|
|
407
|
+
for (const diskMetric of basicMetrics.diskMetrics) {
|
|
408
|
+
const diskAttrs: JSONObject = {};
|
|
409
|
+
if (diskMetric.diskPath) {
|
|
410
|
+
diskAttrs["diskPath"] = diskMetric.diskPath;
|
|
411
|
+
}
|
|
412
|
+
if (diskMetric.device) {
|
|
413
|
+
diskAttrs["device"] = diskMetric.device;
|
|
414
|
+
}
|
|
415
|
+
if (diskMetric.fstype) {
|
|
416
|
+
diskAttrs["fstype"] = diskMetric.fstype;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
await this.pushMonitorMetric({
|
|
420
|
+
projectId: data.projectId,
|
|
421
|
+
monitorId: data.monitorId,
|
|
422
|
+
monitorName: data.monitorName,
|
|
423
|
+
probeName: data.probeName,
|
|
424
|
+
metricName: MonitorMetricType.DiskReadBytesTotal,
|
|
425
|
+
value: diskMetric.readBytes,
|
|
426
|
+
description: "Total bytes read from disk since boot",
|
|
427
|
+
unit: "bytes",
|
|
428
|
+
extraAttributes: diskAttrs,
|
|
429
|
+
metricRows,
|
|
430
|
+
metricNameServiceNameMap,
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
await this.pushMonitorMetric({
|
|
434
|
+
projectId: data.projectId,
|
|
435
|
+
monitorId: data.monitorId,
|
|
436
|
+
monitorName: data.monitorName,
|
|
437
|
+
probeName: data.probeName,
|
|
438
|
+
metricName: MonitorMetricType.DiskWriteBytesTotal,
|
|
439
|
+
value: diskMetric.writeBytes,
|
|
440
|
+
description: "Total bytes written to disk since boot",
|
|
441
|
+
unit: "bytes",
|
|
442
|
+
extraAttributes: diskAttrs,
|
|
443
|
+
metricRows,
|
|
444
|
+
metricNameServiceNameMap,
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
await this.pushMonitorMetric({
|
|
448
|
+
projectId: data.projectId,
|
|
449
|
+
monitorId: data.monitorId,
|
|
450
|
+
monitorName: data.monitorName,
|
|
451
|
+
probeName: data.probeName,
|
|
452
|
+
metricName: MonitorMetricType.DiskReadOpsTotal,
|
|
453
|
+
value: diskMetric.readCount,
|
|
454
|
+
description: "Total disk read operations since boot",
|
|
455
|
+
unit: "ops",
|
|
456
|
+
extraAttributes: diskAttrs,
|
|
457
|
+
metricRows,
|
|
458
|
+
metricNameServiceNameMap,
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
await this.pushMonitorMetric({
|
|
462
|
+
projectId: data.projectId,
|
|
463
|
+
monitorId: data.monitorId,
|
|
464
|
+
monitorName: data.monitorName,
|
|
465
|
+
probeName: data.probeName,
|
|
466
|
+
metricName: MonitorMetricType.DiskWriteOpsTotal,
|
|
467
|
+
value: diskMetric.writeCount,
|
|
468
|
+
description: "Total disk write operations since boot",
|
|
469
|
+
unit: "ops",
|
|
470
|
+
extraAttributes: diskAttrs,
|
|
471
|
+
metricRows,
|
|
472
|
+
metricNameServiceNameMap,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Load average (1/5/15 min). Emitted only when the agent provides it.
|
|
478
|
+
if (basicMetrics.loadMetrics) {
|
|
479
|
+
await this.pushMonitorMetric({
|
|
480
|
+
projectId: data.projectId,
|
|
481
|
+
monitorId: data.monitorId,
|
|
482
|
+
monitorName: data.monitorName,
|
|
483
|
+
probeName: data.probeName,
|
|
484
|
+
metricName: MonitorMetricType.LoadAverage1Min,
|
|
485
|
+
value: basicMetrics.loadMetrics.load1,
|
|
486
|
+
description: "1-minute load average",
|
|
487
|
+
unit: "",
|
|
488
|
+
metricRows,
|
|
489
|
+
metricNameServiceNameMap,
|
|
490
|
+
});
|
|
491
|
+
await this.pushMonitorMetric({
|
|
492
|
+
projectId: data.projectId,
|
|
493
|
+
monitorId: data.monitorId,
|
|
494
|
+
monitorName: data.monitorName,
|
|
495
|
+
probeName: data.probeName,
|
|
496
|
+
metricName: MonitorMetricType.LoadAverage5Min,
|
|
497
|
+
value: basicMetrics.loadMetrics.load5,
|
|
498
|
+
description: "5-minute load average",
|
|
499
|
+
unit: "",
|
|
500
|
+
metricRows,
|
|
501
|
+
metricNameServiceNameMap,
|
|
502
|
+
});
|
|
503
|
+
await this.pushMonitorMetric({
|
|
504
|
+
projectId: data.projectId,
|
|
505
|
+
monitorId: data.monitorId,
|
|
506
|
+
monitorName: data.monitorName,
|
|
507
|
+
probeName: data.probeName,
|
|
508
|
+
metricName: MonitorMetricType.LoadAverage15Min,
|
|
509
|
+
value: basicMetrics.loadMetrics.load15,
|
|
510
|
+
description: "15-minute load average",
|
|
511
|
+
unit: "",
|
|
512
|
+
metricRows,
|
|
513
|
+
metricNameServiceNameMap,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Memory extras: swap + available.
|
|
518
|
+
if (basicMetrics.memoryMetrics) {
|
|
519
|
+
await this.pushMonitorMetric({
|
|
520
|
+
projectId: data.projectId,
|
|
521
|
+
monitorId: data.monitorId,
|
|
522
|
+
monitorName: data.monitorName,
|
|
523
|
+
probeName: data.probeName,
|
|
524
|
+
metricName: MonitorMetricType.SwapUsagePercent,
|
|
525
|
+
value: basicMetrics.memoryMetrics.swapPercentUsed,
|
|
526
|
+
description: "Swap memory usage percentage",
|
|
527
|
+
unit: "%",
|
|
528
|
+
metricRows,
|
|
529
|
+
metricNameServiceNameMap,
|
|
530
|
+
});
|
|
531
|
+
await this.pushMonitorMetric({
|
|
532
|
+
projectId: data.projectId,
|
|
533
|
+
monitorId: data.monitorId,
|
|
534
|
+
monitorName: data.monitorName,
|
|
535
|
+
probeName: data.probeName,
|
|
536
|
+
metricName: MonitorMetricType.MemoryAvailableBytes,
|
|
537
|
+
value: basicMetrics.memoryMetrics.available,
|
|
538
|
+
description: "Memory available to new allocations",
|
|
539
|
+
unit: "bytes",
|
|
540
|
+
metricRows,
|
|
541
|
+
metricNameServiceNameMap,
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// CPU time breakdown — drills down into what the CPU was doing.
|
|
546
|
+
if (basicMetrics.cpuMetrics) {
|
|
547
|
+
await this.pushMonitorMetric({
|
|
548
|
+
projectId: data.projectId,
|
|
549
|
+
monitorId: data.monitorId,
|
|
550
|
+
monitorName: data.monitorName,
|
|
551
|
+
probeName: data.probeName,
|
|
552
|
+
metricName: MonitorMetricType.CPUTimeUserPercent,
|
|
553
|
+
value: basicMetrics.cpuMetrics.timeUserPercent,
|
|
554
|
+
description: "CPU time spent in user space",
|
|
555
|
+
unit: "%",
|
|
556
|
+
metricRows,
|
|
557
|
+
metricNameServiceNameMap,
|
|
558
|
+
});
|
|
559
|
+
await this.pushMonitorMetric({
|
|
560
|
+
projectId: data.projectId,
|
|
561
|
+
monitorId: data.monitorId,
|
|
562
|
+
monitorName: data.monitorName,
|
|
563
|
+
probeName: data.probeName,
|
|
564
|
+
metricName: MonitorMetricType.CPUTimeSystemPercent,
|
|
565
|
+
value: basicMetrics.cpuMetrics.timeSystemPercent,
|
|
566
|
+
description: "CPU time spent in kernel space",
|
|
567
|
+
unit: "%",
|
|
568
|
+
metricRows,
|
|
569
|
+
metricNameServiceNameMap,
|
|
570
|
+
});
|
|
571
|
+
await this.pushMonitorMetric({
|
|
572
|
+
projectId: data.projectId,
|
|
573
|
+
monitorId: data.monitorId,
|
|
574
|
+
monitorName: data.monitorName,
|
|
575
|
+
probeName: data.probeName,
|
|
576
|
+
metricName: MonitorMetricType.CPUTimeIoWaitPercent,
|
|
577
|
+
value: basicMetrics.cpuMetrics.timeIoWaitPercent,
|
|
578
|
+
description: "CPU time spent waiting on I/O",
|
|
579
|
+
unit: "%",
|
|
580
|
+
metricRows,
|
|
581
|
+
metricNameServiceNameMap,
|
|
582
|
+
});
|
|
583
|
+
await this.pushMonitorMetric({
|
|
584
|
+
projectId: data.projectId,
|
|
585
|
+
monitorId: data.monitorId,
|
|
586
|
+
monitorName: data.monitorName,
|
|
587
|
+
probeName: data.probeName,
|
|
588
|
+
metricName: MonitorMetricType.CPUTimeIdlePercent,
|
|
589
|
+
value: basicMetrics.cpuMetrics.timeIdlePercent,
|
|
590
|
+
description: "CPU time spent idle",
|
|
591
|
+
unit: "%",
|
|
592
|
+
metricRows,
|
|
593
|
+
metricNameServiceNameMap,
|
|
594
|
+
});
|
|
595
|
+
await this.pushMonitorMetric({
|
|
596
|
+
projectId: data.projectId,
|
|
597
|
+
monitorId: data.monitorId,
|
|
598
|
+
monitorName: data.monitorName,
|
|
599
|
+
probeName: data.probeName,
|
|
600
|
+
metricName: MonitorMetricType.CPUTimeStealPercent,
|
|
601
|
+
value: basicMetrics.cpuMetrics.timeStealPercent,
|
|
602
|
+
description: "CPU time stolen by the hypervisor",
|
|
603
|
+
unit: "%",
|
|
604
|
+
metricRows,
|
|
605
|
+
metricNameServiceNameMap,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// Network counters — both per-interface and aggregate.
|
|
610
|
+
if (basicMetrics.networkMetrics) {
|
|
611
|
+
const net: typeof basicMetrics.networkMetrics =
|
|
612
|
+
basicMetrics.networkMetrics;
|
|
613
|
+
|
|
614
|
+
for (const iface of net.interfaces || []) {
|
|
615
|
+
const ifaceAttrs: JSONObject = {
|
|
616
|
+
interfaceName: (iface as NetworkInterfaceMetrics).interfaceName,
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
await this.pushMonitorMetric({
|
|
620
|
+
projectId: data.projectId,
|
|
621
|
+
monitorId: data.monitorId,
|
|
622
|
+
monitorName: data.monitorName,
|
|
623
|
+
probeName: data.probeName,
|
|
624
|
+
metricName: MonitorMetricType.NetworkBytesReceivedTotal,
|
|
625
|
+
value: iface.bytesReceived,
|
|
626
|
+
description: "Network bytes received since boot (per-interface)",
|
|
627
|
+
unit: "bytes",
|
|
628
|
+
extraAttributes: ifaceAttrs,
|
|
629
|
+
metricRows,
|
|
630
|
+
metricNameServiceNameMap,
|
|
631
|
+
});
|
|
632
|
+
await this.pushMonitorMetric({
|
|
633
|
+
projectId: data.projectId,
|
|
634
|
+
monitorId: data.monitorId,
|
|
635
|
+
monitorName: data.monitorName,
|
|
636
|
+
probeName: data.probeName,
|
|
637
|
+
metricName: MonitorMetricType.NetworkBytesSentTotal,
|
|
638
|
+
value: iface.bytesSent,
|
|
639
|
+
description: "Network bytes sent since boot (per-interface)",
|
|
640
|
+
unit: "bytes",
|
|
641
|
+
extraAttributes: ifaceAttrs,
|
|
642
|
+
metricRows,
|
|
643
|
+
metricNameServiceNameMap,
|
|
644
|
+
});
|
|
645
|
+
await this.pushMonitorMetric({
|
|
646
|
+
projectId: data.projectId,
|
|
647
|
+
monitorId: data.monitorId,
|
|
648
|
+
monitorName: data.monitorName,
|
|
649
|
+
probeName: data.probeName,
|
|
650
|
+
metricName: MonitorMetricType.NetworkPacketsReceivedTotal,
|
|
651
|
+
value: iface.packetsReceived,
|
|
652
|
+
description: "Network packets received since boot (per-interface)",
|
|
653
|
+
unit: "packets",
|
|
654
|
+
extraAttributes: ifaceAttrs,
|
|
655
|
+
metricRows,
|
|
656
|
+
metricNameServiceNameMap,
|
|
657
|
+
});
|
|
658
|
+
await this.pushMonitorMetric({
|
|
659
|
+
projectId: data.projectId,
|
|
660
|
+
monitorId: data.monitorId,
|
|
661
|
+
monitorName: data.monitorName,
|
|
662
|
+
probeName: data.probeName,
|
|
663
|
+
metricName: MonitorMetricType.NetworkPacketsSentTotal,
|
|
664
|
+
value: iface.packetsSent,
|
|
665
|
+
description: "Network packets sent since boot (per-interface)",
|
|
666
|
+
unit: "packets",
|
|
667
|
+
extraAttributes: ifaceAttrs,
|
|
668
|
+
metricRows,
|
|
669
|
+
metricNameServiceNameMap,
|
|
670
|
+
});
|
|
671
|
+
await this.pushMonitorMetric({
|
|
672
|
+
projectId: data.projectId,
|
|
673
|
+
monitorId: data.monitorId,
|
|
674
|
+
monitorName: data.monitorName,
|
|
675
|
+
probeName: data.probeName,
|
|
676
|
+
metricName: MonitorMetricType.NetworkErrorsIn,
|
|
677
|
+
value: iface.errorsIn,
|
|
678
|
+
description: "Network receive errors since boot (per-interface)",
|
|
679
|
+
unit: "errors",
|
|
680
|
+
extraAttributes: ifaceAttrs,
|
|
681
|
+
metricRows,
|
|
682
|
+
metricNameServiceNameMap,
|
|
683
|
+
});
|
|
684
|
+
await this.pushMonitorMetric({
|
|
685
|
+
projectId: data.projectId,
|
|
686
|
+
monitorId: data.monitorId,
|
|
687
|
+
monitorName: data.monitorName,
|
|
688
|
+
probeName: data.probeName,
|
|
689
|
+
metricName: MonitorMetricType.NetworkErrorsOut,
|
|
690
|
+
value: iface.errorsOut,
|
|
691
|
+
description: "Network transmit errors since boot (per-interface)",
|
|
692
|
+
unit: "errors",
|
|
693
|
+
extraAttributes: ifaceAttrs,
|
|
694
|
+
metricRows,
|
|
695
|
+
metricNameServiceNameMap,
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
await this.pushMonitorMetric({
|
|
700
|
+
projectId: data.projectId,
|
|
701
|
+
monitorId: data.monitorId,
|
|
702
|
+
monitorName: data.monitorName,
|
|
703
|
+
probeName: data.probeName,
|
|
704
|
+
metricName: MonitorMetricType.NetworkConnectionsEstablished,
|
|
705
|
+
value: net.connectionsEstablished,
|
|
706
|
+
description: "Count of ESTABLISHED network connections",
|
|
707
|
+
unit: "connections",
|
|
708
|
+
metricRows,
|
|
709
|
+
metricNameServiceNameMap,
|
|
710
|
+
});
|
|
711
|
+
await this.pushMonitorMetric({
|
|
712
|
+
projectId: data.projectId,
|
|
713
|
+
monitorId: data.monitorId,
|
|
714
|
+
monitorName: data.monitorName,
|
|
715
|
+
probeName: data.probeName,
|
|
716
|
+
metricName: MonitorMetricType.NetworkConnectionsListen,
|
|
717
|
+
value: net.connectionsListen,
|
|
718
|
+
description: "Count of LISTENing network sockets",
|
|
719
|
+
unit: "connections",
|
|
720
|
+
metricRows,
|
|
721
|
+
metricNameServiceNameMap,
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Host uptime.
|
|
726
|
+
if (basicMetrics.hostMetrics) {
|
|
727
|
+
await this.pushMonitorMetric({
|
|
728
|
+
projectId: data.projectId,
|
|
729
|
+
monitorId: data.monitorId,
|
|
730
|
+
monitorName: data.monitorName,
|
|
731
|
+
probeName: data.probeName,
|
|
732
|
+
metricName: MonitorMetricType.HostUptimeSeconds,
|
|
733
|
+
value: basicMetrics.hostMetrics.uptimeSeconds,
|
|
734
|
+
description: "Host uptime in seconds",
|
|
735
|
+
unit: "seconds",
|
|
736
|
+
metricRows,
|
|
737
|
+
metricNameServiceNameMap,
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// Process count — simple scalar derived from the processes array.
|
|
742
|
+
const serverProcesses: Array<unknown> | undefined = (
|
|
743
|
+
data.dataToProcess as ServerMonitorResponse
|
|
744
|
+
).processes;
|
|
745
|
+
if (serverProcesses && serverProcesses.length >= 0) {
|
|
746
|
+
await this.pushMonitorMetric({
|
|
747
|
+
projectId: data.projectId,
|
|
748
|
+
monitorId: data.monitorId,
|
|
749
|
+
monitorName: data.monitorName,
|
|
750
|
+
probeName: data.probeName,
|
|
751
|
+
metricName: MonitorMetricType.ProcessCountTotal,
|
|
752
|
+
value: serverProcesses.length,
|
|
753
|
+
description: "Total running processes on the server",
|
|
754
|
+
unit: "processes",
|
|
755
|
+
metricRows,
|
|
756
|
+
metricNameServiceNameMap,
|
|
757
|
+
});
|
|
336
758
|
}
|
|
337
759
|
}
|
|
338
760
|
|
|
@@ -709,6 +709,7 @@ export default class MonitorResourceUtil {
|
|
|
709
709
|
props: {
|
|
710
710
|
telemetryQuery: telemetryQuery,
|
|
711
711
|
},
|
|
712
|
+
matchesPerSeries: response.perSeriesMatches,
|
|
712
713
|
});
|
|
713
714
|
|
|
714
715
|
await MonitorAlert.criteriaMetCreateAlertsAndUpdateMonitorStatus({
|
|
@@ -721,6 +722,7 @@ export default class MonitorResourceUtil {
|
|
|
721
722
|
props: {
|
|
722
723
|
telemetryQuery: telemetryQuery,
|
|
723
724
|
},
|
|
725
|
+
matchesPerSeries: response.perSeriesMatches,
|
|
724
726
|
});
|
|
725
727
|
} else if (
|
|
726
728
|
!response.criteriaMetId &&
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import MonitorType from "../../../Types/Monitor/MonitorType";
|
|
2
|
+
import Monitor from "../../../Models/DatabaseModels/Monitor";
|
|
2
3
|
import { JSONObject } from "../../../Types/JSON";
|
|
3
4
|
import ProbeMonitorResponse from "../../../Types/Probe/ProbeMonitorResponse";
|
|
4
5
|
import IncomingMonitorRequest from "../../../Types/Monitor/IncomingMonitor/IncomingMonitorRequest";
|
|
@@ -21,6 +22,7 @@ import DomainMonitorResponse from "../../../Types/Monitor/DomainMonitor/DomainMo
|
|
|
21
22
|
import ExternalStatusPageMonitorResponse, {
|
|
22
23
|
ExternalStatusPageComponentStatus,
|
|
23
24
|
} from "../../../Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse";
|
|
25
|
+
import MetricMonitorResponse from "../../../Types/Monitor/MetricMonitor/MetricMonitorResponse";
|
|
24
26
|
import Typeof from "../../../Types/Typeof";
|
|
25
27
|
import VMUtil from "../VM/VMAPI";
|
|
26
28
|
import DataToProcess from "./DataToProcess";
|
|
@@ -37,6 +39,21 @@ export default class MonitorTemplateUtil {
|
|
|
37
39
|
public static buildTemplateStorageMap(data: {
|
|
38
40
|
monitorType: MonitorType;
|
|
39
41
|
dataToProcess: DataToProcess;
|
|
42
|
+
/**
|
|
43
|
+
* The monitor that fired this criterion. Used to expose identity
|
|
44
|
+
* fields (`{{monitorName}}`, `{{monitorId}}`, etc.) to incident
|
|
45
|
+
* and alert title/description templates. Optional for backwards
|
|
46
|
+
* compatibility with existing callers.
|
|
47
|
+
*/
|
|
48
|
+
monitor?: Monitor | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* When set, the attribute values identifying the specific series
|
|
51
|
+
* this template is being rendered for. Each label is exposed to
|
|
52
|
+
* the template under its own key (so `{{host.name}}` works) and
|
|
53
|
+
* also collected under a `seriesLabels` object for iteration.
|
|
54
|
+
* Only populated when a metric monitor fires per-series.
|
|
55
|
+
*/
|
|
56
|
+
seriesLabels?: JSONObject | undefined;
|
|
40
57
|
}): JSONObject {
|
|
41
58
|
let storageMap: JSONObject = {};
|
|
42
59
|
|
|
@@ -315,6 +332,31 @@ export default class MonitorTemplateUtil {
|
|
|
315
332
|
} as JSONObject;
|
|
316
333
|
}
|
|
317
334
|
|
|
335
|
+
if (
|
|
336
|
+
data.monitorType === MonitorType.Metrics ||
|
|
337
|
+
data.monitorType === MonitorType.Kubernetes ||
|
|
338
|
+
data.monitorType === MonitorType.Docker
|
|
339
|
+
) {
|
|
340
|
+
const metricResponse: MetricMonitorResponse =
|
|
341
|
+
data.dataToProcess as MetricMonitorResponse;
|
|
342
|
+
|
|
343
|
+
const queryConfigs: Array<unknown> =
|
|
344
|
+
metricResponse.metricViewConfig?.queryConfigs || [];
|
|
345
|
+
|
|
346
|
+
const firstQuery: unknown = queryConfigs[0];
|
|
347
|
+
const metricName: string | undefined = (
|
|
348
|
+
firstQuery as
|
|
349
|
+
| {
|
|
350
|
+
metricQueryData?: { filterData?: { metricName?: string } };
|
|
351
|
+
}
|
|
352
|
+
| undefined
|
|
353
|
+
)?.metricQueryData?.filterData?.metricName;
|
|
354
|
+
|
|
355
|
+
storageMap = {
|
|
356
|
+
metricName: metricName || "",
|
|
357
|
+
} as JSONObject;
|
|
358
|
+
}
|
|
359
|
+
|
|
318
360
|
if (data.monitorType === MonitorType.ExternalStatusPage) {
|
|
319
361
|
const externalStatusPageResponse:
|
|
320
362
|
| ExternalStatusPageMonitorResponse
|
|
@@ -347,6 +389,63 @@ export default class MonitorTemplateUtil {
|
|
|
347
389
|
logger.error(err);
|
|
348
390
|
}
|
|
349
391
|
|
|
392
|
+
/*
|
|
393
|
+
* Fold series labels onto the storage map so templates like
|
|
394
|
+
* `{{host.name}}` or `{{resource.k8s.container.name}}` resolve at
|
|
395
|
+
* render time. The template engine walks dotted paths as nested
|
|
396
|
+
* property access (`host` → `.name`), so for each dotted label
|
|
397
|
+
* key we build up a nested object rather than storing the flat
|
|
398
|
+
* key. Also expose the full label map under `seriesLabels` for
|
|
399
|
+
* iteration-style templates.
|
|
400
|
+
*/
|
|
401
|
+
if (data.seriesLabels && Object.keys(data.seriesLabels).length > 0) {
|
|
402
|
+
for (const key of Object.keys(data.seriesLabels)) {
|
|
403
|
+
const value: unknown = data.seriesLabels[key];
|
|
404
|
+
if (value === undefined || value === null) {
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
const parts: Array<string> = key.split(".");
|
|
408
|
+
let cursor: JSONObject = storageMap;
|
|
409
|
+
for (let i: number = 0; i < parts.length - 1; i++) {
|
|
410
|
+
const part: string = parts[i]!;
|
|
411
|
+
const existing: unknown = cursor[part];
|
|
412
|
+
if (
|
|
413
|
+
!existing ||
|
|
414
|
+
typeof existing !== "object" ||
|
|
415
|
+
Array.isArray(existing)
|
|
416
|
+
) {
|
|
417
|
+
cursor[part] = {};
|
|
418
|
+
}
|
|
419
|
+
cursor = cursor[part] as JSONObject;
|
|
420
|
+
}
|
|
421
|
+
cursor[parts[parts.length - 1]!] = value as JSONObject[string];
|
|
422
|
+
}
|
|
423
|
+
storageMap["seriesLabels"] = data.seriesLabels;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/*
|
|
427
|
+
* Monitor identity fields. Always exposed (when a monitor is provided),
|
|
428
|
+
* independent of monitorType, so templates like `{{monitorName}}` work
|
|
429
|
+
* uniformly across Server/VM, Probe, Synthetic, Metric monitors, etc.
|
|
430
|
+
*/
|
|
431
|
+
if (data.monitor) {
|
|
432
|
+
if (data.monitor.name) {
|
|
433
|
+
storageMap["monitorName"] = data.monitor.name;
|
|
434
|
+
}
|
|
435
|
+
if (data.monitor.id) {
|
|
436
|
+
storageMap["monitorId"] = data.monitor.id.toString();
|
|
437
|
+
}
|
|
438
|
+
if (data.monitor.description) {
|
|
439
|
+
storageMap["monitorDescription"] = data.monitor.description;
|
|
440
|
+
}
|
|
441
|
+
if (data.monitor.slug) {
|
|
442
|
+
storageMap["monitorSlug"] = data.monitor.slug;
|
|
443
|
+
}
|
|
444
|
+
if (data.monitor.monitorType) {
|
|
445
|
+
storageMap["monitorType"] = data.monitor.monitorType;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
350
449
|
logger.debug(`Storage Map: ${JSON.stringify(storageMap, null, 2)}`);
|
|
351
450
|
|
|
352
451
|
return storageMap;
|