@oneuptime/common 10.4.11 → 10.4.13
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 +332 -0
- package/Models/DatabaseModels/Incident.ts +332 -0
- package/Models/DatabaseModels/RunbookAgent.ts +16 -2
- package/Server/EnvironmentConfig.ts +16 -0
- package/Server/Infrastructure/ClickhouseConfig.ts +14 -0
- package/Server/Infrastructure/ClickhouseDatabase.ts +20 -3
- package/Server/Infrastructure/InMemoryTTLCache.ts +61 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779302536475-AttachKubernetesAndDockerToIncidentAndAlert.ts +253 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1779303924241-AttachServiceToIncidentAndAlert.ts +60 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/TelemetryIngest.ts +6 -38
- package/Server/Middleware/UserAuthorization.ts +1 -11
- package/Server/Services/AnalyticsDatabaseService.ts +33 -1
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +6 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +1 -0
- package/Server/Services/OnCallDutyPolicyScheduleService.ts +17 -0
- package/Server/Services/TelemetryIngestionKeyService.ts +90 -1
- package/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.ts +108 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +13 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +25 -0
- package/Tests/Server/Middleware/UserAuthorization.test.ts +0 -7
- package/Types/Dashboard/DashboardComponentType.ts +0 -1
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +2 -0
- package/Types/Dashboard/DashboardComponents/DashboardTableComponent.ts +74 -1
- package/Types/Dashboard/DashboardTemplates.ts +164 -51
- package/Types/Monitor/CriteriaFilter.ts +13 -0
- package/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.ts +69 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
- package/Types/Monitor/MonitorStep.ts +39 -0
- package/Types/Monitor/MonitorStepDnssecMonitor.ts +59 -0
- package/Types/Monitor/MonitorType.ts +18 -2
- package/Types/OnCallDutyPolicy/UserOverrideUtil.ts +36 -9
- package/Types/Probe/ProbeMonitorResponse.ts +2 -0
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +51 -0
- package/Utils/Dashboard/Components/DashboardTableComponent.ts +80 -17
- package/Utils/Dashboard/Components/Index.ts +0 -7
- package/Utils/Monitor/MonitorMetricType.ts +1 -0
- package/build/dist/Models/DatabaseModels/Alert.js +324 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +324 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookAgent.js +16 -2
- package/build/dist/Models/DatabaseModels/RunbookAgent.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +8 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js +9 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js +12 -3
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js.map +1 -1
- package/build/dist/Server/Infrastructure/InMemoryTTLCache.js +49 -0
- package/build/dist/Server/Infrastructure/InMemoryTTLCache.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779302536475-AttachKubernetesAndDockerToIncidentAndAlert.js +100 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779302536475-AttachKubernetesAndDockerToIncidentAndAlert.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779303924241-AttachServiceToIncidentAndAlert.js +28 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779303924241-AttachServiceToIncidentAndAlert.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +2 -26
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +1 -7
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +23 -2
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +28 -24
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +18 -2
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +83 -0
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.js +94 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.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 -3
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Tests/Server/Middleware/UserAuthorization.test.js +0 -7
- package/build/dist/Tests/Server/Middleware/UserAuthorization.test.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +0 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardTableComponent.js +13 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardTableComponent.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +142 -42
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +12 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.js +2 -0
- package/build/dist/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.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 +26 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js +42 -0
- package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorType.js +16 -2
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js +27 -7
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +47 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardTableComponent.js +68 -16
- package/build/dist/Utils/Dashboard/Components/DashboardTableComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/Index.js +0 -4
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +1 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/package.json +1 -2
- package/Types/Dashboard/DashboardComponents/DashboardHostMetricChartComponent.ts +0 -27
- package/Typings/elkjs.d.ts +0 -30
- package/Utils/Dashboard/Components/DashboardHostMetricChartComponent.ts +0 -132
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardHostMetricChartComponent.js +0 -11
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardHostMetricChartComponent.js.map +0 -1
- package/build/dist/Utils/Dashboard/Components/DashboardHostMetricChartComponent.js +0 -113
- package/build/dist/Utils/Dashboard/Components/DashboardHostMetricChartComponent.js.map +0 -1
|
@@ -5,13 +5,13 @@ import DashboardComponentType from "./DashboardComponentType";
|
|
|
5
5
|
import DashboardChartType from "./Chart/ChartType";
|
|
6
6
|
import ObjectID from "../ObjectID";
|
|
7
7
|
import DashboardBaseComponent from "./DashboardComponents/DashboardBaseComponent";
|
|
8
|
+
import DashboardVariable, { DashboardVariableType } from "./DashboardVariable";
|
|
8
9
|
import IconProp from "../Icon/IconProp";
|
|
9
10
|
import MetricsAggregationType from "../Metrics/MetricsAggregationType";
|
|
10
11
|
import IncidentMetricType from "../Incident/IncidentMetricType";
|
|
11
12
|
import MonitorMetricType from "../Monitor/MonitorMetricType";
|
|
12
13
|
import MetricDashboardMetricType from "../Metrics/MetricDashboardMetricType";
|
|
13
14
|
import { DashboardValueTrendDirection } from "./DashboardComponents/DashboardValueComponent";
|
|
14
|
-
import { HostMetricKind } from "./DashboardComponents/DashboardHostMetricChartComponent";
|
|
15
15
|
|
|
16
16
|
/*
|
|
17
17
|
* Trace / Exception / Profiles entries are intentionally not in this
|
|
@@ -88,6 +88,19 @@ interface MetricConfig {
|
|
|
88
88
|
aggregationType: MetricsAggregationType;
|
|
89
89
|
legend?: string;
|
|
90
90
|
legendUnit?: string;
|
|
91
|
+
/*
|
|
92
|
+
* OpenTelemetry attribute keys to fan the query out across (e.g.
|
|
93
|
+
* ["host.name"] for one series per host). When set, the chart renders
|
|
94
|
+
* one series per unique value combination.
|
|
95
|
+
*/
|
|
96
|
+
groupByAttributeKeys?: Array<string>;
|
|
97
|
+
/*
|
|
98
|
+
* Plot the per-second rate of change instead of the raw cumulative
|
|
99
|
+
* counter. Required for OTel cumulative counters such as
|
|
100
|
+
* `system.disk.io` and `system.network.io` so the chart shows I/O rate
|
|
101
|
+
* rather than bytes-since-boot.
|
|
102
|
+
*/
|
|
103
|
+
transformAsRate?: boolean;
|
|
91
104
|
}
|
|
92
105
|
|
|
93
106
|
function buildMetricQueryConfig(config: MetricConfig): Record<string, unknown> {
|
|
@@ -104,8 +117,10 @@ function buildMetricQueryConfig(config: MetricConfig): Record<string, unknown> {
|
|
|
104
117
|
metricName: config.metricName,
|
|
105
118
|
aggegationType: config.aggregationType,
|
|
106
119
|
},
|
|
107
|
-
groupBy: undefined,
|
|
120
|
+
groupBy: config.groupByAttributeKeys ? { attributes: true } : undefined,
|
|
121
|
+
groupByAttributeKeys: config.groupByAttributeKeys,
|
|
108
122
|
},
|
|
123
|
+
transformAsRate: config.transformAsRate,
|
|
109
124
|
};
|
|
110
125
|
}
|
|
111
126
|
|
|
@@ -383,6 +398,31 @@ function createKubernetesNodeListComponent(data: {
|
|
|
383
398
|
};
|
|
384
399
|
}
|
|
385
400
|
|
|
401
|
+
/*
|
|
402
|
+
* Template variables are pre-built TelemetryAttribute variables that
|
|
403
|
+
* ship with the template — the toolbar renders a "Cluster" /
|
|
404
|
+
* "Namespace" / "Host" picker without the user having to open the
|
|
405
|
+
* Variables modal. Resource attributes from the OTel collector are
|
|
406
|
+
* stored in ClickHouse under the `resource.` prefix (see the comment
|
|
407
|
+
* in MonitorAlert.ts), so the binding keys here mirror what the
|
|
408
|
+
* Kubernetes / Host detail pages already filter on.
|
|
409
|
+
*/
|
|
410
|
+
function createTelemetryAttributeVariable(data: {
|
|
411
|
+
name: string;
|
|
412
|
+
label: string;
|
|
413
|
+
attributeKey: string;
|
|
414
|
+
isMultiSelect?: boolean;
|
|
415
|
+
}): DashboardVariable {
|
|
416
|
+
return {
|
|
417
|
+
id: ObjectID.generate().toString(),
|
|
418
|
+
name: data.name,
|
|
419
|
+
label: data.label,
|
|
420
|
+
type: DashboardVariableType.TelemetryAttribute,
|
|
421
|
+
attributeKey: data.attributeKey,
|
|
422
|
+
isMultiSelect: data.isMultiSelect ?? false,
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
|
|
386
426
|
function createHostListComponent(data: {
|
|
387
427
|
title: string;
|
|
388
428
|
top: number;
|
|
@@ -412,33 +452,6 @@ function createHostListComponent(data: {
|
|
|
412
452
|
};
|
|
413
453
|
}
|
|
414
454
|
|
|
415
|
-
function createHostMetricChartComponent(data: {
|
|
416
|
-
title: string;
|
|
417
|
-
description?: string;
|
|
418
|
-
metricKind: HostMetricKind;
|
|
419
|
-
top: number;
|
|
420
|
-
left: number;
|
|
421
|
-
width: number;
|
|
422
|
-
height: number;
|
|
423
|
-
}): DashboardBaseComponent {
|
|
424
|
-
return {
|
|
425
|
-
_type: ObjectType.DashboardComponent,
|
|
426
|
-
componentType: DashboardComponentType.HostMetricChart,
|
|
427
|
-
componentId: ObjectID.generate(),
|
|
428
|
-
topInDashboardUnits: data.top,
|
|
429
|
-
leftInDashboardUnits: data.left,
|
|
430
|
-
widthInDashboardUnits: data.width,
|
|
431
|
-
heightInDashboardUnits: data.height,
|
|
432
|
-
minHeightInDashboardUnits: 3,
|
|
433
|
-
minWidthInDashboardUnits: 6,
|
|
434
|
-
arguments: {
|
|
435
|
-
title: data.title,
|
|
436
|
-
description: data.description,
|
|
437
|
-
metricKind: data.metricKind,
|
|
438
|
-
},
|
|
439
|
-
};
|
|
440
|
-
}
|
|
441
|
-
|
|
442
455
|
// -- Dashboard configs --
|
|
443
456
|
|
|
444
457
|
function createMonitorDashboardConfig(): DashboardViewConfig {
|
|
@@ -630,9 +643,25 @@ function createMonitorDashboardConfig(): DashboardViewConfig {
|
|
|
630
643
|
}),
|
|
631
644
|
];
|
|
632
645
|
|
|
646
|
+
/*
|
|
647
|
+
* Monitor metrics are stored with bare attribute keys (`monitorName`,
|
|
648
|
+
* `probeName`) rather than the OTel `resource.*` prefix — see
|
|
649
|
+
* MonitorMetricUtil.buildAttributes — so the variable binds to the
|
|
650
|
+
* bare key. Multi-select lets users pin a small group of monitors.
|
|
651
|
+
*/
|
|
652
|
+
const variables: Array<DashboardVariable> = [
|
|
653
|
+
createTelemetryAttributeVariable({
|
|
654
|
+
name: "monitor",
|
|
655
|
+
label: "Monitor",
|
|
656
|
+
attributeKey: "monitorName",
|
|
657
|
+
isMultiSelect: true,
|
|
658
|
+
}),
|
|
659
|
+
];
|
|
660
|
+
|
|
633
661
|
return {
|
|
634
662
|
_type: ObjectType.DashboardViewConfig,
|
|
635
663
|
components,
|
|
664
|
+
variables,
|
|
636
665
|
heightInDashboardUnits: Math.max(DashboardSize.heightInDashboardUnits, 13),
|
|
637
666
|
};
|
|
638
667
|
}
|
|
@@ -1122,9 +1151,31 @@ function createKubernetesDashboardConfig(): DashboardViewConfig {
|
|
|
1122
1151
|
}),
|
|
1123
1152
|
];
|
|
1124
1153
|
|
|
1154
|
+
/*
|
|
1155
|
+
* Pre-built variables let the user scope every widget on the dashboard
|
|
1156
|
+
* to a single cluster / namespace from the toolbar. Multi-select is on
|
|
1157
|
+
* for namespace so users can pick a couple of namespaces at once;
|
|
1158
|
+
* cluster stays single-select since the typical "compare two clusters"
|
|
1159
|
+
* workflow lives on the Compare page.
|
|
1160
|
+
*/
|
|
1161
|
+
const variables: Array<DashboardVariable> = [
|
|
1162
|
+
createTelemetryAttributeVariable({
|
|
1163
|
+
name: "cluster",
|
|
1164
|
+
label: "Cluster",
|
|
1165
|
+
attributeKey: "resource.k8s.cluster.name",
|
|
1166
|
+
}),
|
|
1167
|
+
createTelemetryAttributeVariable({
|
|
1168
|
+
name: "namespace",
|
|
1169
|
+
label: "Namespace",
|
|
1170
|
+
attributeKey: "resource.k8s.namespace.name",
|
|
1171
|
+
isMultiSelect: true,
|
|
1172
|
+
}),
|
|
1173
|
+
];
|
|
1174
|
+
|
|
1125
1175
|
return {
|
|
1126
1176
|
_type: ObjectType.DashboardViewConfig,
|
|
1127
1177
|
components,
|
|
1178
|
+
variables,
|
|
1128
1179
|
heightInDashboardUnits: Math.max(DashboardSize.heightInDashboardUnits, 21),
|
|
1129
1180
|
};
|
|
1130
1181
|
}
|
|
@@ -1442,9 +1493,25 @@ function createMetricsDashboardConfig(): DashboardViewConfig {
|
|
|
1442
1493
|
}),
|
|
1443
1494
|
];
|
|
1444
1495
|
|
|
1496
|
+
/*
|
|
1497
|
+
* Most HTTP / runtime metrics on this dashboard carry the standard
|
|
1498
|
+
* OTel `resource.service.name` attribute, so scoping by service is
|
|
1499
|
+
* the most useful default. Multi-select keeps the cross-service view
|
|
1500
|
+
* available — e.g. compare API and worker on one chart.
|
|
1501
|
+
*/
|
|
1502
|
+
const variables: Array<DashboardVariable> = [
|
|
1503
|
+
createTelemetryAttributeVariable({
|
|
1504
|
+
name: "service",
|
|
1505
|
+
label: "Service",
|
|
1506
|
+
attributeKey: "resource.service.name",
|
|
1507
|
+
isMultiSelect: true,
|
|
1508
|
+
}),
|
|
1509
|
+
];
|
|
1510
|
+
|
|
1445
1511
|
return {
|
|
1446
1512
|
_type: ObjectType.DashboardViewConfig,
|
|
1447
1513
|
components,
|
|
1514
|
+
variables,
|
|
1448
1515
|
heightInDashboardUnits: Math.max(DashboardSize.heightInDashboardUnits, 24),
|
|
1449
1516
|
};
|
|
1450
1517
|
}
|
|
@@ -1453,11 +1520,10 @@ function createHostDashboardConfig(): DashboardViewConfig {
|
|
|
1453
1520
|
/*
|
|
1454
1521
|
* Layout notes:
|
|
1455
1522
|
*
|
|
1456
|
-
* -
|
|
1457
|
-
*
|
|
1458
|
-
*
|
|
1459
|
-
*
|
|
1460
|
-
* widgets auto-scale to percent at render time (see
|
|
1523
|
+
* - Per-host charts fan out via `groupByAttributeKeys: ["host.name"]`
|
|
1524
|
+
* so a single chart renders one series per host. The OTel host
|
|
1525
|
+
* receiver emits `system.cpu.utilization` as a [0, 1] ratio, which
|
|
1526
|
+
* Value/Gauge widgets auto-scale to percent at render time (see
|
|
1461
1527
|
* splitFormattedValue / isFractionScale).
|
|
1462
1528
|
*
|
|
1463
1529
|
* - The Value widget for "Avg Memory" uses `system.memory.usage`
|
|
@@ -1465,11 +1531,10 @@ function createHostDashboardConfig(): DashboardViewConfig {
|
|
|
1465
1531
|
* `system.memory.utilization` is not always emitted by default OTel
|
|
1466
1532
|
* host metrics.
|
|
1467
1533
|
*
|
|
1468
|
-
* - Disk and Network I/O
|
|
1469
|
-
*
|
|
1470
|
-
*
|
|
1471
|
-
*
|
|
1472
|
-
* figure rather than a noisy snapshot.
|
|
1534
|
+
* - Disk and Network I/O charts set `transformAsRate: true` so the
|
|
1535
|
+
* cumulative byte counters render as per-second rates rather than
|
|
1536
|
+
* bytes-since-boot. The matching Value tiles in row 1 keep the
|
|
1537
|
+
* unrated Sum so users see an absolute byte figure over the window.
|
|
1473
1538
|
*/
|
|
1474
1539
|
const components: Array<DashboardBaseComponent> = [
|
|
1475
1540
|
// Row 0: Title
|
|
@@ -1529,21 +1594,31 @@ function createHostDashboardConfig(): DashboardViewConfig {
|
|
|
1529
1594
|
}),
|
|
1530
1595
|
|
|
1531
1596
|
// Row 2-4: Per-host CPU and Memory charts
|
|
1532
|
-
|
|
1597
|
+
createChartComponent({
|
|
1533
1598
|
title: "CPU Utilization by Host",
|
|
1534
|
-
|
|
1599
|
+
chartType: DashboardChartType.Line,
|
|
1535
1600
|
top: 2,
|
|
1536
1601
|
left: 0,
|
|
1537
1602
|
width: 6,
|
|
1538
1603
|
height: 3,
|
|
1604
|
+
metricConfig: {
|
|
1605
|
+
metricName: MetricDashboardMetricType.SystemCpuUtilization,
|
|
1606
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
1607
|
+
groupByAttributeKeys: ["host.name"],
|
|
1608
|
+
},
|
|
1539
1609
|
}),
|
|
1540
|
-
|
|
1610
|
+
createChartComponent({
|
|
1541
1611
|
title: "Memory Usage by Host",
|
|
1542
|
-
|
|
1612
|
+
chartType: DashboardChartType.Line,
|
|
1543
1613
|
top: 2,
|
|
1544
1614
|
left: 6,
|
|
1545
1615
|
width: 6,
|
|
1546
1616
|
height: 3,
|
|
1617
|
+
metricConfig: {
|
|
1618
|
+
metricName: MetricDashboardMetricType.SystemMemoryUsage,
|
|
1619
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
1620
|
+
groupByAttributeKeys: ["host.name"],
|
|
1621
|
+
},
|
|
1547
1622
|
}),
|
|
1548
1623
|
|
|
1549
1624
|
// Row 5: Section header
|
|
@@ -1600,13 +1675,18 @@ function createHostDashboardConfig(): DashboardViewConfig {
|
|
|
1600
1675
|
aggregationType: MetricsAggregationType.Avg,
|
|
1601
1676
|
},
|
|
1602
1677
|
}),
|
|
1603
|
-
|
|
1678
|
+
createChartComponent({
|
|
1604
1679
|
title: "Filesystem Usage by Host",
|
|
1605
|
-
|
|
1680
|
+
chartType: DashboardChartType.Line,
|
|
1606
1681
|
top: 11,
|
|
1607
1682
|
left: 4,
|
|
1608
1683
|
width: 8,
|
|
1609
1684
|
height: 3,
|
|
1685
|
+
metricConfig: {
|
|
1686
|
+
metricName: "system.filesystem.usage",
|
|
1687
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
1688
|
+
groupByAttributeKeys: ["host.name"],
|
|
1689
|
+
},
|
|
1610
1690
|
}),
|
|
1611
1691
|
|
|
1612
1692
|
// Row 14: Section header
|
|
@@ -1620,21 +1700,33 @@ function createHostDashboardConfig(): DashboardViewConfig {
|
|
|
1620
1700
|
}),
|
|
1621
1701
|
|
|
1622
1702
|
// Row 15-17: Disk and network I/O rates per host
|
|
1623
|
-
|
|
1703
|
+
createChartComponent({
|
|
1624
1704
|
title: "Disk I/O by Host",
|
|
1625
|
-
|
|
1705
|
+
chartType: DashboardChartType.Line,
|
|
1626
1706
|
top: 15,
|
|
1627
1707
|
left: 0,
|
|
1628
1708
|
width: 6,
|
|
1629
1709
|
height: 3,
|
|
1710
|
+
metricConfig: {
|
|
1711
|
+
metricName: MetricDashboardMetricType.SystemDiskIo,
|
|
1712
|
+
aggregationType: MetricsAggregationType.Sum,
|
|
1713
|
+
groupByAttributeKeys: ["host.name"],
|
|
1714
|
+
transformAsRate: true,
|
|
1715
|
+
},
|
|
1630
1716
|
}),
|
|
1631
|
-
|
|
1717
|
+
createChartComponent({
|
|
1632
1718
|
title: "Network I/O by Host",
|
|
1633
|
-
|
|
1719
|
+
chartType: DashboardChartType.Line,
|
|
1634
1720
|
top: 15,
|
|
1635
1721
|
left: 6,
|
|
1636
1722
|
width: 6,
|
|
1637
1723
|
height: 3,
|
|
1724
|
+
metricConfig: {
|
|
1725
|
+
metricName: MetricDashboardMetricType.SystemNetworkIo,
|
|
1726
|
+
aggregationType: MetricsAggregationType.Sum,
|
|
1727
|
+
groupByAttributeKeys: ["host.name"],
|
|
1728
|
+
transformAsRate: true,
|
|
1729
|
+
},
|
|
1638
1730
|
}),
|
|
1639
1731
|
|
|
1640
1732
|
// Row 18: Section header
|
|
@@ -1648,13 +1740,18 @@ function createHostDashboardConfig(): DashboardViewConfig {
|
|
|
1648
1740
|
}),
|
|
1649
1741
|
|
|
1650
1742
|
// Row 19-21: Process count chart and recent logs
|
|
1651
|
-
|
|
1743
|
+
createChartComponent({
|
|
1652
1744
|
title: "Process Count by Host",
|
|
1653
|
-
|
|
1745
|
+
chartType: DashboardChartType.Line,
|
|
1654
1746
|
top: 19,
|
|
1655
1747
|
left: 0,
|
|
1656
1748
|
width: 6,
|
|
1657
1749
|
height: 3,
|
|
1750
|
+
metricConfig: {
|
|
1751
|
+
metricName: "system.processes.count",
|
|
1752
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
1753
|
+
groupByAttributeKeys: ["host.name"],
|
|
1754
|
+
},
|
|
1658
1755
|
}),
|
|
1659
1756
|
createLogStreamComponent({
|
|
1660
1757
|
title: "Recent Logs",
|
|
@@ -1665,9 +1762,25 @@ function createHostDashboardConfig(): DashboardViewConfig {
|
|
|
1665
1762
|
}),
|
|
1666
1763
|
];
|
|
1667
1764
|
|
|
1765
|
+
/*
|
|
1766
|
+
* Per-host scoping: the variable defaults to multi-select because the
|
|
1767
|
+
* dashboard's by-host charts already split rendering per host; the
|
|
1768
|
+
* selector lets users narrow to a subset (e.g. just two prod hosts)
|
|
1769
|
+
* without losing the per-host breakdown.
|
|
1770
|
+
*/
|
|
1771
|
+
const variables: Array<DashboardVariable> = [
|
|
1772
|
+
createTelemetryAttributeVariable({
|
|
1773
|
+
name: "host",
|
|
1774
|
+
label: "Host",
|
|
1775
|
+
attributeKey: "resource.host.name",
|
|
1776
|
+
isMultiSelect: true,
|
|
1777
|
+
}),
|
|
1778
|
+
];
|
|
1779
|
+
|
|
1668
1780
|
return {
|
|
1669
1781
|
_type: ObjectType.DashboardViewConfig,
|
|
1670
1782
|
components,
|
|
1783
|
+
variables,
|
|
1671
1784
|
heightInDashboardUnits: Math.max(DashboardSize.heightInDashboardUnits, 22),
|
|
1672
1785
|
};
|
|
1673
1786
|
}
|
|
@@ -84,6 +84,14 @@ export enum CheckOn {
|
|
|
84
84
|
DomainStatusCode = "Domain Status Code",
|
|
85
85
|
DomainIsExpired = "Domain Is Expired",
|
|
86
86
|
|
|
87
|
+
// DNSSEC monitors.
|
|
88
|
+
DnssecChainValid = "DNSSEC Chain Is Valid",
|
|
89
|
+
DnssecDnskeyExists = "DNSSEC DNSKEY Record Exists",
|
|
90
|
+
DnssecDsExists = "DNSSEC DS Record Exists At Parent",
|
|
91
|
+
DnssecSignatureExpiresInDays = "DNSSEC Signature Expires In Days",
|
|
92
|
+
DnssecResolverConsensus = "DNSSEC Resolver Consensus (AD Flag)",
|
|
93
|
+
DnssecNameserverConsistent = "DNSSEC Nameservers Are Consistent",
|
|
94
|
+
|
|
87
95
|
// External Status Page monitors.
|
|
88
96
|
ExternalStatusPageIsOnline = "External Status Page Is Online",
|
|
89
97
|
ExternalStatusPageOverallStatus = "External Status Page Overall Status",
|
|
@@ -279,6 +287,11 @@ export class CriteriaFilterUtil {
|
|
|
279
287
|
checkOn === CheckOn.SnmpIsOnline ||
|
|
280
288
|
checkOn === CheckOn.DnsIsOnline ||
|
|
281
289
|
checkOn === CheckOn.DomainIsExpired ||
|
|
290
|
+
checkOn === CheckOn.DnssecChainValid ||
|
|
291
|
+
checkOn === CheckOn.DnssecDnskeyExists ||
|
|
292
|
+
checkOn === CheckOn.DnssecDsExists ||
|
|
293
|
+
checkOn === CheckOn.DnssecResolverConsensus ||
|
|
294
|
+
checkOn === CheckOn.DnssecNameserverConsistent ||
|
|
282
295
|
checkOn === CheckOn.ExternalStatusPageIsOnline
|
|
283
296
|
) {
|
|
284
297
|
return false;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export interface DnssecKeyRecord {
|
|
2
|
+
flags: number;
|
|
3
|
+
algorithm: number;
|
|
4
|
+
keyTag?: number | undefined;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface DnssecDsRecord {
|
|
8
|
+
keyTag: number;
|
|
9
|
+
algorithm: number;
|
|
10
|
+
digestType: number;
|
|
11
|
+
digest: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface DnssecRrsigRecord {
|
|
15
|
+
typeCovered: string;
|
|
16
|
+
algorithm: number;
|
|
17
|
+
signerName: string;
|
|
18
|
+
keyTag: number;
|
|
19
|
+
inception?: string | undefined;
|
|
20
|
+
expiration?: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface DnssecResolverCheck {
|
|
24
|
+
resolver: string;
|
|
25
|
+
adFlag: boolean;
|
|
26
|
+
servfailWhenValidating: boolean;
|
|
27
|
+
error?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DnssecNameserverCheck {
|
|
31
|
+
nameServer: string;
|
|
32
|
+
soaSerial?: string | undefined;
|
|
33
|
+
rrsigExpiration?: string | undefined;
|
|
34
|
+
error?: string | undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default interface DnssecMonitorResponse {
|
|
38
|
+
isOnline: boolean;
|
|
39
|
+
responseTimeInMs: number;
|
|
40
|
+
failureCause: string;
|
|
41
|
+
domainName: string;
|
|
42
|
+
isTimeout?: boolean | undefined;
|
|
43
|
+
|
|
44
|
+
// Zone signed?
|
|
45
|
+
isZoneSigned: boolean;
|
|
46
|
+
|
|
47
|
+
// DNSKEY presence
|
|
48
|
+
dnskeys: Array<DnssecKeyRecord>;
|
|
49
|
+
|
|
50
|
+
// DS at parent
|
|
51
|
+
parentDsRecords: Array<DnssecDsRecord>;
|
|
52
|
+
isParentDsPresent: boolean;
|
|
53
|
+
|
|
54
|
+
// RRSIG over the A record (zone apex by default)
|
|
55
|
+
rrsigs: Array<DnssecRrsigRecord>;
|
|
56
|
+
earliestSignatureExpiration?: string | undefined;
|
|
57
|
+
daysUntilSignatureExpiry?: number | undefined;
|
|
58
|
+
|
|
59
|
+
// Resolver consensus (AD flag + CD-bit SERVFAIL test)
|
|
60
|
+
resolverChecks: Array<DnssecResolverCheck>;
|
|
61
|
+
resolverConsensusAd: boolean;
|
|
62
|
+
|
|
63
|
+
// Primary/secondary nameserver consistency
|
|
64
|
+
nameserverChecks: Array<DnssecNameserverCheck>;
|
|
65
|
+
isNameserverConsistent: boolean;
|
|
66
|
+
|
|
67
|
+
// Overall chain validity (DNSKEY exists, DS exists, RRSIG valid, AD across resolvers)
|
|
68
|
+
isChainValid: boolean;
|
|
69
|
+
}
|
|
@@ -487,6 +487,33 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
487
487
|
return monitorCriteriaInstance;
|
|
488
488
|
}
|
|
489
489
|
|
|
490
|
+
if (arg.monitorType === MonitorType.DNSSEC) {
|
|
491
|
+
const monitorCriteriaInstance: MonitorCriteriaInstance =
|
|
492
|
+
new MonitorCriteriaInstance();
|
|
493
|
+
|
|
494
|
+
monitorCriteriaInstance.data = {
|
|
495
|
+
id: ObjectID.generate().toString(),
|
|
496
|
+
monitorStatusId: arg.monitorStatusId,
|
|
497
|
+
filterCondition: FilterCondition.All,
|
|
498
|
+
filters: [
|
|
499
|
+
{
|
|
500
|
+
checkOn: CheckOn.DnssecChainValid,
|
|
501
|
+
filterType: FilterType.True,
|
|
502
|
+
value: undefined,
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
incidents: [],
|
|
506
|
+
alerts: [],
|
|
507
|
+
createAlerts: false,
|
|
508
|
+
changeMonitorStatus: true,
|
|
509
|
+
createIncidents: false,
|
|
510
|
+
name: `Check if ${arg.monitorName} DNSSEC chain is valid`,
|
|
511
|
+
description: `This criteria checks if the ${arg.monitorName} DNSSEC chain is valid end-to-end`,
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
return monitorCriteriaInstance;
|
|
515
|
+
}
|
|
516
|
+
|
|
490
517
|
if (arg.monitorType === MonitorType.ExternalStatusPage) {
|
|
491
518
|
const monitorCriteriaInstance: MonitorCriteriaInstance =
|
|
492
519
|
new MonitorCriteriaInstance();
|
|
@@ -695,6 +722,46 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
695
722
|
};
|
|
696
723
|
}
|
|
697
724
|
|
|
725
|
+
if (arg.monitorType === MonitorType.DNSSEC) {
|
|
726
|
+
monitorCriteriaInstance.data = {
|
|
727
|
+
id: ObjectID.generate().toString(),
|
|
728
|
+
monitorStatusId: arg.monitorStatusId,
|
|
729
|
+
filterCondition: FilterCondition.Any,
|
|
730
|
+
filters: [
|
|
731
|
+
{
|
|
732
|
+
checkOn: CheckOn.DnssecChainValid,
|
|
733
|
+
filterType: FilterType.False,
|
|
734
|
+
value: undefined,
|
|
735
|
+
},
|
|
736
|
+
],
|
|
737
|
+
incidents: [
|
|
738
|
+
{
|
|
739
|
+
title: `${arg.monitorName} DNSSEC chain is broken`,
|
|
740
|
+
description: `${arg.monitorName} DNSSEC validation is currently failing.`,
|
|
741
|
+
incidentSeverityId: arg.incidentSeverityId,
|
|
742
|
+
autoResolveIncident: true,
|
|
743
|
+
id: ObjectID.generate().toString(),
|
|
744
|
+
onCallPolicyIds: [],
|
|
745
|
+
},
|
|
746
|
+
],
|
|
747
|
+
changeMonitorStatus: true,
|
|
748
|
+
createIncidents: true,
|
|
749
|
+
createAlerts: false,
|
|
750
|
+
alerts: [
|
|
751
|
+
{
|
|
752
|
+
title: `${arg.monitorName} DNSSEC chain is broken`,
|
|
753
|
+
description: `${arg.monitorName} DNSSEC validation is currently failing.`,
|
|
754
|
+
alertSeverityId: arg.alertSeverityId,
|
|
755
|
+
autoResolveAlert: true,
|
|
756
|
+
id: ObjectID.generate().toString(),
|
|
757
|
+
onCallPolicyIds: [],
|
|
758
|
+
},
|
|
759
|
+
],
|
|
760
|
+
name: `Check if ${arg.monitorName} DNSSEC chain is broken`,
|
|
761
|
+
description: `This criteria checks if the ${arg.monitorName} DNSSEC chain is broken`,
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
|
|
698
765
|
if (arg.monitorType === MonitorType.ExternalStatusPage) {
|
|
699
766
|
monitorCriteriaInstance.data = {
|
|
700
767
|
id: ObjectID.generate().toString(),
|
|
@@ -38,6 +38,9 @@ import MonitorStepDnsMonitor, {
|
|
|
38
38
|
import MonitorStepDomainMonitor, {
|
|
39
39
|
MonitorStepDomainMonitorUtil,
|
|
40
40
|
} from "./MonitorStepDomainMonitor";
|
|
41
|
+
import MonitorStepDnssecMonitor, {
|
|
42
|
+
MonitorStepDnssecMonitorUtil,
|
|
43
|
+
} from "./MonitorStepDnssecMonitor";
|
|
41
44
|
import MonitorStepExternalStatusPageMonitor, {
|
|
42
45
|
MonitorStepExternalStatusPageMonitorUtil,
|
|
43
46
|
} from "./MonitorStepExternalStatusPageMonitor";
|
|
@@ -109,6 +112,9 @@ export interface MonitorStepType {
|
|
|
109
112
|
// Domain monitor
|
|
110
113
|
domainMonitor?: MonitorStepDomainMonitor | undefined;
|
|
111
114
|
|
|
115
|
+
// DNSSEC monitor
|
|
116
|
+
dnssecMonitor?: MonitorStepDnssecMonitor | undefined;
|
|
117
|
+
|
|
112
118
|
// External Status Page monitor
|
|
113
119
|
externalStatusPageMonitor?: MonitorStepExternalStatusPageMonitor | undefined;
|
|
114
120
|
|
|
@@ -150,6 +156,7 @@ export default class MonitorStep extends DatabaseProperty {
|
|
|
150
156
|
snmpMonitor: undefined,
|
|
151
157
|
dnsMonitor: undefined,
|
|
152
158
|
domainMonitor: undefined,
|
|
159
|
+
dnssecMonitor: undefined,
|
|
153
160
|
externalStatusPageMonitor: undefined,
|
|
154
161
|
kubernetesMonitor: undefined,
|
|
155
162
|
dockerMonitor: undefined,
|
|
@@ -191,6 +198,7 @@ export default class MonitorStep extends DatabaseProperty {
|
|
|
191
198
|
snmpMonitor: undefined,
|
|
192
199
|
dnsMonitor: undefined,
|
|
193
200
|
domainMonitor: undefined,
|
|
201
|
+
dnssecMonitor: undefined,
|
|
194
202
|
externalStatusPageMonitor: undefined,
|
|
195
203
|
kubernetesMonitor: undefined,
|
|
196
204
|
dockerMonitor: undefined,
|
|
@@ -334,6 +342,13 @@ export default class MonitorStep extends DatabaseProperty {
|
|
|
334
342
|
return this;
|
|
335
343
|
}
|
|
336
344
|
|
|
345
|
+
public setDnssecMonitor(
|
|
346
|
+
dnssecMonitor: MonitorStepDnssecMonitor,
|
|
347
|
+
): MonitorStep {
|
|
348
|
+
this.data!.dnssecMonitor = dnssecMonitor;
|
|
349
|
+
return this;
|
|
350
|
+
}
|
|
351
|
+
|
|
337
352
|
public setExternalStatusPageMonitor(
|
|
338
353
|
externalStatusPageMonitor: MonitorStepExternalStatusPageMonitor,
|
|
339
354
|
): MonitorStep {
|
|
@@ -508,6 +523,23 @@ export default class MonitorStep extends DatabaseProperty {
|
|
|
508
523
|
}
|
|
509
524
|
}
|
|
510
525
|
|
|
526
|
+
if (monitorType === MonitorType.DNSSEC) {
|
|
527
|
+
if (!value.data.dnssecMonitor) {
|
|
528
|
+
return "DNSSEC configuration is required";
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (!value.data.dnssecMonitor.domainName) {
|
|
532
|
+
return "Domain name is required";
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (
|
|
536
|
+
!value.data.dnssecMonitor.resolvers ||
|
|
537
|
+
value.data.dnssecMonitor.resolvers.length === 0
|
|
538
|
+
) {
|
|
539
|
+
return "At least one resolver is required";
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
511
543
|
if (monitorType === MonitorType.ExternalStatusPage) {
|
|
512
544
|
if (!value.data.externalStatusPageMonitor) {
|
|
513
545
|
return "External status page configuration is required";
|
|
@@ -600,6 +632,9 @@ export default class MonitorStep extends DatabaseProperty {
|
|
|
600
632
|
domainMonitor: this.data.domainMonitor
|
|
601
633
|
? MonitorStepDomainMonitorUtil.toJSON(this.data.domainMonitor)
|
|
602
634
|
: undefined,
|
|
635
|
+
dnssecMonitor: this.data.dnssecMonitor
|
|
636
|
+
? MonitorStepDnssecMonitorUtil.toJSON(this.data.dnssecMonitor)
|
|
637
|
+
: undefined,
|
|
603
638
|
externalStatusPageMonitor: this.data.externalStatusPageMonitor
|
|
604
639
|
? MonitorStepExternalStatusPageMonitorUtil.toJSON(
|
|
605
640
|
this.data.externalStatusPageMonitor,
|
|
@@ -734,6 +769,9 @@ export default class MonitorStep extends DatabaseProperty {
|
|
|
734
769
|
domainMonitor: json["domainMonitor"]
|
|
735
770
|
? (json["domainMonitor"] as JSONObject)
|
|
736
771
|
: undefined,
|
|
772
|
+
dnssecMonitor: json["dnssecMonitor"]
|
|
773
|
+
? (json["dnssecMonitor"] as JSONObject)
|
|
774
|
+
: undefined,
|
|
737
775
|
externalStatusPageMonitor: json["externalStatusPageMonitor"]
|
|
738
776
|
? (json["externalStatusPageMonitor"] as JSONObject)
|
|
739
777
|
: undefined,
|
|
@@ -775,6 +813,7 @@ export default class MonitorStep extends DatabaseProperty {
|
|
|
775
813
|
snmpMonitor: Zod.any().optional(),
|
|
776
814
|
dnsMonitor: Zod.any().optional(),
|
|
777
815
|
domainMonitor: Zod.any().optional(),
|
|
816
|
+
dnssecMonitor: Zod.any().optional(),
|
|
778
817
|
externalStatusPageMonitor: Zod.any().optional(),
|
|
779
818
|
kubernetesMonitor: Zod.any().optional(),
|
|
780
819
|
dockerMonitor: Zod.any().optional(),
|