fix(hono): Name transactions after the matched route handler#21700
Conversation
| // See https://github.com/honojs/hono/blob/9f0dadf141a3242a6c3b77462c7d33c6ce0f599d/src/hono-base.ts#L224-L226 | ||
| const COMPOSED_HANDLER = '__COMPOSED_HANDLER'; | ||
|
|
||
| // Hono doesn't flag middleware, so we infer it from arity (# of params): middleware is `(context, next)`, handlers are `(context)`. |
There was a problem hiding this comment.
m: why not use the same heuristic already used in
?There was a problem hiding this comment.
Good catch! It's using the same heuristic (arity is higher than 2). But those are two different things: when resolving the route name, we only want to extract the path and we don't care about each single middleware. But in patchRoute we also do something with each middleware so there's also the additional check for the argument positions.
But as the arity check is used by both, I'm going to create an utility for that...so this does not diverge in the future.
| const composed = (handler as unknown as Record<string, unknown>)[COMPOSED_HANDLER]; | ||
| const original = typeof composed === 'function' ? composed : handler; | ||
|
|
||
| return (original as (...args: unknown[]) => unknown).length < 2; |
There was a problem hiding this comment.
q: is a handler guaranteed to have only one argument and a middleware to have at least 2?
There was a problem hiding this comment.
Generally, this is the case. And it's also the heuristic Hono uses:
https://github.com/honojs/hono/blob/main/src/utils/handler.ts#L8
Hono transactions were sometimes named
GET /*instead of the real route (e.g.GET /test-routes), which happened when the app registered a global catch-all middleware (app.use(fn)) after its route handlers.For each request, Hono builds a list of all matching entries (both middleware and the actual handler) in registration order. We were naming the transaction after the last entry, but a trailing
app.use(fn)is registered under/*and ends up last, so we picked it instead of the handler. Naming after the responding entry doesn't work either: if a middleware throws before the handler runs, that pointer stays on the middleware (e.g./middleware-http-exception/*).The fix resolves the name to the matched handler specifically. Hono doesn't flag entries as middleware, but middleware takes a
nextarg ((c, next)) and handlers don't ((c)), so we tell them apart by arity: trust the responding entry if it's a handler, otherwise fall back to the last matched handler.