@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.
Files changed (210) hide show
  1. package/Models/DatabaseModels/DockerHostOwnerTeam.ts +464 -0
  2. package/Models/DatabaseModels/DockerHostOwnerUser.ts +463 -0
  3. package/Models/DatabaseModels/Index.ts +24 -0
  4. package/Models/DatabaseModels/KubernetesClusterOwnerTeam.ts +464 -0
  5. package/Models/DatabaseModels/KubernetesClusterOwnerUser.ts +463 -0
  6. package/Models/DatabaseModels/KubernetesResource.ts +548 -0
  7. package/Models/DatabaseModels/MetricPipelineRule.ts +804 -0
  8. package/Models/DatabaseModels/MetricRecordingRule.ts +470 -0
  9. package/Models/DatabaseModels/Monitor.ts +2 -0
  10. package/Models/DatabaseModels/Project.ts +53 -0
  11. package/Models/DatabaseModels/Service.ts +79 -0
  12. package/Models/DatabaseModels/TraceDropFilter.ts +508 -0
  13. package/Models/DatabaseModels/TracePipeline.ts +436 -0
  14. package/Models/DatabaseModels/TracePipelineProcessor.ts +454 -0
  15. package/Models/DatabaseModels/TraceRecordingRule.ts +470 -0
  16. package/Models/DatabaseModels/TraceScrubRule.ts +546 -0
  17. package/Server/API/KubernetesResourceAPI.ts +129 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1776504277320-MigrationName.ts +399 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1776505976155-AddTracePipelineTables.ts +205 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1776509413763-MigrationName.ts +335 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1776541018853-MigrationName.ts +29 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1776544084793-MigrationName.ts +53 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -1
  24. package/Server/Services/DockerHostOwnerTeamService.ts +10 -0
  25. package/Server/Services/DockerHostOwnerUserService.ts +10 -0
  26. package/Server/Services/KubernetesClusterOwnerTeamService.ts +10 -0
  27. package/Server/Services/KubernetesClusterOwnerUserService.ts +10 -0
  28. package/Server/Services/KubernetesResourceService.ts +351 -0
  29. package/Server/Services/MetricPipelineRuleService.ts +10 -0
  30. package/Server/Services/MetricRecordingRuleService.ts +10 -0
  31. package/Server/Services/TraceDropFilterService.ts +10 -0
  32. package/Server/Services/TracePipelineProcessorService.ts +10 -0
  33. package/Server/Services/TracePipelineService.ts +10 -0
  34. package/Server/Services/TraceRecordingRuleService.ts +10 -0
  35. package/Server/Services/TraceScrubRuleService.ts +10 -0
  36. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +71 -9
  37. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +483 -75
  38. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +379 -6
  39. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +502 -0
  40. package/Tests/Utils/MetricUnitUtil.test.ts +216 -0
  41. package/Tests/Utils/Metrics/MetricFormulaEvaluator.test.ts +269 -0
  42. package/Tests/Utils/Metrics/MetricResultUnitConverter.test.ts +231 -0
  43. package/Tests/Utils/RecordingRuleExpression.test.ts +177 -0
  44. package/Types/Kubernetes/KubernetesInventoryExtractor.ts +327 -0
  45. package/Types/Kubernetes/KubernetesObjectParser.ts +1949 -0
  46. package/Types/Metrics/MetricDownsamplingRetentionDays.ts +49 -0
  47. package/Types/Metrics/MetricFormulaConfigData.ts +4 -0
  48. package/Types/Metrics/MetricPipelineRuleFilterCondition.ts +136 -0
  49. package/Types/Metrics/MetricPipelineRuleType.ts +27 -0
  50. package/Types/Metrics/RecordingRuleDefinition.ts +180 -0
  51. package/Types/Monitor/CriteriaFilter.ts +43 -0
  52. package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +70 -0
  53. package/Types/Permission.ts +520 -0
  54. package/Types/Trace/TraceAggregationType.ts +17 -0
  55. package/Types/Trace/TraceDropFilterAction.ts +6 -0
  56. package/Types/Trace/TracePipelineProcessorType.ts +56 -0
  57. package/Types/Trace/TraceRecordingRuleDefinition.ts +218 -0
  58. package/Types/Trace/TraceScrubAction.ts +7 -0
  59. package/Types/Trace/TraceScrubField.ts +8 -0
  60. package/Types/Trace/TraceScrubPatternType.ts +10 -0
  61. package/UI/Components/CardSelect/CardSelect.tsx +9 -1
  62. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +6 -10
  63. package/UI/Components/Forms/Fields/FormField.tsx +1 -0
  64. package/UI/Components/Forms/Types/Field.ts +1 -0
  65. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +57 -0
  66. package/UI/Components/Page/Page.tsx +6 -0
  67. package/Utils/MetricUnitUtil.ts +289 -0
  68. package/Utils/Metrics/MetricFormulaEvaluator.ts +610 -0
  69. package/Utils/Metrics/MetricResultUnitConverter.ts +91 -0
  70. package/Utils/Metrics/RecordingRuleExpression.ts +359 -0
  71. package/Utils/ValueFormatter.ts +137 -13
  72. package/build/dist/Models/DatabaseModels/DockerHostOwnerTeam.js +480 -0
  73. package/build/dist/Models/DatabaseModels/DockerHostOwnerTeam.js.map +1 -0
  74. package/build/dist/Models/DatabaseModels/DockerHostOwnerUser.js +479 -0
  75. package/build/dist/Models/DatabaseModels/DockerHostOwnerUser.js.map +1 -0
  76. package/build/dist/Models/DatabaseModels/Index.js +24 -0
  77. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  78. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerTeam.js +480 -0
  79. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerTeam.js.map +1 -0
  80. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerUser.js +479 -0
  81. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerUser.js.map +1 -0
  82. package/build/dist/Models/DatabaseModels/KubernetesResource.js +590 -0
  83. package/build/dist/Models/DatabaseModels/KubernetesResource.js.map +1 -0
  84. package/build/dist/Models/DatabaseModels/MetricPipelineRule.js +836 -0
  85. package/build/dist/Models/DatabaseModels/MetricPipelineRule.js.map +1 -0
  86. package/build/dist/Models/DatabaseModels/MetricRecordingRule.js +497 -0
  87. package/build/dist/Models/DatabaseModels/MetricRecordingRule.js.map +1 -0
  88. package/build/dist/Models/DatabaseModels/Monitor.js +2 -0
  89. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  90. package/build/dist/Models/DatabaseModels/Project.js +53 -0
  91. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  92. package/build/dist/Models/DatabaseModels/Service.js +79 -0
  93. package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
  94. package/build/dist/Models/DatabaseModels/TraceDropFilter.js +536 -0
  95. package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -0
  96. package/build/dist/Models/DatabaseModels/TracePipeline.js +462 -0
  97. package/build/dist/Models/DatabaseModels/TracePipeline.js.map +1 -0
  98. package/build/dist/Models/DatabaseModels/TracePipelineProcessor.js +476 -0
  99. package/build/dist/Models/DatabaseModels/TracePipelineProcessor.js.map +1 -0
  100. package/build/dist/Models/DatabaseModels/TraceRecordingRule.js +497 -0
  101. package/build/dist/Models/DatabaseModels/TraceRecordingRule.js.map +1 -0
  102. package/build/dist/Models/DatabaseModels/TraceScrubRule.js +575 -0
  103. package/build/dist/Models/DatabaseModels/TraceScrubRule.js.map +1 -0
  104. package/build/dist/Server/API/KubernetesResourceAPI.js +98 -0
  105. package/build/dist/Server/API/KubernetesResourceAPI.js.map +1 -0
  106. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776504277320-MigrationName.js +144 -0
  107. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776504277320-MigrationName.js.map +1 -0
  108. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776505976155-AddTracePipelineTables.js +82 -0
  109. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776505976155-AddTracePipelineTables.js.map +1 -0
  110. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776509413763-MigrationName.js +118 -0
  111. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776509413763-MigrationName.js.map +1 -0
  112. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776541018853-MigrationName.js +16 -0
  113. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776541018853-MigrationName.js.map +1 -0
  114. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776544084793-MigrationName.js +24 -0
  115. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776544084793-MigrationName.js.map +1 -0
  116. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  117. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  118. package/build/dist/Server/Services/DockerHostOwnerTeamService.js +9 -0
  119. package/build/dist/Server/Services/DockerHostOwnerTeamService.js.map +1 -0
  120. package/build/dist/Server/Services/DockerHostOwnerUserService.js +9 -0
  121. package/build/dist/Server/Services/DockerHostOwnerUserService.js.map +1 -0
  122. package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js +9 -0
  123. package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js.map +1 -0
  124. package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js +9 -0
  125. package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js.map +1 -0
  126. package/build/dist/Server/Services/KubernetesResourceService.js +237 -0
  127. package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -0
  128. package/build/dist/Server/Services/MetricPipelineRuleService.js +9 -0
  129. package/build/dist/Server/Services/MetricPipelineRuleService.js.map +1 -0
  130. package/build/dist/Server/Services/MetricRecordingRuleService.js +9 -0
  131. package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -0
  132. package/build/dist/Server/Services/TraceDropFilterService.js +9 -0
  133. package/build/dist/Server/Services/TraceDropFilterService.js.map +1 -0
  134. package/build/dist/Server/Services/TracePipelineProcessorService.js +9 -0
  135. package/build/dist/Server/Services/TracePipelineProcessorService.js.map +1 -0
  136. package/build/dist/Server/Services/TracePipelineService.js +9 -0
  137. package/build/dist/Server/Services/TracePipelineService.js.map +1 -0
  138. package/build/dist/Server/Services/TraceRecordingRuleService.js +9 -0
  139. package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -0
  140. package/build/dist/Server/Services/TraceScrubRuleService.js +9 -0
  141. package/build/dist/Server/Services/TraceScrubRuleService.js.map +1 -0
  142. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +56 -9
  143. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  144. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +335 -53
  145. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
  146. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +277 -5
  147. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  148. package/build/dist/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.js +407 -0
  149. package/build/dist/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.js.map +1 -0
  150. package/build/dist/Tests/Utils/MetricUnitUtil.test.js +159 -0
  151. package/build/dist/Tests/Utils/MetricUnitUtil.test.js.map +1 -0
  152. package/build/dist/Tests/Utils/Metrics/MetricFormulaEvaluator.test.js +224 -0
  153. package/build/dist/Tests/Utils/Metrics/MetricFormulaEvaluator.test.js.map +1 -0
  154. package/build/dist/Tests/Utils/Metrics/MetricResultUnitConverter.test.js +180 -0
  155. package/build/dist/Tests/Utils/Metrics/MetricResultUnitConverter.test.js.map +1 -0
  156. package/build/dist/Tests/Utils/RecordingRuleExpression.test.js +142 -0
  157. package/build/dist/Tests/Utils/RecordingRuleExpression.test.js.map +1 -0
  158. package/build/dist/Types/Kubernetes/KubernetesInventoryExtractor.js +200 -0
  159. package/build/dist/Types/Kubernetes/KubernetesInventoryExtractor.js.map +1 -0
  160. package/build/dist/Types/Kubernetes/KubernetesObjectParser.js +1205 -0
  161. package/build/dist/Types/Kubernetes/KubernetesObjectParser.js.map +1 -0
  162. package/build/dist/Types/Metrics/MetricDownsamplingRetentionDays.js +32 -0
  163. package/build/dist/Types/Metrics/MetricDownsamplingRetentionDays.js.map +1 -0
  164. package/build/dist/Types/Metrics/MetricPipelineRuleFilterCondition.js +103 -0
  165. package/build/dist/Types/Metrics/MetricPipelineRuleFilterCondition.js.map +1 -0
  166. package/build/dist/Types/Metrics/MetricPipelineRuleType.js +27 -0
  167. package/build/dist/Types/Metrics/MetricPipelineRuleType.js.map +1 -0
  168. package/build/dist/Types/Metrics/RecordingRuleDefinition.js +110 -0
  169. package/build/dist/Types/Metrics/RecordingRuleDefinition.js.map +1 -0
  170. package/build/dist/Types/Monitor/CriteriaFilter.js +22 -0
  171. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  172. package/build/dist/Types/Monitor/MetricMonitor/MetricCriteriaContext.js +2 -0
  173. package/build/dist/Types/Monitor/MetricMonitor/MetricCriteriaContext.js.map +1 -0
  174. package/build/dist/Types/Permission.js +454 -0
  175. package/build/dist/Types/Permission.js.map +1 -1
  176. package/build/dist/Types/Trace/TraceAggregationType.js +18 -0
  177. package/build/dist/Types/Trace/TraceAggregationType.js.map +1 -0
  178. package/build/dist/Types/Trace/TraceDropFilterAction.js +7 -0
  179. package/build/dist/Types/Trace/TraceDropFilterAction.js.map +1 -0
  180. package/build/dist/Types/Trace/TracePipelineProcessorType.js +10 -0
  181. package/build/dist/Types/Trace/TracePipelineProcessorType.js.map +1 -0
  182. package/build/dist/Types/Trace/TraceRecordingRuleDefinition.js +145 -0
  183. package/build/dist/Types/Trace/TraceRecordingRuleDefinition.js.map +1 -0
  184. package/build/dist/Types/Trace/TraceScrubAction.js +8 -0
  185. package/build/dist/Types/Trace/TraceScrubAction.js.map +1 -0
  186. package/build/dist/Types/Trace/TraceScrubField.js +9 -0
  187. package/build/dist/Types/Trace/TraceScrubField.js.map +1 -0
  188. package/build/dist/Types/Trace/TraceScrubPatternType.js +11 -0
  189. package/build/dist/Types/Trace/TraceScrubPatternType.js.map +1 -0
  190. package/build/dist/UI/Components/CardSelect/CardSelect.js +3 -1
  191. package/build/dist/UI/Components/CardSelect/CardSelect.js.map +1 -1
  192. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +6 -9
  193. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  194. package/build/dist/UI/Components/Forms/Fields/FormField.js +1 -1
  195. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  196. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +30 -0
  197. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  198. package/build/dist/UI/Components/Page/Page.js +1 -0
  199. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  200. package/build/dist/Utils/MetricUnitUtil.js +232 -0
  201. package/build/dist/Utils/MetricUnitUtil.js.map +1 -0
  202. package/build/dist/Utils/Metrics/MetricFormulaEvaluator.js +453 -0
  203. package/build/dist/Utils/Metrics/MetricFormulaEvaluator.js.map +1 -0
  204. package/build/dist/Utils/Metrics/MetricResultUnitConverter.js +61 -0
  205. package/build/dist/Utils/Metrics/MetricResultUnitConverter.js.map +1 -0
  206. package/build/dist/Utils/Metrics/RecordingRuleExpression.js +298 -0
  207. package/build/dist/Utils/Metrics/RecordingRuleExpression.js.map +1 -0
  208. package/build/dist/Utils/ValueFormatter.js +123 -13
  209. package/build/dist/Utils/ValueFormatter.js.map +1 -1
  210. package/package.json +1 -1
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Per-tier retention (in days) for downsampled metric storage.
3
+ *
4
+ * On Project, this is the default that applies to all services.
5
+ * On Service, this is an optional override — null fields inherit from the project default.
6
+ *
7
+ * Keys are tier identifiers: "raw" (untouched OTel data points), "1m", "5m", "1h", "1d".
8
+ */
9
+
10
+ export default interface MetricDownsamplingRetentionDays {
11
+ raw?: number | null;
12
+ "1m"?: number | null;
13
+ "5m"?: number | null;
14
+ "1h"?: number | null;
15
+ "1d"?: number | null;
16
+ }
17
+
18
+ export const DEFAULT_METRIC_DOWNSAMPLING_RETENTION_DAYS: Record<
19
+ keyof MetricDownsamplingRetentionDays,
20
+ number
21
+ > = {
22
+ raw: 7,
23
+ "1m": 14,
24
+ "5m": 30,
25
+ "1h": 90,
26
+ "1d": 365,
27
+ };
28
+
29
+ export const DEFAULT_METRIC_CARDINALITY_BUDGET: number = 10000;
30
+
31
+ /*
32
+ * Resolves the effective retention days for a given tier, falling back through
33
+ * service override → project default → hardcoded default.
34
+ */
35
+ export function resolveTierRetentionDays(
36
+ tier: keyof MetricDownsamplingRetentionDays,
37
+ serviceOverride: MetricDownsamplingRetentionDays | null | undefined,
38
+ projectDefault: MetricDownsamplingRetentionDays | null | undefined,
39
+ ): number {
40
+ const serviceValue: number | null | undefined = serviceOverride?.[tier];
41
+ if (typeof serviceValue === "number" && serviceValue > 0) {
42
+ return serviceValue;
43
+ }
44
+ const projectValue: number | null | undefined = projectDefault?.[tier];
45
+ if (typeof projectValue === "number" && projectValue > 0) {
46
+ return projectValue;
47
+ }
48
+ return DEFAULT_METRIC_DOWNSAMPLING_RETENTION_DAYS[tier];
49
+ }
@@ -1,7 +1,11 @@
1
1
  import MetricAliasData from "./MetricAliasData";
2
2
  import MetricFormulaData from "./MetricFormulaData";
3
+ import { MetricChartType } from "./MetricQueryConfigData";
3
4
 
4
5
  export default interface MetricFormulaConfigData {
5
6
  metricAliasData: MetricAliasData;
6
7
  metricFormulaData: MetricFormulaData;
8
+ chartType?: MetricChartType | undefined;
9
+ warningThreshold?: number | undefined;
10
+ criticalThreshold?: number | undefined;
7
11
  }
@@ -0,0 +1,136 @@
1
+ export enum MetricPipelineRuleFilterCheckOn {
2
+ MetricName = "Metric Name",
3
+ Attribute = "Attribute",
4
+ }
5
+
6
+ export enum MetricPipelineRuleFilterConditionType {
7
+ EqualTo = "Equal To",
8
+ NotEqualTo = "Not Equal To",
9
+ Contains = "Contains",
10
+ NotContains = "Not Contains",
11
+ StartsWith = "Starts With",
12
+ EndsWith = "Ends With",
13
+ MatchesRegex = "Matches Regex",
14
+ DoesNotMatchRegex = "Does Not Match Regex",
15
+ IsPresent = "Is Present",
16
+ IsNotPresent = "Is Not Present",
17
+ IsEmpty = "Is Empty",
18
+ IsNotEmpty = "Is Not Empty",
19
+ }
20
+
21
+ export default interface MetricPipelineRuleFilterCondition {
22
+ checkOn: MetricPipelineRuleFilterCheckOn;
23
+ // Required when checkOn is Attribute. The attribute key to evaluate on.
24
+ attributeKey?: string | undefined;
25
+ conditionType: MetricPipelineRuleFilterConditionType | undefined;
26
+ // Required for conditions that compare against a value.
27
+ value?: string | undefined;
28
+ }
29
+
30
+ export class MetricPipelineRuleFilterConditionUtil {
31
+ public static getCheckOnOptions(): Array<MetricPipelineRuleFilterCheckOn> {
32
+ return [
33
+ MetricPipelineRuleFilterCheckOn.MetricName,
34
+ MetricPipelineRuleFilterCheckOn.Attribute,
35
+ ];
36
+ }
37
+
38
+ public static getConditionTypesByCheckOn(
39
+ checkOn: MetricPipelineRuleFilterCheckOn,
40
+ ): Array<MetricPipelineRuleFilterConditionType> {
41
+ switch (checkOn) {
42
+ case MetricPipelineRuleFilterCheckOn.MetricName:
43
+ return [
44
+ MetricPipelineRuleFilterConditionType.EqualTo,
45
+ MetricPipelineRuleFilterConditionType.NotEqualTo,
46
+ MetricPipelineRuleFilterConditionType.Contains,
47
+ MetricPipelineRuleFilterConditionType.NotContains,
48
+ MetricPipelineRuleFilterConditionType.StartsWith,
49
+ MetricPipelineRuleFilterConditionType.EndsWith,
50
+ MetricPipelineRuleFilterConditionType.MatchesRegex,
51
+ MetricPipelineRuleFilterConditionType.DoesNotMatchRegex,
52
+ ];
53
+ case MetricPipelineRuleFilterCheckOn.Attribute:
54
+ return [
55
+ MetricPipelineRuleFilterConditionType.IsPresent,
56
+ MetricPipelineRuleFilterConditionType.IsNotPresent,
57
+ MetricPipelineRuleFilterConditionType.IsEmpty,
58
+ MetricPipelineRuleFilterConditionType.IsNotEmpty,
59
+ MetricPipelineRuleFilterConditionType.EqualTo,
60
+ MetricPipelineRuleFilterConditionType.NotEqualTo,
61
+ MetricPipelineRuleFilterConditionType.Contains,
62
+ MetricPipelineRuleFilterConditionType.NotContains,
63
+ MetricPipelineRuleFilterConditionType.StartsWith,
64
+ MetricPipelineRuleFilterConditionType.EndsWith,
65
+ MetricPipelineRuleFilterConditionType.MatchesRegex,
66
+ MetricPipelineRuleFilterConditionType.DoesNotMatchRegex,
67
+ ];
68
+ default:
69
+ return [];
70
+ }
71
+ }
72
+
73
+ public static hasAttributeKeyField(
74
+ checkOn: MetricPipelineRuleFilterCheckOn,
75
+ ): boolean {
76
+ return checkOn === MetricPipelineRuleFilterCheckOn.Attribute;
77
+ }
78
+
79
+ public static hasValueField(
80
+ conditionType: MetricPipelineRuleFilterConditionType | undefined,
81
+ ): boolean {
82
+ if (!conditionType) {
83
+ return false;
84
+ }
85
+ switch (conditionType) {
86
+ case MetricPipelineRuleFilterConditionType.IsPresent:
87
+ case MetricPipelineRuleFilterConditionType.IsNotPresent:
88
+ case MetricPipelineRuleFilterConditionType.IsEmpty:
89
+ case MetricPipelineRuleFilterConditionType.IsNotEmpty:
90
+ return false;
91
+ default:
92
+ return true;
93
+ }
94
+ }
95
+
96
+ public static getValidationError(
97
+ filters: Array<MetricPipelineRuleFilterCondition> | undefined,
98
+ ): string | null {
99
+ if (!filters || filters.length === 0) {
100
+ return null;
101
+ }
102
+
103
+ for (let i: number = 0; i < filters.length; i++) {
104
+ const filter: MetricPipelineRuleFilterCondition = filters[i]!;
105
+ const prefix: string = `Filter #${i + 1}: `;
106
+
107
+ if (!filter.checkOn) {
108
+ return `${prefix}Filter type is required.`;
109
+ }
110
+
111
+ if (!filter.conditionType) {
112
+ return `${prefix}Condition is required.`;
113
+ }
114
+
115
+ if (
116
+ MetricPipelineRuleFilterConditionUtil.hasAttributeKeyField(
117
+ filter.checkOn,
118
+ ) &&
119
+ !filter.attributeKey?.trim()
120
+ ) {
121
+ return `${prefix}Attribute key is required.`;
122
+ }
123
+
124
+ if (
125
+ MetricPipelineRuleFilterConditionUtil.hasValueField(
126
+ filter.conditionType,
127
+ ) &&
128
+ !filter.value?.toString().trim()
129
+ ) {
130
+ return `${prefix}Value is required.`;
131
+ }
132
+ }
133
+
134
+ return null;
135
+ }
136
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Rule types for the metric ingest pipeline. Evaluated per data-point in
3
+ * OtelMetricsIngestService after buildMetricRow() and before the ClickHouse
4
+ * insert buffer.
5
+ *
6
+ * - Filter: keep only rows matching the match expression; drop others.
7
+ * - Drop: drop rows matching the match expression; keep others.
8
+ * - RenameMetric: rename the metric (row.name) from one string to another.
9
+ * - RenameAttribute: rename an attribute key (renameFromKey -> renameToKey).
10
+ * - AddAttribute: add an attribute (addAttributeKey = addAttributeValue).
11
+ * - RemoveAttribute: remove an attribute by key.
12
+ * - RedactAttribute: replace an attribute's value with redactReplacement.
13
+ * - Sample: keep `samplePercentage`% of matching rows; drop the rest.
14
+ */
15
+
16
+ enum MetricPipelineRuleType {
17
+ Filter = "Filter",
18
+ Drop = "Drop",
19
+ RenameMetric = "RenameMetric",
20
+ RenameAttribute = "RenameAttribute",
21
+ AddAttribute = "AddAttribute",
22
+ RemoveAttribute = "RemoveAttribute",
23
+ RedactAttribute = "RedactAttribute",
24
+ Sample = "Sample",
25
+ }
26
+
27
+ export default MetricPipelineRuleType;
@@ -0,0 +1,180 @@
1
+ import AggregationType from "../BaseDatabase/AggregationType";
2
+
3
+ /*
4
+ * A single source metric inside a Recording Rule. Each source is given an
5
+ * alphabetic alias (A, B, C, ...) that can be referenced from the rule's
6
+ * expression string. Aliases are case-sensitive and match /^[A-Z]$/ in v1.
7
+ */
8
+ export interface RecordingRuleSource {
9
+ alias: string;
10
+ metricName: string;
11
+ aggregationType: AggregationType;
12
+ // Optional pre-filter so you can say e.g. "A = sum(http.requests WHERE http.status_code_class = '5xx')".
13
+ filterAttributeKey?: string;
14
+ filterAttributeValue?: string;
15
+ }
16
+
17
+ /*
18
+ * Full stored definition of a Recording Rule. Persisted as a JSONB column on
19
+ * MetricRecordingRule so we don't have to migrate the Postgres schema every
20
+ * time we add a new field.
21
+ */
22
+ export default interface RecordingRuleDefinition {
23
+ sources: Array<RecordingRuleSource>;
24
+ /*
25
+ * Arithmetic expression in our simple DSL: operators + - * /, parentheses,
26
+ * numeric literals, and alias references. Example: "A / B * 100".
27
+ */
28
+ expression: string;
29
+ /*
30
+ * Optional attribute key to group source queries by and preserve on output
31
+ * rows. One derived data point per group per evaluation bucket.
32
+ */
33
+ groupByAttribute?: string;
34
+ }
35
+
36
+ /*
37
+ * Maximum number of source metrics per rule for v1. Kept small to bound the
38
+ * per-cron workload.
39
+ */
40
+ export const RECORDING_RULE_MAX_SOURCES: number = 4;
41
+
42
+ // Maximum expression length for v1. Prevents pathological parser input.
43
+ export const RECORDING_RULE_MAX_EXPRESSION_LENGTH: number = 500;
44
+
45
+ /*
46
+ * Alphabet used to generate source aliases. v1 caps at RECORDING_RULE_MAX_SOURCES
47
+ * so we never exceed the first few letters in practice.
48
+ */
49
+ const ALIAS_ALPHABET: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
50
+
51
+ const ALIAS_REGEX: RegExp = /^[A-Z]$/;
52
+
53
+ const EXPRESSION_REGEX: RegExp = /^[A-Z0-9+\-*/().\s]+$/;
54
+
55
+ export class RecordingRuleDefinitionUtil {
56
+ public static getAggregationOptions(): Array<{
57
+ value: AggregationType;
58
+ label: string;
59
+ }> {
60
+ return [
61
+ { value: AggregationType.Sum, label: "Sum" },
62
+ { value: AggregationType.Avg, label: "Average" },
63
+ { value: AggregationType.Count, label: "Count" },
64
+ { value: AggregationType.Min, label: "Minimum" },
65
+ { value: AggregationType.Max, label: "Maximum" },
66
+ ];
67
+ }
68
+
69
+ public static getNextAlias(
70
+ sources: Array<RecordingRuleSource> | undefined,
71
+ ): string {
72
+ const used: Set<string> = new Set<string>(
73
+ (sources || []).map((s: RecordingRuleSource) => {
74
+ return s.alias;
75
+ }),
76
+ );
77
+ for (const letter of ALIAS_ALPHABET) {
78
+ if (!used.has(letter)) {
79
+ return letter;
80
+ }
81
+ }
82
+ return "A";
83
+ }
84
+
85
+ public static getEmptyDefinition(): RecordingRuleDefinition {
86
+ return {
87
+ sources: [
88
+ {
89
+ alias: "A",
90
+ metricName: "",
91
+ aggregationType: AggregationType.Sum,
92
+ },
93
+ ],
94
+ expression: "A",
95
+ groupByAttribute: "",
96
+ };
97
+ }
98
+
99
+ public static getValidationError(
100
+ definition: RecordingRuleDefinition | undefined,
101
+ ): string | null {
102
+ if (!definition) {
103
+ return "Definition is required.";
104
+ }
105
+
106
+ const sources: Array<RecordingRuleSource> = definition.sources || [];
107
+
108
+ if (sources.length === 0) {
109
+ return "Add at least one source metric.";
110
+ }
111
+
112
+ if (sources.length > RECORDING_RULE_MAX_SOURCES) {
113
+ return `A rule can reference at most ${RECORDING_RULE_MAX_SOURCES} source metrics.`;
114
+ }
115
+
116
+ const aliases: Set<string> = new Set<string>();
117
+ for (let i: number = 0; i < sources.length; i++) {
118
+ const source: RecordingRuleSource = sources[i]!;
119
+ const prefix: string = `Source ${source.alias || `#${i + 1}`}: `;
120
+
121
+ if (!source.alias || !ALIAS_REGEX.test(source.alias)) {
122
+ return `${prefix}Alias must be a single uppercase letter A-Z.`;
123
+ }
124
+
125
+ if (aliases.has(source.alias)) {
126
+ return `${prefix}Duplicate alias. Each source must have a unique letter.`;
127
+ }
128
+ aliases.add(source.alias);
129
+
130
+ if (!source.metricName?.trim()) {
131
+ return `${prefix}Metric name is required.`;
132
+ }
133
+
134
+ if (!source.aggregationType) {
135
+ return `${prefix}Aggregation type is required.`;
136
+ }
137
+
138
+ const hasFilterKey: boolean = Boolean(source.filterAttributeKey?.trim());
139
+ const hasFilterValue: boolean = Boolean(
140
+ source.filterAttributeValue?.trim(),
141
+ );
142
+
143
+ if (hasFilterKey !== hasFilterValue) {
144
+ return `${prefix}Attribute filter needs both a key and a value (or leave both empty).`;
145
+ }
146
+ }
147
+
148
+ const expression: string = (definition.expression || "").trim();
149
+
150
+ if (!expression) {
151
+ return "Expression is required.";
152
+ }
153
+
154
+ if (expression.length > RECORDING_RULE_MAX_EXPRESSION_LENGTH) {
155
+ return `Expression must be ${RECORDING_RULE_MAX_EXPRESSION_LENGTH} characters or fewer.`;
156
+ }
157
+
158
+ // Expression may only use aliases defined in sources.
159
+ const referencedAliases: Set<string> = new Set<string>(
160
+ expression.match(/[A-Z]/g) || [],
161
+ );
162
+ for (const alias of referencedAliases) {
163
+ if (!aliases.has(alias)) {
164
+ return `Expression references alias '${alias}' which is not defined in sources.`;
165
+ }
166
+ }
167
+
168
+ // Must reference at least one alias — otherwise the expression is a constant.
169
+ if (referencedAliases.size === 0) {
170
+ return "Expression must reference at least one source alias (e.g. A, B).";
171
+ }
172
+
173
+ // Reject any character outside the allowed DSL grammar.
174
+ if (!EXPRESSION_REGEX.test(expression)) {
175
+ return "Expression may only contain aliases (A-Z), numbers, operators (+ - * /), parentheses, and spaces.";
176
+ }
177
+
178
+ return null;
179
+ }
180
+ }
@@ -1,4 +1,5 @@
1
1
  import Zod, { ZodSchema } from "../../Utils/Schema/Zod";
2
+ import MetricCriteriaContext from "./MetricMonitor/MetricCriteriaContext";
2
3
 
3
4
  export enum CheckOn {
4
5
  ResponseTime = "Response Time (in ms)",
@@ -103,9 +104,42 @@ export enum EvaluateOverTimeType {
103
104
  AnyValue = "Any Value",
104
105
  }
105
106
 
107
+ export enum NoDataPolicy {
108
+ /*
109
+ * Do not treat missing data as a breach. The criterion simply does
110
+ * not fire. This is the safest default and matches most SaaS tooling.
111
+ */
112
+ Ignore = "Ignore",
113
+ /*
114
+ * Treat missing data points as zero. Preserves the original behavior
115
+ * prior to this policy being configurable — useful for counters where
116
+ * "no events" genuinely means zero.
117
+ */
118
+ TreatAsZero = "Treat As Zero",
119
+ /*
120
+ * Trigger the criterion as a breach regardless of threshold. Use for
121
+ * heartbeat-style metrics where the absence of data is itself the
122
+ * problem.
123
+ */
124
+ Trigger = "Trigger",
125
+ }
126
+
106
127
  export interface MetricMonitorOptions {
107
128
  metricAlias?: string | undefined;
108
129
  metricAggregationType?: EvaluateOverTimeType | undefined;
130
+ /*
131
+ * Governs how the evaluator handles the case where the metric query
132
+ * returned zero samples in the evaluation window. Defaults to Ignore
133
+ * when unset.
134
+ */
135
+ onNoDataPolicy?: NoDataPolicy | undefined;
136
+ /*
137
+ * Unit the user entered the threshold value in (e.g. "MB", "sec").
138
+ * The evaluator converts the threshold into the metric's native unit
139
+ * before comparison. When unset, the threshold is assumed to already
140
+ * be in the metric's native unit (backward compatible).
141
+ */
142
+ thresholdUnit?: string | undefined;
109
143
  }
110
144
 
111
145
  export enum EvaluateOverTimeMinutes {
@@ -134,6 +168,13 @@ export interface CriteriaFilter {
134
168
  value: string | number | undefined;
135
169
  evaluateOverTime?: boolean | undefined;
136
170
  evaluateOverTimeOptions?: EvaluateOverTimeOptions | undefined;
171
+ /*
172
+ * Populated at evaluation time for metric monitors so downstream code
173
+ * (e.g. the root cause builder) can include metric-specific context
174
+ * like metric name, unit, filter/group-by attributes, and the series
175
+ * that actually breached. Not persisted.
176
+ */
177
+ metricCriteriaContext?: MetricCriteriaContext | undefined;
137
178
  }
138
179
 
139
180
  export enum FilterType {
@@ -274,6 +315,8 @@ export const CriteriaFilterSchema: ZodSchema = Zod.object({
274
315
  metricMonitorOptions: Zod.object({
275
316
  metricAlias: Zod.string().optional(),
276
317
  metricAggregationType: Zod.string().optional(),
318
+ onNoDataPolicy: Zod.string().optional(),
319
+ thresholdUnit: Zod.string().optional(),
277
320
  }).optional(),
278
321
  snmpMonitorOptions: Zod.object({
279
322
  oid: Zod.string().optional(),
@@ -0,0 +1,70 @@
1
+ import { JSONObject } from "../../JSON";
2
+ import MetricsAggregationType from "../../Metrics/MetricsAggregationType";
3
+
4
+ /**
5
+ * A per-timestamp snapshot of a variable referenced by a formula —
6
+ * used to show "what did $a and $b evaluate to when c breached?" on the
7
+ * incident root-cause page.
8
+ */
9
+ export interface MetricComponentValue {
10
+ alias: string;
11
+ value: number | null;
12
+ }
13
+
14
+ export interface MetricBreachingSample {
15
+ value: number;
16
+ timestamp: Date;
17
+ attributes: JSONObject;
18
+ /**
19
+ * For formula evaluations: the values of each referenced variable at
20
+ * this timestamp. Keyed by variable alias. Absent for plain metric
21
+ * criteria.
22
+ */
23
+ componentValues?: Array<MetricComponentValue> | undefined;
24
+ }
25
+
26
+ /**
27
+ * Descriptor for one variable referenced by a formula, used to label
28
+ * table columns and render the Metric Details section. Name is the
29
+ * metric display name (usually the metric name, sometimes the formula
30
+ * expression for nested formulas) and unit is the variable's native
31
+ * unit as configured.
32
+ */
33
+ export interface MetricComponent {
34
+ alias: string;
35
+ name: string;
36
+ unit: string | null;
37
+ isFormula: boolean;
38
+ }
39
+
40
+ export default interface MetricCriteriaContext {
41
+ metricName: string;
42
+ alias: string;
43
+ unit: string | null;
44
+ aggregationType: MetricsAggregationType | null;
45
+ isFormula: boolean;
46
+ formulaExpression?: string | undefined;
47
+ filterAttributes: JSONObject;
48
+ groupBy: Array<string>;
49
+ timeWindowMinutes?: number | undefined;
50
+ breachingSample?: MetricBreachingSample | undefined;
51
+ /**
52
+ * All samples in the evaluation window that breached the threshold,
53
+ * in chronological order. Used to render a table of timestamps and
54
+ * values on the incident root-cause page.
55
+ */
56
+ breachingSamples?: Array<MetricBreachingSample> | undefined;
57
+ /**
58
+ * Total number of samples considered during evaluation (including
59
+ * non-breaching ones), so the root cause can show "N of M samples
60
+ * breached" without re-querying.
61
+ */
62
+ totalSamplesInWindow?: number | undefined;
63
+ /**
64
+ * For formulas: metadata for each variable the formula references,
65
+ * in the order they appear in the expression. Consumers use this to
66
+ * label breakdown columns and to surface underlying units/metric
67
+ * names in the Metric Details section.
68
+ */
69
+ components?: Array<MetricComponent> | undefined;
70
+ }