@oneuptime/common 10.0.65 → 10.0.66
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/DockerHostOwnerTeam.ts +464 -0
- package/Models/DatabaseModels/DockerHostOwnerUser.ts +463 -0
- package/Models/DatabaseModels/Index.ts +24 -0
- package/Models/DatabaseModels/KubernetesClusterOwnerTeam.ts +464 -0
- package/Models/DatabaseModels/KubernetesClusterOwnerUser.ts +463 -0
- package/Models/DatabaseModels/KubernetesResource.ts +548 -0
- package/Models/DatabaseModels/MetricPipelineRule.ts +804 -0
- package/Models/DatabaseModels/MetricRecordingRule.ts +470 -0
- package/Models/DatabaseModels/Monitor.ts +2 -0
- package/Models/DatabaseModels/Project.ts +53 -0
- package/Models/DatabaseModels/Service.ts +79 -0
- package/Models/DatabaseModels/TraceDropFilter.ts +508 -0
- package/Models/DatabaseModels/TracePipeline.ts +436 -0
- package/Models/DatabaseModels/TracePipelineProcessor.ts +454 -0
- package/Models/DatabaseModels/TraceRecordingRule.ts +470 -0
- package/Models/DatabaseModels/TraceScrubRule.ts +546 -0
- package/Server/API/KubernetesResourceAPI.ts +129 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776504277320-MigrationName.ts +399 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776505976155-AddTracePipelineTables.ts +205 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776509413763-MigrationName.ts +335 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776541018853-MigrationName.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776544084793-MigrationName.ts +53 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -1
- package/Server/Services/DockerHostOwnerTeamService.ts +10 -0
- package/Server/Services/DockerHostOwnerUserService.ts +10 -0
- package/Server/Services/KubernetesClusterOwnerTeamService.ts +10 -0
- package/Server/Services/KubernetesClusterOwnerUserService.ts +10 -0
- package/Server/Services/KubernetesResourceService.ts +351 -0
- package/Server/Services/MetricPipelineRuleService.ts +10 -0
- package/Server/Services/MetricRecordingRuleService.ts +10 -0
- package/Server/Services/TraceDropFilterService.ts +10 -0
- package/Server/Services/TracePipelineProcessorService.ts +10 -0
- package/Server/Services/TracePipelineService.ts +10 -0
- package/Server/Services/TraceRecordingRuleService.ts +10 -0
- package/Server/Services/TraceScrubRuleService.ts +10 -0
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +71 -9
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +483 -75
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +379 -6
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +502 -0
- package/Tests/Utils/MetricUnitUtil.test.ts +216 -0
- package/Tests/Utils/Metrics/MetricFormulaEvaluator.test.ts +269 -0
- package/Tests/Utils/Metrics/MetricResultUnitConverter.test.ts +231 -0
- package/Tests/Utils/RecordingRuleExpression.test.ts +177 -0
- package/Types/Kubernetes/KubernetesInventoryExtractor.ts +327 -0
- package/Types/Kubernetes/KubernetesObjectParser.ts +1949 -0
- package/Types/Metrics/MetricDownsamplingRetentionDays.ts +49 -0
- package/Types/Metrics/MetricFormulaConfigData.ts +4 -0
- package/Types/Metrics/MetricPipelineRuleFilterCondition.ts +136 -0
- package/Types/Metrics/MetricPipelineRuleType.ts +27 -0
- package/Types/Metrics/RecordingRuleDefinition.ts +180 -0
- package/Types/Monitor/CriteriaFilter.ts +43 -0
- package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +70 -0
- package/Types/Permission.ts +520 -0
- package/Types/Trace/TraceAggregationType.ts +17 -0
- package/Types/Trace/TraceDropFilterAction.ts +6 -0
- package/Types/Trace/TracePipelineProcessorType.ts +56 -0
- package/Types/Trace/TraceRecordingRuleDefinition.ts +218 -0
- package/Types/Trace/TraceScrubAction.ts +7 -0
- package/Types/Trace/TraceScrubField.ts +8 -0
- package/Types/Trace/TraceScrubPatternType.ts +10 -0
- package/UI/Components/CardSelect/CardSelect.tsx +9 -1
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +6 -10
- package/UI/Components/Forms/Fields/FormField.tsx +1 -0
- package/UI/Components/Forms/Types/Field.ts +1 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +57 -0
- package/UI/Components/Page/Page.tsx +6 -0
- package/Utils/MetricUnitUtil.ts +289 -0
- package/Utils/Metrics/MetricFormulaEvaluator.ts +610 -0
- package/Utils/Metrics/MetricResultUnitConverter.ts +91 -0
- package/Utils/Metrics/RecordingRuleExpression.ts +359 -0
- package/Utils/ValueFormatter.ts +137 -13
- package/build/dist/Models/DatabaseModels/DockerHostOwnerTeam.js +480 -0
- package/build/dist/Models/DatabaseModels/DockerHostOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DockerHostOwnerUser.js +479 -0
- package/build/dist/Models/DatabaseModels/DockerHostOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +24 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerTeam.js +480 -0
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerUser.js +479 -0
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/KubernetesResource.js +590 -0
- package/build/dist/Models/DatabaseModels/KubernetesResource.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MetricPipelineRule.js +836 -0
- package/build/dist/Models/DatabaseModels/MetricPipelineRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MetricRecordingRule.js +497 -0
- package/build/dist/Models/DatabaseModels/MetricRecordingRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Monitor.js +2 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +53 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Service.js +79 -0
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js +536 -0
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TracePipeline.js +462 -0
- package/build/dist/Models/DatabaseModels/TracePipeline.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TracePipelineProcessor.js +476 -0
- package/build/dist/Models/DatabaseModels/TracePipelineProcessor.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TraceRecordingRule.js +497 -0
- package/build/dist/Models/DatabaseModels/TraceRecordingRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TraceScrubRule.js +575 -0
- package/build/dist/Models/DatabaseModels/TraceScrubRule.js.map +1 -0
- package/build/dist/Server/API/KubernetesResourceAPI.js +98 -0
- package/build/dist/Server/API/KubernetesResourceAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776504277320-MigrationName.js +144 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776504277320-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776505976155-AddTracePipelineTables.js +82 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776505976155-AddTracePipelineTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776509413763-MigrationName.js +118 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776509413763-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776541018853-MigrationName.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776541018853-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776544084793-MigrationName.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776544084793-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/DockerHostOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/DockerHostOwnerUserService.js +9 -0
- package/build/dist/Server/Services/DockerHostOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js +9 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesResourceService.js +237 -0
- package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -0
- package/build/dist/Server/Services/MetricPipelineRuleService.js +9 -0
- package/build/dist/Server/Services/MetricPipelineRuleService.js.map +1 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js +9 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -0
- package/build/dist/Server/Services/TraceDropFilterService.js +9 -0
- package/build/dist/Server/Services/TraceDropFilterService.js.map +1 -0
- package/build/dist/Server/Services/TracePipelineProcessorService.js +9 -0
- package/build/dist/Server/Services/TracePipelineProcessorService.js.map +1 -0
- package/build/dist/Server/Services/TracePipelineService.js +9 -0
- package/build/dist/Server/Services/TracePipelineService.js.map +1 -0
- package/build/dist/Server/Services/TraceRecordingRuleService.js +9 -0
- package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -0
- package/build/dist/Server/Services/TraceScrubRuleService.js +9 -0
- package/build/dist/Server/Services/TraceScrubRuleService.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +56 -9
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +335 -53
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +277 -5
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.js +407 -0
- package/build/dist/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.js.map +1 -0
- package/build/dist/Tests/Utils/MetricUnitUtil.test.js +159 -0
- package/build/dist/Tests/Utils/MetricUnitUtil.test.js.map +1 -0
- package/build/dist/Tests/Utils/Metrics/MetricFormulaEvaluator.test.js +224 -0
- package/build/dist/Tests/Utils/Metrics/MetricFormulaEvaluator.test.js.map +1 -0
- package/build/dist/Tests/Utils/Metrics/MetricResultUnitConverter.test.js +180 -0
- package/build/dist/Tests/Utils/Metrics/MetricResultUnitConverter.test.js.map +1 -0
- package/build/dist/Tests/Utils/RecordingRuleExpression.test.js +142 -0
- package/build/dist/Tests/Utils/RecordingRuleExpression.test.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesInventoryExtractor.js +200 -0
- package/build/dist/Types/Kubernetes/KubernetesInventoryExtractor.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesObjectParser.js +1205 -0
- package/build/dist/Types/Kubernetes/KubernetesObjectParser.js.map +1 -0
- package/build/dist/Types/Metrics/MetricDownsamplingRetentionDays.js +32 -0
- package/build/dist/Types/Metrics/MetricDownsamplingRetentionDays.js.map +1 -0
- package/build/dist/Types/Metrics/MetricPipelineRuleFilterCondition.js +103 -0
- package/build/dist/Types/Metrics/MetricPipelineRuleFilterCondition.js.map +1 -0
- package/build/dist/Types/Metrics/MetricPipelineRuleType.js +27 -0
- package/build/dist/Types/Metrics/MetricPipelineRuleType.js.map +1 -0
- package/build/dist/Types/Metrics/RecordingRuleDefinition.js +110 -0
- package/build/dist/Types/Metrics/RecordingRuleDefinition.js.map +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js +22 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MetricMonitor/MetricCriteriaContext.js +2 -0
- package/build/dist/Types/Monitor/MetricMonitor/MetricCriteriaContext.js.map +1 -0
- package/build/dist/Types/Permission.js +454 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Trace/TraceAggregationType.js +18 -0
- package/build/dist/Types/Trace/TraceAggregationType.js.map +1 -0
- package/build/dist/Types/Trace/TraceDropFilterAction.js +7 -0
- package/build/dist/Types/Trace/TraceDropFilterAction.js.map +1 -0
- package/build/dist/Types/Trace/TracePipelineProcessorType.js +10 -0
- package/build/dist/Types/Trace/TracePipelineProcessorType.js.map +1 -0
- package/build/dist/Types/Trace/TraceRecordingRuleDefinition.js +145 -0
- package/build/dist/Types/Trace/TraceRecordingRuleDefinition.js.map +1 -0
- package/build/dist/Types/Trace/TraceScrubAction.js +8 -0
- package/build/dist/Types/Trace/TraceScrubAction.js.map +1 -0
- package/build/dist/Types/Trace/TraceScrubField.js +9 -0
- package/build/dist/Types/Trace/TraceScrubField.js.map +1 -0
- package/build/dist/Types/Trace/TraceScrubPatternType.js +11 -0
- package/build/dist/Types/Trace/TraceScrubPatternType.js.map +1 -0
- package/build/dist/UI/Components/CardSelect/CardSelect.js +3 -1
- package/build/dist/UI/Components/CardSelect/CardSelect.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +6 -9
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +30 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Page/Page.js +1 -0
- package/build/dist/UI/Components/Page/Page.js.map +1 -1
- package/build/dist/Utils/MetricUnitUtil.js +232 -0
- package/build/dist/Utils/MetricUnitUtil.js.map +1 -0
- package/build/dist/Utils/Metrics/MetricFormulaEvaluator.js +453 -0
- package/build/dist/Utils/Metrics/MetricFormulaEvaluator.js.map +1 -0
- package/build/dist/Utils/Metrics/MetricResultUnitConverter.js +61 -0
- package/build/dist/Utils/Metrics/MetricResultUnitConverter.js.map +1 -0
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js +298 -0
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js.map +1 -0
- package/build/dist/Utils/ValueFormatter.js +123 -13
- package/build/dist/Utils/ValueFormatter.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,16 +2,26 @@ import AggregateModel from "../../../../Types/BaseDatabase/AggregatedModel";
|
|
|
2
2
|
import AggregatedResult from "../../../../Types/BaseDatabase/AggregatedResult";
|
|
3
3
|
import MetricFormulaConfigData from "../../../../Types/Metrics/MetricFormulaConfigData";
|
|
4
4
|
import MetricQueryConfigData from "../../../../Types/Metrics/MetricQueryConfigData";
|
|
5
|
+
import MetricsAggregationType from "../../../../Types/Metrics/MetricsAggregationType";
|
|
5
6
|
import MetricMonitorResponse from "../../../../Types/Monitor/MetricMonitor/MetricMonitorResponse";
|
|
7
|
+
import MetricCriteriaContext, {
|
|
8
|
+
MetricComponent,
|
|
9
|
+
MetricComponentValue,
|
|
10
|
+
} from "../../../../Types/Monitor/MetricMonitor/MetricCriteriaContext";
|
|
6
11
|
import MonitorStep from "../../../../Types/Monitor/MonitorStep";
|
|
12
|
+
import { JSONObject } from "../../../../Types/JSON";
|
|
7
13
|
import DataToProcess from "../DataToProcess";
|
|
8
14
|
import CompareCriteria from "./CompareCriteria";
|
|
9
15
|
import {
|
|
10
16
|
CheckOn,
|
|
11
17
|
CriteriaFilter,
|
|
12
18
|
EvaluateOverTimeType,
|
|
19
|
+
FilterType,
|
|
20
|
+
NoDataPolicy,
|
|
13
21
|
} from "../../../../Types/Monitor/CriteriaFilter";
|
|
14
22
|
import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
23
|
+
import MetricUnitUtil from "../../../../Utils/MetricUnitUtil";
|
|
24
|
+
import MetricFormulaEvaluator from "../../../../Utils/Metrics/MetricFormulaEvaluator";
|
|
15
25
|
|
|
16
26
|
export default class MetricMonitorCriteria {
|
|
17
27
|
@CaptureSpan()
|
|
@@ -30,100 +40,498 @@ export default class MetricMonitorCriteria {
|
|
|
30
40
|
EvaluateOverTimeType.AnyValue;
|
|
31
41
|
}
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
if (input.criteriaFilter.checkOn !== CheckOn.MetricValue) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const rawThreshold: number | null = CompareCriteria.convertToNumber(
|
|
48
|
+
input.criteriaFilter.value,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const metricAlias: string =
|
|
52
|
+
input.criteriaFilter.metricMonitorOptions?.metricAlias || "";
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
|
|
54
|
+
const metricResponse: MetricMonitorResponse =
|
|
55
|
+
input.dataToProcess as MetricMonitorResponse;
|
|
56
|
+
const metricAggregatedResult: Array<AggregatedResult> =
|
|
57
|
+
metricResponse.metricResult || [];
|
|
38
58
|
|
|
39
|
-
|
|
40
|
-
|
|
59
|
+
const queryConfigs: Array<MetricQueryConfigData> =
|
|
60
|
+
input.monitorStep.data?.metricMonitor?.metricViewConfig?.queryConfigs ||
|
|
61
|
+
[];
|
|
62
|
+
const formulaConfigs: Array<MetricFormulaConfigData> =
|
|
63
|
+
input.monitorStep.data?.metricMonitor?.metricViewConfig?.formulaConfigs ||
|
|
64
|
+
[];
|
|
41
65
|
|
|
42
|
-
|
|
43
|
-
|
|
66
|
+
/*
|
|
67
|
+
* Resolve which query/formula the alias refers to. Use explicit index
|
|
68
|
+
* checks (not `findIndex() || -1`, which incorrectly falls back to -1
|
|
69
|
+
* when the first element matches).
|
|
70
|
+
*/
|
|
71
|
+
let matchedQuery: MetricQueryConfigData | null = null;
|
|
72
|
+
let matchedFormula: MetricFormulaConfigData | null = null;
|
|
73
|
+
let aliasIndex: number = -1;
|
|
44
74
|
|
|
45
|
-
|
|
75
|
+
if (metricAlias) {
|
|
76
|
+
const qIdx: number = queryConfigs.findIndex(
|
|
77
|
+
(q: MetricQueryConfigData) => {
|
|
78
|
+
return q.metricAliasData?.metricVariable === metricAlias;
|
|
79
|
+
},
|
|
80
|
+
);
|
|
46
81
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
82
|
+
if (qIdx >= 0) {
|
|
83
|
+
matchedQuery = queryConfigs[qIdx] || null;
|
|
84
|
+
aliasIndex = qIdx;
|
|
85
|
+
} else {
|
|
86
|
+
const fIdx: number = formulaConfigs.findIndex(
|
|
87
|
+
(f: MetricFormulaConfigData) => {
|
|
88
|
+
return f.metricAliasData?.metricVariable === metricAlias;
|
|
51
89
|
},
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
input.monitorStep.data?.metricMonitor?.metricViewConfig?.formulaConfigs.findIndex(
|
|
58
|
-
(formulaConfig: MetricFormulaConfigData) => {
|
|
59
|
-
return (
|
|
60
|
-
formulaConfig.metricAliasData?.metricVariable === metricAlias
|
|
61
|
-
);
|
|
62
|
-
},
|
|
63
|
-
) || -1;
|
|
64
|
-
|
|
65
|
-
if (formulaIndex >= 0) {
|
|
66
|
-
// add number of queries to the index
|
|
67
|
-
formulaIndex =
|
|
68
|
-
formulaIndex +
|
|
69
|
-
(input.monitorStep.data?.metricMonitor?.metricViewConfig
|
|
70
|
-
?.queryConfigs.length || 0);
|
|
71
|
-
aliasIndex = formulaIndex;
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
if (fIdx >= 0) {
|
|
93
|
+
matchedFormula = formulaConfigs[fIdx] || null;
|
|
94
|
+
aliasIndex = queryConfigs.length + fIdx;
|
|
72
95
|
}
|
|
73
96
|
}
|
|
74
|
-
|
|
75
|
-
metricAggregaredResult &&
|
|
76
|
-
metricAggregaredResult.length >= aliasIndex - 1 &&
|
|
77
|
-
aliasIndex >= 0
|
|
78
|
-
? metricAggregaredResult[aliasIndex]
|
|
79
|
-
: metricAggregaredResult[0] || undefined;
|
|
80
|
-
|
|
81
|
-
if (metricAlias) {
|
|
82
|
-
// find the index of the alias in the dataToProcess.
|
|
83
|
-
const indexOfAlias: number = (
|
|
84
|
-
input.dataToProcess as MetricMonitorResponse
|
|
85
|
-
).metricViewConfig.queryConfigs.findIndex(
|
|
86
|
-
(queryConfig: MetricQueryConfigData) => {
|
|
87
|
-
return queryConfig.metricAliasData?.metricVariable === metricAlias;
|
|
88
|
-
},
|
|
89
|
-
);
|
|
97
|
+
}
|
|
90
98
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
/*
|
|
100
|
+
* If no alias was configured or it didn't match anything, fall back to
|
|
101
|
+
* the first aggregated result / query for a best-effort comparison.
|
|
102
|
+
*/
|
|
103
|
+
const aggregatedResult: AggregatedResult | undefined =
|
|
104
|
+
aliasIndex >= 0
|
|
105
|
+
? metricAggregatedResult[aliasIndex]
|
|
106
|
+
: metricAggregatedResult[0];
|
|
107
|
+
|
|
108
|
+
if (!matchedQuery && !matchedFormula && queryConfigs[0]) {
|
|
109
|
+
matchedQuery = queryConfigs[0];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/*
|
|
113
|
+
* Build the metric context regardless of whether the threshold breaches,
|
|
114
|
+
* so the filter message can still reference the metric if needed.
|
|
115
|
+
*/
|
|
116
|
+
const metricContext: MetricCriteriaContext =
|
|
117
|
+
MetricMonitorCriteria.buildContext({
|
|
118
|
+
matchedQuery,
|
|
119
|
+
matchedFormula,
|
|
120
|
+
metricAlias,
|
|
121
|
+
criteriaFilter: input.criteriaFilter,
|
|
122
|
+
queryConfigs,
|
|
123
|
+
formulaConfigs,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
input.criteriaFilter.metricCriteriaContext = metricContext;
|
|
127
|
+
|
|
128
|
+
if (rawThreshold === null) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/*
|
|
133
|
+
* Sample values arrive already converted into the query's configured
|
|
134
|
+
* display unit (legendUnit) — the upstream fetch step uses
|
|
135
|
+
* MetricResultUnitConverter to normalize OpenTelemetry's native unit
|
|
136
|
+
* into whatever the user picked. So `sampleUnit` here is that
|
|
137
|
+
* legendUnit, and `thresholdUnit` is what the user typed into the
|
|
138
|
+
* criteria threshold. When they differ we convert sample values from
|
|
139
|
+
* legendUnit → thresholdUnit before comparing, so the alert message
|
|
140
|
+
* reads in the unit the user actually chose for the threshold.
|
|
141
|
+
*/
|
|
142
|
+
const sampleUnit: string | undefined = metricContext.unit || undefined;
|
|
143
|
+
const thresholdUnit: string | undefined =
|
|
144
|
+
input.criteriaFilter.metricMonitorOptions?.thresholdUnit || sampleUnit;
|
|
145
|
+
|
|
146
|
+
const displayUnit: string | undefined = thresholdUnit;
|
|
147
|
+
|
|
148
|
+
/*
|
|
149
|
+
* Threshold is entered in thresholdUnit; keep the numeric value as-is
|
|
150
|
+
* for comparison in that same unit.
|
|
151
|
+
*/
|
|
152
|
+
const threshold: number = rawThreshold;
|
|
153
|
+
|
|
154
|
+
const convertToDisplayUnit: (value: number) => number = (
|
|
155
|
+
value: number,
|
|
156
|
+
): number => {
|
|
157
|
+
if (!sampleUnit || !displayUnit || sampleUnit === displayUnit) {
|
|
158
|
+
return value;
|
|
159
|
+
}
|
|
160
|
+
return MetricUnitUtil.convertToMetricUnit({
|
|
161
|
+
value,
|
|
162
|
+
fromUnit: sampleUnit,
|
|
163
|
+
metricUnit: displayUnit,
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
metricContext.unit = displayUnit || null;
|
|
168
|
+
|
|
169
|
+
const samples: Array<AggregateModel> =
|
|
170
|
+
(aggregatedResult && aggregatedResult.data) || [];
|
|
171
|
+
|
|
172
|
+
/*
|
|
173
|
+
* Respect the configured no-data policy. Without this guard, the
|
|
174
|
+
* evaluator silently treats missing data as a value of 0 and can
|
|
175
|
+
* trigger incidents for monitors that simply haven't received data.
|
|
176
|
+
*/
|
|
177
|
+
if (samples.length === 0) {
|
|
178
|
+
const policy: NoDataPolicy =
|
|
179
|
+
input.criteriaFilter.metricMonitorOptions?.onNoDataPolicy ||
|
|
180
|
+
NoDataPolicy.Ignore;
|
|
101
181
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
182
|
+
if (policy === NoDataPolicy.Ignore) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (policy === NoDataPolicy.Trigger) {
|
|
187
|
+
return `No data received for ${metricContext.metricName} in the evaluation window — triggering per no-data policy.`;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// TreatAsZero: fall through to the comparator with value 0.
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const numbersInDisplayUnit: Array<number> = samples.map(
|
|
194
|
+
(d: AggregateModel) => {
|
|
195
|
+
return convertToDisplayUnit(d.value);
|
|
196
|
+
},
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const comparisonMessage: string | null =
|
|
200
|
+
CompareCriteria.compareCriteriaNumbers({
|
|
201
|
+
value: numbersInDisplayUnit.length > 0 ? numbersInDisplayUnit : 0,
|
|
202
|
+
threshold: threshold,
|
|
203
|
+
criteriaFilter: input.criteriaFilter,
|
|
204
|
+
metricDisplayName: metricContext.metricName,
|
|
205
|
+
unit: displayUnit,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
if (!comparisonMessage) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/*
|
|
213
|
+
* Identify every sample that breached so the root cause can render a
|
|
214
|
+
* timestamp/value table instead of a giant one-line list, and keep a
|
|
215
|
+
* total count so we can say "N of M samples breached". Values are
|
|
216
|
+
* stored in the display unit so they match the comparison message.
|
|
217
|
+
*/
|
|
218
|
+
const breachingSamples: Array<{
|
|
219
|
+
value: number;
|
|
220
|
+
timestamp: Date;
|
|
221
|
+
attributes: JSONObject;
|
|
222
|
+
componentValues?: Array<MetricComponentValue>;
|
|
223
|
+
}> = [];
|
|
224
|
+
|
|
225
|
+
/*
|
|
226
|
+
* For formulas, precompute an index from ISO-timestamp → value for
|
|
227
|
+
* every component series so we can show what `a` and `b` were at
|
|
228
|
+
* the moment the formula breached, without re-walking the arrays
|
|
229
|
+
* inside the per-sample loop.
|
|
230
|
+
*/
|
|
231
|
+
const componentValueLookup: Map<string, Map<string, number>> | null =
|
|
232
|
+
matchedFormula
|
|
233
|
+
? MetricMonitorCriteria.buildComponentValueLookup({
|
|
234
|
+
components: metricContext.components || [],
|
|
235
|
+
queryConfigs,
|
|
236
|
+
formulaConfigs,
|
|
237
|
+
metricAggregatedResult,
|
|
238
|
+
})
|
|
239
|
+
: null;
|
|
240
|
+
|
|
241
|
+
for (const sample of samples) {
|
|
242
|
+
const convertedValue: number = convertToDisplayUnit(sample.value);
|
|
243
|
+
const breaches: boolean = MetricMonitorCriteria.sampleBreaches(
|
|
244
|
+
convertedValue,
|
|
245
|
+
threshold,
|
|
246
|
+
input.criteriaFilter.filterType,
|
|
247
|
+
);
|
|
248
|
+
if (breaches) {
|
|
249
|
+
const entry: {
|
|
250
|
+
value: number;
|
|
251
|
+
timestamp: Date;
|
|
252
|
+
attributes: JSONObject;
|
|
253
|
+
componentValues?: Array<MetricComponentValue>;
|
|
254
|
+
} = {
|
|
255
|
+
value: convertedValue,
|
|
256
|
+
timestamp: sample.timestamp,
|
|
257
|
+
attributes: MetricMonitorCriteria.extractLabelAttributes(sample),
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
if (componentValueLookup && metricContext.components) {
|
|
261
|
+
entry.componentValues = MetricMonitorCriteria.resolveComponentValues({
|
|
262
|
+
timestamp: sample.timestamp,
|
|
263
|
+
components: metricContext.components,
|
|
264
|
+
lookup: componentValueLookup,
|
|
265
|
+
});
|
|
108
266
|
}
|
|
267
|
+
|
|
268
|
+
breachingSamples.push(entry);
|
|
109
269
|
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
metricContext.totalSamplesInWindow = samples.length;
|
|
273
|
+
|
|
274
|
+
if (breachingSamples.length > 0) {
|
|
275
|
+
metricContext.breachingSample = breachingSamples[0];
|
|
276
|
+
metricContext.breachingSamples = breachingSamples;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return comparisonMessage;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private static buildComponentValueLookup(input: {
|
|
283
|
+
components: Array<MetricComponent>;
|
|
284
|
+
queryConfigs: Array<MetricQueryConfigData>;
|
|
285
|
+
formulaConfigs: Array<MetricFormulaConfigData>;
|
|
286
|
+
metricAggregatedResult: Array<AggregatedResult>;
|
|
287
|
+
}): Map<string, Map<string, number>> {
|
|
288
|
+
// Map of alias -> (isoTimestamp -> value)
|
|
289
|
+
const lookup: Map<string, Map<string, number>> = new Map();
|
|
290
|
+
|
|
291
|
+
for (const component of input.components) {
|
|
292
|
+
const queryIdx: number = input.queryConfigs.findIndex(
|
|
293
|
+
(q: MetricQueryConfigData) => {
|
|
294
|
+
return (
|
|
295
|
+
(q.metricAliasData?.metricVariable || "").toLowerCase() ===
|
|
296
|
+
component.alias
|
|
297
|
+
);
|
|
298
|
+
},
|
|
299
|
+
);
|
|
110
300
|
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
301
|
+
let resultIndex: number = -1;
|
|
302
|
+
if (queryIdx >= 0) {
|
|
303
|
+
resultIndex = queryIdx;
|
|
304
|
+
} else {
|
|
305
|
+
const formulaIdx: number = input.formulaConfigs.findIndex(
|
|
306
|
+
(fc: MetricFormulaConfigData) => {
|
|
307
|
+
return (
|
|
308
|
+
(fc.metricAliasData?.metricVariable || "").toLowerCase() ===
|
|
309
|
+
component.alias
|
|
310
|
+
);
|
|
116
311
|
},
|
|
117
312
|
);
|
|
313
|
+
if (formulaIdx >= 0) {
|
|
314
|
+
resultIndex = input.queryConfigs.length + formulaIdx;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (resultIndex < 0) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const series: AggregatedResult | undefined =
|
|
323
|
+
input.metricAggregatedResult[resultIndex];
|
|
324
|
+
if (!series) {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const timestampMap: Map<string, number> = new Map();
|
|
329
|
+
for (const row of series.data) {
|
|
330
|
+
const iso: string = MetricMonitorCriteria.toIsoTimestamp(row.timestamp);
|
|
331
|
+
timestampMap.set(iso, row.value);
|
|
332
|
+
}
|
|
333
|
+
lookup.set(component.alias, timestampMap);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return lookup;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
private static resolveComponentValues(input: {
|
|
340
|
+
timestamp: Date | string;
|
|
341
|
+
components: Array<MetricComponent>;
|
|
342
|
+
lookup: Map<string, Map<string, number>>;
|
|
343
|
+
}): Array<MetricComponentValue> {
|
|
344
|
+
const iso: string = MetricMonitorCriteria.toIsoTimestamp(input.timestamp);
|
|
345
|
+
return input.components.map((component: MetricComponent) => {
|
|
346
|
+
const series: Map<string, number> | undefined = input.lookup.get(
|
|
347
|
+
component.alias,
|
|
348
|
+
);
|
|
349
|
+
const value: number | undefined = series ? series.get(iso) : undefined;
|
|
350
|
+
return {
|
|
351
|
+
alias: component.alias,
|
|
352
|
+
value: typeof value === "number" ? value : null,
|
|
353
|
+
};
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
private static toIsoTimestamp(value: Date | string): string {
|
|
358
|
+
const date: Date = value instanceof Date ? value : new Date(value);
|
|
359
|
+
return isNaN(date.getTime()) ? String(value) : date.toISOString();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
private static sampleBreaches(
|
|
363
|
+
value: number,
|
|
364
|
+
threshold: number,
|
|
365
|
+
filterType: FilterType | undefined,
|
|
366
|
+
): boolean {
|
|
367
|
+
switch (filterType) {
|
|
368
|
+
case FilterType.GreaterThan:
|
|
369
|
+
return value > threshold;
|
|
370
|
+
case FilterType.GreaterThanOrEqualTo:
|
|
371
|
+
return value >= threshold;
|
|
372
|
+
case FilterType.LessThan:
|
|
373
|
+
return value < threshold;
|
|
374
|
+
case FilterType.LessThanOrEqualTo:
|
|
375
|
+
return value <= threshold;
|
|
376
|
+
case FilterType.EqualTo:
|
|
377
|
+
return value === threshold;
|
|
378
|
+
case FilterType.NotEqualTo:
|
|
379
|
+
return value !== threshold;
|
|
380
|
+
default:
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
private static extractLabelAttributes(sample: AggregateModel): JSONObject {
|
|
386
|
+
/*
|
|
387
|
+
* AggregatedModel has a string index signature that holds group-by
|
|
388
|
+
* attributes alongside `timestamp` and `value`. Strip the known keys
|
|
389
|
+
* to get the label dictionary.
|
|
390
|
+
*/
|
|
391
|
+
const labels: JSONObject = {};
|
|
392
|
+
for (const key of Object.keys(sample)) {
|
|
393
|
+
if (key === "timestamp" || key === "value") {
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
const v: unknown = (sample as unknown as JSONObject)[key];
|
|
397
|
+
if (v === undefined || v === null) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
labels[key] = v as JSONObject[string];
|
|
401
|
+
}
|
|
402
|
+
return labels;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
private static buildContext(input: {
|
|
406
|
+
matchedQuery: MetricQueryConfigData | null;
|
|
407
|
+
matchedFormula: MetricFormulaConfigData | null;
|
|
408
|
+
metricAlias: string;
|
|
409
|
+
criteriaFilter: CriteriaFilter;
|
|
410
|
+
queryConfigs: Array<MetricQueryConfigData>;
|
|
411
|
+
formulaConfigs: Array<MetricFormulaConfigData>;
|
|
412
|
+
}): MetricCriteriaContext {
|
|
413
|
+
const q: MetricQueryConfigData | null = input.matchedQuery;
|
|
414
|
+
const f: MetricFormulaConfigData | null = input.matchedFormula;
|
|
415
|
+
|
|
416
|
+
const metricName: string =
|
|
417
|
+
(q?.metricQueryData?.filterData?.metricName as string | undefined) ||
|
|
418
|
+
f?.metricFormulaData?.metricFormula ||
|
|
419
|
+
q?.metricAliasData?.title ||
|
|
420
|
+
f?.metricAliasData?.title ||
|
|
421
|
+
"Metric";
|
|
422
|
+
|
|
423
|
+
const unit: string | null =
|
|
424
|
+
(q?.metricAliasData?.legendUnit as string | undefined) ||
|
|
425
|
+
(f?.metricAliasData?.legendUnit as string | undefined) ||
|
|
426
|
+
null;
|
|
427
|
+
|
|
428
|
+
const aggregationType: MetricsAggregationType | null =
|
|
429
|
+
(q?.metricQueryData?.filterData?.aggegationType as
|
|
430
|
+
| MetricsAggregationType
|
|
431
|
+
| undefined) || null;
|
|
432
|
+
|
|
433
|
+
const filterAttributes: JSONObject =
|
|
434
|
+
(q?.metricQueryData?.filterData?.attributes as JSONObject | undefined) ||
|
|
435
|
+
{};
|
|
436
|
+
|
|
437
|
+
const groupBy: Array<string> = q?.metricQueryData?.groupBy
|
|
438
|
+
? Object.keys(q.metricQueryData.groupBy as Record<string, unknown>)
|
|
439
|
+
: [];
|
|
440
|
+
|
|
441
|
+
const components: Array<MetricComponent> | undefined = f
|
|
442
|
+
? MetricMonitorCriteria.buildFormulaComponents({
|
|
443
|
+
formulaConfig: f,
|
|
444
|
+
queryConfigs: input.queryConfigs,
|
|
445
|
+
formulaConfigs: input.formulaConfigs,
|
|
446
|
+
})
|
|
447
|
+
: undefined;
|
|
448
|
+
|
|
449
|
+
return {
|
|
450
|
+
metricName,
|
|
451
|
+
alias: input.metricAlias,
|
|
452
|
+
unit,
|
|
453
|
+
aggregationType,
|
|
454
|
+
isFormula: Boolean(f),
|
|
455
|
+
formulaExpression: f?.metricFormulaData?.metricFormula,
|
|
456
|
+
filterAttributes,
|
|
457
|
+
groupBy,
|
|
458
|
+
timeWindowMinutes:
|
|
459
|
+
input.criteriaFilter.evaluateOverTimeOptions?.timeValueInMinutes,
|
|
460
|
+
...(components && components.length > 0 ? { components } : {}),
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Resolve the variables the formula references to their source
|
|
466
|
+
* query/formula definitions so the root cause can label each
|
|
467
|
+
* component column with its metric name and native unit.
|
|
468
|
+
*/
|
|
469
|
+
private static buildFormulaComponents(input: {
|
|
470
|
+
formulaConfig: MetricFormulaConfigData;
|
|
471
|
+
queryConfigs: Array<MetricQueryConfigData>;
|
|
472
|
+
formulaConfigs: Array<MetricFormulaConfigData>;
|
|
473
|
+
}): Array<MetricComponent> {
|
|
474
|
+
const formula: string =
|
|
475
|
+
input.formulaConfig.metricFormulaData?.metricFormula || "";
|
|
476
|
+
const referenced: Array<string> =
|
|
477
|
+
MetricFormulaEvaluator.getReferencedVariables(formula);
|
|
478
|
+
|
|
479
|
+
const components: Array<MetricComponent> = [];
|
|
480
|
+
const seen: Set<string> = new Set<string>();
|
|
481
|
+
|
|
482
|
+
for (const alias of referenced) {
|
|
483
|
+
const normalizedAlias: string = alias.toLowerCase();
|
|
484
|
+
if (seen.has(normalizedAlias)) {
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
seen.add(normalizedAlias);
|
|
488
|
+
|
|
489
|
+
const queryMatch: MetricQueryConfigData | undefined =
|
|
490
|
+
input.queryConfigs.find((q: MetricQueryConfigData) => {
|
|
491
|
+
return (
|
|
492
|
+
(q.metricAliasData?.metricVariable || "").toLowerCase() ===
|
|
493
|
+
normalizedAlias
|
|
494
|
+
);
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
if (queryMatch) {
|
|
498
|
+
const name: string =
|
|
499
|
+
(queryMatch.metricQueryData?.filterData?.metricName as
|
|
500
|
+
| string
|
|
501
|
+
| undefined) ||
|
|
502
|
+
queryMatch.metricAliasData?.title ||
|
|
503
|
+
normalizedAlias;
|
|
504
|
+
components.push({
|
|
505
|
+
alias: normalizedAlias,
|
|
506
|
+
name,
|
|
507
|
+
unit: queryMatch.metricAliasData?.legendUnit || null,
|
|
508
|
+
isFormula: false,
|
|
509
|
+
});
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const formulaMatch: MetricFormulaConfigData | undefined =
|
|
514
|
+
input.formulaConfigs.find((fc: MetricFormulaConfigData) => {
|
|
515
|
+
return (
|
|
516
|
+
(fc.metricAliasData?.metricVariable || "").toLowerCase() ===
|
|
517
|
+
normalizedAlias
|
|
518
|
+
);
|
|
519
|
+
});
|
|
118
520
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
521
|
+
if (formulaMatch) {
|
|
522
|
+
const name: string =
|
|
523
|
+
formulaMatch.metricAliasData?.title ||
|
|
524
|
+
formulaMatch.metricFormulaData?.metricFormula ||
|
|
525
|
+
normalizedAlias;
|
|
526
|
+
components.push({
|
|
527
|
+
alias: normalizedAlias,
|
|
528
|
+
name,
|
|
529
|
+
unit: formulaMatch.metricAliasData?.legendUnit || null,
|
|
530
|
+
isFormula: true,
|
|
123
531
|
});
|
|
124
532
|
}
|
|
125
533
|
}
|
|
126
534
|
|
|
127
|
-
return
|
|
535
|
+
return components;
|
|
128
536
|
}
|
|
129
537
|
}
|