Skip to content

Commit d2e6490

Browse files
authored
feat: wrap route handlers with tracing at build time (#4240)
1 parent 97568a0 commit d2e6490

2 files changed

Lines changed: 68 additions & 8 deletions

File tree

src/build/virtual/routing.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ export default function routing(nitro: Nitro) {
1515
"_importHash"
1616
);
1717

18+
const traceH3 = !!nitro.options.tracingChannel?.h3;
19+
1820
return /* js */ `
1921
import * as __routeRules__ from "#nitro/runtime/route-rules";
2022
import * as srvxNode from "srvx/node"
21-
import * as h3 from "h3";
23+
import * as h3 from "h3";${traceH3 ? `\nimport { wrapHandlerWithTracing } from "h3/tracing";` : ""}
2224
2325
export const findRouteRules = ${nitro.routing.routeRules.compileToString({ serialize: serializeRouteRule, matchAll: true })}
2426
@@ -41,7 +43,7 @@ ${allHandlers
4143
)
4244
.join("\n")}
4345
44-
export const findRoute = ${nitro.routing.routes.compileToString({ serialize: serializeHandler })}
46+
export const findRoute = ${nitro.routing.routes.compileToString({ serialize: (h) => serializeHandler(h, { tracing: traceH3 }) })}
4547
4648
export const findRoutedMiddleware = ${nitro.routing.routedMiddleware.compileToString({ serialize: serializeHandler, matchAll: true })};
4749
@@ -61,18 +63,20 @@ function uniqueBy<T>(arr: T[], key: keyof T): T[] {
6163

6264
type MaybeArray<T> = T | T[];
6365

64-
function serializeHandler(h: MaybeArray<NitroEventHandler & { _importHash: string }>): string {
66+
function serializeHandler(
67+
h: MaybeArray<NitroEventHandler & { _importHash: string }>,
68+
opts: { tracing?: boolean } = {}
69+
): string {
6570
const meta = Array.isArray(h) ? h[0] : h;
71+
const handler = Array.isArray(h)
72+
? `multiHandler(${h.map((handler) => serializeHandlerFn(handler)).join(",")})`
73+
: serializeHandlerFn(h);
6674

6775
return `{${[
6876
`route:${JSON.stringify(meta.route)}`,
6977
meta.method && `method:${JSON.stringify(meta.method)}`,
7078
meta.meta && `meta:${JSON.stringify(meta.meta)}`,
71-
`handler:${
72-
Array.isArray(h)
73-
? `multiHandler(${h.map((handler) => serializeHandlerFn(handler)).join(",")})`
74-
: serializeHandlerFn(h)
75-
}`,
79+
`handler:${opts.tracing ? `wrapHandlerWithTracing(${handler})` : handler}`,
7680
]
7781
.filter(Boolean)
7882
.join(",")}}`;

test/unit/virtual-routing.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { describe, expect, it } from "vitest";
2+
import type { Nitro, NitroEventHandler } from "nitro/types";
3+
4+
import routing from "../../src/build/virtual/routing.ts";
5+
6+
function createNitroStub(tracingChannel: Nitro["options"]["tracingChannel"]): Nitro {
7+
const handler: NitroEventHandler & { _importHash: string } = {
8+
route: "/foo",
9+
method: "GET",
10+
handler: "/path/to/handler.ts",
11+
_importHash: "_abc123",
12+
};
13+
14+
return {
15+
options: {
16+
tracingChannel,
17+
},
18+
routing: {
19+
routes: {
20+
routes: [{ route: "/foo", method: "GET", data: handler }],
21+
compileToString: ({ serialize }: { serialize: (h: unknown) => string }) =>
22+
`{"/foo":${serialize(handler)}}`,
23+
},
24+
routedMiddleware: {
25+
routes: [],
26+
compileToString: () => `{}`,
27+
},
28+
globalMiddleware: [],
29+
routeRules: {
30+
compileToString: () => `() => []`,
31+
},
32+
},
33+
} as unknown as Nitro;
34+
}
35+
36+
describe("virtual/routing template", () => {
37+
it("does not wrap route handlers when tracingChannel is disabled", () => {
38+
const template = routing(createNitroStub(undefined)).template();
39+
expect(template).not.toContain("h3/tracing");
40+
expect(template).not.toContain("wrapHandlerWithTracing");
41+
});
42+
43+
it("does not wrap route handlers when tracingChannel.h3 is false", () => {
44+
const template = routing(
45+
createNitroStub({ srvx: true, h3: false, unstorage: true })
46+
).template();
47+
expect(template).not.toContain("h3/tracing");
48+
expect(template).not.toContain("wrapHandlerWithTracing");
49+
});
50+
51+
it("wraps route handlers with wrapHandlerWithTracing when tracingChannel.h3 is true", () => {
52+
const template = routing(createNitroStub({ srvx: true, h3: true, unstorage: true })).template();
53+
expect(template).toContain(`import { wrapHandlerWithTracing } from "h3/tracing"`);
54+
expect(template).toContain("wrapHandlerWithTracing(h3.toEventHandler(_abc123))");
55+
});
56+
});

0 commit comments

Comments
 (0)