@miragon/pulse-analytics-client 0.0.0-stage → 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 +84 -2
  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 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Miragon GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,85 @@
1
- # Temporary Holding Version
1
+ # @miragon/pulse-analytics-client
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Prometheus client and PromQL query layer for Camunda 7 / CIB Seven process analytics. It pairs a thin
4
+ HTTP client for the Prometheus query API with a set of typed, purpose-built query functions and the
5
+ **metrics contract** — the single source of truth for the `camunda_*` metric names and labels the
6
+ [engine plugin](../../../../engine-plugins) emits.
7
+
8
+ Used by [`@miragon/pulse-analytics-connector`](../analytics-connector) to power the `analytics_*` MCP tools, but
9
+ usable by any project that reads Camunda process metrics from Prometheus.
10
+
11
+ ## Exports
12
+
13
+ | Subpath | Contents |
14
+ | ----------- | -------------------------------------------------------------------------------------- |
15
+ | `.` | Prometheus client + `METRIC_NAMES` + query re-exports |
16
+ | `./queries` | Typed PromQL query functions (performance, bottlenecks, failures, comparisons, health) |
17
+ | `./schemas` | Zod input schemas for the query functions |
18
+ | `./widgets` | Shared widget data types for the analytics dashboards |
19
+
20
+ ## Query functions
21
+
22
+ `src/queries/` provides one composable function per analysis, each returning a typed result rather
23
+ than a raw Prometheus matrix:
24
+
25
+ - `performance` — throughput, duration percentiles over a window
26
+ - `element` — per-activity bottleneck analysis
27
+ - `failures` — failed / incident-bearing instances
28
+ - `cluster-compare`, `version-compare`, `engine-compare` — side-by-side comparisons
29
+ - `health` — live operational snapshot (running WIP, open incidents, dead jobs, backlog, alerts)
30
+ - `dashboard` — the aggregate feed behind the analytics dashboard widget
31
+
32
+ ```ts
33
+ import { createPrometheusClient } from "@miragon/pulse-analytics-client"
34
+ import { analyzePerformance } from "@miragon/pulse-analytics-client/queries"
35
+
36
+ const prom = createPrometheusClient({ url: "http://localhost:9090" })
37
+ const perf = await analyzePerformance(prom, {
38
+ processDefinitionKey: "loanApproval",
39
+ period: "24h",
40
+ includeActivityBreakdown: true,
41
+ })
42
+ ```
43
+
44
+ `createPrometheusClient` also takes optional auth — `bearerToken`, or
45
+ `username` + `password` (userinfo in `url` is moved into the Basic header) —
46
+ extra `headers` (e.g. a tenant id) and a per-query `timeoutMs` (default
47
+ 30 000 ms). Ambiguous auth throws at construction. Query errors never carry
48
+ the URL or a credential and truncate upstream bodies, so they are safe to show
49
+ a model. `withCallerSignal(client, signal)` makes every query abort with the
50
+ caller's signal as well.
51
+
52
+ ## Metrics contract
53
+
54
+ [`metrics-contract.json`](metrics-contract.json) is the **single source of truth** for metric names
55
+ and labels. The Kotlin plugin emits the OTEL instruments (`otelName`) that surface in Prometheus as
56
+ `camunda_*` series (`promName`), and consumers reference them through `METRIC_NAMES`
57
+ ([`src/metric-names.ts`](src/metric-names.ts)) — **never raw strings**. Both sides are verified
58
+ against the contract:
59
+
60
+ - TypeScript: [`src/metrics-contract.test.ts`](src/metrics-contract.test.ts) (vitest) checks the
61
+ metric names; [`src/metrics-contract-labels.test.ts`](src/metrics-contract-labels.test.ts) runs
62
+ every exported query function and checks each label its PromQL names (matchers, `by`/`without`,
63
+ `on`/`ignoring`/`group_*`) against the labels the contract declares for that series, alert
64
+ rules and Grafana dashboards included
65
+ - Kotlin: `MetricsContractTest.kt` (Gradle), incl. the millisecond bucket bounds each histogram
66
+ registers
67
+
68
+ The contract also sets how a series is READ, and the same tests check every query, alert rule and
69
+ dashboard panel against it. PromQL of your own uses the exported helpers:
70
+
71
+ - `increaseIn(series, window)` for a counter or histogram: a series is created on its first event,
72
+ and `increase()`/`rate()` never count a series' first sample, so the first incident of a type at
73
+ an activity would read 0. A series born inside the window counts with its whole value.
74
+ - `engineState(gauge, selector)` for a gauge: every node of a clustered engine reports the same
75
+ engine-wide rows, folded with `max by (<its labels>)` before anything sums them.
76
+ - Durations are whole milliseconds (`*_duration_milliseconds`).
77
+
78
+ A rename that skips the contract — or a consumer (queries, alert rules, Grafana dashboards) — fails
79
+ one of these tests. Only attach model-bounded labels (definition key, activity id, engine id);
80
+ never instance ids, business keys, or variable values.
81
+
82
+ ## Publishing
83
+
84
+ Published to GitHub Packages (`npm.pkg.github.com`, restricted access) via release-please. The
85
+ `metrics-contract.json` ships in the package so downstream consumers can validate against it.
@@ -0,0 +1,12 @@
1
+ export { createPrometheusClient, withCallerSignal, DEFAULT_PROMETHEUS_TIMEOUT_MS, type PrometheusQueryOptions, escapeLabelValue, engineMatcher, engineIdsOf, selector, PERIOD_RANGE, PERIODS, RETENTION_DAYS, type PrometheusConfig, type PrometheusClient, type PromSample, type EngineFilterInput, type Period, } from "./prometheus.js";
2
+ export { METRIC_NAMES, GAUGE_LABELS, type MetricName, type GaugeName } from "./metric-names.js";
3
+ export { increaseIn, engineState } from "./queries/helpers.js";
4
+ export type { CountWindow } from "./queries/windows.js";
5
+ export { ENGINE_ALERT_NAME_PATTERN, ENGINE_HEALTH_STATUS_RULE } from "./queries/health.js";
6
+ export { ACTIVITY_BREAKDOWN_LIMIT } from "./queries/dashboard.js";
7
+ export * as schemas from "./schemas/index.js";
8
+ export * as queries from "./queries/index.js";
9
+ export * as widgets from "./widgets.js";
10
+ export type { CompareKpis, CompareKpiDelta, ErrorPatternRow, FailedInstancesResult, PerformanceResult, PerformanceKPI, ActivityBreakdownRow, PeriodComparisonKpi, PeriodActivityComparisonRow, PeriodComparisonResult, ElementBottleneckRow, ElementBottleneckResult, ElementHeatResult, ClusterCompareResult, ClusterCompareKpi, ClusterCompareDelta, VersionCompareResult, VersionCompareKpi, VersionCompareDelta, EngineCompareResult, EngineCompareKpi, EngineCompareDelta, EngineLandscapeResult, EngineLandscapeEngine, EngineLandscapeProcess, EngineHealthResult, HealthCount, HealthAlert, } from "./queries/index.js";
11
+ export type { ErrorPatternItem, ProcessFailureItem, FailureDashboardData, ActivityBreakdownItem, DefinitionBreakdownItem, AnalyticsDashboardData, PreviousPeriodFlows, } from "./widgets.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,6BAA6B,EAC7B,KAAK,sBAAsB,EAC3B,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,MAAM,GACZ,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAI/F,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAC9D,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGvD,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAA;AAC1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC,YAAY,EACV,WAAW,EACX,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,WAAW,EACX,WAAW,GACZ,MAAM,oBAAoB,CAAA;AAE3B,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,cAAc,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ export { createPrometheusClient, withCallerSignal, DEFAULT_PROMETHEUS_TIMEOUT_MS, escapeLabelValue, engineMatcher, engineIdsOf, selector, PERIOD_RANGE, PERIODS, RETENTION_DAYS, } from "./prometheus.js";
2
+ export { METRIC_NAMES, GAUGE_LABELS } from "./metric-names.js";
3
+ // The reading rules of metrics-contract.json, for PromQL of your own: a
4
+ // counter or histogram through the born-series count, a gauge folded over a
5
+ // clustered engine's nodes.
6
+ export { increaseIn, engineState } from "./queries/helpers.js";
7
+ // Constants, not queries: kept out of the `queries` namespace, whose every
8
+ // member the query scenarios enumerate.
9
+ export { ENGINE_ALERT_NAME_PATTERN, ENGINE_HEALTH_STATUS_RULE } from "./queries/health.js";
10
+ export { ACTIVITY_BREAKDOWN_LIMIT } from "./queries/dashboard.js";
11
+ export * as schemas from "./schemas/index.js";
12
+ export * as queries from "./queries/index.js";
13
+ export * as widgets from "./widgets.js";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,6BAA6B,EAE7B,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,cAAc,GAMf,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAmC,MAAM,mBAAmB,CAAA;AAC/F,wEAAwE;AACxE,4EAA4E;AAC5E,4BAA4B;AAC5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAE9D,2EAA2E;AAC3E,wCAAwC;AACxC,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAA;AAC1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Prometheus series names for the engine-plugin metrics, mirroring
3
+ * `packages/connectors/analytics/analytics-client/metrics-contract.json` — the single source of
4
+ * truth for the Kotlin↔TS metric contract. Change the contract first; the
5
+ * contract test (`src/metrics-contract.test.ts`) diffs this object against the
6
+ * JSON, so a drift fails `pnpm test`.
7
+ *
8
+ * Histogram entries are the base series name — append `_sum` / `_count` /
9
+ * `_bucket` at the call site. Hand-maintained (not imported from the JSON)
10
+ * because the contract file lives outside the tsconfig `rootDir`.
11
+ */
12
+ export declare const METRIC_NAMES: {
13
+ readonly processInstanceStarted: "camunda_process_instance_started_total";
14
+ readonly processInstanceEnded: "camunda_process_instance_ended_total";
15
+ readonly activityEnded: "camunda_activity_ended_total";
16
+ readonly userTaskCreated: "camunda_usertask_created_total";
17
+ readonly userTaskCompleted: "camunda_usertask_completed_total";
18
+ readonly incidentCreated: "camunda_incident_created_total";
19
+ readonly incidentResolved: "camunda_incident_resolved_total";
20
+ readonly processInstanceDuration: "camunda_process_instance_duration_milliseconds";
21
+ readonly activityDuration: "camunda_activity_duration_milliseconds";
22
+ readonly userTaskDuration: "camunda_usertask_duration_milliseconds";
23
+ readonly processInstancesRunning: "camunda_process_instances_running";
24
+ readonly jobsFailed: "camunda_jobs_failed";
25
+ readonly incidentsOpen: "camunda_incidents_open";
26
+ readonly jobsExecutable: "camunda_jobs_executable";
27
+ readonly jobsSuspended: "camunda_jobs_suspended";
28
+ readonly jobsDueFuture: "camunda_jobs_due_future";
29
+ readonly userTasksOpen: "camunda_usertasks_open";
30
+ readonly processDefinitionsDeployed: "camunda_process_definitions_deployed";
31
+ readonly externalTasksOpen: "camunda_external_tasks_open";
32
+ };
33
+ export type MetricName = (typeof METRIC_NAMES)[keyof typeof METRIC_NAMES];
34
+ /** The engine-state gauges: every one is an engine-wide figure, reported alike by every node. */
35
+ export type GaugeName = typeof METRIC_NAMES.processInstancesRunning | typeof METRIC_NAMES.jobsFailed | typeof METRIC_NAMES.incidentsOpen | typeof METRIC_NAMES.jobsExecutable | typeof METRIC_NAMES.jobsSuspended | typeof METRIC_NAMES.jobsDueFuture | typeof METRIC_NAMES.userTasksOpen | typeof METRIC_NAMES.processDefinitionsDeployed | typeof METRIC_NAMES.externalTasksOpen;
36
+ /**
37
+ * The contract labels of each gauge: what makes one of its rows. A clustered
38
+ * engine's nodes are folded over exactly these (`max by`, contract rule 3), so
39
+ * node identity labels (`instance`, `job`) drop out and nothing else does. The
40
+ * contract test diffs this map against the JSON.
41
+ */
42
+ export declare const GAUGE_LABELS: Readonly<Record<GaugeName, readonly string[]>>;
43
+ //# sourceMappingURL=metric-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metric-names.d.ts","sourceRoot":"","sources":["../src/metric-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;CAuBf,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAA;AAEzE,iGAAiG;AACjG,MAAM,MAAM,SAAS,GACjB,OAAO,YAAY,CAAC,uBAAuB,GAC3C,OAAO,YAAY,CAAC,UAAU,GAC9B,OAAO,YAAY,CAAC,aAAa,GACjC,OAAO,YAAY,CAAC,cAAc,GAClC,OAAO,YAAY,CAAC,aAAa,GACjC,OAAO,YAAY,CAAC,aAAa,GACjC,OAAO,YAAY,CAAC,aAAa,GACjC,OAAO,YAAY,CAAC,0BAA0B,GAC9C,OAAO,YAAY,CAAC,iBAAiB,CAAA;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC,CAUvE,CAAA"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Prometheus series names for the engine-plugin metrics, mirroring
3
+ * `packages/connectors/analytics/analytics-client/metrics-contract.json` — the single source of
4
+ * truth for the Kotlin↔TS metric contract. Change the contract first; the
5
+ * contract test (`src/metrics-contract.test.ts`) diffs this object against the
6
+ * JSON, so a drift fails `pnpm test`.
7
+ *
8
+ * Histogram entries are the base series name — append `_sum` / `_count` /
9
+ * `_bucket` at the call site. Hand-maintained (not imported from the JSON)
10
+ * because the contract file lives outside the tsconfig `rootDir`.
11
+ */
12
+ export const METRIC_NAMES = {
13
+ // Counters (history-event stream)
14
+ processInstanceStarted: "camunda_process_instance_started_total",
15
+ processInstanceEnded: "camunda_process_instance_ended_total",
16
+ activityEnded: "camunda_activity_ended_total",
17
+ userTaskCreated: "camunda_usertask_created_total",
18
+ userTaskCompleted: "camunda_usertask_completed_total",
19
+ incidentCreated: "camunda_incident_created_total",
20
+ incidentResolved: "camunda_incident_resolved_total",
21
+ // Histograms in whole milliseconds (base name; `_sum`/`_count`/`_bucket` series implied)
22
+ processInstanceDuration: "camunda_process_instance_duration_milliseconds",
23
+ activityDuration: "camunda_activity_duration_milliseconds",
24
+ userTaskDuration: "camunda_usertask_duration_milliseconds",
25
+ // Gauges (point-in-time engine state)
26
+ processInstancesRunning: "camunda_process_instances_running",
27
+ jobsFailed: "camunda_jobs_failed",
28
+ incidentsOpen: "camunda_incidents_open",
29
+ jobsExecutable: "camunda_jobs_executable",
30
+ jobsSuspended: "camunda_jobs_suspended",
31
+ jobsDueFuture: "camunda_jobs_due_future",
32
+ userTasksOpen: "camunda_usertasks_open",
33
+ processDefinitionsDeployed: "camunda_process_definitions_deployed",
34
+ externalTasksOpen: "camunda_external_tasks_open",
35
+ };
36
+ /**
37
+ * The contract labels of each gauge: what makes one of its rows. A clustered
38
+ * engine's nodes are folded over exactly these (`max by`, contract rule 3), so
39
+ * node identity labels (`instance`, `job`) drop out and nothing else does. The
40
+ * contract test diffs this map against the JSON.
41
+ */
42
+ export const GAUGE_LABELS = {
43
+ [METRIC_NAMES.processInstancesRunning]: ["process_definition_key", "engine_id"],
44
+ [METRIC_NAMES.jobsFailed]: ["process_definition_key", "engine_id"],
45
+ [METRIC_NAMES.incidentsOpen]: ["process_definition_key", "incident_type", "engine_id"],
46
+ [METRIC_NAMES.jobsExecutable]: ["engine_id"],
47
+ [METRIC_NAMES.jobsSuspended]: ["engine_id"],
48
+ [METRIC_NAMES.jobsDueFuture]: ["engine_id"],
49
+ [METRIC_NAMES.userTasksOpen]: ["status", "engine_id"],
50
+ [METRIC_NAMES.processDefinitionsDeployed]: ["process_definition_key", "engine_id"],
51
+ [METRIC_NAMES.externalTasksOpen]: ["engine_id"],
52
+ };
53
+ //# sourceMappingURL=metric-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metric-names.js","sourceRoot":"","sources":["../src/metric-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,kCAAkC;IAClC,sBAAsB,EAAE,wCAAwC;IAChE,oBAAoB,EAAE,sCAAsC;IAC5D,aAAa,EAAE,8BAA8B;IAC7C,eAAe,EAAE,gCAAgC;IACjD,iBAAiB,EAAE,kCAAkC;IACrD,eAAe,EAAE,gCAAgC;IACjD,gBAAgB,EAAE,iCAAiC;IACnD,yFAAyF;IACzF,uBAAuB,EAAE,gDAAgD;IACzE,gBAAgB,EAAE,wCAAwC;IAC1D,gBAAgB,EAAE,wCAAwC;IAC1D,sCAAsC;IACtC,uBAAuB,EAAE,mCAAmC;IAC5D,UAAU,EAAE,qBAAqB;IACjC,aAAa,EAAE,wBAAwB;IACvC,cAAc,EAAE,yBAAyB;IACzC,aAAa,EAAE,wBAAwB;IACvC,aAAa,EAAE,yBAAyB;IACxC,aAAa,EAAE,wBAAwB;IACvC,0BAA0B,EAAE,sCAAsC;IAClE,iBAAiB,EAAE,6BAA6B;CACxC,CAAA;AAgBV;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAmD;IAC1E,CAAC,YAAY,CAAC,uBAAuB,CAAC,EAAE,CAAC,wBAAwB,EAAE,WAAW,CAAC;IAC/E,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC,wBAAwB,EAAE,WAAW,CAAC;IAClE,CAAC,YAAY,CAAC,aAAa,CAAC,EAAE,CAAC,wBAAwB,EAAE,eAAe,EAAE,WAAW,CAAC;IACtF,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC,WAAW,CAAC;IAC5C,CAAC,YAAY,CAAC,aAAa,CAAC,EAAE,CAAC,WAAW,CAAC;IAC3C,CAAC,YAAY,CAAC,aAAa,CAAC,EAAE,CAAC,WAAW,CAAC;IAC3C,CAAC,YAAY,CAAC,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;IACrD,CAAC,YAAY,CAAC,0BAA0B,CAAC,EAAE,CAAC,wBAAwB,EAAE,WAAW,CAAC;IAClF,CAAC,YAAY,CAAC,iBAAiB,CAAC,EAAE,CAAC,WAAW,CAAC;CAChD,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=metrics-contract-labels.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-contract-labels.test.d.ts","sourceRoot":"","sources":["../src/metrics-contract-labels.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,169 @@
1
+ import { readFileSync, readdirSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+ import { join } from "node:path";
4
+ import { describe, expect, it } from "vitest";
5
+ import { checkQueryLabels, contractCatalog, } from "./promql-labels.test-support.js";
6
+ import { alertExpressions, dashboardQueries } from "./promql-sources.test-support.js";
7
+ import { readingRuleViolations } from "./promql-reading-rules.test-support.js";
8
+ import { RETENTION_DAYS } from "./prometheus.js";
9
+ import { ENGINE_ALERT_NAME_PATTERN } from "./queries/health.js";
10
+ import { DAY_SECONDS, nowSeconds, rangeSeconds } from "./queries/windows.js";
11
+ import { SCENARIOS, exportedQueryFunctions, recordingClient, } from "./query-scenarios.test-support.js";
12
+ /**
13
+ * Behavioural half of the metrics contract: instead of scanning source text,
14
+ * run every exported query function against a recording Prometheus client and
15
+ * check each PromQL it actually sends — every matcher label, every
16
+ * `by`/`without` grouping label, every `on`/`ignoring`/`group_*` label — against
17
+ * the labels `metrics-contract.json` declares for that series. The alert rules
18
+ * and Grafana dashboards go through the same checker.
19
+ *
20
+ * A text scan cannot see a label that only exists in a composed selector; this
21
+ * one caught `analytics_version_compare` filtering the incident counter on
22
+ * `process_definition_version`, a label that series never carries (#327).
23
+ */
24
+ const here = (rel) => fileURLToPath(new URL(rel, import.meta.url));
25
+ // src/ → analytics-client → analytics → connectors → packages → repo root
26
+ const repoRoot = here("../../../../..");
27
+ const contract = JSON.parse(readFileSync(here("../metrics-contract.json"), "utf8"));
28
+ const alertsFile = join(repoRoot, "playground/docker/prometheus/alerts.yml");
29
+ const dashboardsDir = join(repoRoot, "playground/docker/grafana/dashboards");
30
+ /**
31
+ * Non-contract series Prometheus synthesises itself. `up` carries the scrape
32
+ * target labels (no target relabelling in prometheus.yml). `ALERTS` carries
33
+ * `alertname`/`alertstate`, each rule's static `severity` and the labels its
34
+ * expression yields — derived from alerts.yml below, never hand-listed, so a
35
+ * rule that stops aggregating by a label also drops it here.
36
+ */
37
+ const UP_LABELS = ["job", "instance"];
38
+ const ALERTS_BASE_LABELS = ["alertname", "alertstate", "severity"];
39
+ const ruleCatalog = contractCatalog(contract.metrics, { up: { labels: UP_LABELS } });
40
+ const alertsYaml = readFileSync(alertsFile, "utf8");
41
+ const alertRules = alertExpressions(alertsYaml);
42
+ const alertLabels = new Set([
43
+ ...ALERTS_BASE_LABELS,
44
+ ...alertRules.flatMap((expr) => checkQueryLabels(expr, ruleCatalog).resultLabels ?? []),
45
+ ]);
46
+ const catalog = contractCatalog(contract.metrics, {
47
+ up: { labels: UP_LABELS },
48
+ ALERTS: { labels: [...alertLabels] },
49
+ });
50
+ /** Violations of one PromQL source, each prefixed with where it came from. */
51
+ function violationsOf(origin, promql) {
52
+ return checkQueryLabels(promql, catalog).violations.map((v) => `${origin}: ${v}\n ${promql}`);
53
+ }
54
+ describe("metrics contract — labels each query actually sends", () => {
55
+ it("has a scenario for every exported query function", () => {
56
+ expect(Object.keys(SCENARIOS).sort()).toEqual(exportedQueryFunctions().sort());
57
+ });
58
+ it.each(Object.entries(SCENARIOS))("%s names only labels its series declare", async (name, scenarios) => {
59
+ const violations = [];
60
+ let checked = 0;
61
+ for (const run of scenarios) {
62
+ const { ch, sent } = recordingClient();
63
+ await run(ch);
64
+ expect(sent.length, `${name} sent no PromQL`).toBeGreaterThan(0);
65
+ for (const promql of sent) {
66
+ violations.push(...violationsOf(name, promql));
67
+ checked += checkQueryLabels(promql, catalog).checkedLabels;
68
+ }
69
+ }
70
+ expect(violations).toEqual([]);
71
+ // Every query scopes by at least one label (engine, process, …) — 0
72
+ // here means the scenario args or the checker went blind.
73
+ expect(checked, `${name}: no label reference was checked`).toBeGreaterThan(0);
74
+ });
75
+ });
76
+ describe("metrics contract — labels in alert rules and dashboards", () => {
77
+ it("alert rule expressions name only declared labels", () => {
78
+ expect(alertRules.length).toBeGreaterThan(0);
79
+ // Every `expr:` in the file was extracted — none hides in a YAML shape
80
+ // (flow mapping, …) the extractor does not read.
81
+ expect(alertRules).toHaveLength(alertsYaml.match(/\bexpr:/g)?.length ?? 0);
82
+ expect(alertRules.flatMap((expr) => violationsOf("alerts.yml", expr))).toEqual([]);
83
+ for (const expr of alertRules) {
84
+ // A rule that selects no series or yields no vector was not checked —
85
+ // e.g. an expression that parsed as one PromQL string literal.
86
+ const { series, resultLabels } = checkQueryLabels(expr, catalog);
87
+ expect(series, `alerts.yml selects no series: ${expr}`).not.toEqual([]);
88
+ expect(resultLabels, `alerts.yml yields no vector: ${expr}`).toBeDefined();
89
+ }
90
+ // The rules aggregate by engine_id — `engineHealth` filters ALERTS on it.
91
+ expect(alertLabels.has("engine_id")).toBe(true);
92
+ });
93
+ it("every shipped alert rule is named so engineHealth recognises it as the module's own", () => {
94
+ // Engine-less alerts (CibSevenEngineNoMetrics) only count when their name
95
+ // matches — a rule outside the pattern would silently drop out of the
96
+ // fleet-wide verdict, and a shared Prometheus' foreign alerts must not count.
97
+ const names = [...alertsYaml.matchAll(/^\s*-\s*alert:\s*(\S+)\s*$/gm)].map((m) => m[1]);
98
+ expect(names).toHaveLength(alertRules.length);
99
+ const own = new RegExp(`^(?:${ENGINE_ALERT_NAME_PATTERN})$`);
100
+ expect(names.filter((name) => !own.test(name))).toEqual([]);
101
+ });
102
+ it("Grafana dashboard queries name only declared labels", () => {
103
+ const files = readdirSync(dashboardsDir).filter((f) => f.endsWith(".json"));
104
+ expect(files.length).toBeGreaterThan(0);
105
+ let expressions = 0;
106
+ const violations = [];
107
+ for (const file of files) {
108
+ const dashboard = JSON.parse(readFileSync(join(dashboardsDir, file), "utf8"));
109
+ for (const promql of dashboardQueries(dashboard)) {
110
+ expressions++;
111
+ violations.push(...violationsOf(`dashboards/${file}`, promql));
112
+ const { series } = checkQueryLabels(promql, catalog);
113
+ expect(series, `dashboards/${file} selects no series: ${promql}`).not.toEqual([]);
114
+ }
115
+ }
116
+ expect(expressions).toBeGreaterThan(0);
117
+ expect(violations).toEqual([]);
118
+ });
119
+ });
120
+ /**
121
+ * Contract rules 2 and 3 over every consumer: a counter or histogram is read
122
+ * only through the born-series count, a gauge only folded over its nodes.
123
+ * Queries may read plain `increase()` only over a window of an hour or less
124
+ * at the retention edge (`increaseIn` has no hour to check there); the alert
125
+ * rules and dashboards never.
126
+ */
127
+ describe("metrics contract — reading rules", () => {
128
+ const plainIncreaseAllowed = (range, at) => {
129
+ const now = nowSeconds();
130
+ const seconds = rangeSeconds(range);
131
+ return seconds <= 3600 && (at ?? now) - seconds - 3600 < now - RETENTION_DAYS * DAY_SECONDS;
132
+ };
133
+ it.each(Object.entries(SCENARIOS))("%s reads counters and gauges by the rules", async (name, scenarios) => {
134
+ const violations = [];
135
+ for (const run of scenarios) {
136
+ const { ch, sent } = recordingClient();
137
+ await run(ch);
138
+ for (const promql of sent) {
139
+ violations.push(...readingRuleViolations(promql, contract.metrics, { plainIncreaseAllowed }).map((v) => `${name}: ${v}\n ${promql}`));
140
+ }
141
+ }
142
+ expect(violations).toEqual([]);
143
+ });
144
+ it("alert rules read counters and gauges by the rules", () => {
145
+ const violations = alertRules.flatMap((expr) => readingRuleViolations(expr, contract.metrics).map((v) => `alerts.yml: ${v}\n ${expr}`));
146
+ expect(violations).toEqual([]);
147
+ });
148
+ it("Grafana panels read counters and gauges by the rules", () => {
149
+ const violations = [];
150
+ for (const file of readdirSync(dashboardsDir).filter((f) => f.endsWith(".json"))) {
151
+ const dashboard = JSON.parse(readFileSync(join(dashboardsDir, file), "utf8"));
152
+ // Panel expressions only: a templating `label_values(…)` lists label
153
+ // values, it reads no counter or gauge value.
154
+ for (const promql of panelExpressions(dashboard)) {
155
+ violations.push(...readingRuleViolations(promql, contract.metrics).map((v) => `dashboards/${file}: ${v}\n ${promql}`));
156
+ }
157
+ }
158
+ expect(violations).toEqual([]);
159
+ });
160
+ });
161
+ /** Every panel `expr` of a dashboard. */
162
+ function panelExpressions(node) {
163
+ if (Array.isArray(node))
164
+ return node.flatMap(panelExpressions);
165
+ if (node === null || typeof node !== "object")
166
+ return [];
167
+ return Object.entries(node).flatMap(([key, value]) => key === "expr" && typeof value === "string" ? [value] : panelExpressions(value));
168
+ }
169
+ //# sourceMappingURL=metrics-contract-labels.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-contract-labels.test.js","sourceRoot":"","sources":["../src/metrics-contract-labels.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=metrics-contract.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-contract.test.d.ts","sourceRoot":"","sources":["../src/metrics-contract.test.ts"],"names":[],"mappings":""}