@checkstack/healthcheck-http-backend 0.1.0 → 0.1.2
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 +45 -0
- package/package.json +1 -1
- package/src/request-collector.ts +4 -3
- package/src/strategy.test.ts +12 -22
- package/src/strategy.ts +4 -30
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# @checkstack/healthcheck-http-backend
|
|
2
2
|
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f533141: Enforce health result factory function usage via branded types
|
|
8
|
+
|
|
9
|
+
- Added `healthResultSchema()` builder that enforces the use of factory functions at compile-time
|
|
10
|
+
- Added `healthResultArray()` factory for array fields (e.g., DNS resolved values)
|
|
11
|
+
- Added branded `HealthResultField<T>` type to mark schemas created by factory functions
|
|
12
|
+
- Consolidated `ChartType` and `HealthResultMeta` into `@checkstack/common` as single source of truth
|
|
13
|
+
- Updated all 12 health check strategies and 11 collectors to use `healthResultSchema()`
|
|
14
|
+
- Using raw `z.number()` etc. inside `healthResultSchema()` now causes a TypeScript error
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [9faec1f]
|
|
17
|
+
- Updated dependencies [827b286]
|
|
18
|
+
- Updated dependencies [f533141]
|
|
19
|
+
- Updated dependencies [aa4a8ab]
|
|
20
|
+
- @checkstack/backend-api@0.3.0
|
|
21
|
+
- @checkstack/common@0.2.0
|
|
22
|
+
- @checkstack/healthcheck-common@0.3.0
|
|
23
|
+
|
|
24
|
+
## 0.1.1
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- 97c5a6b: Add UUID-based collector identification for better multiple collector support
|
|
29
|
+
|
|
30
|
+
**Breaking Change**: Existing health check configurations with collectors need to be recreated.
|
|
31
|
+
|
|
32
|
+
- Each collector instance now has a unique UUID assigned on creation
|
|
33
|
+
- Collector results are stored under the UUID key with `_collectorId` and `_assertionFailed` metadata
|
|
34
|
+
- Auto-charts correctly display separate charts for each collector instance
|
|
35
|
+
- Charts are now grouped by collector instance with clear headings
|
|
36
|
+
- Assertion status card shows pass/fail for each collector
|
|
37
|
+
- Renamed "Success" to "HTTP Success" to clarify it's about HTTP request success
|
|
38
|
+
- Fixed deletion of collectors not persisting to database
|
|
39
|
+
- Fixed duplicate React key warnings in auto-chart grid
|
|
40
|
+
|
|
41
|
+
- Updated dependencies [97c5a6b]
|
|
42
|
+
- Updated dependencies [8e43507]
|
|
43
|
+
- Updated dependencies [97c5a6b]
|
|
44
|
+
- @checkstack/backend-api@0.2.0
|
|
45
|
+
- @checkstack/common@0.1.0
|
|
46
|
+
- @checkstack/healthcheck-common@0.2.0
|
|
47
|
+
|
|
3
48
|
## 0.1.0
|
|
4
49
|
|
|
5
50
|
### Minor Changes
|
package/package.json
CHANGED
package/src/request-collector.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
healthResultString,
|
|
11
11
|
healthResultBoolean,
|
|
12
12
|
healthResultJSONPath,
|
|
13
|
+
healthResultSchema,
|
|
13
14
|
} from "@checkstack/healthcheck-common";
|
|
14
15
|
import { pluginMetadata } from "./plugin-metadata";
|
|
15
16
|
import type { HttpTransportClient } from "./transport-client";
|
|
@@ -42,7 +43,7 @@ export type RequestConfig = z.infer<typeof requestConfigSchema>;
|
|
|
42
43
|
// RESULT SCHEMAS
|
|
43
44
|
// ============================================================================
|
|
44
45
|
|
|
45
|
-
const requestResultSchema =
|
|
46
|
+
const requestResultSchema = healthResultSchema({
|
|
46
47
|
statusCode: healthResultNumber({
|
|
47
48
|
"x-chart-type": "counter",
|
|
48
49
|
"x-chart-label": "Status Code",
|
|
@@ -64,13 +65,13 @@ const requestResultSchema = z.object({
|
|
|
64
65
|
}),
|
|
65
66
|
success: healthResultBoolean({
|
|
66
67
|
"x-chart-type": "boolean",
|
|
67
|
-
"x-chart-label": "Success",
|
|
68
|
+
"x-chart-label": "HTTP Success",
|
|
68
69
|
}),
|
|
69
70
|
});
|
|
70
71
|
|
|
71
72
|
export type RequestResult = z.infer<typeof requestResultSchema>;
|
|
72
73
|
|
|
73
|
-
const requestAggregatedSchema =
|
|
74
|
+
const requestAggregatedSchema = healthResultSchema({
|
|
74
75
|
avgResponseTimeMs: healthResultNumber({
|
|
75
76
|
"x-chart-type": "line",
|
|
76
77
|
"x-chart-label": "Avg Response Time",
|
package/src/strategy.test.ts
CHANGED
|
@@ -181,16 +181,16 @@ describe("HttpHealthCheckStrategy", () => {
|
|
|
181
181
|
});
|
|
182
182
|
|
|
183
183
|
describe("aggregateResult", () => {
|
|
184
|
-
it("should
|
|
184
|
+
it("should count errors correctly", () => {
|
|
185
185
|
const runs = [
|
|
186
186
|
{
|
|
187
187
|
id: "1",
|
|
188
|
-
status: "
|
|
188
|
+
status: "unhealthy" as const,
|
|
189
189
|
latencyMs: 100,
|
|
190
190
|
checkId: "c1",
|
|
191
191
|
timestamp: new Date(),
|
|
192
192
|
metadata: {
|
|
193
|
-
|
|
193
|
+
error: "Connection refused",
|
|
194
194
|
},
|
|
195
195
|
},
|
|
196
196
|
{
|
|
@@ -199,40 +199,34 @@ describe("HttpHealthCheckStrategy", () => {
|
|
|
199
199
|
latencyMs: 150,
|
|
200
200
|
checkId: "c1",
|
|
201
201
|
timestamp: new Date(),
|
|
202
|
-
metadata: {
|
|
203
|
-
statusCode: 200,
|
|
204
|
-
},
|
|
202
|
+
metadata: {},
|
|
205
203
|
},
|
|
206
204
|
{
|
|
207
205
|
id: "3",
|
|
208
|
-
status: "
|
|
206
|
+
status: "unhealthy" as const,
|
|
209
207
|
latencyMs: 120,
|
|
210
208
|
checkId: "c1",
|
|
211
209
|
timestamp: new Date(),
|
|
212
210
|
metadata: {
|
|
213
|
-
|
|
211
|
+
error: "Timeout",
|
|
214
212
|
},
|
|
215
213
|
},
|
|
216
214
|
];
|
|
217
215
|
|
|
218
216
|
const aggregated = strategy.aggregateResult(runs);
|
|
219
217
|
|
|
220
|
-
expect(aggregated.
|
|
221
|
-
expect(aggregated.statusCodeCounts["404"]).toBe(1);
|
|
222
|
-
expect(aggregated.successRate).toBe(100);
|
|
218
|
+
expect(aggregated.errorCount).toBe(2);
|
|
223
219
|
});
|
|
224
220
|
|
|
225
|
-
it("should
|
|
221
|
+
it("should return zero errors when all runs succeed", () => {
|
|
226
222
|
const runs = [
|
|
227
223
|
{
|
|
228
224
|
id: "1",
|
|
229
|
-
status: "
|
|
225
|
+
status: "healthy" as const,
|
|
230
226
|
latencyMs: 100,
|
|
231
227
|
checkId: "c1",
|
|
232
228
|
timestamp: new Date(),
|
|
233
|
-
metadata: {
|
|
234
|
-
error: "Connection refused",
|
|
235
|
-
},
|
|
229
|
+
metadata: {},
|
|
236
230
|
},
|
|
237
231
|
{
|
|
238
232
|
id: "2",
|
|
@@ -240,17 +234,13 @@ describe("HttpHealthCheckStrategy", () => {
|
|
|
240
234
|
latencyMs: 150,
|
|
241
235
|
checkId: "c1",
|
|
242
236
|
timestamp: new Date(),
|
|
243
|
-
metadata: {
|
|
244
|
-
statusCode: 200,
|
|
245
|
-
responseTime: 100,
|
|
246
|
-
},
|
|
237
|
+
metadata: {},
|
|
247
238
|
},
|
|
248
239
|
];
|
|
249
240
|
|
|
250
241
|
const aggregated = strategy.aggregateResult(runs);
|
|
251
242
|
|
|
252
|
-
expect(aggregated.errorCount).toBe(
|
|
253
|
-
expect(aggregated.successRate).toBe(50);
|
|
243
|
+
expect(aggregated.errorCount).toBe(0);
|
|
254
244
|
});
|
|
255
245
|
});
|
|
256
246
|
});
|
package/src/strategy.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
healthResultNumber,
|
|
10
10
|
healthResultString,
|
|
11
|
+
healthResultSchema,
|
|
11
12
|
} from "@checkstack/healthcheck-common";
|
|
12
13
|
import type {
|
|
13
14
|
HttpTransportClient,
|
|
@@ -47,15 +48,7 @@ interface HttpConfigV2 extends HttpConfigV1 {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
/** Per-run result metadata */
|
|
50
|
-
const httpResultMetadataSchema =
|
|
51
|
-
statusCode: healthResultNumber({
|
|
52
|
-
"x-chart-type": "pie",
|
|
53
|
-
"x-chart-label": "Status Code",
|
|
54
|
-
}).optional(),
|
|
55
|
-
contentType: healthResultString({
|
|
56
|
-
"x-chart-type": "counter",
|
|
57
|
-
"x-chart-label": "Content Type",
|
|
58
|
-
}).optional(),
|
|
51
|
+
const httpResultMetadataSchema = healthResultSchema({
|
|
59
52
|
error: healthResultString({
|
|
60
53
|
"x-chart-type": "status",
|
|
61
54
|
"x-chart-label": "Error",
|
|
@@ -65,15 +58,7 @@ const httpResultMetadataSchema = z.object({
|
|
|
65
58
|
type HttpResultMetadata = z.infer<typeof httpResultMetadataSchema>;
|
|
66
59
|
|
|
67
60
|
/** Aggregated metadata for buckets */
|
|
68
|
-
const httpAggregatedMetadataSchema =
|
|
69
|
-
statusCodeCounts: z.record(z.string(), z.number()).meta({
|
|
70
|
-
"x-chart-type": "pie",
|
|
71
|
-
"x-chart-label": "Status Code Distribution",
|
|
72
|
-
}),
|
|
73
|
-
successRate: healthResultNumber({
|
|
74
|
-
"x-chart-type": "gauge",
|
|
75
|
-
"x-chart-label": "Success Rate (%)",
|
|
76
|
-
}),
|
|
61
|
+
const httpAggregatedMetadataSchema = healthResultSchema({
|
|
77
62
|
errorCount: healthResultNumber({
|
|
78
63
|
"x-chart-type": "counter",
|
|
79
64
|
"x-chart-label": "Errors",
|
|
@@ -137,26 +122,15 @@ export class HttpHealthCheckStrategy
|
|
|
137
122
|
aggregateResult(
|
|
138
123
|
runs: HealthCheckRunForAggregation<HttpResultMetadata>[]
|
|
139
124
|
): HttpAggregatedMetadata {
|
|
140
|
-
const statusCodeCounts: Record<string, number> = {};
|
|
141
125
|
let errorCount = 0;
|
|
142
|
-
let successCount = 0;
|
|
143
126
|
|
|
144
127
|
for (const run of runs) {
|
|
145
128
|
if (run.metadata?.error) {
|
|
146
129
|
errorCount++;
|
|
147
|
-
} else {
|
|
148
|
-
successCount++;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (run.metadata?.statusCode !== undefined) {
|
|
152
|
-
const key = String(run.metadata.statusCode);
|
|
153
|
-
statusCodeCounts[key] = (statusCodeCounts[key] || 0) + 1;
|
|
154
130
|
}
|
|
155
131
|
}
|
|
156
|
-
const successRate =
|
|
157
|
-
runs.length > 0 ? Math.round((successCount / runs.length) * 100) : 0;
|
|
158
132
|
|
|
159
|
-
return {
|
|
133
|
+
return { errorCount };
|
|
160
134
|
}
|
|
161
135
|
|
|
162
136
|
/**
|