@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,219 @@
1
+ import { GAUGE_LABELS, METRIC_NAMES as M } from "../metric-names.js";
2
+ import { RETENTION_DAYS } from "../prometheus.js";
3
+ import { DAY_SECONDS, nowSeconds, rangeSeconds } from "./windows.js";
4
+ /** Round to one decimal place (KPI seconds / percentages). */
5
+ export const round1 = (n) => Math.round(n * 10) / 10;
6
+ /** Milliseconds (the duration histograms' unit) as seconds, one decimal. */
7
+ export const secondsOf = (ms) => round1(ms / 1000);
8
+ /** {@link secondsOf} that passes `null` (not measured) through. */
9
+ export const secondsOrNull = (ms) => (ms === null ? null : secondsOf(ms));
10
+ /**
11
+ * How long a series must have been silent before a window for it to count as
12
+ * born inside that window. Long enough that a scrape gap at the window's start
13
+ * does not pass an old series off as new (its whole history would then count).
14
+ */
15
+ const BORN_LOOKBACK = "1h";
16
+ const BORN_LOOKBACK_SECONDS = 3600;
17
+ /**
18
+ * What a counter or histogram series recorded inside `w`, per series — the
19
+ * ONE way every query reads a counter (contract rule 2). The plugin creates a
20
+ * series on its first event, and `increase()` never counts a series' first
21
+ * sample: a rare event such as the first incident of a type at an activity
22
+ * would read 0. So a series that existed before the window counts its
23
+ * `increase()`, and a series born inside it counts its whole value.
24
+ * `series` is a metric name plus its selector, e.g. `camunda_x{engine_id="a"}`.
25
+ *
26
+ * The check looks at the hour before the window. Where that hour lies past
27
+ * the retention (the 30-day period), Prometheus has deleted it and every
28
+ * series would pass for new, counting its whole history; there it looks at
29
+ * the window's own first hour instead: a series silent then was born later.
30
+ * Only a window of an hour or less at the retention edge has no hour to look
31
+ * at and reads plain `increase()`, which can miss a series' first sample but
32
+ * never counts what happened before the window.
33
+ */
34
+ export function increaseIn(series, w) {
35
+ const at = w.at === undefined ? "" : ` @ ${w.at}`;
36
+ const plain = `increase(${series}[${w.range}]${at})`;
37
+ const offset = bornCheckOffset(w);
38
+ if (offset === null)
39
+ return plain;
40
+ const silent = `present_over_time(${series}[${BORN_LOOKBACK}]${at} offset ${offset})`;
41
+ return (`((${plain} and ${silent})` +
42
+ ` or (max_over_time(${series}[${w.range}]${at}) unless ${silent}))`);
43
+ }
44
+ /**
45
+ * How far back from the window's end the born check's hour ends: the window's
46
+ * start (the hour before it), or, where that hour lies past the retention,
47
+ * the end of the window's first hour; `null` when the window has none.
48
+ */
49
+ function bornCheckOffset(w, now = nowSeconds()) {
50
+ const seconds = rangeSeconds(w.range);
51
+ const start = (w.at ?? now) - seconds;
52
+ if (start - BORN_LOOKBACK_SECONDS >= now - RETENTION_DAYS * DAY_SECONDS)
53
+ return w.range;
54
+ return seconds > BORN_LOOKBACK_SECONDS ? `${seconds - BORN_LOOKBACK_SECONDS}s` : null;
55
+ }
56
+ /**
57
+ * An engine-state gauge with one row per engine-wide figure (contract rule 3):
58
+ * every node of a clustered engine reports the same rows, so the nodes are
59
+ * folded with `max` over the gauge's contract labels before anything sums them.
60
+ */
61
+ export const engineState = (gauge, sel) => `max by (${GAUGE_LABELS[gauge].join(", ")})(${gauge}${sel})`;
62
+ /**
63
+ * Parse an ISO datetime into epoch seconds. Throws a caller-readable error
64
+ * instead of letting a NaN reach PromQL as `[NaNs] @ NaN` (Prometheus would
65
+ * answer with an opaque parse error).
66
+ */
67
+ export function parseIsoSeconds(value, field) {
68
+ const ms = Date.parse(value);
69
+ if (!Number.isFinite(ms)) {
70
+ throw new Error(`${field} "${value}" is not a parseable ISO datetime (expected e.g. 2026-07-01T12:00:00Z)`);
71
+ }
72
+ return Math.round(ms / 1000);
73
+ }
74
+ /**
75
+ * Value of the first sample, or 0 when the query returned no series — for
76
+ * COUNTS (`sum(increase(…))`), where "no series in the window" means nothing
77
+ * happened. Never use it for a duration or a gauge: there a missing series is
78
+ * "not measured", see {@link firstOrNull}.
79
+ */
80
+ export const first = (s) => (s.length ? s[0].value : 0);
81
+ /**
82
+ * Value of the first sample, or `null` when the query returned none — for
83
+ * durations and live gauges. A duration over an empty window is NaN
84
+ * (`0 / 0`, `histogram_quantile` over all-zero buckets), which the client
85
+ * drops, so "nothing ended in the window" lands here as `null`, never as a
86
+ * plausible 0 s. A per-key gauge without a series is 0 while the engines
87
+ * report and "not reported" only while they do not — decide that with
88
+ * {@link reportingEnginesQuery}, never from the gauge's own series.
89
+ */
90
+ export const firstOrNull = (s) => (s.length ? s[0].value : null);
91
+ /**
92
+ * The engine-state presence probe — one series per engine in scope that
93
+ * reports its state gauges. `camunda_jobs_executable` carries `engine_id`
94
+ * only and is registered on every tick, 0 included; the per-key gauges are
95
+ * not: the metrics plugin registers a row only for what exists (no incident
96
+ * open → no `camunda_incidents_open` series at all). So a per-key gauge
97
+ * without a series is a measured 0 while this probe answers, and "not
98
+ * reported" only while it does not. `engineSel` must hold the engine matcher
99
+ * alone — the gauge has no other label to match.
100
+ */
101
+ export const reportingEnginesQuery = (engineSel) => engineState(M.jobsExecutable, engineSel);
102
+ /** The engine ids the {@link reportingEnginesQuery} probe answered for, ascending. */
103
+ export const reportingEngineIds = (samples) => [...new Set(samples.flatMap((s) => (s.metric.engine_id ? [s.metric.engine_id] : [])))].sort();
104
+ /** The as-of stamp of a result: now, as an ISO timestamp (the instant queries evaluate at now). */
105
+ export const asOfNow = () => new Date().toISOString();
106
+ /**
107
+ * Index sample values by one label, dropping samples that miss the label.
108
+ * The last sample wins on duplicate label values.
109
+ */
110
+ export function byLabel(samples, label) {
111
+ const out = {};
112
+ for (const s of samples) {
113
+ const k = s.metric[label];
114
+ if (k !== undefined)
115
+ out[k] = s.value;
116
+ }
117
+ return out;
118
+ }
119
+ /**
120
+ * `part` per 100 of `base`, one decimal — `null` when `base` is 0 (a rate of
121
+ * nothing is undefined, not 0 %). Incident rates divide incidents by
122
+ * instances; one instance can carry several incidents, so they may exceed 100.
123
+ */
124
+ export function ratePct(part, base) {
125
+ return base > 0 ? round1((part * 100) / base) : null;
126
+ }
127
+ /**
128
+ * Percentage change from `before` to `after`, rounded to two decimals. `null`
129
+ * when either side is not measured or the baseline is 0 — never a −100 % from
130
+ * a missing value or a division by zero.
131
+ */
132
+ export function pctChange(before, after) {
133
+ if (before === null || after === null || before === 0)
134
+ return null;
135
+ return Math.round(((after - before) / before) * 10000) / 100;
136
+ }
137
+ /** Percentage-point difference of two rates; `null` when either is not measured. */
138
+ export function ppDelta(before, after) {
139
+ return before === null || after === null ? null : round1(after - before);
140
+ }
141
+ /**
142
+ * The shared instance-KPI PromQL block used by the dashboard, performance and
143
+ * compare modules: counts via {@link increaseIn} over the window, durations
144
+ * from the histogram (`histogram_quantile` for p50/p95, sum/count for the
145
+ * mean), in MILLISECONDS — the histogram's unit; callers convert. Callers pick
146
+ * the strings they need.
147
+ *
148
+ * The duration histogram is recorded when an instance ENDS (any end state), so
149
+ * every duration covers the instances that ended inside the window only —
150
+ * still-running long instances are not in it (survivorship), and an empty
151
+ * window yields no value at all.
152
+ */
153
+ export function kpiQueries(scope, w) {
154
+ const { sel, completedSel } = scope;
155
+ const duration = M.processInstanceDuration;
156
+ return {
157
+ started: `sum(${increaseIn(`${M.processInstanceStarted}${sel}`, w)})`,
158
+ completed: `sum(${increaseIn(`${M.processInstanceEnded}${completedSel}`, w)})`,
159
+ incidents: `sum(${increaseIn(`${M.incidentCreated}${sel}`, w)})`,
160
+ avgDuration: `sum(${increaseIn(`${duration}_sum${sel}`, w)}) / sum(${increaseIn(`${duration}_count${sel}`, w)})`,
161
+ medianDuration: `histogram_quantile(0.5, sum by (le)(${increaseIn(`${duration}_bucket${sel}`, w)}))`,
162
+ p95Duration: `histogram_quantile(0.95, sum by (le)(${increaseIn(`${duration}_bucket${sel}`, w)}))`,
163
+ };
164
+ }
165
+ /**
166
+ * Runs the KPI block shared by the compare modules (cluster / engine /
167
+ * version) for one partition: five queries, plus the element-scoped incident
168
+ * count when `scope.elementIncidentSel` is set.
169
+ */
170
+ export async function queryCompareKpis(ch, scope, w) {
171
+ const q = kpiQueries(scope, w);
172
+ const element = scope.elementIncidentSel;
173
+ const [total, completed, incidents, avg, p95, elementIncidents] = await Promise.all([
174
+ ch.instant(q.started),
175
+ ch.instant(q.completed),
176
+ ch.instant(q.incidents),
177
+ ch.instant(q.avgDuration),
178
+ ch.instant(q.p95Duration),
179
+ element === undefined
180
+ ? Promise.resolve(null)
181
+ : ch.instant(`sum(${increaseIn(`${M.incidentCreated}${element}`, w)})`),
182
+ ]);
183
+ const instances = Math.round(first(total));
184
+ const incidentCount = Math.round(first(incidents));
185
+ const elementCount = elementIncidents === null ? null : Math.round(first(elementIncidents));
186
+ return {
187
+ instance_count: instances,
188
+ completed_count: Math.round(first(completed)),
189
+ incident_count: incidentCount,
190
+ incident_rate_pct: ratePct(incidentCount, instances),
191
+ element_incident_count: elementCount,
192
+ element_incident_rate_pct: elementCount === null ? null : ratePct(elementCount, instances),
193
+ avg_duration_sec: secondsOrNull(firstOrNull(avg)),
194
+ p95_duration_sec: secondsOrNull(firstOrNull(p95)),
195
+ };
196
+ }
197
+ /**
198
+ * Shared delta block of the compare modules. `days` are the two windows'
199
+ * actual lengths; the start counts are compared per day.
200
+ */
201
+ export function compareKpiDelta(baseline, other, days) {
202
+ const perDay = (count, d) => (d > 0 ? count / d : null);
203
+ return {
204
+ started_per_day_delta_pct: pctChange(perDay(baseline.instance_count, days.baseline), perDay(other.instance_count, days.other)),
205
+ incident_rate_delta_pp: ppDelta(baseline.incident_rate_pct, other.incident_rate_pct),
206
+ element_incident_rate_delta_pp: ppDelta(baseline.element_incident_rate_pct, other.element_incident_rate_pct),
207
+ avg_duration_delta_pct: pctChange(baseline.avg_duration_sec, other.avg_duration_sec),
208
+ p95_duration_delta_pct: pctChange(baseline.p95_duration_sec, other.p95_duration_sec),
209
+ };
210
+ }
211
+ /**
212
+ * Whether a comparison is below the trust threshold: a partition with fewer
213
+ * than `minBucketSize` started instances (the rates' base) OR fewer completed
214
+ * ones (the durations' sample) is noise, not a signal.
215
+ */
216
+ export function belowMinBucket(partitions, minBucketSize) {
217
+ return partitions.some((p) => p.instance_count < minBucketSize || p.completed_count < minBucketSize);
218
+ }
219
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/queries/helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=helpers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.test.d.ts","sourceRoot":"","sources":["../../src/queries/helpers.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { increaseIn } from "./helpers.js";
3
+ import { DAY_SECONDS, rangeSeconds } from "./windows.js";
4
+ const NOW = Date.UTC(2026, 9, 12, 12, 0, 0);
5
+ const NOW_SECONDS = NOW / 1000;
6
+ beforeEach(() => {
7
+ vi.useFakeTimers({ toFake: ["Date"], now: NOW });
8
+ });
9
+ afterEach(() => {
10
+ vi.useRealTimers();
11
+ });
12
+ describe("increaseIn", () => {
13
+ it("counts a series born inside the window with its whole value", () => {
14
+ expect(increaseIn('camunda_x_total{engine_id="a"}', { range: "7d" })).toBe('((increase(camunda_x_total{engine_id="a"}[7d]) and present_over_time(camunda_x_total{engine_id="a"}[1h] offset 7d))' +
15
+ ' or (max_over_time(camunda_x_total{engine_id="a"}[7d]) unless present_over_time(camunda_x_total{engine_id="a"}[1h] offset 7d)))');
16
+ });
17
+ it("pins every part of a window that ends in the past", () => {
18
+ const at = NOW_SECONDS - 3 * DAY_SECONDS;
19
+ expect(increaseIn("camunda_x_total", { range: "86400s", at })).toBe(`((increase(camunda_x_total[86400s] @ ${at}) and present_over_time(camunda_x_total[1h] @ ${at} offset 86400s))` +
20
+ ` or (max_over_time(camunda_x_total[86400s] @ ${at}) unless present_over_time(camunda_x_total[1h] @ ${at} offset 86400s)))`);
21
+ });
22
+ it("checks the window's first hour where the hour before it lies past the retention", () => {
23
+ // 30 days back reaches the retention edge: the series silent in the window's
24
+ // first hour (30d − 1h = 2588400s before its end) were born inside it.
25
+ expect(increaseIn("camunda_x_total", { range: "30d" })).toBe("((increase(camunda_x_total[30d]) and present_over_time(camunda_x_total[1h] offset 2588400s))" +
26
+ " or (max_over_time(camunda_x_total[30d]) unless present_over_time(camunda_x_total[1h] offset 2588400s)))");
27
+ const at = NOW_SECONDS - 29 * DAY_SECONDS;
28
+ expect(increaseIn("camunda_x_total", { range: "1d", at })).toContain(`present_over_time(camunda_x_total[1h] @ ${at} offset 82800s)`);
29
+ // The hour before the window starts exactly at the retention edge: still that hour.
30
+ const edge = NOW_SECONDS - 30 * DAY_SECONDS + 3600 + DAY_SECONDS;
31
+ expect(increaseIn("camunda_x_total", { range: "1d", at: edge })).toContain(`present_over_time(camunda_x_total[1h] @ ${edge} offset 1d)`);
32
+ expect(increaseIn("camunda_x_total", { range: "1d", at: edge - 1 })).toContain(`present_over_time(camunda_x_total[1h] @ ${edge - 1} offset 82800s)`);
33
+ });
34
+ it("reads plain increase() for a window of an hour or less at the retention edge", () => {
35
+ const at = NOW_SECONDS - 30 * DAY_SECONDS + 1800;
36
+ expect(increaseIn("camunda_x_total", { range: "3600s", at })).toBe(`increase(camunda_x_total[3600s] @ ${at})`);
37
+ });
38
+ it("refuses a range it cannot measure", () => {
39
+ expect(() => increaseIn("camunda_x_total", { range: "1d12h" })).toThrow(/single-unit/);
40
+ });
41
+ });
42
+ describe("rangeSeconds", () => {
43
+ it("measures every single-unit PromQL duration", () => {
44
+ expect(["30s", "5m", "2h", "1d", "1w"].map(rangeSeconds)).toEqual([
45
+ 30,
46
+ 300,
47
+ 7200,
48
+ DAY_SECONDS,
49
+ 7 * DAY_SECONDS,
50
+ ]);
51
+ });
52
+ });
53
+ //# sourceMappingURL=helpers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.test.js","sourceRoot":"","sources":["../../src/queries/helpers.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export type { CompareKpis, CompareKpiDelta } from "./helpers.js";
2
+ export { analyzePerformance, comparePeriods } from "./performance.js";
3
+ export type { PerformanceResult, PerformanceKPI, ActivityBreakdownRow, PeriodComparisonKpi, PeriodActivityComparisonRow, PeriodComparisonResult, } from "./performance.js";
4
+ export { findFailedInstances } from "./failures.js";
5
+ export type { ErrorPatternRow, FailedInstancesResult } from "./failures.js";
6
+ export { elementBottleneck, elementHeat } from "./element.js";
7
+ export type { ElementBottleneckRow, ElementBottleneckResult, ElementHeatResult } from "./element.js";
8
+ export { clusterCompare } from "./cluster-compare.js";
9
+ export type { ClusterCompareResult, ClusterCompareKpi, ClusterCompareDelta, } from "./cluster-compare.js";
10
+ export { versionCompare } from "./version-compare.js";
11
+ export type { VersionCompareResult, VersionCompareKpi, VersionCompareDelta, } from "./version-compare.js";
12
+ export { engineCompare } from "./engine-compare.js";
13
+ export type { EngineCompareResult, EngineCompareKpi, EngineCompareDelta } from "./engine-compare.js";
14
+ export { engineLandscape } from "./engine-landscape.js";
15
+ export type { EngineLandscapeResult, EngineLandscapeEngine, EngineLandscapeProcess, } from "./engine-landscape.js";
16
+ export { dashboardData, failureDashboardData } from "./dashboard.js";
17
+ export { engineHealth } from "./health.js";
18
+ export type { EngineHealthResult, HealthCount, HealthAlert } from "./health.js";
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/queries/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAChE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACrE,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC3E,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC7D,YAAY,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACpG,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACpG,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,YAAY,EACV,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,10 @@
1
+ export { analyzePerformance, comparePeriods } from "./performance.js";
2
+ export { findFailedInstances } from "./failures.js";
3
+ export { elementBottleneck, elementHeat } from "./element.js";
4
+ export { clusterCompare } from "./cluster-compare.js";
5
+ export { versionCompare } from "./version-compare.js";
6
+ export { engineCompare } from "./engine-compare.js";
7
+ export { engineLandscape } from "./engine-landscape.js";
8
+ export { dashboardData, failureDashboardData } from "./dashboard.js";
9
+ export { engineHealth } from "./health.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/queries/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AASrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAEnD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAMrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAMrD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAMvD,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,103 @@
1
+ import { type EngineFilterInput, type PrometheusClient } from "../prometheus.js";
2
+ export interface PerformanceKPI {
3
+ process_definition_key: string;
4
+ /** Instances started in the window. */
5
+ total_instances: number;
6
+ /** Instances that ended with state COMPLETED in the window. */
7
+ completed: number;
8
+ /** Incidents created in the window — incidents, not failed instances. */
9
+ incident_count: number;
10
+ /** `incident_count` per 100 started instances (may exceed 100); null when nothing started. */
11
+ incident_rate_pct: number | null;
12
+ /** Durations of the instances that ENDED in the window; null when none did. */
13
+ avg_duration_sec: number | null;
14
+ median_duration_sec: number | null;
15
+ p95_duration_sec: number | null;
16
+ }
17
+ export interface ActivityBreakdownRow {
18
+ activity_id: string;
19
+ /** Not a metric label — resolve names from the BPMN. Always null. */
20
+ activity_name: null;
21
+ activity_type: string;
22
+ execution_count: number;
23
+ avg_duration_sec: number | null;
24
+ median_duration_sec: number | null;
25
+ p95_duration_sec: number | null;
26
+ total_time_sec: number;
27
+ }
28
+ export interface PeriodComparisonKpi {
29
+ period: string;
30
+ /** The window actually measured, after clamping to now and retention. */
31
+ window_from: string;
32
+ window_to: string;
33
+ window_days: number;
34
+ /** True when clamping cut the requested window short. */
35
+ partial: boolean;
36
+ total_instances: number;
37
+ /**
38
+ * `total_instances` per day of the window's exact length — the figure to
39
+ * compare across windows of different length. Always measured: a clamped
40
+ * window is never empty (`clampWindow` refuses one).
41
+ */
42
+ started_per_day: number;
43
+ completed: number;
44
+ incident_count: number;
45
+ incident_rate_pct: number | null;
46
+ avg_duration_sec: number | null;
47
+ median_sec: number | null;
48
+ p95_sec: number | null;
49
+ }
50
+ export interface PeriodActivityComparisonRow {
51
+ activity_id: string;
52
+ activity_name: null;
53
+ period: string;
54
+ executions: number;
55
+ avg_sec: number | null;
56
+ p95_sec: number | null;
57
+ }
58
+ /** Result of {@link analyzePerformance}. */
59
+ export interface PerformanceResult {
60
+ /** The engine ids covered; `null` = every engine Prometheus holds (unscoped library call). */
61
+ engines: string[] | null;
62
+ kpi: PerformanceKPI | null;
63
+ activityBreakdown: ActivityBreakdownRow[];
64
+ }
65
+ export interface PeriodComparisonResult {
66
+ /** The engine ids covered; `null` = every engine Prometheus holds (unscoped library call). */
67
+ engines: string[] | null;
68
+ kpiComparison: PeriodComparisonKpi[];
69
+ activityComparison?: PeriodActivityComparisonRow[];
70
+ }
71
+ /**
72
+ * Process performance KPIs over a rolling window, from OTEL metrics.
73
+ *
74
+ * Counts come from {@link increaseIn} over the period; durations from the histogram
75
+ * (`histogram_quantile` for p50/p95, sum/count for the mean) and cover the
76
+ * instances that ENDED in the window — `null` when none did. `incident_count`
77
+ * counts incidents created (metrics carry no per-instance terminal-failure
78
+ * state). `kpi` is null only when the window saw no start, end or incident.
79
+ */
80
+ export declare function analyzePerformance(ch: PrometheusClient, params: {
81
+ processDefinitionKey: string;
82
+ period: string;
83
+ includeActivityBreakdown: boolean;
84
+ engine?: EngineFilterInput;
85
+ }): Promise<PerformanceResult>;
86
+ /**
87
+ * Compare two explicit execution windows. Each is read as a real historical
88
+ * window via the PromQL `@ <end>` modifier, clamped to `[now − retention,
89
+ * now]` and reported with its ACTUAL bounds (`window_*`, `partial`). Windows
90
+ * of different length are not comparable by count, so each KPI row also
91
+ * carries `started_per_day`. A reversed window, or one entirely in the future
92
+ * or before retention, is refused.
93
+ */
94
+ export declare function comparePeriods(ch: PrometheusClient, params: {
95
+ processDefinitionKey: string;
96
+ periodAFrom: string;
97
+ periodATo: string;
98
+ periodBFrom: string;
99
+ periodBTo: string;
100
+ includeActivityBreakdown: boolean;
101
+ engine?: EngineFilterInput;
102
+ }): Promise<PeriodComparisonResult>;
103
+ //# sourceMappingURL=performance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/queries/performance.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,iBAAiB,EAEtB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAA;AAyBzB,MAAM,WAAW,cAAc;IAC7B,sBAAsB,EAAE,MAAM,CAAA;IAC9B,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAA;IACvB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAA;IACtB,8FAA8F;IAC9F,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,+EAA+E;IAC/E,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAA;IACnB,qEAAqE;IACrE,aAAa,EAAE,IAAI,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,MAAM,WAAW,2BAA2B;IAC1C,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,8FAA8F;IAC9F,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IACxB,GAAG,EAAE,cAAc,GAAG,IAAI,CAAA;IAC1B,iBAAiB,EAAE,oBAAoB,EAAE,CAAA;CAC1C;AAED,MAAM,WAAW,sBAAsB;IACrC,8FAA8F;IAC9F,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IACxB,aAAa,EAAE,mBAAmB,EAAE,CAAA;IACpC,kBAAkB,CAAC,EAAE,2BAA2B,EAAE,CAAA;CACnD;AAeD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,gBAAgB,EACpB,MAAM,EAAE;IACN,oBAAoB,EAAE,MAAM,CAAA;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,wBAAwB,EAAE,OAAO,CAAA;IACjC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAC3B,GACA,OAAO,CAAC,iBAAiB,CAAC,CAgD5B;AAyCD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,gBAAgB,EACpB,MAAM,EAAE;IACN,oBAAoB,EAAE,MAAM,CAAA;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,wBAAwB,EAAE,OAAO,CAAA;IACjC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAC3B,GACA,OAAO,CAAC,sBAAsB,CAAC,CAuBjC"}
@@ -0,0 +1,173 @@
1
+ import { engineIdsOf, engineMatcher, escapeLabelValue, selector, } from "../prometheus.js";
2
+ import { METRIC_NAMES as M } from "../metric-names.js";
3
+ import { byLabel, first, firstOrNull, increaseIn, kpiQueries, parseIsoSeconds, ratePct, round1, secondsOf, secondsOrNull, } from "./helpers.js";
4
+ import { clampWindow, DAY_SECONDS, daysOf, isoOf, nowSeconds, windowAt, } from "./windows.js";
5
+ /** `{process_definition_key=..., engine_id=...}` plus any extra matchers. */
6
+ function pdkSelector(key, engineId, ...extra) {
7
+ return selector(`process_definition_key="${escapeLabelValue(key)}"`, engineMatcher(engineId), ...extra);
8
+ }
9
+ /**
10
+ * Process performance KPIs over a rolling window, from OTEL metrics.
11
+ *
12
+ * Counts come from {@link increaseIn} over the period; durations from the histogram
13
+ * (`histogram_quantile` for p50/p95, sum/count for the mean) and cover the
14
+ * instances that ENDED in the window — `null` when none did. `incident_count`
15
+ * counts incidents created (metrics carry no per-instance terminal-failure
16
+ * state). `kpi` is null only when the window saw no start, end or incident.
17
+ */
18
+ export async function analyzePerformance(ch, params) {
19
+ const range = params.period ?? "7d";
20
+ const q = kpiQueries({
21
+ sel: pdkSelector(params.processDefinitionKey, params.engine),
22
+ completedSel: pdkSelector(params.processDefinitionKey, params.engine, 'state="COMPLETED"'),
23
+ }, { range });
24
+ const [total, completed, incidents, avg, median, p95] = await Promise.all([
25
+ ch.instant(q.started),
26
+ ch.instant(q.completed),
27
+ ch.instant(q.incidents),
28
+ ch.instant(q.avgDuration),
29
+ ch.instant(q.medianDuration),
30
+ ch.instant(q.p95Duration),
31
+ ]);
32
+ const totalInstances = Math.round(first(total));
33
+ const completedCount = Math.round(first(completed));
34
+ const incidentCount = Math.round(first(incidents));
35
+ const avgMs = firstOrNull(avg);
36
+ const observed = totalInstances > 0 || completedCount > 0 || incidentCount > 0 || avgMs !== null;
37
+ const kpi = observed
38
+ ? {
39
+ process_definition_key: params.processDefinitionKey,
40
+ total_instances: totalInstances,
41
+ completed: completedCount,
42
+ incident_count: incidentCount,
43
+ incident_rate_pct: ratePct(incidentCount, totalInstances),
44
+ avg_duration_sec: secondsOrNull(avgMs),
45
+ median_duration_sec: secondsOrNull(firstOrNull(median)),
46
+ p95_duration_sec: secondsOrNull(firstOrNull(p95)),
47
+ }
48
+ : null;
49
+ let activityBreakdown = [];
50
+ if (params.includeActivityBreakdown) {
51
+ activityBreakdown = await activityBreakdownRows(ch, params.processDefinitionKey, { range }, params.engine);
52
+ }
53
+ return { engines: engineIdsOf(params.engine), kpi, activityBreakdown };
54
+ }
55
+ async function activityBreakdownRows(ch, key, w, engineId) {
56
+ const sel = pdkSelector(key, engineId);
57
+ const inWindow = (series) => increaseIn(series, w);
58
+ const [counts, sums, median, p95] = await Promise.all([
59
+ ch.instant(`sum by (activity_id, activity_type)(${inWindow(`${M.activityEnded}${sel}`)})`),
60
+ ch.instant(`sum by (activity_id)(${inWindow(`${M.activityDuration}_sum${sel}`)})`),
61
+ ch.instant(`histogram_quantile(0.5, sum by (activity_id, le)(${inWindow(`${M.activityDuration}_bucket${sel}`)}))`),
62
+ ch.instant(`histogram_quantile(0.95, sum by (activity_id, le)(${inWindow(`${M.activityDuration}_bucket${sel}`)}))`),
63
+ ]);
64
+ const sumBy = byLabel(sums, "activity_id");
65
+ const medianBy = byLabel(median, "activity_id");
66
+ const p95By = byLabel(p95, "activity_id");
67
+ const rows = counts.map((c) => {
68
+ const id = c.metric.activity_id ?? "";
69
+ const count = Math.round(c.value);
70
+ const sumMs = sumBy[id];
71
+ return {
72
+ activity_id: id,
73
+ activity_name: null,
74
+ activity_type: c.metric.activity_type ?? "",
75
+ execution_count: count,
76
+ avg_duration_sec: sumMs !== undefined && count > 0 ? secondsOf(sumMs / count) : null,
77
+ median_duration_sec: secondsOrNull(medianBy[id] ?? null),
78
+ p95_duration_sec: secondsOrNull(p95By[id] ?? null),
79
+ total_time_sec: secondsOf(sumMs ?? 0),
80
+ };
81
+ });
82
+ return rows.sort((a, b) => b.total_time_sec - a.total_time_sec).slice(0, 20);
83
+ }
84
+ /**
85
+ * Compare two explicit execution windows. Each is read as a real historical
86
+ * window via the PromQL `@ <end>` modifier, clamped to `[now − retention,
87
+ * now]` and reported with its ACTUAL bounds (`window_*`, `partial`). Windows
88
+ * of different length are not comparable by count, so each KPI row also
89
+ * carries `started_per_day`. A reversed window, or one entirely in the future
90
+ * or before retention, is refused.
91
+ */
92
+ export async function comparePeriods(ch, params) {
93
+ const now = nowSeconds();
94
+ const a = explicitWindow("periodA", params.periodAFrom, params.periodATo, now);
95
+ const b = explicitWindow("periodB", params.periodBFrom, params.periodBTo, now);
96
+ const [kpiA, kpiB] = await Promise.all([
97
+ periodKpi(ch, params.processDefinitionKey, "Period A", a, params.engine),
98
+ periodKpi(ch, params.processDefinitionKey, "Period B", b, params.engine),
99
+ ]);
100
+ const result = {
101
+ engines: engineIdsOf(params.engine),
102
+ kpiComparison: [kpiA, kpiB],
103
+ };
104
+ if (params.includeActivityBreakdown) {
105
+ const [actA, actB] = await Promise.all([
106
+ periodActivities(ch, params.processDefinitionKey, "Period A", a, params.engine),
107
+ periodActivities(ch, params.processDefinitionKey, "Period B", b, params.engine),
108
+ ]);
109
+ result.activityComparison = [...actA, ...actB].sort((x, y) => x.activity_id.localeCompare(y.activity_id) || x.period.localeCompare(y.period));
110
+ }
111
+ return result;
112
+ }
113
+ function explicitWindow(name, from, to, now) {
114
+ return clampWindow(name, parseIsoSeconds(from, `${name}From`), parseIsoSeconds(to, `${name}To`), now);
115
+ }
116
+ async function periodKpi(ch, key, label, w, engineId) {
117
+ const q = kpiQueries({
118
+ sel: pdkSelector(key, engineId),
119
+ completedSel: pdkSelector(key, engineId, 'state="COMPLETED"'),
120
+ }, windowAt(w));
121
+ const [total, completed, incidents, avg, median, p95] = await Promise.all([
122
+ ch.instant(q.started),
123
+ ch.instant(q.completed),
124
+ ch.instant(q.incidents),
125
+ ch.instant(q.avgDuration),
126
+ ch.instant(q.medianDuration),
127
+ ch.instant(q.p95Duration),
128
+ ]);
129
+ const totalInstances = Math.round(first(total));
130
+ const incidentCount = Math.round(first(incidents));
131
+ return {
132
+ period: label,
133
+ window_from: isoOf(w.from),
134
+ window_to: isoOf(w.to),
135
+ window_days: daysOf(w.seconds),
136
+ partial: w.partial,
137
+ total_instances: totalInstances,
138
+ // From the exact length — the rounded window_days is for display: a
139
+ // 10-minute window is 0.01 d there (−30 %), a 5-minute one 0.00 d.
140
+ started_per_day: round1((totalInstances * DAY_SECONDS) / w.seconds),
141
+ completed: Math.round(first(completed)),
142
+ incident_count: incidentCount,
143
+ incident_rate_pct: ratePct(incidentCount, totalInstances),
144
+ avg_duration_sec: secondsOrNull(firstOrNull(avg)),
145
+ median_sec: secondsOrNull(firstOrNull(median)),
146
+ p95_sec: secondsOrNull(firstOrNull(p95)),
147
+ };
148
+ }
149
+ async function periodActivities(ch, key, label, w, engineId) {
150
+ const sel = pdkSelector(key, engineId);
151
+ const inWindow = (series) => increaseIn(series, windowAt(w));
152
+ const [counts, sums, p95] = await Promise.all([
153
+ ch.instant(`sum by (activity_id)(${inWindow(`${M.activityEnded}${sel}`)})`),
154
+ ch.instant(`sum by (activity_id)(${inWindow(`${M.activityDuration}_sum${sel}`)})`),
155
+ ch.instant(`histogram_quantile(0.95, sum by (activity_id, le)(${inWindow(`${M.activityDuration}_bucket${sel}`)}))`),
156
+ ]);
157
+ const sumBy = byLabel(sums, "activity_id");
158
+ const p95By = byLabel(p95, "activity_id");
159
+ return counts.map((c) => {
160
+ const id = c.metric.activity_id ?? "";
161
+ const executions = Math.round(c.value);
162
+ const sumMs = sumBy[id];
163
+ return {
164
+ activity_id: id,
165
+ activity_name: null,
166
+ period: label,
167
+ executions,
168
+ avg_sec: sumMs !== undefined && executions > 0 ? secondsOf(sumMs / executions) : null,
169
+ p95_sec: secondsOrNull(p95By[id] ?? null),
170
+ };
171
+ });
172
+ }
173
+ //# sourceMappingURL=performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../src/queries/performance.ts"],"names":[],"mappings":"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"}