@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
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
import MetricMonitorCriteria from "../../../../../Server/Utils/Monitor/Criteria/MetricMonitorCriteria";
|
|
2
|
+
import AggregateModel from "../../../../../Types/BaseDatabase/AggregatedModel";
|
|
3
|
+
import AggregatedResult from "../../../../../Types/BaseDatabase/AggregatedResult";
|
|
4
|
+
import {
|
|
5
|
+
CheckOn,
|
|
6
|
+
CriteriaFilter,
|
|
7
|
+
EvaluateOverTimeType,
|
|
8
|
+
FilterType,
|
|
9
|
+
NoDataPolicy,
|
|
10
|
+
} from "../../../../../Types/Monitor/CriteriaFilter";
|
|
11
|
+
import MetricAliasData from "../../../../../Types/Metrics/MetricAliasData";
|
|
12
|
+
import MetricFormulaConfigData from "../../../../../Types/Metrics/MetricFormulaConfigData";
|
|
13
|
+
import MetricQueryConfigData from "../../../../../Types/Metrics/MetricQueryConfigData";
|
|
14
|
+
import MetricQueryData from "../../../../../Types/Metrics/MetricQueryData";
|
|
15
|
+
import MetricsViewConfig from "../../../../../Types/Metrics/MetricsViewConfig";
|
|
16
|
+
import MetricMonitorResponse from "../../../../../Types/Monitor/MetricMonitor/MetricMonitorResponse";
|
|
17
|
+
import MetricFormulaEvaluator from "../../../../../Utils/Metrics/MetricFormulaEvaluator";
|
|
18
|
+
import MonitorStep from "../../../../../Types/Monitor/MonitorStep";
|
|
19
|
+
import RollingTime from "../../../../../Types/RollingTime/RollingTime";
|
|
20
|
+
import ObjectID from "../../../../../Types/ObjectID";
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* Light helper that assembles a MonitorStep + MetricMonitorResponse pair
|
|
24
|
+
* for a single metric alias "a" with the supplied native unit, so each
|
|
25
|
+
* test can just tweak the criteria filter + sample values.
|
|
26
|
+
*/
|
|
27
|
+
function buildInputs(input: {
|
|
28
|
+
metricNativeUnit: string;
|
|
29
|
+
sampleValues: Array<number>;
|
|
30
|
+
criteriaFilter: CriteriaFilter;
|
|
31
|
+
}): {
|
|
32
|
+
criteriaFilter: CriteriaFilter;
|
|
33
|
+
monitorStep: MonitorStep;
|
|
34
|
+
dataToProcess: MetricMonitorResponse;
|
|
35
|
+
} {
|
|
36
|
+
const aliasData: MetricAliasData = {
|
|
37
|
+
metricVariable: "a",
|
|
38
|
+
title: "Response Time",
|
|
39
|
+
description: undefined,
|
|
40
|
+
legend: undefined,
|
|
41
|
+
legendUnit: input.metricNativeUnit,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const queryConfig: MetricQueryConfigData = {
|
|
45
|
+
metricAliasData: aliasData,
|
|
46
|
+
metricQueryData: {
|
|
47
|
+
filterData: {
|
|
48
|
+
metricName: "response_time",
|
|
49
|
+
},
|
|
50
|
+
} as unknown as MetricQueryData,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const metricViewConfig: MetricsViewConfig = {
|
|
54
|
+
queryConfigs: [queryConfig],
|
|
55
|
+
formulaConfigs: [],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const monitorStep: MonitorStep = new MonitorStep();
|
|
59
|
+
monitorStep.data = {
|
|
60
|
+
id: ObjectID.generate().toString(),
|
|
61
|
+
monitorCriteria: { data: undefined } as never,
|
|
62
|
+
} as unknown as MonitorStep["data"];
|
|
63
|
+
monitorStep.data!.metricMonitor = {
|
|
64
|
+
metricViewConfig,
|
|
65
|
+
rollingTime: RollingTime.Past1Minute,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const aggregated: AggregatedResult = {
|
|
69
|
+
data: input.sampleValues.map((v: number) => {
|
|
70
|
+
return {
|
|
71
|
+
timestamp: new Date(),
|
|
72
|
+
value: v,
|
|
73
|
+
} as AggregateModel;
|
|
74
|
+
}),
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const dataToProcess: MetricMonitorResponse = {
|
|
78
|
+
projectId: ObjectID.generate(),
|
|
79
|
+
metricResult: [aggregated],
|
|
80
|
+
metricViewConfig,
|
|
81
|
+
monitorId: ObjectID.generate(),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
criteriaFilter: input.criteriaFilter,
|
|
86
|
+
monitorStep,
|
|
87
|
+
dataToProcess,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
describe("MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet", () => {
|
|
92
|
+
test("no thresholdUnit → threshold evaluated in metric's native unit (backward compatible)", async () => {
|
|
93
|
+
const criteriaFilter: CriteriaFilter = {
|
|
94
|
+
checkOn: CheckOn.MetricValue,
|
|
95
|
+
filterType: FilterType.GreaterThan,
|
|
96
|
+
value: "2000",
|
|
97
|
+
metricMonitorOptions: {
|
|
98
|
+
metricAlias: "a",
|
|
99
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const inputs: ReturnType<typeof buildInputs> = buildInputs({
|
|
104
|
+
metricNativeUnit: "ms",
|
|
105
|
+
sampleValues: [2500],
|
|
106
|
+
criteriaFilter,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const message: string | null =
|
|
110
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet(inputs);
|
|
111
|
+
|
|
112
|
+
expect(message).toBeTruthy();
|
|
113
|
+
expect(message).toContain("greater than 2000 ms");
|
|
114
|
+
expect(message).toContain("2500 ms");
|
|
115
|
+
expect(criteriaFilter.metricCriteriaContext?.unit).toBe("ms");
|
|
116
|
+
expect(criteriaFilter.metricCriteriaContext?.breachingSample?.value).toBe(
|
|
117
|
+
2500,
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("thresholdUnit 'sec' with metric in 'ms' converts samples to sec for the comparison + message", async () => {
|
|
122
|
+
const criteriaFilter: CriteriaFilter = {
|
|
123
|
+
checkOn: CheckOn.MetricValue,
|
|
124
|
+
filterType: FilterType.GreaterThan,
|
|
125
|
+
value: "2",
|
|
126
|
+
metricMonitorOptions: {
|
|
127
|
+
metricAlias: "a",
|
|
128
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
129
|
+
thresholdUnit: "sec",
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// 2500 ms == 2.5 sec — should breach "greater than 2 sec"
|
|
134
|
+
const inputs: ReturnType<typeof buildInputs> = buildInputs({
|
|
135
|
+
metricNativeUnit: "ms",
|
|
136
|
+
sampleValues: [2500],
|
|
137
|
+
criteriaFilter,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const message: string | null =
|
|
141
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet(inputs);
|
|
142
|
+
|
|
143
|
+
expect(message).toBeTruthy();
|
|
144
|
+
expect(message).toContain("greater than 2 sec");
|
|
145
|
+
expect(message).toContain("2.5 sec");
|
|
146
|
+
expect(criteriaFilter.metricCriteriaContext?.unit).toBe("sec");
|
|
147
|
+
expect(criteriaFilter.metricCriteriaContext?.breachingSample?.value).toBe(
|
|
148
|
+
2.5,
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("thresholdUnit 'GB' with metric in 'bytes' breaches on 2.5 GB > 2 GB", async () => {
|
|
153
|
+
const criteriaFilter: CriteriaFilter = {
|
|
154
|
+
checkOn: CheckOn.MetricValue,
|
|
155
|
+
filterType: FilterType.GreaterThan,
|
|
156
|
+
value: "2",
|
|
157
|
+
metricMonitorOptions: {
|
|
158
|
+
metricAlias: "a",
|
|
159
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
160
|
+
thresholdUnit: "GB",
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const inputs: ReturnType<typeof buildInputs> = buildInputs({
|
|
165
|
+
metricNativeUnit: "bytes",
|
|
166
|
+
sampleValues: [2.5e9],
|
|
167
|
+
criteriaFilter,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const message: string | null =
|
|
171
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet(inputs);
|
|
172
|
+
|
|
173
|
+
expect(message).toBeTruthy();
|
|
174
|
+
expect(message).toContain("greater than 2 GB");
|
|
175
|
+
expect(message).toContain("2.5 GB");
|
|
176
|
+
expect(criteriaFilter.metricCriteriaContext?.unit).toBe("GB");
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test("thresholdUnit 'GB' — under-threshold samples do not trigger", async () => {
|
|
180
|
+
const criteriaFilter: CriteriaFilter = {
|
|
181
|
+
checkOn: CheckOn.MetricValue,
|
|
182
|
+
filterType: FilterType.GreaterThan,
|
|
183
|
+
value: "2",
|
|
184
|
+
metricMonitorOptions: {
|
|
185
|
+
metricAlias: "a",
|
|
186
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
187
|
+
thresholdUnit: "GB",
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// 1.5 GB = 1.5e9 bytes — under 2 GB, should NOT breach.
|
|
192
|
+
const inputs: ReturnType<typeof buildInputs> = buildInputs({
|
|
193
|
+
metricNativeUnit: "bytes",
|
|
194
|
+
sampleValues: [1.5e9],
|
|
195
|
+
criteriaFilter,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const message: string | null =
|
|
199
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet(inputs);
|
|
200
|
+
|
|
201
|
+
expect(message).toBeNull();
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test("thresholdUnit in an incompatible family falls back gracefully (no conversion)", async () => {
|
|
205
|
+
/*
|
|
206
|
+
* User incorrectly picked 'MB' but metric is in ms. Conversion should
|
|
207
|
+
* no-op and comparison proceeds in the user's raw unit.
|
|
208
|
+
*/
|
|
209
|
+
const criteriaFilter: CriteriaFilter = {
|
|
210
|
+
checkOn: CheckOn.MetricValue,
|
|
211
|
+
filterType: FilterType.GreaterThan,
|
|
212
|
+
value: "1000",
|
|
213
|
+
metricMonitorOptions: {
|
|
214
|
+
metricAlias: "a",
|
|
215
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
216
|
+
thresholdUnit: "MB",
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const inputs: ReturnType<typeof buildInputs> = buildInputs({
|
|
221
|
+
metricNativeUnit: "ms",
|
|
222
|
+
sampleValues: [5000],
|
|
223
|
+
criteriaFilter,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const message: string | null =
|
|
227
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet(inputs);
|
|
228
|
+
|
|
229
|
+
/*
|
|
230
|
+
* No conversion possible, so the displayed unit/values use user's MB
|
|
231
|
+
* label but values are passed through.
|
|
232
|
+
*/
|
|
233
|
+
expect(message).toBeTruthy();
|
|
234
|
+
expect(message).toContain("MB");
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
test("no data + NoDataPolicy.Trigger triggers regardless of threshold", async () => {
|
|
238
|
+
const criteriaFilter: CriteriaFilter = {
|
|
239
|
+
checkOn: CheckOn.MetricValue,
|
|
240
|
+
filterType: FilterType.GreaterThan,
|
|
241
|
+
value: "2",
|
|
242
|
+
metricMonitorOptions: {
|
|
243
|
+
metricAlias: "a",
|
|
244
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
245
|
+
thresholdUnit: "GB",
|
|
246
|
+
onNoDataPolicy: NoDataPolicy.Trigger,
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const inputs: ReturnType<typeof buildInputs> = buildInputs({
|
|
251
|
+
metricNativeUnit: "bytes",
|
|
252
|
+
sampleValues: [],
|
|
253
|
+
criteriaFilter,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const message: string | null =
|
|
257
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet(inputs);
|
|
258
|
+
|
|
259
|
+
expect(message).toBeTruthy();
|
|
260
|
+
expect(message).toContain("No data received");
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("breaching sample value is recorded in the user's chosen display unit", async () => {
|
|
264
|
+
const criteriaFilter: CriteriaFilter = {
|
|
265
|
+
checkOn: CheckOn.MetricValue,
|
|
266
|
+
filterType: FilterType.GreaterThan,
|
|
267
|
+
value: "1",
|
|
268
|
+
metricMonitorOptions: {
|
|
269
|
+
metricAlias: "a",
|
|
270
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
271
|
+
thresholdUnit: "sec",
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const inputs: ReturnType<typeof buildInputs> = buildInputs({
|
|
276
|
+
metricNativeUnit: "ms",
|
|
277
|
+
sampleValues: [500, 3000, 800],
|
|
278
|
+
criteriaFilter,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet(inputs);
|
|
282
|
+
|
|
283
|
+
expect(criteriaFilter.metricCriteriaContext?.breachingSample?.value).toBe(
|
|
284
|
+
3,
|
|
285
|
+
);
|
|
286
|
+
expect(criteriaFilter.metricCriteriaContext?.unit).toBe("sec");
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
test("collects every breaching sample and totalSamplesInWindow", async () => {
|
|
290
|
+
const criteriaFilter: CriteriaFilter = {
|
|
291
|
+
checkOn: CheckOn.MetricValue,
|
|
292
|
+
filterType: FilterType.GreaterThan,
|
|
293
|
+
value: "100",
|
|
294
|
+
metricMonitorOptions: {
|
|
295
|
+
metricAlias: "a",
|
|
296
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const inputs: ReturnType<typeof buildInputs> = buildInputs({
|
|
301
|
+
metricNativeUnit: "ms",
|
|
302
|
+
// 4 breach (>100), 1 does not
|
|
303
|
+
sampleValues: [120, 150, 80, 200, 300],
|
|
304
|
+
criteriaFilter,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet(inputs);
|
|
308
|
+
|
|
309
|
+
const ctx: NonNullable<CriteriaFilter["metricCriteriaContext"]> =
|
|
310
|
+
criteriaFilter.metricCriteriaContext!;
|
|
311
|
+
|
|
312
|
+
expect(ctx.totalSamplesInWindow).toBe(5);
|
|
313
|
+
expect(ctx.breachingSamples).toBeDefined();
|
|
314
|
+
expect(ctx.breachingSamples?.length).toBe(4);
|
|
315
|
+
expect(
|
|
316
|
+
ctx.breachingSamples?.map((s: { value: number }) => {
|
|
317
|
+
return s.value;
|
|
318
|
+
}),
|
|
319
|
+
).toEqual([120, 150, 200, 300]);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
test("formula criteria populates components and per-sample component values", async () => {
|
|
323
|
+
// Build two query configs (a: ms, b: ms) and a formula c = a + b (ms).
|
|
324
|
+
const sharedTimestamps: Array<Date> = [
|
|
325
|
+
new Date("2026-04-20T11:00:00.000Z"),
|
|
326
|
+
new Date("2026-04-20T11:01:00.000Z"),
|
|
327
|
+
];
|
|
328
|
+
|
|
329
|
+
const queryA: MetricQueryConfigData = {
|
|
330
|
+
metricAliasData: {
|
|
331
|
+
metricVariable: "a",
|
|
332
|
+
title: "",
|
|
333
|
+
description: "",
|
|
334
|
+
legend: "",
|
|
335
|
+
legendUnit: "ms",
|
|
336
|
+
},
|
|
337
|
+
metricQueryData: {
|
|
338
|
+
filterData: {
|
|
339
|
+
metricName: "request_latency",
|
|
340
|
+
},
|
|
341
|
+
} as unknown as MetricQueryData,
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
const queryB: MetricQueryConfigData = {
|
|
345
|
+
metricAliasData: {
|
|
346
|
+
metricVariable: "b",
|
|
347
|
+
title: "",
|
|
348
|
+
description: "",
|
|
349
|
+
legend: "",
|
|
350
|
+
legendUnit: "ms",
|
|
351
|
+
},
|
|
352
|
+
metricQueryData: {
|
|
353
|
+
filterData: {
|
|
354
|
+
metricName: "db_latency",
|
|
355
|
+
},
|
|
356
|
+
} as unknown as MetricQueryData,
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const formulaC: MetricFormulaConfigData = {
|
|
360
|
+
metricAliasData: {
|
|
361
|
+
metricVariable: "c",
|
|
362
|
+
title: "",
|
|
363
|
+
description: "",
|
|
364
|
+
legend: "",
|
|
365
|
+
legendUnit: "ms",
|
|
366
|
+
},
|
|
367
|
+
metricFormulaData: {
|
|
368
|
+
metricFormula: "a + b",
|
|
369
|
+
},
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
const queryAResult: AggregatedResult = {
|
|
373
|
+
data: [
|
|
374
|
+
{ timestamp: sharedTimestamps[0], value: 40 } as AggregateModel,
|
|
375
|
+
{ timestamp: sharedTimestamps[1], value: 60 } as AggregateModel,
|
|
376
|
+
],
|
|
377
|
+
};
|
|
378
|
+
const queryBResult: AggregatedResult = {
|
|
379
|
+
data: [
|
|
380
|
+
{ timestamp: sharedTimestamps[0], value: 70 } as AggregateModel,
|
|
381
|
+
{ timestamp: sharedTimestamps[1], value: 80 } as AggregateModel,
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
/*
|
|
386
|
+
* c = a + b, evaluated via the shared evaluator so the synthetic series
|
|
387
|
+
* matches the production code path exactly.
|
|
388
|
+
*/
|
|
389
|
+
const formulaCResult: AggregatedResult =
|
|
390
|
+
MetricFormulaEvaluator.evaluateFormula({
|
|
391
|
+
formula: "a + b",
|
|
392
|
+
queryConfigs: [queryA, queryB],
|
|
393
|
+
formulaConfigs: [],
|
|
394
|
+
results: [queryAResult, queryBResult],
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
const metricViewConfig: MetricsViewConfig = {
|
|
398
|
+
queryConfigs: [queryA, queryB],
|
|
399
|
+
formulaConfigs: [formulaC],
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const monitorStep: MonitorStep = new MonitorStep();
|
|
403
|
+
monitorStep.data = {
|
|
404
|
+
id: ObjectID.generate().toString(),
|
|
405
|
+
monitorCriteria: { data: undefined } as never,
|
|
406
|
+
} as unknown as MonitorStep["data"];
|
|
407
|
+
monitorStep.data!.metricMonitor = {
|
|
408
|
+
metricViewConfig,
|
|
409
|
+
rollingTime: RollingTime.Past1Minute,
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
const dataToProcess: MetricMonitorResponse = {
|
|
413
|
+
projectId: ObjectID.generate(),
|
|
414
|
+
metricResult: [queryAResult, queryBResult, formulaCResult],
|
|
415
|
+
metricViewConfig,
|
|
416
|
+
monitorId: ObjectID.generate(),
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
const criteriaFilter: CriteriaFilter = {
|
|
420
|
+
checkOn: CheckOn.MetricValue,
|
|
421
|
+
filterType: FilterType.GreaterThan,
|
|
422
|
+
value: "100",
|
|
423
|
+
metricMonitorOptions: {
|
|
424
|
+
metricAlias: "c",
|
|
425
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
426
|
+
},
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
|
|
430
|
+
criteriaFilter,
|
|
431
|
+
monitorStep,
|
|
432
|
+
dataToProcess,
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
const ctx: NonNullable<CriteriaFilter["metricCriteriaContext"]> =
|
|
436
|
+
criteriaFilter.metricCriteriaContext!;
|
|
437
|
+
|
|
438
|
+
expect(ctx.isFormula).toBe(true);
|
|
439
|
+
expect(ctx.formulaExpression).toBe("a + b");
|
|
440
|
+
|
|
441
|
+
// Components describe each formula variable with its source metric + unit.
|
|
442
|
+
expect(ctx.components).toBeDefined();
|
|
443
|
+
expect(ctx.components?.length).toBe(2);
|
|
444
|
+
expect(ctx.components?.[0]).toMatchObject({
|
|
445
|
+
alias: "a",
|
|
446
|
+
name: "request_latency",
|
|
447
|
+
unit: "ms",
|
|
448
|
+
isFormula: false,
|
|
449
|
+
});
|
|
450
|
+
expect(ctx.components?.[1]).toMatchObject({
|
|
451
|
+
alias: "b",
|
|
452
|
+
name: "db_latency",
|
|
453
|
+
unit: "ms",
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// Both formula points breach > 100 (40+70=110, 60+80=140).
|
|
457
|
+
expect(ctx.breachingSamples?.length).toBe(2);
|
|
458
|
+
const first: NonNullable<typeof ctx.breachingSamples>[number] =
|
|
459
|
+
ctx.breachingSamples![0]!;
|
|
460
|
+
expect(first.value).toBe(110);
|
|
461
|
+
expect(first.componentValues).toBeDefined();
|
|
462
|
+
expect(first.componentValues).toEqual([
|
|
463
|
+
{ alias: "a", value: 40 },
|
|
464
|
+
{ alias: "b", value: 70 },
|
|
465
|
+
]);
|
|
466
|
+
|
|
467
|
+
const second: NonNullable<typeof ctx.breachingSamples>[number] =
|
|
468
|
+
ctx.breachingSamples![1]!;
|
|
469
|
+
expect(second.value).toBe(140);
|
|
470
|
+
expect(second.componentValues).toEqual([
|
|
471
|
+
{ alias: "a", value: 60 },
|
|
472
|
+
{ alias: "b", value: 80 },
|
|
473
|
+
]);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
test("summarises Filter Conditions Met when more than 5 values breach", async () => {
|
|
477
|
+
const criteriaFilter: CriteriaFilter = {
|
|
478
|
+
checkOn: CheckOn.MetricValue,
|
|
479
|
+
filterType: FilterType.GreaterThan,
|
|
480
|
+
value: "100",
|
|
481
|
+
metricMonitorOptions: {
|
|
482
|
+
metricAlias: "a",
|
|
483
|
+
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
484
|
+
},
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
const inputs: ReturnType<typeof buildInputs> = buildInputs({
|
|
488
|
+
metricNativeUnit: "ms",
|
|
489
|
+
sampleValues: [110, 120, 130, 140, 150, 160, 170, 180, 190, 200],
|
|
490
|
+
criteriaFilter,
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
const message: string | null =
|
|
494
|
+
await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet(inputs);
|
|
495
|
+
|
|
496
|
+
expect(message).toBeTruthy();
|
|
497
|
+
expect(message).toContain("10 samples between 110 and 200");
|
|
498
|
+
expect(message).toContain("greater than 100 ms");
|
|
499
|
+
// The raw comma-joined dump is no longer in the message
|
|
500
|
+
expect(message).not.toContain("110, 120, 130, 140, 150, 160");
|
|
501
|
+
});
|
|
502
|
+
});
|