@checkstack/healthcheck-http-backend 0.2.5 → 0.3.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/CHANGELOG.md +24 -0
- package/package.json +1 -1
- package/src/request-collector.test.ts +3 -3
- package/src/request-collector.ts +20 -31
- package/src/strategy.test.ts +2 -2
- package/src/strategy.ts +15 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @checkstack/healthcheck-http-backend
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3dd1914: Migrate health check strategies to VersionedAggregated with \_type discriminator
|
|
8
|
+
|
|
9
|
+
All 13 health check strategies now use `VersionedAggregated` for their `aggregatedResult` property, enabling automatic bucket merging with 100% mathematical fidelity.
|
|
10
|
+
|
|
11
|
+
**Key changes:**
|
|
12
|
+
|
|
13
|
+
- **`_type` discriminator**: All aggregated state objects now include a required `_type` field (`"average"`, `"rate"`, `"counter"`, `"minmax"`) for reliable type detection
|
|
14
|
+
- The `HealthCheckStrategy` interface now requires `aggregatedResult` to be a `VersionedAggregated<AggregatedResultShape>`
|
|
15
|
+
- Strategy/collector `mergeResult` methods return state objects with `_type` (e.g., `{ _type: "average", _sum, _count, avg }`)
|
|
16
|
+
- `mergeAggregatedBucketResults`, `combineBuckets`, and `reaggregateBuckets` now require `registry` and `strategyId` parameters
|
|
17
|
+
- `HealthCheckService` constructor now requires both `registry` and `collectorRegistry` parameters
|
|
18
|
+
- Frontend `extractComputedValue` now uses `_type` discriminator for robust type detection
|
|
19
|
+
|
|
20
|
+
**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.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [3dd1914]
|
|
25
|
+
- @checkstack/backend-api@0.7.0
|
|
26
|
+
|
|
3
27
|
## 0.2.5
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -156,8 +156,8 @@ describe("RequestCollector", () => {
|
|
|
156
156
|
let aggregated = collector.mergeResult(undefined, runs[0]);
|
|
157
157
|
aggregated = collector.mergeResult(aggregated, runs[1]);
|
|
158
158
|
|
|
159
|
-
expect(aggregated.avgResponseTimeMs).toBe(75);
|
|
160
|
-
expect(aggregated.successRate).toBe(100);
|
|
159
|
+
expect(aggregated.avgResponseTimeMs.avg).toBe(75);
|
|
160
|
+
expect(aggregated.successRate.rate).toBe(100);
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
it("should calculate success rate correctly", () => {
|
|
@@ -199,7 +199,7 @@ describe("RequestCollector", () => {
|
|
|
199
199
|
let aggregated = collector.mergeResult(undefined, runs[0]);
|
|
200
200
|
aggregated = collector.mergeResult(aggregated, runs[1]);
|
|
201
201
|
|
|
202
|
-
expect(aggregated.successRate).toBe(50);
|
|
202
|
+
expect(aggregated.successRate.rate).toBe(50);
|
|
203
203
|
});
|
|
204
204
|
});
|
|
205
205
|
|
package/src/request-collector.ts
CHANGED
|
@@ -7,8 +7,10 @@ import {
|
|
|
7
7
|
type CollectorStrategy,
|
|
8
8
|
mergeAverage,
|
|
9
9
|
mergeRate,
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
VersionedAggregated,
|
|
11
|
+
aggregatedAverage,
|
|
12
|
+
aggregatedRate,
|
|
13
|
+
type InferAggregatedResult,
|
|
12
14
|
} from "@checkstack/backend-api";
|
|
13
15
|
import {
|
|
14
16
|
healthResultNumber,
|
|
@@ -80,32 +82,24 @@ const requestResultSchema = healthResultSchema({
|
|
|
80
82
|
|
|
81
83
|
export type RequestResult = z.infer<typeof requestResultSchema>;
|
|
82
84
|
|
|
83
|
-
//
|
|
84
|
-
const
|
|
85
|
-
avgResponseTimeMs:
|
|
85
|
+
// Aggregated result fields definition
|
|
86
|
+
const requestAggregatedFields = {
|
|
87
|
+
avgResponseTimeMs: aggregatedAverage({
|
|
86
88
|
"x-chart-type": "line",
|
|
87
89
|
"x-chart-label": "Avg Response Time",
|
|
88
90
|
"x-chart-unit": "ms",
|
|
89
91
|
}),
|
|
90
|
-
successRate:
|
|
92
|
+
successRate: aggregatedRate({
|
|
91
93
|
"x-chart-type": "gauge",
|
|
92
94
|
"x-chart-label": "Success Rate",
|
|
93
95
|
"x-chart-unit": "%",
|
|
94
96
|
}),
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Internal state for incremental aggregation (not shown in charts)
|
|
98
|
-
const requestAggregatedInternalSchema = z.object({
|
|
99
|
-
_responseTime: averageStateSchema.optional(),
|
|
100
|
-
_success: rateStateSchema.optional(),
|
|
101
|
-
});
|
|
97
|
+
};
|
|
102
98
|
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
export type RequestAggregatedResult = z.infer<typeof requestAggregatedSchema>;
|
|
99
|
+
// Type inferred automatically from field definitions
|
|
100
|
+
export type RequestAggregatedResult = InferAggregatedResult<
|
|
101
|
+
typeof requestAggregatedFields
|
|
102
|
+
>;
|
|
109
103
|
|
|
110
104
|
// ============================================================================
|
|
111
105
|
// REQUEST COLLECTOR
|
|
@@ -131,9 +125,9 @@ export class RequestCollector implements CollectorStrategy<
|
|
|
131
125
|
|
|
132
126
|
config = new Versioned({ version: 1, schema: requestConfigSchema });
|
|
133
127
|
result = new Versioned({ version: 1, schema: requestResultSchema });
|
|
134
|
-
aggregatedResult = new
|
|
128
|
+
aggregatedResult = new VersionedAggregated({
|
|
135
129
|
version: 1,
|
|
136
|
-
|
|
130
|
+
fields: requestAggregatedFields,
|
|
137
131
|
});
|
|
138
132
|
|
|
139
133
|
async execute({
|
|
@@ -182,17 +176,12 @@ export class RequestCollector implements CollectorStrategy<
|
|
|
182
176
|
existing: RequestAggregatedResult | undefined,
|
|
183
177
|
newRun: HealthCheckRunForAggregation<RequestResult>,
|
|
184
178
|
): RequestAggregatedResult {
|
|
185
|
-
const responseTime = mergeAverage(
|
|
186
|
-
existing?._responseTime,
|
|
187
|
-
newRun.metadata?.responseTimeMs,
|
|
188
|
-
);
|
|
189
|
-
const success = mergeRate(existing?._success, newRun.metadata?.success);
|
|
190
|
-
|
|
191
179
|
return {
|
|
192
|
-
avgResponseTimeMs:
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
180
|
+
avgResponseTimeMs: mergeAverage(
|
|
181
|
+
existing?.avgResponseTimeMs,
|
|
182
|
+
newRun.metadata?.responseTimeMs,
|
|
183
|
+
),
|
|
184
|
+
successRate: mergeRate(existing?.successRate, newRun.metadata?.success),
|
|
196
185
|
};
|
|
197
186
|
}
|
|
198
187
|
}
|
package/src/strategy.test.ts
CHANGED
|
@@ -218,7 +218,7 @@ describe("HttpHealthCheckStrategy", () => {
|
|
|
218
218
|
aggregated = strategy.mergeResult(aggregated, runs[1]);
|
|
219
219
|
aggregated = strategy.mergeResult(aggregated, runs[2]);
|
|
220
220
|
|
|
221
|
-
expect(aggregated.errorCount).toBe(2);
|
|
221
|
+
expect(aggregated.errorCount.count).toBe(2);
|
|
222
222
|
});
|
|
223
223
|
|
|
224
224
|
it("should return zero errors when all runs succeed", () => {
|
|
@@ -245,7 +245,7 @@ describe("HttpHealthCheckStrategy", () => {
|
|
|
245
245
|
let aggregated = strategy.mergeResult(undefined, runs[0]);
|
|
246
246
|
aggregated = strategy.mergeResult(aggregated, runs[1]);
|
|
247
247
|
|
|
248
|
-
expect(aggregated.errorCount).toBe(0);
|
|
248
|
+
expect(aggregated.errorCount.count).toBe(0);
|
|
249
249
|
});
|
|
250
250
|
});
|
|
251
251
|
});
|
package/src/strategy.ts
CHANGED
|
@@ -2,12 +2,14 @@ import {
|
|
|
2
2
|
HealthCheckStrategy,
|
|
3
3
|
HealthCheckRunForAggregation,
|
|
4
4
|
Versioned,
|
|
5
|
+
VersionedAggregated,
|
|
6
|
+
aggregatedCounter,
|
|
7
|
+
mergeCounter,
|
|
5
8
|
z,
|
|
9
|
+
type InferAggregatedResult,
|
|
6
10
|
type ConnectedClient,
|
|
7
|
-
mergeCounter,
|
|
8
11
|
} from "@checkstack/backend-api";
|
|
9
12
|
import {
|
|
10
|
-
healthResultNumber,
|
|
11
13
|
healthResultString,
|
|
12
14
|
healthResultSchema,
|
|
13
15
|
} from "@checkstack/healthcheck-common";
|
|
@@ -58,15 +60,15 @@ const httpResultMetadataSchema = healthResultSchema({
|
|
|
58
60
|
|
|
59
61
|
type HttpResultMetadata = z.infer<typeof httpResultMetadataSchema>;
|
|
60
62
|
|
|
61
|
-
/** Aggregated
|
|
62
|
-
const
|
|
63
|
-
errorCount:
|
|
63
|
+
/** Aggregated field definitions for bucket merging */
|
|
64
|
+
const httpAggregatedFields = {
|
|
65
|
+
errorCount: aggregatedCounter({
|
|
64
66
|
"x-chart-type": "counter",
|
|
65
67
|
"x-chart-label": "Errors",
|
|
66
68
|
}),
|
|
67
|
-
}
|
|
69
|
+
};
|
|
68
70
|
|
|
69
|
-
type
|
|
71
|
+
type HttpAggregatedResult = InferAggregatedResult<typeof httpAggregatedFields>;
|
|
70
72
|
|
|
71
73
|
// ============================================================================
|
|
72
74
|
// STRATEGY
|
|
@@ -76,7 +78,7 @@ export class HttpHealthCheckStrategy implements HealthCheckStrategy<
|
|
|
76
78
|
HttpHealthCheckConfig,
|
|
77
79
|
HttpTransportClient,
|
|
78
80
|
HttpResultMetadata,
|
|
79
|
-
|
|
81
|
+
typeof httpAggregatedFields
|
|
80
82
|
> {
|
|
81
83
|
id = "http";
|
|
82
84
|
displayName = "HTTP/HTTPS Health Check";
|
|
@@ -112,21 +114,18 @@ export class HttpHealthCheckStrategy implements HealthCheckStrategy<
|
|
|
112
114
|
schema: httpResultMetadataSchema,
|
|
113
115
|
});
|
|
114
116
|
|
|
115
|
-
aggregatedResult
|
|
117
|
+
aggregatedResult = new VersionedAggregated({
|
|
116
118
|
version: 1,
|
|
117
|
-
|
|
119
|
+
fields: httpAggregatedFields,
|
|
118
120
|
});
|
|
119
121
|
|
|
120
122
|
mergeResult(
|
|
121
|
-
existing:
|
|
123
|
+
existing: HttpAggregatedResult | undefined,
|
|
122
124
|
newRun: HealthCheckRunForAggregation<HttpResultMetadata>,
|
|
123
|
-
):
|
|
125
|
+
): HttpAggregatedResult {
|
|
124
126
|
const hasError = !!newRun.metadata?.error;
|
|
125
127
|
return {
|
|
126
|
-
errorCount: mergeCounter(
|
|
127
|
-
existing ? { count: existing.errorCount } : undefined,
|
|
128
|
-
hasError,
|
|
129
|
-
).count,
|
|
128
|
+
errorCount: mergeCounter(existing?.errorCount, hasError),
|
|
130
129
|
};
|
|
131
130
|
}
|
|
132
131
|
|