@checkstack/healthcheck-script-backend 0.2.0 → 0.3.1
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/CHANGELOG.md +48 -0
- package/package.json +4 -4
- package/src/execute-collector.test.ts +3 -3
- package/src/execute-collector.ts +20 -34
- package/src/inline-script-collector.test.ts +2 -2
- package/src/inline-script-collector.ts +19 -35
- package/src/strategy.test.ts +7 -7
- package/src/strategy.ts +31 -65
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
# @checkstack/healthcheck-script-backend
|
|
2
2
|
|
|
3
|
+
## 0.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 869b4ab: ## Health Check Execution Improvements
|
|
8
|
+
|
|
9
|
+
### Breaking Changes (backend-api)
|
|
10
|
+
|
|
11
|
+
- `HealthCheckStrategy.createClient()` now accepts `unknown` instead of `TConfig` due to TypeScript contravariance constraints. Implementations should use `this.config.validate(config)` to narrow the type.
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- **Platform-level hard timeout**: The executor now wraps the entire health check execution (connection + all collectors) in a single timeout, ensuring checks never hang indefinitely.
|
|
16
|
+
- **Parallel collector execution**: Collectors now run in parallel using `Promise.allSettled()`, improving performance while ensuring all collectors complete regardless of individual failures.
|
|
17
|
+
- **Base strategy config schema**: All strategy configs now extend `baseStrategyConfigSchema` which provides a standardized `timeout` field with sensible defaults (30s, min 100ms).
|
|
18
|
+
|
|
19
|
+
### Fixes
|
|
20
|
+
|
|
21
|
+
- Fixed HTTP and Jenkins strategies clearing timeouts before reading the full response body.
|
|
22
|
+
- Simplified registry type signatures by using default type parameters.
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [869b4ab]
|
|
25
|
+
- @checkstack/backend-api@0.8.0
|
|
26
|
+
|
|
27
|
+
## 0.3.0
|
|
28
|
+
|
|
29
|
+
### Minor Changes
|
|
30
|
+
|
|
31
|
+
- 3dd1914: Migrate health check strategies to VersionedAggregated with \_type discriminator
|
|
32
|
+
|
|
33
|
+
All 13 health check strategies now use `VersionedAggregated` for their `aggregatedResult` property, enabling automatic bucket merging with 100% mathematical fidelity.
|
|
34
|
+
|
|
35
|
+
**Key changes:**
|
|
36
|
+
|
|
37
|
+
- **`_type` discriminator**: All aggregated state objects now include a required `_type` field (`"average"`, `"rate"`, `"counter"`, `"minmax"`) for reliable type detection
|
|
38
|
+
- The `HealthCheckStrategy` interface now requires `aggregatedResult` to be a `VersionedAggregated<AggregatedResultShape>`
|
|
39
|
+
- Strategy/collector `mergeResult` methods return state objects with `_type` (e.g., `{ _type: "average", _sum, _count, avg }`)
|
|
40
|
+
- `mergeAggregatedBucketResults`, `combineBuckets`, and `reaggregateBuckets` now require `registry` and `strategyId` parameters
|
|
41
|
+
- `HealthCheckService` constructor now requires both `registry` and `collectorRegistry` parameters
|
|
42
|
+
- Frontend `extractComputedValue` now uses `_type` discriminator for robust type detection
|
|
43
|
+
|
|
44
|
+
**Breaking Change**: State objects now require `_type`. Merge functions automatically add `_type` to output. The bucket merging functions and `HealthCheckService` now require additional required parameters.
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- Updated dependencies [3dd1914]
|
|
49
|
+
- @checkstack/backend-api@0.7.0
|
|
50
|
+
|
|
3
51
|
## 0.2.0
|
|
4
52
|
|
|
5
53
|
### Minor Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/healthcheck-script-backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"lint:code": "eslint . --max-warnings 0"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@checkstack/backend-api": "0.
|
|
13
|
-
"@checkstack/common": "0.6.
|
|
14
|
-
"@checkstack/healthcheck-common": "0.8.
|
|
12
|
+
"@checkstack/backend-api": "0.7.0",
|
|
13
|
+
"@checkstack/common": "0.6.2",
|
|
14
|
+
"@checkstack/healthcheck-common": "0.8.2"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@types/bun": "^1.0.0",
|
|
@@ -139,8 +139,8 @@ describe("ExecuteCollector", () => {
|
|
|
139
139
|
let aggregated = collector.mergeResult(undefined, runs[0]);
|
|
140
140
|
aggregated = collector.mergeResult(aggregated, runs[1]);
|
|
141
141
|
|
|
142
|
-
expect(aggregated.avgExecutionTimeMs).toBe(75);
|
|
143
|
-
expect(aggregated.successRate).toBe(100);
|
|
142
|
+
expect(aggregated.avgExecutionTimeMs.avg).toBe(75);
|
|
143
|
+
expect(aggregated.successRate.rate).toBe(100);
|
|
144
144
|
});
|
|
145
145
|
|
|
146
146
|
it("should calculate success rate correctly", () => {
|
|
@@ -181,7 +181,7 @@ describe("ExecuteCollector", () => {
|
|
|
181
181
|
let aggregated = collector.mergeResult(undefined, runs[0]);
|
|
182
182
|
aggregated = collector.mergeResult(aggregated, runs[1]);
|
|
183
183
|
|
|
184
|
-
expect(aggregated.successRate).toBe(50);
|
|
184
|
+
expect(aggregated.successRate.rate).toBe(50);
|
|
185
185
|
});
|
|
186
186
|
});
|
|
187
187
|
|
package/src/execute-collector.ts
CHANGED
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
type CollectorResult,
|
|
7
7
|
type CollectorStrategy,
|
|
8
8
|
mergeAverage,
|
|
9
|
-
averageStateSchema,
|
|
10
9
|
mergeRate,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
VersionedAggregated,
|
|
11
|
+
aggregatedAverage,
|
|
12
|
+
aggregatedRate,
|
|
13
|
+
type InferAggregatedResult,
|
|
14
14
|
} from "@checkstack/backend-api";
|
|
15
15
|
import {
|
|
16
16
|
healthResultNumber,
|
|
@@ -78,29 +78,24 @@ const executeResultSchema = healthResultSchema({
|
|
|
78
78
|
|
|
79
79
|
export type ExecuteResult = z.infer<typeof executeResultSchema>;
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
// Aggregated result fields definition
|
|
82
|
+
const executeAggregatedFields = {
|
|
83
|
+
avgExecutionTimeMs: aggregatedAverage({
|
|
83
84
|
"x-chart-type": "line",
|
|
84
85
|
"x-chart-label": "Avg Execution Time",
|
|
85
86
|
"x-chart-unit": "ms",
|
|
86
87
|
}),
|
|
87
|
-
successRate:
|
|
88
|
+
successRate: aggregatedRate({
|
|
88
89
|
"x-chart-type": "gauge",
|
|
89
90
|
"x-chart-label": "Success Rate",
|
|
90
91
|
"x-chart-unit": "%",
|
|
91
92
|
}),
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const executeAggregatedInternalSchema = z.object({
|
|
95
|
-
_executionTime: averageStateSchema.optional(),
|
|
96
|
-
_success: rateStateSchema.optional(),
|
|
97
|
-
});
|
|
93
|
+
};
|
|
98
94
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
export type ExecuteAggregatedResult = z.infer<typeof executeAggregatedSchema>;
|
|
95
|
+
// Type inferred from field definitions
|
|
96
|
+
export type ExecuteAggregatedResult = InferAggregatedResult<
|
|
97
|
+
typeof executeAggregatedFields
|
|
98
|
+
>;
|
|
104
99
|
|
|
105
100
|
// ============================================================================
|
|
106
101
|
// EXECUTE COLLECTOR
|
|
@@ -126,9 +121,9 @@ export class ExecuteCollector implements CollectorStrategy<
|
|
|
126
121
|
|
|
127
122
|
config = new Versioned({ version: 1, schema: executeConfigSchema });
|
|
128
123
|
result = new Versioned({ version: 1, schema: executeResultSchema });
|
|
129
|
-
aggregatedResult = new
|
|
124
|
+
aggregatedResult = new VersionedAggregated({
|
|
130
125
|
version: 1,
|
|
131
|
-
|
|
126
|
+
fields: executeAggregatedFields,
|
|
132
127
|
});
|
|
133
128
|
|
|
134
129
|
async execute({
|
|
@@ -173,21 +168,12 @@ export class ExecuteCollector implements CollectorStrategy<
|
|
|
173
168
|
): ExecuteAggregatedResult {
|
|
174
169
|
const metadata = run.metadata;
|
|
175
170
|
|
|
176
|
-
const executionTimeState = mergeAverage(
|
|
177
|
-
existing?._executionTime as AverageState | undefined,
|
|
178
|
-
metadata?.executionTimeMs,
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
const successState = mergeRate(
|
|
182
|
-
existing?._success as RateState | undefined,
|
|
183
|
-
metadata?.success,
|
|
184
|
-
);
|
|
185
|
-
|
|
186
171
|
return {
|
|
187
|
-
avgExecutionTimeMs:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
172
|
+
avgExecutionTimeMs: mergeAverage(
|
|
173
|
+
existing?.avgExecutionTimeMs,
|
|
174
|
+
metadata?.executionTimeMs,
|
|
175
|
+
),
|
|
176
|
+
successRate: mergeRate(existing?.successRate, metadata?.success),
|
|
191
177
|
};
|
|
192
178
|
}
|
|
193
179
|
}
|
|
@@ -249,8 +249,8 @@ describe("InlineScriptCollector", () => {
|
|
|
249
249
|
aggregated = collector.mergeResult(aggregated, run2 as never);
|
|
250
250
|
aggregated = collector.mergeResult(aggregated, run3 as never);
|
|
251
251
|
|
|
252
|
-
expect(aggregated.avgExecutionTimeMs).toBe(150); // (100+200+150)/3
|
|
253
|
-
expect(aggregated.successRate).toBeCloseTo(67, 0); // 2/3 * 100 = ~67
|
|
252
|
+
expect(aggregated.avgExecutionTimeMs.avg).toBe(150); // (100+200+150)/3
|
|
253
|
+
expect(aggregated.successRate.rate).toBeCloseTo(67, 0); // 2/3 * 100 = ~67
|
|
254
254
|
});
|
|
255
255
|
});
|
|
256
256
|
});
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
type CollectorResult,
|
|
8
8
|
type CollectorStrategy,
|
|
9
9
|
mergeAverage,
|
|
10
|
-
averageStateSchema,
|
|
11
10
|
mergeRate,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
VersionedAggregated,
|
|
12
|
+
aggregatedAverage,
|
|
13
|
+
aggregatedRate,
|
|
14
|
+
type InferAggregatedResult,
|
|
15
15
|
} from "@checkstack/backend-api";
|
|
16
16
|
import {
|
|
17
17
|
healthResultNumber,
|
|
@@ -179,30 +179,23 @@ const inlineScriptResultSchema = healthResultSchema({
|
|
|
179
179
|
|
|
180
180
|
export type InlineScriptResult = z.infer<typeof inlineScriptResultSchema>;
|
|
181
181
|
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
// Aggregated result fields definition
|
|
183
|
+
const inlineScriptAggregatedFields = {
|
|
184
|
+
avgExecutionTimeMs: aggregatedAverage({
|
|
184
185
|
"x-chart-type": "line",
|
|
185
186
|
"x-chart-label": "Avg Execution Time",
|
|
186
187
|
"x-chart-unit": "ms",
|
|
187
188
|
}),
|
|
188
|
-
successRate:
|
|
189
|
+
successRate: aggregatedRate({
|
|
189
190
|
"x-chart-type": "gauge",
|
|
190
191
|
"x-chart-label": "Success Rate",
|
|
191
192
|
"x-chart-unit": "%",
|
|
192
193
|
}),
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const inlineScriptAggregatedInternalSchema = z.object({
|
|
196
|
-
_executionTime: averageStateSchema.optional(),
|
|
197
|
-
_success: rateStateSchema.optional(),
|
|
198
|
-
});
|
|
194
|
+
};
|
|
199
195
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
export type InlineScriptAggregatedResult = z.infer<
|
|
205
|
-
typeof inlineScriptAggregatedSchema
|
|
196
|
+
// Type inferred from field definitions
|
|
197
|
+
export type InlineScriptAggregatedResult = InferAggregatedResult<
|
|
198
|
+
typeof inlineScriptAggregatedFields
|
|
206
199
|
>;
|
|
207
200
|
|
|
208
201
|
// ============================================================================
|
|
@@ -253,9 +246,9 @@ export class InlineScriptCollector implements CollectorStrategy<
|
|
|
253
246
|
|
|
254
247
|
config = new Versioned({ version: 1, schema: inlineScriptConfigSchema });
|
|
255
248
|
result = new Versioned({ version: 1, schema: inlineScriptResultSchema });
|
|
256
|
-
aggregatedResult = new
|
|
249
|
+
aggregatedResult = new VersionedAggregated({
|
|
257
250
|
version: 1,
|
|
258
|
-
|
|
251
|
+
fields: inlineScriptAggregatedFields,
|
|
259
252
|
});
|
|
260
253
|
|
|
261
254
|
async execute({
|
|
@@ -344,21 +337,12 @@ export class InlineScriptCollector implements CollectorStrategy<
|
|
|
344
337
|
): InlineScriptAggregatedResult {
|
|
345
338
|
const metadata = run.metadata;
|
|
346
339
|
|
|
347
|
-
const executionTimeState = mergeAverage(
|
|
348
|
-
existing?._executionTime as AverageState | undefined,
|
|
349
|
-
metadata?.executionTimeMs,
|
|
350
|
-
);
|
|
351
|
-
|
|
352
|
-
const successState = mergeRate(
|
|
353
|
-
existing?._success as RateState | undefined,
|
|
354
|
-
metadata?.success,
|
|
355
|
-
);
|
|
356
|
-
|
|
357
340
|
return {
|
|
358
|
-
avgExecutionTimeMs:
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
341
|
+
avgExecutionTimeMs: mergeAverage(
|
|
342
|
+
existing?.avgExecutionTimeMs,
|
|
343
|
+
metadata?.executionTimeMs,
|
|
344
|
+
),
|
|
345
|
+
successRate: mergeRate(existing?.successRate, metadata?.success),
|
|
362
346
|
};
|
|
363
347
|
}
|
|
364
348
|
}
|
package/src/strategy.test.ts
CHANGED
|
@@ -175,10 +175,10 @@ describe("ScriptHealthCheckStrategy", () => {
|
|
|
175
175
|
let aggregated = strategy.mergeResult(undefined, runs[0]);
|
|
176
176
|
aggregated = strategy.mergeResult(aggregated, runs[1]);
|
|
177
177
|
|
|
178
|
-
expect(aggregated.avgExecutionTime).toBe(75);
|
|
179
|
-
expect(aggregated.successRate).toBe(100);
|
|
180
|
-
expect(aggregated.errorCount).toBe(0);
|
|
181
|
-
expect(aggregated.timeoutCount).toBe(0);
|
|
178
|
+
expect(aggregated.avgExecutionTime.avg).toBe(75);
|
|
179
|
+
expect(aggregated.successRate.rate).toBe(100);
|
|
180
|
+
expect(aggregated.errorCount.count).toBe(0);
|
|
181
|
+
expect(aggregated.timeoutCount.count).toBe(0);
|
|
182
182
|
});
|
|
183
183
|
|
|
184
184
|
it("should count errors and timeouts", () => {
|
|
@@ -217,9 +217,9 @@ describe("ScriptHealthCheckStrategy", () => {
|
|
|
217
217
|
let aggregated = strategy.mergeResult(undefined, runs[0]);
|
|
218
218
|
aggregated = strategy.mergeResult(aggregated, runs[1]);
|
|
219
219
|
|
|
220
|
-
expect(aggregated.errorCount).toBe(1);
|
|
221
|
-
expect(aggregated.timeoutCount).toBe(1);
|
|
222
|
-
expect(aggregated.successRate).toBe(0);
|
|
220
|
+
expect(aggregated.errorCount.count).toBe(1);
|
|
221
|
+
expect(aggregated.timeoutCount.count).toBe(1);
|
|
222
|
+
expect(aggregated.successRate.rate).toBe(0);
|
|
223
223
|
});
|
|
224
224
|
});
|
|
225
225
|
});
|
package/src/strategy.ts
CHANGED
|
@@ -3,17 +3,17 @@ import {
|
|
|
3
3
|
HealthCheckStrategy,
|
|
4
4
|
HealthCheckRunForAggregation,
|
|
5
5
|
Versioned,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
VersionedAggregated,
|
|
7
|
+
aggregatedAverage,
|
|
8
|
+
aggregatedRate,
|
|
9
|
+
aggregatedCounter,
|
|
8
10
|
mergeAverage,
|
|
9
|
-
averageStateSchema,
|
|
10
11
|
mergeRate,
|
|
11
|
-
rateStateSchema,
|
|
12
12
|
mergeCounter,
|
|
13
|
-
|
|
14
|
-
type
|
|
15
|
-
type
|
|
16
|
-
|
|
13
|
+
z,
|
|
14
|
+
type ConnectedClient,
|
|
15
|
+
type InferAggregatedResult,
|
|
16
|
+
baseStrategyConfigSchema,
|
|
17
17
|
} from "@checkstack/backend-api";
|
|
18
18
|
import {
|
|
19
19
|
healthResultBoolean,
|
|
@@ -35,13 +35,7 @@ import type {
|
|
|
35
35
|
* Configuration schema for Script health checks.
|
|
36
36
|
* Global defaults only - action params moved to ExecuteCollector.
|
|
37
37
|
*/
|
|
38
|
-
export const scriptConfigSchema =
|
|
39
|
-
timeout: z
|
|
40
|
-
.number()
|
|
41
|
-
.min(100)
|
|
42
|
-
.default(30_000)
|
|
43
|
-
.describe("Default execution timeout in milliseconds"),
|
|
44
|
-
});
|
|
38
|
+
export const scriptConfigSchema = baseStrategyConfigSchema.extend({});
|
|
45
39
|
|
|
46
40
|
export type ScriptConfig = z.infer<typeof scriptConfigSchema>;
|
|
47
41
|
export type ScriptConfigInput = z.input<typeof scriptConfigSchema>;
|
|
@@ -88,44 +82,31 @@ const scriptResultSchema = healthResultSchema({
|
|
|
88
82
|
|
|
89
83
|
type ScriptResult = z.infer<typeof scriptResultSchema>;
|
|
90
84
|
|
|
91
|
-
/**
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const scriptAggregatedDisplaySchema = healthResultSchema({
|
|
95
|
-
avgExecutionTime: healthResultNumber({
|
|
85
|
+
/** Aggregated field definitions for bucket merging */
|
|
86
|
+
const scriptAggregatedFields = {
|
|
87
|
+
avgExecutionTime: aggregatedAverage({
|
|
96
88
|
"x-chart-type": "line",
|
|
97
89
|
"x-chart-label": "Avg Execution Time",
|
|
98
90
|
"x-chart-unit": "ms",
|
|
99
91
|
}),
|
|
100
|
-
successRate:
|
|
92
|
+
successRate: aggregatedRate({
|
|
101
93
|
"x-chart-type": "gauge",
|
|
102
94
|
"x-chart-label": "Success Rate",
|
|
103
95
|
"x-chart-unit": "%",
|
|
104
96
|
}),
|
|
105
|
-
errorCount:
|
|
97
|
+
errorCount: aggregatedCounter({
|
|
106
98
|
"x-chart-type": "counter",
|
|
107
99
|
"x-chart-label": "Errors",
|
|
108
100
|
}),
|
|
109
|
-
timeoutCount:
|
|
101
|
+
timeoutCount: aggregatedCounter({
|
|
110
102
|
"x-chart-type": "counter",
|
|
111
103
|
"x-chart-label": "Timeouts",
|
|
112
104
|
}),
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const scriptAggregatedInternalSchema = z.object({
|
|
116
|
-
_executionTime: averageStateSchema
|
|
117
|
-
.optional(),
|
|
118
|
-
_success: rateStateSchema
|
|
119
|
-
.optional(),
|
|
120
|
-
_errors: counterStateSchema.optional(),
|
|
121
|
-
_timeouts: counterStateSchema.optional(),
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
const scriptAggregatedSchema = scriptAggregatedDisplaySchema.merge(
|
|
125
|
-
scriptAggregatedInternalSchema,
|
|
126
|
-
);
|
|
105
|
+
};
|
|
127
106
|
|
|
128
|
-
type ScriptAggregatedResult =
|
|
107
|
+
type ScriptAggregatedResult = InferAggregatedResult<
|
|
108
|
+
typeof scriptAggregatedFields
|
|
109
|
+
>;
|
|
129
110
|
|
|
130
111
|
// ============================================================================
|
|
131
112
|
// SCRIPT EXECUTOR INTERFACE (for testability)
|
|
@@ -208,7 +189,7 @@ export class ScriptHealthCheckStrategy implements HealthCheckStrategy<
|
|
|
208
189
|
ScriptConfig,
|
|
209
190
|
ScriptTransportClient,
|
|
210
191
|
ScriptResult,
|
|
211
|
-
|
|
192
|
+
typeof scriptAggregatedFields
|
|
212
193
|
> {
|
|
213
194
|
id = "script";
|
|
214
195
|
displayName = "Script Health Check";
|
|
@@ -248,9 +229,9 @@ export class ScriptHealthCheckStrategy implements HealthCheckStrategy<
|
|
|
248
229
|
],
|
|
249
230
|
});
|
|
250
231
|
|
|
251
|
-
aggregatedResult
|
|
232
|
+
aggregatedResult = new VersionedAggregated({
|
|
252
233
|
version: 1,
|
|
253
|
-
|
|
234
|
+
fields: scriptAggregatedFields,
|
|
254
235
|
});
|
|
255
236
|
|
|
256
237
|
mergeResult(
|
|
@@ -259,36 +240,21 @@ export class ScriptHealthCheckStrategy implements HealthCheckStrategy<
|
|
|
259
240
|
): ScriptAggregatedResult {
|
|
260
241
|
const metadata = run.metadata;
|
|
261
242
|
|
|
262
|
-
const
|
|
263
|
-
existing?.
|
|
243
|
+
const avgExecutionTime = mergeAverage(
|
|
244
|
+
existing?.avgExecutionTime,
|
|
264
245
|
metadata?.executionTimeMs,
|
|
265
246
|
);
|
|
266
247
|
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
metadata?.success,
|
|
270
|
-
);
|
|
248
|
+
const isSuccess = metadata?.success ?? false;
|
|
249
|
+
const successRate = mergeRate(existing?.successRate, isSuccess);
|
|
271
250
|
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
metadata?.error !== undefined,
|
|
275
|
-
);
|
|
251
|
+
const hasError = metadata?.error !== undefined;
|
|
252
|
+
const errorCount = mergeCounter(existing?.errorCount, hasError);
|
|
276
253
|
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
metadata?.timedOut === true,
|
|
280
|
-
);
|
|
254
|
+
const hasTimeout = metadata?.timedOut === true;
|
|
255
|
+
const timeoutCount = mergeCounter(existing?.timeoutCount, hasTimeout);
|
|
281
256
|
|
|
282
|
-
return {
|
|
283
|
-
avgExecutionTime: executionTimeState.avg,
|
|
284
|
-
successRate: successState.rate,
|
|
285
|
-
errorCount: errorState.count,
|
|
286
|
-
timeoutCount: timeoutState.count,
|
|
287
|
-
_executionTime: executionTimeState,
|
|
288
|
-
_success: successState,
|
|
289
|
-
_errors: errorState,
|
|
290
|
-
_timeouts: timeoutState,
|
|
291
|
-
};
|
|
257
|
+
return { avgExecutionTime, successRate, errorCount, timeoutCount };
|
|
292
258
|
}
|
|
293
259
|
|
|
294
260
|
async createClient(
|