@miragon/pulse-analytics-client 0.0.0-bootstrap.0 → 0.21.0

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 (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -3
  3. package/dist/index.d.ts +12 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +14 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/metric-names.d.ts +43 -0
  8. package/dist/metric-names.d.ts.map +1 -0
  9. package/dist/metric-names.js +53 -0
  10. package/dist/metric-names.js.map +1 -0
  11. package/dist/metrics-contract-labels.test.d.ts +2 -0
  12. package/dist/metrics-contract-labels.test.d.ts.map +1 -0
  13. package/dist/metrics-contract-labels.test.js +169 -0
  14. package/dist/metrics-contract-labels.test.js.map +1 -0
  15. package/dist/metrics-contract.test.d.ts +2 -0
  16. package/dist/metrics-contract.test.d.ts.map +1 -0
  17. package/dist/metrics-contract.test.js +247 -0
  18. package/dist/metrics-contract.test.js.map +1 -0
  19. package/dist/prometheus-client.test.d.ts +2 -0
  20. package/dist/prometheus-client.test.d.ts.map +1 -0
  21. package/dist/prometheus-client.test.js +265 -0
  22. package/dist/prometheus-client.test.js.map +1 -0
  23. package/dist/prometheus.d.ts +100 -0
  24. package/dist/prometheus.d.ts.map +1 -0
  25. package/dist/prometheus.js +295 -0
  26. package/dist/prometheus.js.map +1 -0
  27. package/dist/prometheus.test.d.ts +2 -0
  28. package/dist/prometheus.test.d.ts.map +1 -0
  29. package/dist/prometheus.test.js +54 -0
  30. package/dist/prometheus.test.js.map +1 -0
  31. package/dist/promql-labels.test-support.d.ts +53 -0
  32. package/dist/promql-labels.test-support.d.ts.map +1 -0
  33. package/dist/promql-labels.test-support.js +237 -0
  34. package/dist/promql-labels.test-support.js.map +1 -0
  35. package/dist/promql-labels.test.d.ts +2 -0
  36. package/dist/promql-labels.test.d.ts.map +1 -0
  37. package/dist/promql-labels.test.js +190 -0
  38. package/dist/promql-labels.test.js.map +1 -0
  39. package/dist/promql-parse.test-support.d.ts +57 -0
  40. package/dist/promql-parse.test-support.d.ts.map +1 -0
  41. package/dist/promql-parse.test-support.js +284 -0
  42. package/dist/promql-parse.test-support.js.map +1 -0
  43. package/dist/promql-reading-rules.test-support.d.ts +29 -0
  44. package/dist/promql-reading-rules.test-support.d.ts.map +1 -0
  45. package/dist/promql-reading-rules.test-support.js +79 -0
  46. package/dist/promql-reading-rules.test-support.js.map +1 -0
  47. package/dist/promql-reading-rules.test.d.ts +2 -0
  48. package/dist/promql-reading-rules.test.d.ts.map +1 -0
  49. package/dist/promql-reading-rules.test.js +61 -0
  50. package/dist/promql-reading-rules.test.js.map +1 -0
  51. package/dist/promql-sources.test-support.d.ts +29 -0
  52. package/dist/promql-sources.test-support.d.ts.map +1 -0
  53. package/dist/promql-sources.test-support.js +112 -0
  54. package/dist/promql-sources.test-support.js.map +1 -0
  55. package/dist/promql-sources.test.d.ts +2 -0
  56. package/dist/promql-sources.test.d.ts.map +1 -0
  57. package/dist/promql-sources.test.js +93 -0
  58. package/dist/promql-sources.test.js.map +1 -0
  59. package/dist/queries/as-of.test.d.ts +2 -0
  60. package/dist/queries/as-of.test.d.ts.map +1 -0
  61. package/dist/queries/as-of.test.js +80 -0
  62. package/dist/queries/as-of.test.js.map +1 -0
  63. package/dist/queries/cluster-compare.d.ts +62 -0
  64. package/dist/queries/cluster-compare.d.ts.map +1 -0
  65. package/dist/queries/cluster-compare.js +70 -0
  66. package/dist/queries/cluster-compare.js.map +1 -0
  67. package/dist/queries/cluster-compare.test.d.ts +2 -0
  68. package/dist/queries/cluster-compare.test.d.ts.map +1 -0
  69. package/dist/queries/cluster-compare.test.js +81 -0
  70. package/dist/queries/cluster-compare.test.js.map +1 -0
  71. package/dist/queries/dashboard.d.ts +60 -0
  72. package/dist/queries/dashboard.d.ts.map +1 -0
  73. package/dist/queries/dashboard.js +292 -0
  74. package/dist/queries/dashboard.js.map +1 -0
  75. package/dist/queries/dashboard.test.d.ts +2 -0
  76. package/dist/queries/dashboard.test.d.ts.map +1 -0
  77. package/dist/queries/dashboard.test.js +423 -0
  78. package/dist/queries/dashboard.test.js.map +1 -0
  79. package/dist/queries/element.d.ts +68 -0
  80. package/dist/queries/element.d.ts.map +1 -0
  81. package/dist/queries/element.js +98 -0
  82. package/dist/queries/element.js.map +1 -0
  83. package/dist/queries/element.test.d.ts +2 -0
  84. package/dist/queries/element.test.d.ts.map +1 -0
  85. package/dist/queries/element.test.js +105 -0
  86. package/dist/queries/element.test.js.map +1 -0
  87. package/dist/queries/engine-compare.d.ts +52 -0
  88. package/dist/queries/engine-compare.d.ts.map +1 -0
  89. package/dist/queries/engine-compare.js +57 -0
  90. package/dist/queries/engine-compare.js.map +1 -0
  91. package/dist/queries/engine-compare.test.d.ts +2 -0
  92. package/dist/queries/engine-compare.test.d.ts.map +1 -0
  93. package/dist/queries/engine-compare.test.js +159 -0
  94. package/dist/queries/engine-compare.test.js.map +1 -0
  95. package/dist/queries/engine-landscape.d.ts +92 -0
  96. package/dist/queries/engine-landscape.d.ts.map +1 -0
  97. package/dist/queries/engine-landscape.js +183 -0
  98. package/dist/queries/engine-landscape.js.map +1 -0
  99. package/dist/queries/engine-landscape.test.d.ts +2 -0
  100. package/dist/queries/engine-landscape.test.d.ts.map +1 -0
  101. package/dist/queries/engine-landscape.test.js +171 -0
  102. package/dist/queries/engine-landscape.test.js.map +1 -0
  103. package/dist/queries/failures.d.ts +33 -0
  104. package/dist/queries/failures.d.ts.map +1 -0
  105. package/dist/queries/failures.js +31 -0
  106. package/dist/queries/failures.js.map +1 -0
  107. package/dist/queries/health.d.ts +77 -0
  108. package/dist/queries/health.d.ts.map +1 -0
  109. package/dist/queries/health.js +126 -0
  110. package/dist/queries/health.js.map +1 -0
  111. package/dist/queries/health.test.d.ts +2 -0
  112. package/dist/queries/health.test.d.ts.map +1 -0
  113. package/dist/queries/health.test.js +187 -0
  114. package/dist/queries/health.test.js.map +1 -0
  115. package/dist/queries/helpers.d.ts +184 -0
  116. package/dist/queries/helpers.d.ts.map +1 -0
  117. package/dist/queries/helpers.js +219 -0
  118. package/dist/queries/helpers.js.map +1 -0
  119. package/dist/queries/helpers.test.d.ts +2 -0
  120. package/dist/queries/helpers.test.d.ts.map +1 -0
  121. package/dist/queries/helpers.test.js +53 -0
  122. package/dist/queries/helpers.test.js.map +1 -0
  123. package/dist/queries/index.d.ts +19 -0
  124. package/dist/queries/index.d.ts.map +1 -0
  125. package/dist/queries/index.js +10 -0
  126. package/dist/queries/index.js.map +1 -0
  127. package/dist/queries/performance.d.ts +103 -0
  128. package/dist/queries/performance.d.ts.map +1 -0
  129. package/dist/queries/performance.js +173 -0
  130. package/dist/queries/performance.js.map +1 -0
  131. package/dist/queries/performance.test.d.ts +2 -0
  132. package/dist/queries/performance.test.d.ts.map +1 -0
  133. package/dist/queries/performance.test.js +265 -0
  134. package/dist/queries/performance.test.js.map +1 -0
  135. package/dist/queries/version-compare.d.ts +41 -0
  136. package/dist/queries/version-compare.d.ts.map +1 -0
  137. package/dist/queries/version-compare.js +44 -0
  138. package/dist/queries/version-compare.js.map +1 -0
  139. package/dist/queries/version-compare.test.d.ts +2 -0
  140. package/dist/queries/version-compare.test.d.ts.map +1 -0
  141. package/dist/queries/version-compare.test.js +162 -0
  142. package/dist/queries/version-compare.test.js.map +1 -0
  143. package/dist/queries/windows.d.ts +40 -0
  144. package/dist/queries/windows.d.ts.map +1 -0
  145. package/dist/queries/windows.js +56 -0
  146. package/dist/queries/windows.js.map +1 -0
  147. package/dist/query-honesty.test.d.ts +2 -0
  148. package/dist/query-honesty.test.d.ts.map +1 -0
  149. package/dist/query-honesty.test.js +294 -0
  150. package/dist/query-honesty.test.js.map +1 -0
  151. package/dist/query-scenarios.test-support.d.ts +49 -0
  152. package/dist/query-scenarios.test-support.d.ts.map +1 -0
  153. package/dist/query-scenarios.test-support.js +146 -0
  154. package/dist/query-scenarios.test-support.js.map +1 -0
  155. package/dist/schemas/cluster-compare.d.ts +11 -0
  156. package/dist/schemas/cluster-compare.d.ts.map +1 -0
  157. package/dist/schemas/cluster-compare.js +35 -0
  158. package/dist/schemas/cluster-compare.js.map +1 -0
  159. package/dist/schemas/engine-compare.d.ts +10 -0
  160. package/dist/schemas/engine-compare.d.ts.map +1 -0
  161. package/dist/schemas/engine-compare.js +27 -0
  162. package/dist/schemas/engine-compare.js.map +1 -0
  163. package/dist/schemas/engine-landscape.d.ts +5 -0
  164. package/dist/schemas/engine-landscape.d.ts.map +1 -0
  165. package/dist/schemas/engine-landscape.js +8 -0
  166. package/dist/schemas/engine-landscape.js.map +1 -0
  167. package/dist/schemas/failures.d.ts +8 -0
  168. package/dist/schemas/failures.d.ts.map +1 -0
  169. package/dist/schemas/failures.js +9 -0
  170. package/dist/schemas/failures.js.map +1 -0
  171. package/dist/schemas/health.d.ts +5 -0
  172. package/dist/schemas/health.d.ts.map +1 -0
  173. package/dist/schemas/health.js +6 -0
  174. package/dist/schemas/health.js.map +1 -0
  175. package/dist/schemas/index.d.ts +10 -0
  176. package/dist/schemas/index.d.ts.map +1 -0
  177. package/dist/schemas/index.js +10 -0
  178. package/dist/schemas/index.js.map +1 -0
  179. package/dist/schemas/path.d.ts +15 -0
  180. package/dist/schemas/path.d.ts.map +1 -0
  181. package/dist/schemas/path.js +21 -0
  182. package/dist/schemas/path.js.map +1 -0
  183. package/dist/schemas/performance.d.ts +23 -0
  184. package/dist/schemas/performance.d.ts.map +1 -0
  185. package/dist/schemas/performance.js +21 -0
  186. package/dist/schemas/performance.js.map +1 -0
  187. package/dist/schemas/shared.d.ts +34 -0
  188. package/dist/schemas/shared.d.ts.map +1 -0
  189. package/dist/schemas/shared.js +34 -0
  190. package/dist/schemas/shared.js.map +1 -0
  191. package/dist/schemas/version-compare.d.ts +10 -0
  192. package/dist/schemas/version-compare.d.ts.map +1 -0
  193. package/dist/schemas/version-compare.js +25 -0
  194. package/dist/schemas/version-compare.js.map +1 -0
  195. package/dist/widgets.d.ts +138 -0
  196. package/dist/widgets.d.ts.map +1 -0
  197. package/dist/widgets.js +2 -0
  198. package/dist/widgets.js.map +1 -0
  199. package/metrics-contract.json +174 -0
  200. package/package.json +72 -5
@@ -0,0 +1,126 @@
1
+ import { engineIdsOf, engineMatcher, selector, } from "../prometheus.js";
2
+ import { METRIC_NAMES as M } from "../metric-names.js";
3
+ import { engineState, reportingEnginesQuery } from "./helpers.js";
4
+ /**
5
+ * Name pattern (RE2) of the alert rules this module ships
6
+ * (`playground/docker/prometheus/alerts.yml`). An alert WITHOUT an
7
+ * `engine_id` label — a pipeline-level rule such as `CibSevenEngineNoMetrics`
8
+ * — only counts when it matches this pattern: in a shared Prometheus every
9
+ * other engine-less alert belongs to somebody else.
10
+ */
11
+ export const ENGINE_ALERT_NAME_PATTERN = "CibSeven.+";
12
+ /**
13
+ * How {@link engineHealth} decides `status`, in words — carried in every
14
+ * result (`statusRule`) and the tool description, so no reader mistakes this
15
+ * alert-based verdict for camunda7_show_engine_health's incident-count one:
16
+ * the two judge different data by different rules and may disagree for the
17
+ * same engine (500 open incidents without a firing critical alert stay
18
+ * "degraded" here).
19
+ */
20
+ export const ENGINE_HEALTH_STATUS_RULE = "From Prometheus, over the engines in scope: unknown when none of them reports metrics; critical only while a severity=critical alert fires for them (fleet-wide also an engine-less CibSeven* alert); degraded with any such firing alert, dead job, open incident or an engine in scope that reports nothing; else healthy.";
21
+ const first = (s) => (s.length ? Math.round(s[0].value) : 0);
22
+ const total = (s) => Math.round(s.reduce((sum, x) => sum + x.value, 0));
23
+ function counts(samples, label) {
24
+ return samples
25
+ .map((s) => ({ label: s.metric[label] ?? "", count: Math.round(s.value) }))
26
+ .filter((c) => c.count !== 0)
27
+ .sort((a, b) => b.count - a.count);
28
+ }
29
+ function alerts(samples) {
30
+ return samples.map((s) => ({
31
+ name: s.metric.alertname ?? "",
32
+ severity: s.metric.severity ?? "",
33
+ scope: s.metric.process_definition_key ?? s.metric.incident_type ?? s.metric.engine_id ?? "",
34
+ }));
35
+ }
36
+ /**
37
+ * The `ALERTS` selection for one alert state. With an engine scope: the
38
+ * alerts carrying one of its `engine_id`s, plus — only for a fleet-wide
39
+ * verdict — this module's engine-less rules. Without one: this module's
40
+ * rules only.
41
+ */
42
+ function alertsQuery(state, engine, includeFleetAlerts) {
43
+ const own = `alertname=~"${ENGINE_ALERT_NAME_PATTERN}"`;
44
+ const stateMatcher = `alertstate="${state}"`;
45
+ const engineSel = engineMatcher(engine);
46
+ if (!engineSel)
47
+ return `ALERTS${selector(stateMatcher, own)}`;
48
+ const scoped = `ALERTS${selector(stateMatcher, engineSel)}`;
49
+ return includeFleetAlerts
50
+ ? `${scoped} or ALERTS${selector(stateMatcher, own, `engine_id=""`)}`
51
+ : scoped;
52
+ }
53
+ /**
54
+ * Live operational health of the engine(s), from the point-in-time gauges plus
55
+ * Prometheus' own `ALERTS` series. A one-call ops snapshot: running WIP, open
56
+ * incidents, dead jobs, job/task/external-task backlog, and which alert rules
57
+ * are firing/pending.
58
+ *
59
+ * Absence is not health: the engine-only gauges (`jobs_executable`,
60
+ * `external_tasks_open`) double as the presence probe, so an engine that
61
+ * sends nothing — or an id that matches no series — reads `unknown` (none in
62
+ * scope reports) or lands in `silentEngines` (degrading the verdict), never
63
+ * `healthy`. `includeFleetAlerts` (default: exactly when `engine` is
64
+ * omitted) adds the module's engine-less alerts — set it when `engine` lists
65
+ * the whole configured fleet.
66
+ */
67
+ export async function engineHealth(ch, params) {
68
+ const sel = selector(engineMatcher(params.engine));
69
+ const fleet = params.includeFleetAlerts ?? engineIdsOf(params.engine) === null;
70
+ const [runningByDef, incidentsByType, deadJobs, executableByEngine, suspendedJobs, openTasks, unassignedTasks, externalByEngine, deployedKeys, firing, pending,] = await Promise.all([
71
+ ch.instant(`sum by (process_definition_key)(${engineState(M.processInstancesRunning, sel)})`),
72
+ ch.instant(`sum by (incident_type)(${engineState(M.incidentsOpen, sel)})`),
73
+ ch.instant(`sum(${engineState(M.jobsFailed, sel)})`),
74
+ ch.instant(reportingEnginesQuery(sel)),
75
+ ch.instant(`sum(${engineState(M.jobsSuspended, sel)})`),
76
+ ch.instant(`sum(${engineState(M.userTasksOpen, selector(`status="total"`, engineMatcher(params.engine)))})`),
77
+ ch.instant(`sum(${engineState(M.userTasksOpen, selector(`status="unassigned"`, engineMatcher(params.engine)))})`),
78
+ ch.instant(engineState(M.externalTasksOpen, sel)),
79
+ // Distinct keys, not series: a key deployed on two engines counts once.
80
+ ch.instant(`count(count by (process_definition_key)(${engineState(M.processDefinitionsDeployed, sel)}))`),
81
+ ch.instant(alertsQuery("firing", params.engine, fleet)),
82
+ ch.instant(alertsQuery("pending", params.engine, fleet)),
83
+ ]);
84
+ const runningByDefinition = counts(runningByDef, "process_definition_key");
85
+ const openIncidentsByType = counts(incidentsByType, "incident_type");
86
+ const firingAlerts = alerts(firing);
87
+ const pendingAlerts = alerts(pending);
88
+ const openIncidents = openIncidentsByType.reduce((s, c) => s + c.count, 0);
89
+ const runningInstances = runningByDefinition.reduce((s, c) => s + c.count, 0);
90
+ const dead = first(deadJobs);
91
+ const engines = engineIdsOf(params.engine);
92
+ const reportingEngines = [
93
+ ...new Set([...executableByEngine, ...externalByEngine]
94
+ .map((s) => s.metric.engine_id)
95
+ .filter((id) => !!id)),
96
+ ].sort();
97
+ const silentEngines = (engines ?? []).filter((id) => !reportingEngines.includes(id));
98
+ const status = reportingEngines.length === 0
99
+ ? "unknown"
100
+ : firingAlerts.some((a) => a.severity === "critical")
101
+ ? "critical"
102
+ : firingAlerts.length > 0 || dead > 0 || openIncidents > 0 || silentEngines.length > 0
103
+ ? "degraded"
104
+ : "healthy";
105
+ return {
106
+ status,
107
+ statusRule: ENGINE_HEALTH_STATUS_RULE,
108
+ engines,
109
+ reportingEngines,
110
+ silentEngines,
111
+ runningInstances,
112
+ runningByDefinition,
113
+ openIncidents,
114
+ openIncidentsByType,
115
+ deadJobs: dead,
116
+ executableJobs: total(executableByEngine),
117
+ suspendedJobs: first(suspendedJobs),
118
+ openUserTasks: first(openTasks),
119
+ unassignedUserTasks: first(unassignedTasks),
120
+ openExternalTasks: total(externalByEngine),
121
+ deployedDefinitionKeys: first(deployedKeys),
122
+ firingAlerts,
123
+ pendingAlerts,
124
+ };
125
+ }
126
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/queries/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=health.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.test.d.ts","sourceRoot":"","sources":["../../src/queries/health.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,187 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { ENGINE_HEALTH_STATUS_RULE, engineHealth } from "./health.js";
3
+ const sample = (metric, value) => ({ metric, value });
4
+ /** Answers each gauge by its metric name; ALERTS by its alertstate. */
5
+ function mockClient(fixture = {}) {
6
+ const scalar = (value) => (value === undefined ? [] : [sample({}, value)]);
7
+ const perEngine = (value) => (fixture.reporting ?? ["prod-a"]).map((engine_id) => sample({ engine_id }, value));
8
+ const instant = vi.fn(async (q) => {
9
+ if (q.startsWith("ALERTS")) {
10
+ return (q.includes('"firing"') ? fixture.firing : fixture.pending) ?? [];
11
+ }
12
+ if (q.includes("process_instances_running"))
13
+ return fixture.running ?? [];
14
+ if (q.includes("incidents_open"))
15
+ return fixture.incidents ?? [];
16
+ if (q.includes("jobs_failed"))
17
+ return scalar(fixture.dead);
18
+ if (q.includes("jobs_executable"))
19
+ return perEngine(6.2);
20
+ if (q.includes("jobs_suspended"))
21
+ return scalar(2);
22
+ if (q.includes('status="total"'))
23
+ return scalar(9);
24
+ if (q.includes('status="unassigned"'))
25
+ return scalar(4);
26
+ if (q.includes("external_tasks_open"))
27
+ return perEngine(3.3);
28
+ if (q.includes("process_definitions_deployed"))
29
+ return scalar(3);
30
+ return [];
31
+ });
32
+ const ch = { instant };
33
+ return { ch, instant };
34
+ }
35
+ const alert = (alertname, severity, scope = {}) => sample({ alertname, severity, ...scope }, 1);
36
+ describe("engineHealth snapshot", () => {
37
+ it("reports every gauge, rounded, with breakdowns sorted and zero rows dropped", async () => {
38
+ const { ch } = mockClient({
39
+ reporting: ["prod-a", "prod-b"],
40
+ running: [
41
+ sample({ process_definition_key: "invoice" }, 2),
42
+ sample({ process_definition_key: "order" }, 7.4),
43
+ sample({ process_definition_key: "idle" }, 0.2),
44
+ sample({}, 1),
45
+ ],
46
+ incidents: [sample({ incident_type: "failedJob" }, 3)],
47
+ dead: 1.6,
48
+ });
49
+ const result = await engineHealth(ch, {});
50
+ expect(result).toMatchObject({
51
+ engines: null,
52
+ reportingEngines: ["prod-a", "prod-b"],
53
+ silentEngines: [],
54
+ runningInstances: 10,
55
+ runningByDefinition: [
56
+ { label: "order", count: 7 },
57
+ { label: "invoice", count: 2 },
58
+ { label: "", count: 1 },
59
+ ],
60
+ openIncidents: 3,
61
+ openIncidentsByType: [{ label: "failedJob", count: 3 }],
62
+ deadJobs: 2,
63
+ // Summed across the reporting engines.
64
+ executableJobs: 12,
65
+ suspendedJobs: 2,
66
+ openUserTasks: 9,
67
+ unassignedUserTasks: 4,
68
+ openExternalTasks: 7,
69
+ deployedDefinitionKeys: 3,
70
+ });
71
+ });
72
+ it("names each alert's scope by process, else incident type, else engine", async () => {
73
+ const { ch } = mockClient({
74
+ firing: [
75
+ alert("A", "warning", { process_definition_key: "order", incident_type: "x" }),
76
+ alert("B", "warning", { incident_type: "failedJob", engine_id: "prod-a" }),
77
+ alert("C", "warning", { engine_id: "prod-a" }),
78
+ sample({}, 1),
79
+ ],
80
+ pending: [alert("D", "info")],
81
+ });
82
+ const result = await engineHealth(ch, {});
83
+ expect(result.firingAlerts).toEqual([
84
+ { name: "A", severity: "warning", scope: "order" },
85
+ { name: "B", severity: "warning", scope: "failedJob" },
86
+ { name: "C", severity: "warning", scope: "prod-a" },
87
+ { name: "", severity: "", scope: "" },
88
+ ]);
89
+ expect(result.pendingAlerts).toEqual([{ name: "D", severity: "info", scope: "" }]);
90
+ });
91
+ });
92
+ /**
93
+ * #340: the verdict is alert-based and says so — the same engine may be
94
+ * "critical" in camunda7_show_engine_health (incident counts) and only
95
+ * "degraded" here. #336: silence is not health.
96
+ */
97
+ describe("engineHealth verdict", () => {
98
+ it.each([
99
+ ["a reporting engine without any signal", {}, "healthy"],
100
+ ["one open incident", { incidents: [sample({ incident_type: "failedJob" }, 1)] }, "degraded"],
101
+ ["one dead job", { dead: 1 }, "degraded"],
102
+ ["a firing warning", { firing: [alert("Slow", "warning")] }, "degraded"],
103
+ ["a firing critical alert", { firing: [alert("NoMetrics", "critical")] }, "critical"],
104
+ ["a merely PENDING critical alert", { pending: [alert("NoMetrics", "critical")] }, "healthy"],
105
+ [
106
+ "500 open incidents without a critical alert",
107
+ { incidents: [sample({ incident_type: "failedJob" }, 500)] },
108
+ "degraded",
109
+ ],
110
+ ["no engine reporting any metric", { reporting: [] }, "unknown"],
111
+ [
112
+ "no engine reporting, even with a critical alert firing",
113
+ { reporting: [], firing: [alert("CibSevenEngineNoMetrics", "critical")] },
114
+ "unknown",
115
+ ],
116
+ ])("%s → %s", async (_label, fixture, status) => {
117
+ const result = await engineHealth(mockClient(fixture).ch, {});
118
+ expect(result.status).toBe(status);
119
+ expect(result.statusRule).toBe(ENGINE_HEALTH_STATUS_RULE);
120
+ });
121
+ it("reads an engine that sends nothing — or a mistyped id — as unknown, never healthy (N76)", async () => {
122
+ const { ch } = mockClient({ reporting: [] });
123
+ const result = await engineHealth(ch, { engine: "prod-b" });
124
+ expect(result).toMatchObject({
125
+ status: "unknown",
126
+ engines: ["prod-b"],
127
+ reportingEngines: [],
128
+ silentEngines: ["prod-b"],
129
+ });
130
+ });
131
+ it("degrades a scope in which one engine is silent", async () => {
132
+ const { ch } = mockClient({ reporting: ["prod-a"] });
133
+ const result = await engineHealth(ch, { engine: ["prod-a", "prod-b"] });
134
+ expect(result).toMatchObject({
135
+ status: "degraded",
136
+ reportingEngines: ["prod-a"],
137
+ silentEngines: ["prod-b"],
138
+ });
139
+ });
140
+ it("states its rule in words", () => {
141
+ expect(ENGINE_HEALTH_STATUS_RULE).toBe("From Prometheus, over the engines in scope: unknown when none of them reports metrics; critical only while a severity=critical alert fires for them (fleet-wide also an engine-less CibSeven* alert); degraded with any such firing alert, dead job, open incident or an engine in scope that reports nothing; else healthy.");
142
+ });
143
+ });
144
+ describe("engineHealth PromQL", () => {
145
+ it("scopes every gauge and the ALERTS series to the engine filter", async () => {
146
+ const { ch, instant } = mockClient();
147
+ await engineHealth(ch, { engine: "prod-a" });
148
+ const sel = '{engine_id="prod-a"}';
149
+ // Every gauge folded over its own labels first: a clustered engine's nodes
150
+ // report the same engine-wide rows.
151
+ const perKey = "max by (process_definition_key, engine_id)";
152
+ expect(instant.mock.calls.map(([q]) => q)).toEqual([
153
+ `sum by (process_definition_key)(${perKey}(camunda_process_instances_running${sel}))`,
154
+ `sum by (incident_type)(max by (process_definition_key, incident_type, engine_id)(camunda_incidents_open${sel}))`,
155
+ `sum(${perKey}(camunda_jobs_failed${sel}))`,
156
+ `max by (engine_id)(camunda_jobs_executable${sel})`,
157
+ `sum(max by (engine_id)(camunda_jobs_suspended${sel}))`,
158
+ `sum(max by (status, engine_id)(camunda_usertasks_open{status="total",engine_id="prod-a"}))`,
159
+ `sum(max by (status, engine_id)(camunda_usertasks_open{status="unassigned",engine_id="prod-a"}))`,
160
+ `max by (engine_id)(camunda_external_tasks_open${sel})`,
161
+ `count(count by (process_definition_key)(${perKey}(camunda_process_definitions_deployed${sel})))`,
162
+ // One engine named: only alerts carrying its engine_id — an unrelated
163
+ // alert in a shared Prometheus cannot turn its verdict critical.
164
+ `ALERTS{alertstate="firing",engine_id="prod-a"}`,
165
+ `ALERTS{alertstate="pending",engine_id="prod-a"}`,
166
+ ]);
167
+ });
168
+ it("adds the module's engine-less alerts only for the whole fleet", async () => {
169
+ const { ch, instant } = mockClient();
170
+ await engineHealth(ch, { engine: ["prod-a", "prod-b"], includeFleetAlerts: true });
171
+ const alertQueries = instant.mock.calls.map(([q]) => q).filter((q) => q.startsWith("ALERTS"));
172
+ expect(alertQueries).toEqual([
173
+ 'ALERTS{alertstate="firing",engine_id=~"prod-a|prod-b"} or ALERTS{alertstate="firing",alertname=~"CibSeven.+",engine_id=""}',
174
+ 'ALERTS{alertstate="pending",engine_id=~"prod-a|prod-b"} or ALERTS{alertstate="pending",alertname=~"CibSeven.+",engine_id=""}',
175
+ ]);
176
+ });
177
+ it("reads only the module's own rules when unscoped — never a shared Prometheus' foreign alerts", async () => {
178
+ const { ch, instant } = mockClient();
179
+ await engineHealth(ch, {});
180
+ const alertQueries = instant.mock.calls.map(([q]) => q).filter((q) => q.startsWith("ALERTS"));
181
+ expect(alertQueries).toEqual([
182
+ 'ALERTS{alertstate="firing",alertname=~"CibSeven.+"}',
183
+ 'ALERTS{alertstate="pending",alertname=~"CibSeven.+"}',
184
+ ]);
185
+ });
186
+ });
187
+ //# sourceMappingURL=health.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.test.js","sourceRoot":"","sources":["../../src/queries/health.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,184 @@
1
+ import type { PrometheusClient, PromSample } from "../prometheus.js";
2
+ import { type GaugeName } from "../metric-names.js";
3
+ import { type CountWindow } from "./windows.js";
4
+ /** Round to one decimal place (KPI seconds / percentages). */
5
+ export declare const round1: (n: number) => number;
6
+ /** Milliseconds (the duration histograms' unit) as seconds, one decimal. */
7
+ export declare const secondsOf: (ms: number) => number;
8
+ /** {@link secondsOf} that passes `null` (not measured) through. */
9
+ export declare const secondsOrNull: (ms: number | null) => number | null;
10
+ /**
11
+ * What a counter or histogram series recorded inside `w`, per series — the
12
+ * ONE way every query reads a counter (contract rule 2). The plugin creates a
13
+ * series on its first event, and `increase()` never counts a series' first
14
+ * sample: a rare event such as the first incident of a type at an activity
15
+ * would read 0. So a series that existed before the window counts its
16
+ * `increase()`, and a series born inside it counts its whole value.
17
+ * `series` is a metric name plus its selector, e.g. `camunda_x{engine_id="a"}`.
18
+ *
19
+ * The check looks at the hour before the window. Where that hour lies past
20
+ * the retention (the 30-day period), Prometheus has deleted it and every
21
+ * series would pass for new, counting its whole history; there it looks at
22
+ * the window's own first hour instead: a series silent then was born later.
23
+ * Only a window of an hour or less at the retention edge has no hour to look
24
+ * at and reads plain `increase()`, which can miss a series' first sample but
25
+ * never counts what happened before the window.
26
+ */
27
+ export declare function increaseIn(series: string, w: CountWindow): string;
28
+ /**
29
+ * An engine-state gauge with one row per engine-wide figure (contract rule 3):
30
+ * every node of a clustered engine reports the same rows, so the nodes are
31
+ * folded with `max` over the gauge's contract labels before anything sums them.
32
+ */
33
+ export declare const engineState: (gauge: GaugeName, sel: string) => string;
34
+ /**
35
+ * Parse an ISO datetime into epoch seconds. Throws a caller-readable error
36
+ * instead of letting a NaN reach PromQL as `[NaNs] @ NaN` (Prometheus would
37
+ * answer with an opaque parse error).
38
+ */
39
+ export declare function parseIsoSeconds(value: string, field: string): number;
40
+ /**
41
+ * Value of the first sample, or 0 when the query returned no series — for
42
+ * COUNTS (`sum(increase(…))`), where "no series in the window" means nothing
43
+ * happened. Never use it for a duration or a gauge: there a missing series is
44
+ * "not measured", see {@link firstOrNull}.
45
+ */
46
+ export declare const first: (s: PromSample[]) => number;
47
+ /**
48
+ * Value of the first sample, or `null` when the query returned none — for
49
+ * durations and live gauges. A duration over an empty window is NaN
50
+ * (`0 / 0`, `histogram_quantile` over all-zero buckets), which the client
51
+ * drops, so "nothing ended in the window" lands here as `null`, never as a
52
+ * plausible 0 s. A per-key gauge without a series is 0 while the engines
53
+ * report and "not reported" only while they do not — decide that with
54
+ * {@link reportingEnginesQuery}, never from the gauge's own series.
55
+ */
56
+ export declare const firstOrNull: (s: PromSample[]) => number | null;
57
+ /**
58
+ * The engine-state presence probe — one series per engine in scope that
59
+ * reports its state gauges. `camunda_jobs_executable` carries `engine_id`
60
+ * only and is registered on every tick, 0 included; the per-key gauges are
61
+ * not: the metrics plugin registers a row only for what exists (no incident
62
+ * open → no `camunda_incidents_open` series at all). So a per-key gauge
63
+ * without a series is a measured 0 while this probe answers, and "not
64
+ * reported" only while it does not. `engineSel` must hold the engine matcher
65
+ * alone — the gauge has no other label to match.
66
+ */
67
+ export declare const reportingEnginesQuery: (engineSel: string) => string;
68
+ /** The engine ids the {@link reportingEnginesQuery} probe answered for, ascending. */
69
+ export declare const reportingEngineIds: (samples: PromSample[]) => string[];
70
+ /** The as-of stamp of a result: now, as an ISO timestamp (the instant queries evaluate at now). */
71
+ export declare const asOfNow: () => string;
72
+ /**
73
+ * Index sample values by one label, dropping samples that miss the label.
74
+ * The last sample wins on duplicate label values.
75
+ */
76
+ export declare function byLabel(samples: PromSample[], label: string): Record<string, number>;
77
+ /**
78
+ * `part` per 100 of `base`, one decimal — `null` when `base` is 0 (a rate of
79
+ * nothing is undefined, not 0 %). Incident rates divide incidents by
80
+ * instances; one instance can carry several incidents, so they may exceed 100.
81
+ */
82
+ export declare function ratePct(part: number, base: number): number | null;
83
+ /**
84
+ * Percentage change from `before` to `after`, rounded to two decimals. `null`
85
+ * when either side is not measured or the baseline is 0 — never a −100 % from
86
+ * a missing value or a division by zero.
87
+ */
88
+ export declare function pctChange(before: number | null, after: number | null): number | null;
89
+ /** Percentage-point difference of two rates; `null` when either is not measured. */
90
+ export declare function ppDelta(before: number | null, after: number | null): number | null;
91
+ /** Label selectors scoping one KPI partition (a window, an engine, a version …). */
92
+ export interface KpiScope {
93
+ /** Base selector: instance starts, incidents and durations. */
94
+ sel: string;
95
+ /** Base selector additionally matching `state="COMPLETED"` (completed count). */
96
+ completedSel: string;
97
+ /**
98
+ * Selector for the element-scoped incident count — the base selector
99
+ * narrowed to one `activity_id`. Absent: no element scope, no element query.
100
+ */
101
+ elementIncidentSel?: string;
102
+ }
103
+ /**
104
+ * The shared instance-KPI PromQL block used by the dashboard, performance and
105
+ * compare modules: counts via {@link increaseIn} over the window, durations
106
+ * from the histogram (`histogram_quantile` for p50/p95, sum/count for the
107
+ * mean), in MILLISECONDS — the histogram's unit; callers convert. Callers pick
108
+ * the strings they need.
109
+ *
110
+ * The duration histogram is recorded when an instance ENDS (any end state), so
111
+ * every duration covers the instances that ended inside the window only —
112
+ * still-running long instances are not in it (survivorship), and an empty
113
+ * window yields no value at all.
114
+ */
115
+ export declare function kpiQueries(scope: KpiScope, w: CountWindow): {
116
+ started: string;
117
+ completed: string;
118
+ incidents: string;
119
+ avgDuration: string;
120
+ medianDuration: string;
121
+ p95Duration: string;
122
+ };
123
+ /** The KPI core every compare module reports per partition. */
124
+ export interface CompareKpis {
125
+ /** Process instances STARTED in the window. */
126
+ instance_count: number;
127
+ /** Instances that ended with state COMPLETED in the window. */
128
+ completed_count: number;
129
+ /** Incidents CREATED in the window (every activity of the scope). */
130
+ incident_count: number;
131
+ /**
132
+ * `incident_count` per 100 started instances — `null` when nothing started.
133
+ * Several incidents per instance are possible, so it may exceed 100.
134
+ */
135
+ incident_rate_pct: number | null;
136
+ /** Incidents created at the `activityId` element — `null` without one. */
137
+ element_incident_count: number | null;
138
+ /** `element_incident_count` per 100 started instances — `null` without an element or starts. */
139
+ element_incident_rate_pct: number | null;
140
+ /** Mean duration of the instances that ENDED in the window — `null` when none did. */
141
+ avg_duration_sec: number | null;
142
+ /** p95 duration of the instances that ENDED in the window — `null` when none did. */
143
+ p95_duration_sec: number | null;
144
+ }
145
+ /**
146
+ * Runs the KPI block shared by the compare modules (cluster / engine /
147
+ * version) for one partition: five queries, plus the element-scoped incident
148
+ * count when `scope.elementIncidentSel` is set.
149
+ */
150
+ export declare function queryCompareKpis(ch: PrometheusClient, scope: KpiScope, w: CountWindow): Promise<CompareKpis>;
151
+ /**
152
+ * Deltas of `other` vs `baseline`: percentage points for rates, percent
153
+ * otherwise. Every delta is `null` when either side is not measured or the
154
+ * baseline is 0.
155
+ */
156
+ export interface CompareKpiDelta {
157
+ /**
158
+ * Change in instances started PER DAY — equal windows make it the plain
159
+ * count change; windows of different length (a clamped post-deploy window)
160
+ * still compare fairly.
161
+ */
162
+ started_per_day_delta_pct: number | null;
163
+ incident_rate_delta_pp: number | null;
164
+ element_incident_rate_delta_pp: number | null;
165
+ avg_duration_delta_pct: number | null;
166
+ p95_duration_delta_pct: number | null;
167
+ }
168
+ type DeltaInput = Pick<CompareKpis, "instance_count" | "incident_rate_pct" | "element_incident_rate_pct" | "avg_duration_sec" | "p95_duration_sec">;
169
+ /**
170
+ * Shared delta block of the compare modules. `days` are the two windows'
171
+ * actual lengths; the start counts are compared per day.
172
+ */
173
+ export declare function compareKpiDelta(baseline: DeltaInput, other: DeltaInput, days: {
174
+ baseline: number;
175
+ other: number;
176
+ }): CompareKpiDelta;
177
+ /**
178
+ * Whether a comparison is below the trust threshold: a partition with fewer
179
+ * than `minBucketSize` started instances (the rates' base) OR fewer completed
180
+ * ones (the durations' sample) is noise, not a signal.
181
+ */
182
+ export declare function belowMinBucket(partitions: ReadonlyArray<Pick<CompareKpis, "instance_count" | "completed_count">>, minBucketSize: number): boolean;
183
+ export {};
184
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/queries/helpers.ts"],"names":[],"mappings":"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"}