-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathpatchAppUse.ts
More file actions
64 lines (58 loc) · 2.22 KB
/
patchAppUse.ts
File metadata and controls
64 lines (58 loc) · 2.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import {
captureException,
SEMANTIC_ATTRIBUTE_SENTRY_OP,
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
SPAN_STATUS_ERROR,
SPAN_STATUS_OK,
startInactiveSpan,
} from '@sentry/core';
import type { Hono, MiddlewareHandler } from 'hono';
const MIDDLEWARE_ORIGIN = 'auto.middleware.hono';
/**
* Patches `app.use` so that every middleware registered through it is automatically
* wrapped in a Sentry span. Supports both forms: `app.use(...handlers)` and `app.use(path, ...handlers)`.
*/
export function patchAppUse(app: Hono): void {
app.use = new Proxy(app.use, {
apply(target: typeof app.use, thisArg: typeof app, args: Parameters<typeof app.use>): ReturnType<typeof app.use> {
const [first, ...rest] = args as [unknown, ...MiddlewareHandler[]];
if (typeof first === 'string') {
const wrappedHandlers = rest.map(handler => wrapMiddlewareWithSpan(handler));
return Reflect.apply(target, thisArg, [first, ...wrappedHandlers]);
}
const allHandlers = [first as MiddlewareHandler, ...rest].map(handler => wrapMiddlewareWithSpan(handler));
return Reflect.apply(target, thisArg, allHandlers);
},
});
}
/**
* Wraps a Hono middleware handler so that its execution is traced as a Sentry span.
* Uses startInactiveSpan so that all middleware spans are siblings under the request/transaction
* (onion order: A → B → handler → B → A does not nest B under A in the trace).
*/
function wrapMiddlewareWithSpan(handler: MiddlewareHandler): MiddlewareHandler {
return async function sentryTracedMiddleware(context, next) {
const span = startInactiveSpan({
name: handler.name || '<anonymous>',
op: 'middleware.hono',
onlyIfParent: true,
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'middleware.hono',
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: MIDDLEWARE_ORIGIN,
},
});
try {
const result = await handler(context, next);
span.setStatus({ code: SPAN_STATUS_OK });
return result;
} catch (error) {
span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
captureException(error, {
mechanism: { handled: false, type: MIDDLEWARE_ORIGIN },
});
throw error;
} finally {
span.end();
}
};
}