Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 264ad0b

Browse files
feat(nuxt): Implement server middleware instrumentation (#17796)
This pull request introduces instrumentation for Nuxt middleware, ensuring that all middleware handlers are automatically wrapped with tracing and error reporting functionality. The integration is achieved through build-time transformation. recap: * Adds a new build-time Rollup plugin (`middlewareInstrumentationPlugin`) that automatically wraps all detected middleware handlers with Sentry instrumentation during the Nitro build process. * Implements the `wrapMiddlewareHandler` utility, which wraps middleware handlers to start a Sentry span, capture request data, record exceptions, and flush events in serverless environments. * Updates the Nuxt module setup to inject Sentry middleware imports and instrumentation hooks during initialization, ensuring the new tracing logic is included in server builds. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds build-time wrapping of Nuxt server middleware with Sentry spans and error capture, plus Nuxt 3/4 e2e and unit tests. > > - **SDK/Runtime**: > - Implement `wrapMiddlewareHandlerWithSentry` in `packages/nuxt/src/runtime/hooks/wrapMiddlewareHandler.ts` to start spans, set attributes (op, origin, route, method, headers), handle hook arrays (`onRequest`, `onBeforeResponse`), and capture errors. > - Add middleware build-time transformation via `packages/nuxt/src/vite/middlewareConfig.ts` (server import + Rollup plugin to wrap `defineEventHandler`/`eventHandler`). > - Integrate instrumentation in `packages/nuxt/src/module.ts` by calling `addMiddlewareImports` and `addMiddlewareInstrumentation` during Nitro init when server config is present. > - **Tests**: > - Add e2e apps and Playwright tests for Nuxt 3 and Nuxt 4 (`dev-packages/e2e-tests/test-applications/nuxt-{3,4}`) covering span creation, attributes, parent-child relationships, and error propagation across hooks and arrays. > - Add unit tests for wrapper behavior in `packages/nuxt/test/runtime/hooks/wrapMiddlewareHandler.test.ts`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9a4a1f3. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 11ea830 commit 264ad0b

File tree

18 files changed

+1716
-0
lines changed

18 files changed

+1716
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { defineEventHandler, getHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Simple API endpoint that will trigger all server middleware
5+
return {
6+
message: 'Server middleware test endpoint',
7+
path: event.path,
8+
method: event.method,
9+
headers: {
10+
'x-first-middleware': getHeader(event, 'x-first-middleware'),
11+
'x-second-middleware': getHeader(event, 'x-second-middleware'),
12+
'x-auth-middleware': getHeader(event, 'x-auth-middleware'),
13+
},
14+
};
15+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineEventHandler, setHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Set a header to indicate this middleware ran
5+
setHeader(event, 'x-first-middleware', 'executed');
6+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { eventHandler, setHeader } from '#imports';
2+
3+
// tests out the eventHandler alias
4+
export default eventHandler(async event => {
5+
// Set a header to indicate this middleware ran
6+
setHeader(event, 'x-second-middleware', 'executed');
7+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { defineEventHandler, setHeader, getQuery } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Check if we should throw an error
5+
const query = getQuery(event);
6+
if (query.throwError === 'true') {
7+
throw new Error('Auth middleware error');
8+
}
9+
10+
// Set a header to indicate this middleware ran
11+
setHeader(event, 'x-auth-middleware', 'executed');
12+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { defineEventHandler, setHeader, getQuery } from '#imports';
2+
3+
export default defineEventHandler({
4+
onRequest: async event => {
5+
// Set a header to indicate the onRequest hook ran
6+
setHeader(event, 'x-hooks-onrequest', 'executed');
7+
8+
// Check if we should throw an error in onRequest
9+
const query = getQuery(event);
10+
if (query.throwOnRequestError === 'true') {
11+
throw new Error('OnRequest hook error');
12+
}
13+
},
14+
15+
handler: async event => {
16+
// Set a header to indicate the main handler ran
17+
setHeader(event, 'x-hooks-handler', 'executed');
18+
19+
// Check if we should throw an error in handler
20+
const query = getQuery(event);
21+
if (query.throwHandlerError === 'true') {
22+
throw new Error('Handler error');
23+
}
24+
},
25+
26+
onBeforeResponse: async (event, response) => {
27+
// Set a header to indicate the onBeforeResponse hook ran
28+
setHeader(event, 'x-hooks-onbeforeresponse', 'executed');
29+
30+
// Check if we should throw an error in onBeforeResponse
31+
const query = getQuery(event);
32+
if (query.throwOnBeforeResponseError === 'true') {
33+
throw new Error('OnBeforeResponse hook error');
34+
}
35+
},
36+
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { defineEventHandler, setHeader, getQuery } from '#imports';
2+
3+
export default defineEventHandler({
4+
// Array of onRequest handlers
5+
onRequest: [
6+
async event => {
7+
setHeader(event, 'x-array-onrequest-0', 'executed');
8+
9+
const query = getQuery(event);
10+
if (query.throwOnRequest0Error === 'true') {
11+
throw new Error('OnRequest[0] hook error');
12+
}
13+
},
14+
async event => {
15+
setHeader(event, 'x-array-onrequest-1', 'executed');
16+
17+
const query = getQuery(event);
18+
if (query.throwOnRequest1Error === 'true') {
19+
throw new Error('OnRequest[1] hook error');
20+
}
21+
},
22+
],
23+
24+
handler: async event => {
25+
setHeader(event, 'x-array-handler', 'executed');
26+
},
27+
28+
// Array of onBeforeResponse handlers
29+
onBeforeResponse: [
30+
async (event, response) => {
31+
setHeader(event, 'x-array-onbeforeresponse-0', 'executed');
32+
33+
const query = getQuery(event);
34+
if (query.throwOnBeforeResponse0Error === 'true') {
35+
throw new Error('OnBeforeResponse[0] hook error');
36+
}
37+
},
38+
async (event, response) => {
39+
setHeader(event, 'x-array-onbeforeresponse-1', 'executed');
40+
41+
const query = getQuery(event);
42+
if (query.throwOnBeforeResponse1Error === 'true') {
43+
throw new Error('OnBeforeResponse[1] hook error');
44+
}
45+
},
46+
],
47+
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /