@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.
- package/LICENSE +21 -0
- package/README.md +83 -3
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/metric-names.d.ts +43 -0
- package/dist/metric-names.d.ts.map +1 -0
- package/dist/metric-names.js +53 -0
- package/dist/metric-names.js.map +1 -0
- package/dist/metrics-contract-labels.test.d.ts +2 -0
- package/dist/metrics-contract-labels.test.d.ts.map +1 -0
- package/dist/metrics-contract-labels.test.js +169 -0
- package/dist/metrics-contract-labels.test.js.map +1 -0
- package/dist/metrics-contract.test.d.ts +2 -0
- package/dist/metrics-contract.test.d.ts.map +1 -0
- package/dist/metrics-contract.test.js +247 -0
- package/dist/metrics-contract.test.js.map +1 -0
- package/dist/prometheus-client.test.d.ts +2 -0
- package/dist/prometheus-client.test.d.ts.map +1 -0
- package/dist/prometheus-client.test.js +265 -0
- package/dist/prometheus-client.test.js.map +1 -0
- package/dist/prometheus.d.ts +100 -0
- package/dist/prometheus.d.ts.map +1 -0
- package/dist/prometheus.js +295 -0
- package/dist/prometheus.js.map +1 -0
- package/dist/prometheus.test.d.ts +2 -0
- package/dist/prometheus.test.d.ts.map +1 -0
- package/dist/prometheus.test.js +54 -0
- package/dist/prometheus.test.js.map +1 -0
- package/dist/promql-labels.test-support.d.ts +53 -0
- package/dist/promql-labels.test-support.d.ts.map +1 -0
- package/dist/promql-labels.test-support.js +237 -0
- package/dist/promql-labels.test-support.js.map +1 -0
- package/dist/promql-labels.test.d.ts +2 -0
- package/dist/promql-labels.test.d.ts.map +1 -0
- package/dist/promql-labels.test.js +190 -0
- package/dist/promql-labels.test.js.map +1 -0
- package/dist/promql-parse.test-support.d.ts +57 -0
- package/dist/promql-parse.test-support.d.ts.map +1 -0
- package/dist/promql-parse.test-support.js +284 -0
- package/dist/promql-parse.test-support.js.map +1 -0
- package/dist/promql-reading-rules.test-support.d.ts +29 -0
- package/dist/promql-reading-rules.test-support.d.ts.map +1 -0
- package/dist/promql-reading-rules.test-support.js +79 -0
- package/dist/promql-reading-rules.test-support.js.map +1 -0
- package/dist/promql-reading-rules.test.d.ts +2 -0
- package/dist/promql-reading-rules.test.d.ts.map +1 -0
- package/dist/promql-reading-rules.test.js +61 -0
- package/dist/promql-reading-rules.test.js.map +1 -0
- package/dist/promql-sources.test-support.d.ts +29 -0
- package/dist/promql-sources.test-support.d.ts.map +1 -0
- package/dist/promql-sources.test-support.js +112 -0
- package/dist/promql-sources.test-support.js.map +1 -0
- package/dist/promql-sources.test.d.ts +2 -0
- package/dist/promql-sources.test.d.ts.map +1 -0
- package/dist/promql-sources.test.js +93 -0
- package/dist/promql-sources.test.js.map +1 -0
- package/dist/queries/as-of.test.d.ts +2 -0
- package/dist/queries/as-of.test.d.ts.map +1 -0
- package/dist/queries/as-of.test.js +80 -0
- package/dist/queries/as-of.test.js.map +1 -0
- package/dist/queries/cluster-compare.d.ts +62 -0
- package/dist/queries/cluster-compare.d.ts.map +1 -0
- package/dist/queries/cluster-compare.js +70 -0
- package/dist/queries/cluster-compare.js.map +1 -0
- package/dist/queries/cluster-compare.test.d.ts +2 -0
- package/dist/queries/cluster-compare.test.d.ts.map +1 -0
- package/dist/queries/cluster-compare.test.js +81 -0
- package/dist/queries/cluster-compare.test.js.map +1 -0
- package/dist/queries/dashboard.d.ts +60 -0
- package/dist/queries/dashboard.d.ts.map +1 -0
- package/dist/queries/dashboard.js +292 -0
- package/dist/queries/dashboard.js.map +1 -0
- package/dist/queries/dashboard.test.d.ts +2 -0
- package/dist/queries/dashboard.test.d.ts.map +1 -0
- package/dist/queries/dashboard.test.js +423 -0
- package/dist/queries/dashboard.test.js.map +1 -0
- package/dist/queries/element.d.ts +68 -0
- package/dist/queries/element.d.ts.map +1 -0
- package/dist/queries/element.js +98 -0
- package/dist/queries/element.js.map +1 -0
- package/dist/queries/element.test.d.ts +2 -0
- package/dist/queries/element.test.d.ts.map +1 -0
- package/dist/queries/element.test.js +105 -0
- package/dist/queries/element.test.js.map +1 -0
- package/dist/queries/engine-compare.d.ts +52 -0
- package/dist/queries/engine-compare.d.ts.map +1 -0
- package/dist/queries/engine-compare.js +57 -0
- package/dist/queries/engine-compare.js.map +1 -0
- package/dist/queries/engine-compare.test.d.ts +2 -0
- package/dist/queries/engine-compare.test.d.ts.map +1 -0
- package/dist/queries/engine-compare.test.js +159 -0
- package/dist/queries/engine-compare.test.js.map +1 -0
- package/dist/queries/engine-landscape.d.ts +92 -0
- package/dist/queries/engine-landscape.d.ts.map +1 -0
- package/dist/queries/engine-landscape.js +183 -0
- package/dist/queries/engine-landscape.js.map +1 -0
- package/dist/queries/engine-landscape.test.d.ts +2 -0
- package/dist/queries/engine-landscape.test.d.ts.map +1 -0
- package/dist/queries/engine-landscape.test.js +171 -0
- package/dist/queries/engine-landscape.test.js.map +1 -0
- package/dist/queries/failures.d.ts +33 -0
- package/dist/queries/failures.d.ts.map +1 -0
- package/dist/queries/failures.js +31 -0
- package/dist/queries/failures.js.map +1 -0
- package/dist/queries/health.d.ts +77 -0
- package/dist/queries/health.d.ts.map +1 -0
- package/dist/queries/health.js +126 -0
- package/dist/queries/health.js.map +1 -0
- package/dist/queries/health.test.d.ts +2 -0
- package/dist/queries/health.test.d.ts.map +1 -0
- package/dist/queries/health.test.js +187 -0
- package/dist/queries/health.test.js.map +1 -0
- package/dist/queries/helpers.d.ts +184 -0
- package/dist/queries/helpers.d.ts.map +1 -0
- package/dist/queries/helpers.js +219 -0
- package/dist/queries/helpers.js.map +1 -0
- package/dist/queries/helpers.test.d.ts +2 -0
- package/dist/queries/helpers.test.d.ts.map +1 -0
- package/dist/queries/helpers.test.js +53 -0
- package/dist/queries/helpers.test.js.map +1 -0
- package/dist/queries/index.d.ts +19 -0
- package/dist/queries/index.d.ts.map +1 -0
- package/dist/queries/index.js +10 -0
- package/dist/queries/index.js.map +1 -0
- package/dist/queries/performance.d.ts +103 -0
- package/dist/queries/performance.d.ts.map +1 -0
- package/dist/queries/performance.js +173 -0
- package/dist/queries/performance.js.map +1 -0
- package/dist/queries/performance.test.d.ts +2 -0
- package/dist/queries/performance.test.d.ts.map +1 -0
- package/dist/queries/performance.test.js +265 -0
- package/dist/queries/performance.test.js.map +1 -0
- package/dist/queries/version-compare.d.ts +41 -0
- package/dist/queries/version-compare.d.ts.map +1 -0
- package/dist/queries/version-compare.js +44 -0
- package/dist/queries/version-compare.js.map +1 -0
- package/dist/queries/version-compare.test.d.ts +2 -0
- package/dist/queries/version-compare.test.d.ts.map +1 -0
- package/dist/queries/version-compare.test.js +162 -0
- package/dist/queries/version-compare.test.js.map +1 -0
- package/dist/queries/windows.d.ts +40 -0
- package/dist/queries/windows.d.ts.map +1 -0
- package/dist/queries/windows.js +56 -0
- package/dist/queries/windows.js.map +1 -0
- package/dist/query-honesty.test.d.ts +2 -0
- package/dist/query-honesty.test.d.ts.map +1 -0
- package/dist/query-honesty.test.js +294 -0
- package/dist/query-honesty.test.js.map +1 -0
- package/dist/query-scenarios.test-support.d.ts +49 -0
- package/dist/query-scenarios.test-support.d.ts.map +1 -0
- package/dist/query-scenarios.test-support.js +146 -0
- package/dist/query-scenarios.test-support.js.map +1 -0
- package/dist/schemas/cluster-compare.d.ts +11 -0
- package/dist/schemas/cluster-compare.d.ts.map +1 -0
- package/dist/schemas/cluster-compare.js +35 -0
- package/dist/schemas/cluster-compare.js.map +1 -0
- package/dist/schemas/engine-compare.d.ts +10 -0
- package/dist/schemas/engine-compare.d.ts.map +1 -0
- package/dist/schemas/engine-compare.js +27 -0
- package/dist/schemas/engine-compare.js.map +1 -0
- package/dist/schemas/engine-landscape.d.ts +5 -0
- package/dist/schemas/engine-landscape.d.ts.map +1 -0
- package/dist/schemas/engine-landscape.js +8 -0
- package/dist/schemas/engine-landscape.js.map +1 -0
- package/dist/schemas/failures.d.ts +8 -0
- package/dist/schemas/failures.d.ts.map +1 -0
- package/dist/schemas/failures.js +9 -0
- package/dist/schemas/failures.js.map +1 -0
- package/dist/schemas/health.d.ts +5 -0
- package/dist/schemas/health.d.ts.map +1 -0
- package/dist/schemas/health.js +6 -0
- package/dist/schemas/health.js.map +1 -0
- package/dist/schemas/index.d.ts +10 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +10 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/path.d.ts +15 -0
- package/dist/schemas/path.d.ts.map +1 -0
- package/dist/schemas/path.js +21 -0
- package/dist/schemas/path.js.map +1 -0
- package/dist/schemas/performance.d.ts +23 -0
- package/dist/schemas/performance.d.ts.map +1 -0
- package/dist/schemas/performance.js +21 -0
- package/dist/schemas/performance.js.map +1 -0
- package/dist/schemas/shared.d.ts +34 -0
- package/dist/schemas/shared.d.ts.map +1 -0
- package/dist/schemas/shared.js +34 -0
- package/dist/schemas/shared.js.map +1 -0
- package/dist/schemas/version-compare.d.ts +10 -0
- package/dist/schemas/version-compare.d.ts.map +1 -0
- package/dist/schemas/version-compare.js +25 -0
- package/dist/schemas/version-compare.js.map +1 -0
- package/dist/widgets.d.ts +138 -0
- package/dist/widgets.d.ts.map +1 -0
- package/dist/widgets.js +2 -0
- package/dist/widgets.js.map +1 -0
- package/metrics-contract.json +174 -0
- package/package.json +72 -5
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { elementBottleneck } from "./element.js";
|
|
3
|
+
/** Mock Prometheus client that dispatches canned samples by the PromQL it sees. */
|
|
4
|
+
function mockClient() {
|
|
5
|
+
const instant = vi.fn(async (q) => {
|
|
6
|
+
if (q.includes("activity_type")) {
|
|
7
|
+
return [
|
|
8
|
+
{ metric: { activity_id: "A", activity_type: "serviceTask" }, value: 10 },
|
|
9
|
+
{ metric: { activity_id: "B", activity_type: "userTask" }, value: 5 },
|
|
10
|
+
];
|
|
11
|
+
}
|
|
12
|
+
// Durations in ms, the histogram's unit.
|
|
13
|
+
if (q.includes("histogram_quantile")) {
|
|
14
|
+
return [
|
|
15
|
+
{ metric: { activity_id: "A" }, value: 15_000 },
|
|
16
|
+
{ metric: { activity_id: "B" }, value: 6_000 },
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
if (q.includes("duration_milliseconds_sum")) {
|
|
20
|
+
return [
|
|
21
|
+
{ metric: { activity_id: "A" }, value: 100_000 },
|
|
22
|
+
{ metric: { activity_id: "B" }, value: 20_000 },
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
if (q.includes("incident_created")) {
|
|
26
|
+
return [{ metric: { activity_id: "A" }, value: 2 }];
|
|
27
|
+
}
|
|
28
|
+
// counts: activity_ended_total grouped by activity_id only
|
|
29
|
+
return [
|
|
30
|
+
{ metric: { activity_id: "A" }, value: 10 },
|
|
31
|
+
{ metric: { activity_id: "B" }, value: 5 },
|
|
32
|
+
];
|
|
33
|
+
});
|
|
34
|
+
const ch = { instant };
|
|
35
|
+
return { ch, instant };
|
|
36
|
+
}
|
|
37
|
+
describe("elementBottleneck", () => {
|
|
38
|
+
it("ranks activities by time contribution and maps incident rate; wait time is null on metrics", async () => {
|
|
39
|
+
const { ch } = mockClient();
|
|
40
|
+
const res = await elementBottleneck(ch, {
|
|
41
|
+
processDefinitionKey: "miraveloLeasing",
|
|
42
|
+
period: "7d",
|
|
43
|
+
minBucketSize: 1,
|
|
44
|
+
maxResults: 10,
|
|
45
|
+
});
|
|
46
|
+
expect(res.activities).toHaveLength(2);
|
|
47
|
+
const [a, b] = res.activities;
|
|
48
|
+
expect(a).toMatchObject({
|
|
49
|
+
activity_id: "A",
|
|
50
|
+
activity_type: "serviceTask",
|
|
51
|
+
execution_count: 10,
|
|
52
|
+
avg_duration_sec: 10,
|
|
53
|
+
p95_duration_sec: 15,
|
|
54
|
+
total_time_sec: 100,
|
|
55
|
+
incident_count: 2,
|
|
56
|
+
incident_rate_pct: 20,
|
|
57
|
+
bottleneck_score_sec: 100,
|
|
58
|
+
avg_wait_sec: null,
|
|
59
|
+
total_wait_sec: null,
|
|
60
|
+
});
|
|
61
|
+
// B has fewer/shorter executions → ranked below A
|
|
62
|
+
expect(b.activity_id).toBe("B");
|
|
63
|
+
expect(b.incident_count).toBe(0);
|
|
64
|
+
expect(res.suppressedActivities).toBe(0);
|
|
65
|
+
});
|
|
66
|
+
it("suppresses activities below minBucketSize", async () => {
|
|
67
|
+
const { ch } = mockClient();
|
|
68
|
+
const res = await elementBottleneck(ch, {
|
|
69
|
+
processDefinitionKey: "miraveloLeasing",
|
|
70
|
+
period: "7d",
|
|
71
|
+
minBucketSize: 8,
|
|
72
|
+
maxResults: 10,
|
|
73
|
+
});
|
|
74
|
+
// only A (count 10) clears the threshold; B (count 5) is suppressed
|
|
75
|
+
expect(res.activities.map((r) => r.activity_id)).toEqual(["A"]);
|
|
76
|
+
expect(res.suppressedActivities).toBe(1);
|
|
77
|
+
});
|
|
78
|
+
it("reports a missing histogram sample as an unmeasured p95, never 0 s", async () => {
|
|
79
|
+
const instant = vi.fn(async (q) => q.includes("histogram_quantile") ||
|
|
80
|
+
q.includes("duration_milliseconds_sum") ||
|
|
81
|
+
q.includes("incident")
|
|
82
|
+
? []
|
|
83
|
+
: [{ metric: { activity_id: "A", activity_type: "serviceTask" }, value: 4 }]);
|
|
84
|
+
const res = await elementBottleneck({ instant }, { processDefinitionKey: "k", period: "7d", minBucketSize: 1, maxResults: 5 });
|
|
85
|
+
expect(res.activities[0]).toMatchObject({
|
|
86
|
+
execution_count: 4,
|
|
87
|
+
avg_duration_sec: null,
|
|
88
|
+
p95_duration_sec: null,
|
|
89
|
+
incident_rate_pct: 0,
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
it("scopes every query to the process definition key and period", async () => {
|
|
93
|
+
const { ch, instant } = mockClient();
|
|
94
|
+
await elementBottleneck(ch, {
|
|
95
|
+
processDefinitionKey: "myKey",
|
|
96
|
+
period: "30d",
|
|
97
|
+
minBucketSize: 1,
|
|
98
|
+
maxResults: 5,
|
|
99
|
+
});
|
|
100
|
+
const queries = instant.mock.calls.map((c) => c[0]);
|
|
101
|
+
expect(queries.every((q) => q.includes('process_definition_key="myKey"'))).toBe(true);
|
|
102
|
+
expect(queries.every((q) => q.includes("[30d]"))).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=element.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.test.js","sourceRoot":"","sources":["../../src/queries/element.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type PrometheusClient } from "../prometheus.js";
|
|
2
|
+
import { type CompareKpiDelta, type CompareKpis } from "./helpers.js";
|
|
3
|
+
export interface EngineCompareKpi extends CompareKpis {
|
|
4
|
+
engineId: string;
|
|
5
|
+
bucket: "engineA" | "engineB";
|
|
6
|
+
}
|
|
7
|
+
export type EngineCompareDelta = CompareKpiDelta;
|
|
8
|
+
export interface EngineCompareResult {
|
|
9
|
+
engineA: string;
|
|
10
|
+
engineB: string;
|
|
11
|
+
processDefinitionKey: string;
|
|
12
|
+
windowDays: number;
|
|
13
|
+
activityId: string | null;
|
|
14
|
+
minBucketSize: number;
|
|
15
|
+
suppressed: boolean;
|
|
16
|
+
kpis: EngineCompareKpi[];
|
|
17
|
+
delta: EngineCompareDelta;
|
|
18
|
+
/**
|
|
19
|
+
* When the figures were read from Prometheus (ISO timestamp): the "Stand"
|
|
20
|
+
* a view shows. Optional only for payloads recorded before it existed.
|
|
21
|
+
*/
|
|
22
|
+
asOf?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Side-by-side comparison of ONE process definition as it runs on two engines,
|
|
26
|
+
* over a shared rolling window. The engine is a metric label (`engine_id`) and
|
|
27
|
+
* all engines write to one Prometheus, so the partition is exact with no
|
|
28
|
+
* per-engine DB fan-out.
|
|
29
|
+
*
|
|
30
|
+
* `processDefinitionKey` is required by design. Comparing two engines' entire
|
|
31
|
+
* workloads would compare their PROCESS MIXES: engines host different
|
|
32
|
+
* processes, so an engine running an inherently error-prone process reads
|
|
33
|
+
* "worse" no matter how healthy it is — a textbook confound (the same
|
|
34
|
+
* aggregation can even invert the per-process truth, Simpson's paradox).
|
|
35
|
+
* Holding the process fixed is what makes a delta attributable to the engine.
|
|
36
|
+
* The cross-engine picture without that scope is `engineLandscape`, which
|
|
37
|
+
* reports mix-independent signals instead (absolute load, engine-owned job
|
|
38
|
+
* backlog) and names the keys deployed on several engines — the valid inputs
|
|
39
|
+
* here.
|
|
40
|
+
*
|
|
41
|
+
* `incident_count`/`incident_rate_pct` cover every activity; with `activityId`
|
|
42
|
+
* the `element_incident_*` fields add the count at that element.
|
|
43
|
+
*/
|
|
44
|
+
export declare function engineCompare(ch: PrometheusClient, params: {
|
|
45
|
+
processDefinitionKey: string;
|
|
46
|
+
engineA: string;
|
|
47
|
+
engineB: string;
|
|
48
|
+
windowDays: number;
|
|
49
|
+
activityId?: string;
|
|
50
|
+
minBucketSize: number;
|
|
51
|
+
}): Promise<EngineCompareResult>;
|
|
52
|
+
//# sourceMappingURL=engine-compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-compare.d.ts","sourceRoot":"","sources":["../../src/queries/engine-compare.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACpF,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,cAAc,CAAA;AAErB,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,SAAS,GAAG,SAAS,CAAA;CAC9B;AAED,MAAM,MAAM,kBAAkB,GAAG,eAAe,CAAA;AAEhD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,oBAAoB,EAAE,MAAM,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,OAAO,CAAA;IACnB,IAAI,EAAE,gBAAgB,EAAE,CAAA;IACxB,KAAK,EAAE,kBAAkB,CAAA;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,gBAAgB,EACpB,MAAM,EAAE;IACN,oBAAoB,EAAE,MAAM,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;CACtB,GACA,OAAO,CAAC,mBAAmB,CAAC,CAuB9B"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { escapeLabelValue, selector } from "../prometheus.js";
|
|
2
|
+
import { asOfNow, belowMinBucket, compareKpiDelta, queryCompareKpis, } from "./helpers.js";
|
|
3
|
+
/**
|
|
4
|
+
* Side-by-side comparison of ONE process definition as it runs on two engines,
|
|
5
|
+
* over a shared rolling window. The engine is a metric label (`engine_id`) and
|
|
6
|
+
* all engines write to one Prometheus, so the partition is exact with no
|
|
7
|
+
* per-engine DB fan-out.
|
|
8
|
+
*
|
|
9
|
+
* `processDefinitionKey` is required by design. Comparing two engines' entire
|
|
10
|
+
* workloads would compare their PROCESS MIXES: engines host different
|
|
11
|
+
* processes, so an engine running an inherently error-prone process reads
|
|
12
|
+
* "worse" no matter how healthy it is — a textbook confound (the same
|
|
13
|
+
* aggregation can even invert the per-process truth, Simpson's paradox).
|
|
14
|
+
* Holding the process fixed is what makes a delta attributable to the engine.
|
|
15
|
+
* The cross-engine picture without that scope is `engineLandscape`, which
|
|
16
|
+
* reports mix-independent signals instead (absolute load, engine-owned job
|
|
17
|
+
* backlog) and names the keys deployed on several engines — the valid inputs
|
|
18
|
+
* here.
|
|
19
|
+
*
|
|
20
|
+
* `incident_count`/`incident_rate_pct` cover every activity; with `activityId`
|
|
21
|
+
* the `element_incident_*` fields add the count at that element.
|
|
22
|
+
*/
|
|
23
|
+
export async function engineCompare(ch, params) {
|
|
24
|
+
const minBucket = Math.max(1, Math.floor(params.minBucketSize));
|
|
25
|
+
const windowDays = Math.max(1, Math.floor(params.windowDays));
|
|
26
|
+
const range = `${windowDays}d`;
|
|
27
|
+
const asOf = asOfNow();
|
|
28
|
+
const [a, b] = await Promise.all([
|
|
29
|
+
engineKpi(ch, params, "engineA", params.engineA, range),
|
|
30
|
+
engineKpi(ch, params, "engineB", params.engineB, range),
|
|
31
|
+
]);
|
|
32
|
+
return {
|
|
33
|
+
asOf,
|
|
34
|
+
engineA: params.engineA,
|
|
35
|
+
engineB: params.engineB,
|
|
36
|
+
processDefinitionKey: params.processDefinitionKey,
|
|
37
|
+
windowDays,
|
|
38
|
+
activityId: params.activityId ?? null,
|
|
39
|
+
minBucketSize: minBucket,
|
|
40
|
+
suppressed: belowMinBucket([a, b], minBucket),
|
|
41
|
+
kpis: [a, b],
|
|
42
|
+
delta: compareKpiDelta(a, b, { baseline: windowDays, other: windowDays }),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function engineKpi(ch, params, bucket, engineId, range) {
|
|
46
|
+
const engine = `engine_id="${escapeLabelValue(engineId)}"`;
|
|
47
|
+
const keyMatcher = `process_definition_key="${escapeLabelValue(params.processDefinitionKey)}"`;
|
|
48
|
+
const kpis = await queryCompareKpis(ch, {
|
|
49
|
+
sel: selector(keyMatcher, engine),
|
|
50
|
+
completedSel: selector(keyMatcher, `state="COMPLETED"`, engine),
|
|
51
|
+
elementIncidentSel: params.activityId
|
|
52
|
+
? selector(keyMatcher, `activity_id="${escapeLabelValue(params.activityId)}"`, engine)
|
|
53
|
+
: undefined,
|
|
54
|
+
}, { range });
|
|
55
|
+
return { engineId, bucket, ...kpis };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=engine-compare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-compare.js","sourceRoot":"","sources":["../../src/queries/engine-compare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAyB,MAAM,kBAAkB,CAAA;AACpF,OAAO,EACL,OAAO,EACP,cAAc,EACd,eAAe,EACf,gBAAgB,GAGjB,MAAM,cAAc,CAAA;AA0BrB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAoB,EACpB,MAOC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAA;IAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAA;IAC7D,MAAM,KAAK,GAAG,GAAG,UAAU,GAAG,CAAA;IAC9B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IAEtB,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC/B,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC;QACvD,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC;KACxD,CAAC,CAAA;IAEF,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;QACjD,UAAU;QACV,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,IAAI;QACrC,aAAa,EAAE,SAAS;QACxB,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC;QAC7C,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACZ,KAAK,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;KAC1E,CAAA;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,EAAoB,EACpB,MAA6D,EAC7D,MAA6B,EAC7B,QAAgB,EAChB,KAAa;IAEb,MAAM,MAAM,GAAG,cAAc,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAA;IAC1D,MAAM,UAAU,GAAG,2BAA2B,gBAAgB,CAAC,MAAM,CAAC,oBAAoB,CAAC,GAAG,CAAA;IAC9F,MAAM,IAAI,GAAG,MAAM,gBAAgB,CACjC,EAAE,EACF;QACE,GAAG,EAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QACjC,YAAY,EAAE,QAAQ,CAAC,UAAU,EAAE,mBAAmB,EAAE,MAAM,CAAC;QAC/D,kBAAkB,EAAE,MAAM,CAAC,UAAU;YACnC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;YACtF,CAAC,CAAC,SAAS;KACd,EACD,EAAE,KAAK,EAAE,CACV,CAAA;IACD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAAA;AACtC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-compare.test.d.ts","sourceRoot":"","sources":["../../src/queries/engine-compare.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { engineCompare } from "./engine-compare.js";
|
|
3
|
+
const v = (value) => ({ metric: {}, value });
|
|
4
|
+
/** Mock Prometheus client with distinct canned KPIs per engine_id partition. */
|
|
5
|
+
function mockClient(byEngine = {
|
|
6
|
+
"prod-a": { started: 100, completed: 80, incidents: 10, avg: 10, p95: 20 },
|
|
7
|
+
"prod-b": { started: 50, completed: 40, incidents: 10, avg: 12, p95: 30 },
|
|
8
|
+
}) {
|
|
9
|
+
const instant = vi.fn(async (q) => {
|
|
10
|
+
const engine = q.includes('engine_id="prod-a"') ? byEngine["prod-a"] : byEngine["prod-b"];
|
|
11
|
+
const maybe = (value) => (value === null ? [] : [v(value)]);
|
|
12
|
+
// Canned durations are seconds; the histogram answers in ms.
|
|
13
|
+
const ms = (sec) => (sec === null ? null : sec * 1000);
|
|
14
|
+
if (q.includes("histogram_quantile"))
|
|
15
|
+
return maybe(ms(engine.p95));
|
|
16
|
+
if (q.includes("duration_milliseconds_sum"))
|
|
17
|
+
return maybe(ms(engine.avg));
|
|
18
|
+
if (q.includes("incident_created") && q.includes("activity_id")) {
|
|
19
|
+
return [v(engine.elementIncidents ?? 0)];
|
|
20
|
+
}
|
|
21
|
+
if (q.includes("incident_created"))
|
|
22
|
+
return [v(engine.incidents)];
|
|
23
|
+
if (q.includes('state="COMPLETED"'))
|
|
24
|
+
return [v(engine.completed)];
|
|
25
|
+
return [v(engine.started)];
|
|
26
|
+
});
|
|
27
|
+
const ch = { instant };
|
|
28
|
+
return { ch, instant };
|
|
29
|
+
}
|
|
30
|
+
const params = {
|
|
31
|
+
processDefinitionKey: "order",
|
|
32
|
+
engineA: "prod-a",
|
|
33
|
+
engineB: "prod-b",
|
|
34
|
+
windowDays: 14,
|
|
35
|
+
minBucketSize: 10,
|
|
36
|
+
};
|
|
37
|
+
describe("engineCompare", () => {
|
|
38
|
+
it("computes per-engine KPIs and the B-vs-A delta for one process", async () => {
|
|
39
|
+
const { ch } = mockClient();
|
|
40
|
+
const res = await engineCompare(ch, params);
|
|
41
|
+
expect(res).toMatchObject({
|
|
42
|
+
engineA: "prod-a",
|
|
43
|
+
engineB: "prod-b",
|
|
44
|
+
processDefinitionKey: "order",
|
|
45
|
+
windowDays: 14,
|
|
46
|
+
activityId: null,
|
|
47
|
+
minBucketSize: 10,
|
|
48
|
+
suppressed: false,
|
|
49
|
+
});
|
|
50
|
+
expect(res.kpis).toEqual([
|
|
51
|
+
{
|
|
52
|
+
engineId: "prod-a",
|
|
53
|
+
bucket: "engineA",
|
|
54
|
+
instance_count: 100,
|
|
55
|
+
completed_count: 80,
|
|
56
|
+
incident_count: 10,
|
|
57
|
+
incident_rate_pct: 10,
|
|
58
|
+
element_incident_count: null,
|
|
59
|
+
element_incident_rate_pct: null,
|
|
60
|
+
avg_duration_sec: 10,
|
|
61
|
+
p95_duration_sec: 20,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
engineId: "prod-b",
|
|
65
|
+
bucket: "engineB",
|
|
66
|
+
instance_count: 50,
|
|
67
|
+
completed_count: 40,
|
|
68
|
+
incident_count: 10,
|
|
69
|
+
incident_rate_pct: 20,
|
|
70
|
+
element_incident_count: null,
|
|
71
|
+
element_incident_rate_pct: null,
|
|
72
|
+
avg_duration_sec: 12,
|
|
73
|
+
p95_duration_sec: 30,
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
expect(res.delta).toEqual({
|
|
77
|
+
started_per_day_delta_pct: -50,
|
|
78
|
+
incident_rate_delta_pp: 10,
|
|
79
|
+
element_incident_rate_delta_pp: null,
|
|
80
|
+
avg_duration_delta_pct: 20,
|
|
81
|
+
p95_duration_delta_pct: 50,
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
it("reports the element's incidents NEXT TO the process-wide ones, never instead", async () => {
|
|
85
|
+
const { ch, instant } = mockClient({
|
|
86
|
+
"prod-a": {
|
|
87
|
+
started: 100,
|
|
88
|
+
completed: 80,
|
|
89
|
+
incidents: 10,
|
|
90
|
+
elementIncidents: 4,
|
|
91
|
+
avg: 10,
|
|
92
|
+
p95: 20,
|
|
93
|
+
},
|
|
94
|
+
"prod-b": {
|
|
95
|
+
started: 50,
|
|
96
|
+
completed: 40,
|
|
97
|
+
incidents: 10,
|
|
98
|
+
elementIncidents: 1,
|
|
99
|
+
avg: 12,
|
|
100
|
+
p95: 30,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
const res = await engineCompare(ch, { ...params, activityId: "Task_check" });
|
|
104
|
+
expect(res.kpis.map((k) => [k.incident_rate_pct, k.element_incident_rate_pct])).toEqual([
|
|
105
|
+
[10, 4],
|
|
106
|
+
[20, 2],
|
|
107
|
+
]);
|
|
108
|
+
expect(res.delta.element_incident_rate_delta_pp).toBe(-2);
|
|
109
|
+
// One extra query per engine, only for the element count.
|
|
110
|
+
expect(instant.mock.calls.filter(([q]) => q.includes('activity_id="Task_check"'))).toHaveLength(2);
|
|
111
|
+
});
|
|
112
|
+
it("flags the comparison as suppressed when one engine misses minBucketSize", async () => {
|
|
113
|
+
const { ch } = mockClient();
|
|
114
|
+
// prod-b only has 50 instances
|
|
115
|
+
expect((await engineCompare(ch, { ...params, minBucketSize: 60 })).suppressed).toBe(true);
|
|
116
|
+
});
|
|
117
|
+
it("flags it suppressed when too few instances COMPLETED — the durations' sample", async () => {
|
|
118
|
+
const { ch } = mockClient({
|
|
119
|
+
"prod-a": { started: 100, completed: 80, incidents: 0, avg: 10, p95: 20 },
|
|
120
|
+
"prod-b": { started: 100, completed: 3, incidents: 0, avg: 1, p95: 2 },
|
|
121
|
+
});
|
|
122
|
+
expect((await engineCompare(ch, params)).suppressed).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
it("reads 'nothing ended' as an unmeasured duration and suppresses its delta (N78)", async () => {
|
|
125
|
+
// prod-b started work but nothing ended yet: the duration ratio is NaN,
|
|
126
|
+
// which the client drops — formerly a 0 s duration and a −100 % delta.
|
|
127
|
+
const { ch } = mockClient({
|
|
128
|
+
"prod-a": { started: 100, completed: 80, incidents: 5, avg: 10, p95: 20 },
|
|
129
|
+
"prod-b": { started: 40, completed: 0, incidents: 0, avg: null, p95: null },
|
|
130
|
+
});
|
|
131
|
+
const res = await engineCompare(ch, params);
|
|
132
|
+
expect(res.kpis[1]).toMatchObject({ avg_duration_sec: null, p95_duration_sec: null });
|
|
133
|
+
expect(res.delta.avg_duration_delta_pct).toBeNull();
|
|
134
|
+
expect(res.delta.p95_duration_delta_pct).toBeNull();
|
|
135
|
+
expect(res.suppressed).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
it("returns null deltas instead of dividing by a zero baseline", async () => {
|
|
138
|
+
const instant = vi.fn(async () => []);
|
|
139
|
+
const res = await engineCompare({ instant }, { ...params, windowDays: 7, minBucketSize: 1 });
|
|
140
|
+
expect(res.suppressed).toBe(true);
|
|
141
|
+
expect(Object.values(res.delta).every((d) => d === null)).toBe(true);
|
|
142
|
+
expect(res.kpis.every((k) => k.incident_rate_pct === null)).toBe(true);
|
|
143
|
+
});
|
|
144
|
+
it("partitions every query by exactly one engine_id and always holds the process fixed", async () => {
|
|
145
|
+
const { ch, instant } = mockClient();
|
|
146
|
+
await engineCompare(ch, params);
|
|
147
|
+
const queries = instant.mock.calls.map((c) => c[0]);
|
|
148
|
+
expect(queries).toHaveLength(10);
|
|
149
|
+
const aQueries = queries.filter((q) => q.includes('engine_id="prod-a"'));
|
|
150
|
+
const bQueries = queries.filter((q) => q.includes('engine_id="prod-b"'));
|
|
151
|
+
expect(aQueries).toHaveLength(5);
|
|
152
|
+
expect(bQueries).toHaveLength(5);
|
|
153
|
+
// The scope that makes the delta attributable to the engine rather than to
|
|
154
|
+
// a different process mix — never absent.
|
|
155
|
+
expect(queries.every((q) => q.includes('process_definition_key="order"'))).toBe(true);
|
|
156
|
+
expect(queries.every((q) => q.includes("[14d]"))).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
//# sourceMappingURL=engine-compare.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-compare.test.js","sourceRoot":"","sources":["../../src/queries/engine-compare.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { type EngineFilterInput, type PrometheusClient } from "../prometheus.js";
|
|
2
|
+
/**
|
|
3
|
+
* Per-engine row of the landscape. Absolute counts only — see the module note.
|
|
4
|
+
* Every count is `null` for an engine that reports nothing (`reporting:
|
|
5
|
+
* false`): its figures are unknown, never a plausible 0.
|
|
6
|
+
*/
|
|
7
|
+
export interface EngineLandscapeEngine {
|
|
8
|
+
engineId: string;
|
|
9
|
+
/**
|
|
10
|
+
* `false` when the engine contributed no series at all: the plugin is down,
|
|
11
|
+
* the engine is unreachable, or it was never scraped. Only reachable when the
|
|
12
|
+
* caller passes the expected engine ids — an engine that reports nothing is
|
|
13
|
+
* otherwise indistinguishable from one that does not exist.
|
|
14
|
+
*/
|
|
15
|
+
reporting: boolean;
|
|
16
|
+
runningInstances: number | null;
|
|
17
|
+
openIncidents: number | null;
|
|
18
|
+
failedJobs: number | null;
|
|
19
|
+
executableJobs: number | null;
|
|
20
|
+
suspendedJobs: number | null;
|
|
21
|
+
jobsDueFuture: number | null;
|
|
22
|
+
openExternalTasks: number | null;
|
|
23
|
+
deployedDefinitionKeys: number | null;
|
|
24
|
+
/** Keys present on this engine only — the load no other engine shares. */
|
|
25
|
+
exclusiveDefinitionKeys: number | null;
|
|
26
|
+
}
|
|
27
|
+
/** One row of the process × engine inventory matrix. */
|
|
28
|
+
export interface EngineLandscapeProcess {
|
|
29
|
+
processDefinitionKey: string;
|
|
30
|
+
/** Engines this key is deployed on (or reports live state for), ascending. */
|
|
31
|
+
engineIds: string[];
|
|
32
|
+
/** Present on ≥2 engines — the only case where an A/B engine compare holds. */
|
|
33
|
+
shared: boolean;
|
|
34
|
+
/** Running instances per engine id; engines without running work are absent. */
|
|
35
|
+
runningByEngine: Record<string, number>;
|
|
36
|
+
runningTotal: number;
|
|
37
|
+
openIncidentsTotal: number;
|
|
38
|
+
failedJobsTotal: number;
|
|
39
|
+
}
|
|
40
|
+
export interface EngineLandscapeResult {
|
|
41
|
+
/** Ascending by engine id — deliberately not a ranking (see the module note). */
|
|
42
|
+
engines: EngineLandscapeEngine[];
|
|
43
|
+
/** Shared keys first, then by running instances descending, then by key. */
|
|
44
|
+
processes: EngineLandscapeProcess[];
|
|
45
|
+
/** Keys present on ≥2 engines — the valid drill-down targets for engineCompare. */
|
|
46
|
+
sharedProcessKeys: string[];
|
|
47
|
+
totals: {
|
|
48
|
+
engineCount: number;
|
|
49
|
+
reportingEngineCount: number;
|
|
50
|
+
processKeyCount: number;
|
|
51
|
+
sharedProcessKeyCount: number;
|
|
52
|
+
/** The sums over the reporting engines; `null` while no engine reports (unknown, not 0). */
|
|
53
|
+
runningInstances: number | null;
|
|
54
|
+
openIncidents: number | null;
|
|
55
|
+
failedJobs: number | null;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* When the figures were read from Prometheus (ISO timestamp): the "Stand"
|
|
59
|
+
* a view shows. Optional only for payloads recorded before it existed.
|
|
60
|
+
*/
|
|
61
|
+
asOf?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Cross-engine landscape: what runs where, how much of it, and which engines
|
|
65
|
+
* carry a backlog.
|
|
66
|
+
*
|
|
67
|
+
* Deliberately NOT an engine-vs-engine scoreboard. Rates (failure rate,
|
|
68
|
+
* incident rate, duration) aggregated per engine measure that engine's PROCESS
|
|
69
|
+
* MIX, not the engine: an engine hosting an inherently error-prone process
|
|
70
|
+
* reads "unhealthy" while running perfectly. So this query reports the two
|
|
71
|
+
* things that survive a different mix per engine:
|
|
72
|
+
*
|
|
73
|
+
* 1. Absolute counts (running instances, open incidents, failed jobs) — they
|
|
74
|
+
* say where work and trouble physically sit, which is what an operator
|
|
75
|
+
* acts on, and they stay additive across engines.
|
|
76
|
+
* 2. The engine-owned backlog gauges (`jobs_executable`, `jobs_suspended`,
|
|
77
|
+
* `jobs_due_future`, `external_tasks_open`), whose contract labels are
|
|
78
|
+
* `engine_id` ONLY. With no process dimension there is no mix to confound
|
|
79
|
+
* them, so these genuinely do rank engines against each other.
|
|
80
|
+
*
|
|
81
|
+
* The inventory matrix then names the one place a KPI comparison IS sound: a
|
|
82
|
+
* process definition key present on two or more engines (`sharedProcessKeys`)
|
|
83
|
+
* — the drill-down {@link engineCompare} requires.
|
|
84
|
+
*
|
|
85
|
+
* Pass `engine` as the array of CONFIGURED engine ids to also surface engines
|
|
86
|
+
* that report nothing (`reporting: false`); without it the landscape can only
|
|
87
|
+
* show engines Prometheus has series for.
|
|
88
|
+
*/
|
|
89
|
+
export declare function engineLandscape(ch: PrometheusClient, params?: {
|
|
90
|
+
engine?: EngineFilterInput;
|
|
91
|
+
}): Promise<EngineLandscapeResult>;
|
|
92
|
+
//# sourceMappingURL=engine-landscape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-landscape.d.ts","sourceRoot":"","sources":["../../src/queries/engine-landscape.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EAEtB,MAAM,kBAAkB,CAAA;AAQzB;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,SAAS,EAAE,OAAO,CAAA;IAIlB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAIzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAEhC,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,0EAA0E;IAC1E,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAA;CACvC;AAED,wDAAwD;AACxD,MAAM,WAAW,sBAAsB;IACrC,oBAAoB,EAAE,MAAM,CAAA;IAC5B,8EAA8E;IAC9E,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,+EAA+E;IAC/E,MAAM,EAAE,OAAO,CAAA;IACf,gFAAgF;IAChF,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC,YAAY,EAAE,MAAM,CAAA;IACpB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,OAAO,EAAE,qBAAqB,EAAE,CAAA;IAChC,4EAA4E;IAC5E,SAAS,EAAE,sBAAsB,EAAE,CAAA;IACnC,mFAAmF;IACnF,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,MAAM,EAAE;QACN,WAAW,EAAE,MAAM,CAAA;QACnB,oBAAoB,EAAE,MAAM,CAAA;QAC5B,eAAe,EAAE,MAAM,CAAA;QACvB,qBAAqB,EAAE,MAAM,CAAA;QAC7B,4FAA4F;QAC5F,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;QAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;QAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAC1B,CAAA;IACD;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AASD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,gBAAgB,EACpB,MAAM,GAAE;IAAE,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAAO,GAC1C,OAAO,CAAC,qBAAqB,CAAC,CA4HhC"}
|