@oneuptime/common 10.2.15 → 10.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Server/API/DashboardAPI.ts +0 -6
- package/Server/Services/IncidentService.ts +60 -23
- package/Types/Dashboard/DashboardTemplates.ts +226 -968
- package/Types/Dashboard/DashboardVariable.ts +0 -8
- package/Utils/ValueFormatter.ts +21 -0
- package/build/dist/Server/API/DashboardAPI.js +0 -3
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +55 -18
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +214 -926
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Utils/ValueFormatter.js +20 -0
- package/build/dist/Utils/ValueFormatter.js.map +1 -1
- package/package.json +1 -1
|
@@ -346,11 +346,6 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
346
346
|
throw new BadDataException("attributeKey is required.");
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
-
const metricNameRaw: string | undefined =
|
|
350
|
-
req.body && (req.body["metricName"] as string);
|
|
351
|
-
const metricName: string | undefined =
|
|
352
|
-
metricNameRaw && metricNameRaw.trim() ? metricNameRaw : undefined;
|
|
353
|
-
|
|
354
349
|
const telemetryTypeRaw: string | undefined =
|
|
355
350
|
req.body && (req.body["telemetryType"] as string);
|
|
356
351
|
let telemetryType: TelemetryType = TelemetryType.Metric;
|
|
@@ -386,7 +381,6 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
386
381
|
projectId: dashboard.projectId,
|
|
387
382
|
telemetryType,
|
|
388
383
|
attributeKey: attributeKey.trim(),
|
|
389
|
-
metricName,
|
|
390
384
|
});
|
|
391
385
|
|
|
392
386
|
return Response.sendJsonObjectResponse(req, res, {
|
|
@@ -49,6 +49,7 @@ import Metric, {
|
|
|
49
49
|
import OneUptimeDate from "../../Types/Date";
|
|
50
50
|
import TelemetryUtil from "../Utils/Telemetry/Telemetry";
|
|
51
51
|
import logger, { LogAttributes } from "../Utils/Logger";
|
|
52
|
+
import NotEqual from "../../Types/BaseDatabase/NotEqual";
|
|
52
53
|
import IncidentFeedService from "./IncidentFeedService";
|
|
53
54
|
import IncidentSlaService from "./IncidentSlaService";
|
|
54
55
|
import { setIsPublicForMarkdownImages } from "../Utils/InlineImageAccessTokenSync";
|
|
@@ -2563,12 +2564,25 @@ ${incidentSeverity.name}
|
|
|
2563
2564
|
const firstIncidentStateTimeline: IncidentStateTimeline | undefined =
|
|
2564
2565
|
incidentStateTimelines[0];
|
|
2565
2566
|
|
|
2566
|
-
|
|
2567
|
-
|
|
2567
|
+
/*
|
|
2568
|
+
* Delete the existing metrics for this incident so the time-varying
|
|
2569
|
+
* ones (TimeToAcknowledge / TimeToResolve / IncidentDuration /
|
|
2570
|
+
* TimeInState) get rewritten with the latest state-timeline values
|
|
2571
|
+
* on this refresh. IncidentCount is excluded from the delete: it is
|
|
2572
|
+
* a constant `value = 1` keyed by `serviceId + bucketTime` that
|
|
2573
|
+
* never changes. Re-emitting it across refreshes inflated the
|
|
2574
|
+
* 1-minute aggregating materialized view (`MetricItemAggMV1m_mv`),
|
|
2575
|
+
* because the MV trigger only fires on inserts — ALTER DELETE
|
|
2576
|
+
* mutations don't roll back the previously-accumulated
|
|
2577
|
+
* `sumState` / `countState`. That's why the Incident Dashboard
|
|
2578
|
+
* sum-of-IncidentCount widget read ~33% higher than the actual
|
|
2579
|
+
* unique-incident count.
|
|
2580
|
+
*/
|
|
2568
2581
|
await MetricService.deleteBy({
|
|
2569
2582
|
query: {
|
|
2570
2583
|
projectId: incident.projectId,
|
|
2571
2584
|
serviceId: data.incidentId,
|
|
2585
|
+
name: new NotEqual<string>(IncidentMetricType.IncidentCount),
|
|
2572
2586
|
},
|
|
2573
2587
|
props: {
|
|
2574
2588
|
isRoot: true,
|
|
@@ -2623,36 +2637,59 @@ ${incidentSeverity.name}
|
|
|
2623
2637
|
ownerTeamNames: ownerTeamNames.join(", "),
|
|
2624
2638
|
};
|
|
2625
2639
|
|
|
2626
|
-
|
|
2640
|
+
/*
|
|
2641
|
+
* Only emit IncidentCount on the very first refresh (i.e. when no
|
|
2642
|
+
* existing IncidentCount row is present for this serviceId). See
|
|
2643
|
+
* the delete comment above — emitting it on every refresh would
|
|
2644
|
+
* accumulate phantom `sumState` entries in the MV that ALTER
|
|
2645
|
+
* DELETE can't undo. By keeping the original row alive and never
|
|
2646
|
+
* re-emitting, the dashboard Sum stays equal to the true count of
|
|
2647
|
+
* distinct incidents.
|
|
2648
|
+
*/
|
|
2649
|
+
const existingIncidentCount: PositiveNumber = await MetricService.countBy({
|
|
2650
|
+
query: {
|
|
2651
|
+
projectId: incident.projectId,
|
|
2652
|
+
serviceId: data.incidentId,
|
|
2653
|
+
name: IncidentMetricType.IncidentCount,
|
|
2654
|
+
},
|
|
2655
|
+
skip: 0,
|
|
2656
|
+
limit: 1,
|
|
2657
|
+
props: {
|
|
2658
|
+
isRoot: true,
|
|
2659
|
+
},
|
|
2660
|
+
});
|
|
2627
2661
|
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
incidentCountMetric.
|
|
2636
|
-
|
|
2662
|
+
if (existingIncidentCount.toNumber() === 0) {
|
|
2663
|
+
const incidentCountMetric: Metric = new Metric();
|
|
2664
|
+
|
|
2665
|
+
incidentCountMetric.projectId = incident.projectId;
|
|
2666
|
+
incidentCountMetric.serviceId = incident.id!;
|
|
2667
|
+
incidentCountMetric.serviceType = ServiceType.Incident;
|
|
2668
|
+
incidentCountMetric.name = IncidentMetricType.IncidentCount;
|
|
2669
|
+
incidentCountMetric.value = 1;
|
|
2670
|
+
incidentCountMetric.attributes = { ...baseMetricAttributes };
|
|
2671
|
+
incidentCountMetric.attributeKeys = TelemetryUtil.getAttributeKeys(
|
|
2672
|
+
incidentCountMetric.attributes,
|
|
2673
|
+
);
|
|
2637
2674
|
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2675
|
+
incidentCountMetric.time = incidentStartsAt;
|
|
2676
|
+
incidentCountMetric.timeUnixNano = OneUptimeDate.toUnixNano(
|
|
2677
|
+
incidentCountMetric.time,
|
|
2678
|
+
);
|
|
2679
|
+
incidentCountMetric.metricPointType = MetricPointType.Sum;
|
|
2680
|
+
incidentCountMetric.retentionDate = incidentMetricRetentionDate;
|
|
2644
2681
|
|
|
2645
|
-
|
|
2682
|
+
itemsToSave.push(incidentCountMetric);
|
|
2683
|
+
}
|
|
2646
2684
|
|
|
2647
|
-
//
|
|
2685
|
+
// Always register the metric type so it shows up in the type catalog.
|
|
2648
2686
|
const metricType: MetricType = new MetricType();
|
|
2649
|
-
metricType.name =
|
|
2687
|
+
metricType.name = IncidentMetricType.IncidentCount;
|
|
2650
2688
|
metricType.description = "Number of incidents created";
|
|
2651
2689
|
metricType.unit = "";
|
|
2652
2690
|
metricType.services = [];
|
|
2653
2691
|
|
|
2654
|
-
|
|
2655
|
-
metricTypesMap[incidentCountMetric.name] = metricType;
|
|
2692
|
+
metricTypesMap[IncidentMetricType.IncidentCount] = metricType;
|
|
2656
2693
|
|
|
2657
2694
|
// is the incident acknowledged?
|
|
2658
2695
|
const isIncidentAcknowledged: boolean = incidentStateTimelines.some(
|