hono-webhooks 0.3.0 → 0.4.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/README.md +38 -47
- package/dist/cli-commands.d.ts +1 -0
- package/dist/cli.js +5674 -233
- package/dist/otel.d.ts +31 -0
- package/dist/otel.js +77 -0
- package/package.json +22 -4
- package/src/cli-commands.ts +270 -0
- package/src/cli.ts +4 -253
- package/src/otel.ts +127 -0
package/README.md
CHANGED
|
@@ -545,63 +545,47 @@ createWebhooks(webhooks, {
|
|
|
545
545
|
})
|
|
546
546
|
```
|
|
547
547
|
|
|
548
|
-
### OpenTelemetry
|
|
548
|
+
### OpenTelemetry
|
|
549
549
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
const duration = metrics.getMeter('webhooks').createHistogram('webhook.duration', { unit: 'ms' })
|
|
550
|
+
`hono-webhooks/otel` puts each request in a server span and records two
|
|
551
|
+
metrics. It needs `@opentelemetry/api` (an optional peer dependency):
|
|
554
552
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
duration.record(e.durationMs, {
|
|
558
|
-
'http.route': e.route ?? 'unmatched',
|
|
559
|
-
'http.request.method': e.method,
|
|
560
|
-
'http.response.status_code': e.status
|
|
561
|
-
})
|
|
562
|
-
})
|
|
553
|
+
```bash
|
|
554
|
+
bun add @opentelemetry/api
|
|
563
555
|
```
|
|
564
556
|
|
|
565
|
-
### OpenTelemetry traces
|
|
566
|
-
|
|
567
|
-
One span per request, named by the route pattern (low cardinality), with
|
|
568
|
-
`onEvent` logs attached to it:
|
|
569
|
-
|
|
570
557
|
```ts
|
|
571
|
-
import {
|
|
572
|
-
|
|
573
|
-
const tracer = trace.getTracer('webhooks')
|
|
558
|
+
import { otelWebhooks } from 'hono-webhooks/otel'
|
|
574
559
|
|
|
575
560
|
createWebhooks(webhooks, {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
},
|
|
587
|
-
async (span) => {
|
|
588
|
-
try {
|
|
589
|
-
const res = await next()
|
|
590
|
-
span.setAttribute('http.response.status_code', res.status)
|
|
591
|
-
if (res.status >= 500) span.setStatus({ code: SpanStatusCode.ERROR })
|
|
592
|
-
return res
|
|
593
|
-
} finally {
|
|
594
|
-
span.end()
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
),
|
|
598
|
-
onEvent: (e) => {
|
|
599
|
-
// trace.getActiveSpan() is the span above
|
|
600
|
-
if (e.error instanceof Error) trace.getActiveSpan()?.recordException(e.error)
|
|
601
|
-
}
|
|
561
|
+
...otelWebhooks({
|
|
562
|
+
ignoreRoutes: ['/health'],
|
|
563
|
+
onWebhookCall(call, event) {
|
|
564
|
+
// `call` is summarizeEvent(event); the request's span is active here
|
|
565
|
+
logger.info('webhook.completed', { route: call.route, status: call.status })
|
|
566
|
+
}
|
|
567
|
+
}),
|
|
568
|
+
// onWebhookCall logs errors with the route and span
|
|
569
|
+
logErrors: false
|
|
602
570
|
})
|
|
603
571
|
```
|
|
604
572
|
|
|
573
|
+
- **Span** `webhook: POST /orders/:id` (kind `SERVER`) with `http.method`,
|
|
574
|
+
`http.route`, `http.status_code`, `webhook.duration_ms`, `webhook.success`
|
|
575
|
+
and, for validation failures, `webhook.validation_error`. Status is `ERROR`
|
|
576
|
+
for 4xx and 5xx; 5xx errors are recorded as exceptions. Spans created in
|
|
577
|
+
handlers nest under it when an OTel context manager is registered.
|
|
578
|
+
- **Metrics** `webhook_request_total` (counter) and
|
|
579
|
+
`webhook_request_duration_ms` (histogram, ms), both by `route` (the pattern,
|
|
580
|
+
`__unmatched__` for a 404) and `status` (`success` below 400, else `failed`).
|
|
581
|
+
- `ignoreRoutes` skips metrics only; the span and `onWebhookCall` still run.
|
|
582
|
+
- `tracer` and `meter` default to `trace.getTracer('webhooks')` and
|
|
583
|
+
`metrics.getMeter('webhooks')`. The meter is resolved on the first request,
|
|
584
|
+
so registering the SDK after import works.
|
|
585
|
+
|
|
586
|
+
It returns `{ around, onEvent }`. To add your own, call them from yours, or
|
|
587
|
+
use `onWebhookCall` instead of `onEvent`.
|
|
588
|
+
|
|
605
589
|
### Skipping noise
|
|
606
590
|
|
|
607
591
|
`onEvent` fires for everything, so filter in the hook:
|
|
@@ -771,6 +755,11 @@ import {
|
|
|
771
755
|
hmac // (options) => a scheme like the ones above
|
|
772
756
|
} from 'hono-webhooks/signatures'
|
|
773
757
|
|
|
758
|
+
import {
|
|
759
|
+
otelWebhooks, // (options?) => { around, onEvent } with spans and metrics
|
|
760
|
+
UNMATCHED_ROUTE // '__unmatched__', the route label for 404s
|
|
761
|
+
} from 'hono-webhooks/otel'
|
|
762
|
+
|
|
774
763
|
import type {
|
|
775
764
|
Webhook,
|
|
776
765
|
WebhookConfig,
|
|
@@ -791,6 +780,8 @@ import type {
|
|
|
791
780
|
PathParams,
|
|
792
781
|
StandardSchemaV1
|
|
793
782
|
} from 'hono-webhooks'
|
|
783
|
+
|
|
784
|
+
import type { OtelWebhooksOptions } from 'hono-webhooks/otel'
|
|
794
785
|
```
|
|
795
786
|
|
|
796
787
|
Use `Webhook` to type a list: `const all: Webhook<AppEnv>[] = [a, b]`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const cli: import("hanzio/cli").Cli;
|