diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/app/generation-functions/with-redirect/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-14/app/generation-functions/with-redirect/page.tsx
deleted file mode 100644
index f1f37d7a32c6..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-14/app/generation-functions/with-redirect/page.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import { redirect } from 'next/navigation';
-
-export const dynamic = 'force-dynamic';
-
-export default function PageWithRedirect() {
- return
Hello World!
;
-}
-
-export async function generateMetadata() {
- redirect('/');
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts
index 084824824225..384e1e35055d 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts
+++ b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts
@@ -108,20 +108,3 @@ test('Should send a transaction and an error event for a faulty generateViewport
expect(errorEvent.transaction).toBe('Page.generateViewport (/generation-functions)');
});
-
-test('Should send a transaction event with correct status for a generateMetadata() function invocation with redirect()', async ({
- page,
-}) => {
- const testTitle = 'redirect-foobar';
-
- const transactionPromise = waitForTransaction('nextjs-14', async transactionEvent => {
- return (
- transactionEvent.contexts?.trace?.data?.['http.target'] ===
- `/generation-functions/with-redirect?metadataTitle=${testTitle}`
- );
- });
-
- await page.goto(`/generation-functions/with-redirect?metadataTitle=${testTitle}`);
-
- expect((await transactionPromise).contexts?.trace?.status).toBe('ok');
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/route-handlers/[param]/route.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/route-handlers/[param]/route.ts
index df5361852508..13535427a3b8 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/route-handlers/[param]/route.ts
+++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/route-handlers/[param]/route.ts
@@ -5,5 +5,5 @@ export async function GET() {
}
export async function POST() {
- return NextResponse.json({ name: 'John Doe' }, { status: 403 });
+ return NextResponse.json({ name: 'John Doe' }, { status: 400 });
}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts
index 02f2b6dc4f24..946f9e20911a 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts
+++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts
@@ -28,7 +28,7 @@ test('Should create a transaction for route handlers and correctly set span stat
const routehandlerTransaction = await routehandlerTransactionPromise;
- expect(routehandlerTransaction.contexts?.trace?.status).toBe('permission_denied');
+ expect(routehandlerTransaction.contexts?.trace?.status).toBe('invalid_argument');
expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
});
diff --git a/dev-packages/e2e-tests/test-applications/node-express/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express/src/app.ts
index 35b21a97b9aa..9f7b0055b66d 100644
--- a/dev-packages/e2e-tests/test-applications/node-express/src/app.ts
+++ b/dev-packages/e2e-tests/test-applications/node-express/src/app.ts
@@ -143,8 +143,8 @@ export const appRouter = t.router({
.mutation(() => {
throw new Error('I crashed in a trpc handler');
}),
- unauthorized: procedure.mutation(() => {
- throw new TRPCError({ code: 'UNAUTHORIZED', cause: new Error('Unauthorized') });
+ badRequest: procedure.mutation(() => {
+ throw new TRPCError({ code: 'BAD_REQUEST', cause: new Error('Bad Request') });
}),
});
diff --git a/dev-packages/e2e-tests/test-applications/node-express/tests/trpc.test.ts b/dev-packages/e2e-tests/test-applications/node-express/tests/trpc.test.ts
index 3cb458f81175..e27789b7e4c5 100644
--- a/dev-packages/e2e-tests/test-applications/node-express/tests/trpc.test.ts
+++ b/dev-packages/e2e-tests/test-applications/node-express/tests/trpc.test.ts
@@ -109,12 +109,12 @@ test('Should record transaction and error for a trpc handler that returns a stat
const transactionEventPromise = waitForTransaction('node-express', transactionEvent => {
return (
transactionEvent.transaction === 'POST /trpc' &&
- !!transactionEvent.spans?.find(span => span.description === 'trpc/unauthorized')
+ !!transactionEvent.spans?.find(span => span.description === 'trpc/badRequest')
);
});
const errorEventPromise = waitForError('node-express', errorEvent => {
- return !!errorEvent?.exception?.values?.some(exception => exception.value?.includes('Unauthorized'));
+ return !!errorEvent?.exception?.values?.some(exception => exception.value?.includes('Bad Request'));
});
const trpcClient = createTRPCProxyClient({
@@ -125,7 +125,7 @@ test('Should record transaction and error for a trpc handler that returns a stat
],
});
- await expect(trpcClient.unauthorized.mutate()).rejects.toBeDefined();
+ await expect(trpcClient.badRequest.mutate()).rejects.toBeDefined();
await expect(transactionEventPromise).resolves.toBeDefined();
await expect(errorEventPromise).resolves.toBeDefined();
diff --git a/dev-packages/node-integration-tests/suites/express-v5/tracing/scenario-filterStatusCode.mjs b/dev-packages/node-integration-tests/suites/express-v5/tracing/scenario-filterStatusCode.mjs
index f2e20014f48f..c53a72951970 100644
--- a/dev-packages/node-integration-tests/suites/express-v5/tracing/scenario-filterStatusCode.mjs
+++ b/dev-packages/node-integration-tests/suites/express-v5/tracing/scenario-filterStatusCode.mjs
@@ -8,6 +8,18 @@ app.get('/', (_req, res) => {
res.send({ response: 'response 0' });
});
+app.get('/401', (_req, res) => {
+ res.status(401).send({ response: 'response 401' });
+});
+
+app.get('/402', (_req, res) => {
+ res.status(402).send({ response: 'response 402' });
+});
+
+app.get('/403', (_req, res) => {
+ res.status(403).send({ response: 'response 403' });
+});
+
app.get('/499', (_req, res) => {
res.status(499).send({ response: 'response 499' });
});
diff --git a/dev-packages/node-integration-tests/suites/express-v5/tracing/scenario.mjs b/dev-packages/node-integration-tests/suites/express-v5/tracing/scenario.mjs
index fe3e190a4bdd..b0aebcbe8a79 100644
--- a/dev-packages/node-integration-tests/suites/express-v5/tracing/scenario.mjs
+++ b/dev-packages/node-integration-tests/suites/express-v5/tracing/scenario.mjs
@@ -15,6 +15,18 @@ app.get('/', (_req, res) => {
res.send({ response: 'response 0' });
});
+app.get('/401', (_req, res) => {
+ res.status(401).send({ response: 'response 401' });
+});
+
+app.get('/402', (_req, res) => {
+ res.status(402).send({ response: 'response 402' });
+});
+
+app.get('/403', (_req, res) => {
+ res.status(403).send({ response: 'response 403' });
+});
+
app.get('/test/express', (_req, res) => {
res.send({ response: 'response 1' });
});
diff --git a/dev-packages/node-integration-tests/suites/express-v5/tracing/test.ts b/dev-packages/node-integration-tests/suites/express-v5/tracing/test.ts
index 4618f801a087..5ed3878572b8 100644
--- a/dev-packages/node-integration-tests/suites/express-v5/tracing/test.ts
+++ b/dev-packages/node-integration-tests/suites/express-v5/tracing/test.ts
@@ -89,16 +89,16 @@ describe('express v5 tracing', () => {
await runner.completed();
});
- test('ignores 404 routes by default', async () => {
+ test.each(['/401', '/402', '/403', '/does-not-exist'])('ignores %s route by default', async (url: string) => {
const runner = createRunner()
.expect({
- // No transaction is sent for the 404 route
+ // No transaction is sent for the 401, 402, 403, 404 routes
transaction: {
transaction: 'GET /',
},
})
.start();
- runner.makeRequest('get', '/does-not-exist', { expectError: true });
+ runner.makeRequest('get', url, { expectError: true });
runner.makeRequest('get', '/');
await runner.completed();
});
@@ -284,33 +284,41 @@ describe('express v5 tracing', () => {
'scenario-filterStatusCode.mjs',
'instrument-filterStatusCode.mjs',
(createRunner, test) => {
- // We opt-out of the default 404 filtering in order to test how 404 spans are handled
- test('handles 404 route correctly', async () => {
- const runner = createRunner()
- .expect({
- transaction: {
- transaction: 'GET /does-not-exist',
- contexts: {
- trace: {
- span_id: expect.stringMatching(/[a-f0-9]{16}/),
- trace_id: expect.stringMatching(/[a-f0-9]{32}/),
- data: {
- 'http.response.status_code': 404,
- url: expect.stringMatching(/\/does-not-exist$/),
- 'http.method': 'GET',
- 'http.url': expect.stringMatching(/\/does-not-exist$/),
- 'http.target': '/does-not-exist',
+ // We opt-out of the default [401, 404] fitering in order to test how these spans are handled
+ test.each([
+ { status_code: 401, url: '/401', status: 'unauthenticated' },
+ { status_code: 402, url: '/402', status: 'invalid_argument' },
+ { status_code: 403, url: '/403', status: 'permission_denied' },
+ { status_code: 404, url: '/does-not-exist', status: 'not_found' },
+ ])(
+ 'handles %s route correctly',
+ async ({ status_code, url, status }: { status_code: number; url: string; status: string }) => {
+ const runner = createRunner()
+ .expect({
+ transaction: {
+ transaction: `GET ${url}`,
+ contexts: {
+ trace: {
+ span_id: expect.stringMatching(/[a-f0-9]{16}/),
+ trace_id: expect.stringMatching(/[a-f0-9]{32}/),
+ data: {
+ 'http.response.status_code': status_code,
+ url: expect.stringMatching(url),
+ 'http.method': 'GET',
+ 'http.url': expect.stringMatching(url),
+ 'http.target': url,
+ },
+ op: 'http.server',
+ status,
},
- op: 'http.server',
- status: 'not_found',
},
},
- },
- })
- .start();
- runner.makeRequest('get', '/does-not-exist', { expectError: true });
- await runner.completed();
- });
+ })
+ .start();
+ runner.makeRequest('get', url, { expectError: true });
+ await runner.completed();
+ },
+ );
test('filters defined status codes', async () => {
const runner = createRunner()
diff --git a/dev-packages/node-integration-tests/suites/express/tracing/scenario-filterStatusCode.mjs b/dev-packages/node-integration-tests/suites/express/tracing/scenario-filterStatusCode.mjs
index f2e20014f48f..c53a72951970 100644
--- a/dev-packages/node-integration-tests/suites/express/tracing/scenario-filterStatusCode.mjs
+++ b/dev-packages/node-integration-tests/suites/express/tracing/scenario-filterStatusCode.mjs
@@ -8,6 +8,18 @@ app.get('/', (_req, res) => {
res.send({ response: 'response 0' });
});
+app.get('/401', (_req, res) => {
+ res.status(401).send({ response: 'response 401' });
+});
+
+app.get('/402', (_req, res) => {
+ res.status(402).send({ response: 'response 402' });
+});
+
+app.get('/403', (_req, res) => {
+ res.status(403).send({ response: 'response 403' });
+});
+
app.get('/499', (_req, res) => {
res.status(499).send({ response: 'response 499' });
});
diff --git a/dev-packages/node-integration-tests/suites/express/tracing/scenario.mjs b/dev-packages/node-integration-tests/suites/express/tracing/scenario.mjs
index 8b48ee0dbc44..4e32a052908d 100644
--- a/dev-packages/node-integration-tests/suites/express/tracing/scenario.mjs
+++ b/dev-packages/node-integration-tests/suites/express/tracing/scenario.mjs
@@ -15,6 +15,18 @@ app.get('/', (_req, res) => {
res.send({ response: 'response 0' });
});
+app.get('/401', (_req, res) => {
+ res.status(401).send({ response: 'response 401' });
+});
+
+app.get('/402', (_req, res) => {
+ res.status(402).send({ response: 'response 402' });
+});
+
+app.get('/403', (_req, res) => {
+ res.status(403).send({ response: 'response 403' });
+});
+
app.get('/test/express', (_req, res) => {
res.send({ response: 'response 1' });
});
diff --git a/dev-packages/node-integration-tests/suites/express/tracing/test.ts b/dev-packages/node-integration-tests/suites/express/tracing/test.ts
index 63706c0e5cb2..f5a772dbf096 100644
--- a/dev-packages/node-integration-tests/suites/express/tracing/test.ts
+++ b/dev-packages/node-integration-tests/suites/express/tracing/test.ts
@@ -90,16 +90,16 @@ describe('express tracing', () => {
await runner.completed();
});
- test('ignores 404 routes by default', async () => {
+ test.each(['/401', '/402', '/403', '/does-not-exist'])('ignores %s route by default', async (url: string) => {
const runner = createRunner()
.expect({
- // No transaction is sent for the 404 route
+ // No transaction is sent for the 401, 402, 403, 404 routes
transaction: {
transaction: 'GET /',
},
})
.start();
- runner.makeRequest('get', '/does-not-exist', { expectError: true });
+ runner.makeRequest('get', url, { expectError: true });
runner.makeRequest('get', '/');
await runner.completed();
});
@@ -315,34 +315,42 @@ describe('express tracing', () => {
'scenario-filterStatusCode.mjs',
'instrument-filterStatusCode.mjs',
(createRunner, test) => {
- // We opt-out of the default 404 filtering in order to test how 404 spans are handled
- test('handles 404 route correctly', async () => {
- const runner = createRunner()
- .expect({
- transaction: {
- // FIXME: This is incorrect, sadly :(
- transaction: 'GET /',
- contexts: {
- trace: {
- span_id: expect.stringMatching(/[a-f0-9]{16}/),
- trace_id: expect.stringMatching(/[a-f0-9]{32}/),
- data: {
- 'http.response.status_code': 404,
- url: expect.stringMatching(/\/does-not-exist$/),
- 'http.method': 'GET',
- 'http.url': expect.stringMatching(/\/does-not-exist$/),
- 'http.target': '/does-not-exist',
+ // We opt-out of the default [401, 404] filtering in order to test how these spans are handled
+ test.each([
+ { status_code: 401, url: '/401', status: 'unauthenticated' },
+ { status_code: 402, url: '/402', status: 'invalid_argument' },
+ { status_code: 403, url: '/403', status: 'permission_denied' },
+ { status_code: 404, url: '/does-not-exist', status: 'not_found' },
+ ])(
+ 'handles %s route correctly',
+ async ({ status_code, url, status }: { status_code: number; url: string; status: string }) => {
+ const runner = createRunner()
+ .expect({
+ transaction: {
+ // TODO(v10): This is incorrect on OpenTelemetry v1 but can be fixed in v2
+ transaction: `GET ${status_code === 404 ? '/' : url}`,
+ contexts: {
+ trace: {
+ span_id: expect.stringMatching(/[a-f0-9]{16}/),
+ trace_id: expect.stringMatching(/[a-f0-9]{32}/),
+ data: {
+ 'http.response.status_code': status_code,
+ url: expect.stringMatching(url),
+ 'http.method': 'GET',
+ 'http.url': expect.stringMatching(url),
+ 'http.target': url,
+ },
+ op: 'http.server',
+ status,
},
- op: 'http.server',
- status: 'not_found',
},
},
- },
- })
- .start();
- runner.makeRequest('get', '/does-not-exist', { expectError: true });
- await runner.completed();
- });
+ })
+ .start();
+ runner.makeRequest('get', url, { expectError: true });
+ await runner.completed();
+ },
+ );
test('filters defined status codes', async () => {
const runner = createRunner()
diff --git a/dev-packages/rollup-utils/npmHelpers.mjs b/dev-packages/rollup-utils/npmHelpers.mjs
index 83053aaeea98..cff113d622d6 100644
--- a/dev-packages/rollup-utils/npmHelpers.mjs
+++ b/dev-packages/rollup-utils/npmHelpers.mjs
@@ -93,7 +93,7 @@ export function makeBaseNPMConfig(options = {}) {
}
return true;
- }
+ },
},
plugins: [nodeResolvePlugin, sucrasePlugin, debugBuildStatementReplacePlugin, rrwebBuildPlugin, cleanupPlugin],
diff --git a/packages/node-core/src/integrations/http/index.ts b/packages/node-core/src/integrations/http/index.ts
index 8bd69c22a8e7..7e574712990d 100644
--- a/packages/node-core/src/integrations/http/index.ts
+++ b/packages/node-core/src/integrations/http/index.ts
@@ -57,7 +57,7 @@ interface HttpOptions {
* By default, spans with 404 status code are ignored.
* Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.
*
- * @default `[404]`
+ * @default `[[401, 404], [300, 399]]`
*/
dropSpansForIncomingRequestStatusCodes?: (number | [number, number])[];
@@ -105,7 +105,10 @@ const instrumentSentryHttp = generateInstrumentOnce {
- const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [404];
+ const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [
+ [401, 404],
+ [300, 399],
+ ];
return {
name: INTEGRATION_NAME,
diff --git a/packages/node/src/integrations/http/index.ts b/packages/node/src/integrations/http/index.ts
index e46e830f9d16..e56842be85cb 100644
--- a/packages/node/src/integrations/http/index.ts
+++ b/packages/node/src/integrations/http/index.ts
@@ -79,7 +79,7 @@ interface HttpOptions {
* By default, spans with 404 status code are ignored.
* Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.
*
- * @default `[404]`
+ * @default `[[401, 404], [300, 399]]`
*/
dropSpansForIncomingRequestStatusCodes?: (number | [number, number])[];
@@ -184,7 +184,10 @@ export function _shouldInstrumentSpans(options: HttpOptions, clientOptions: Part
* It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.
*/
export const httpIntegration = defineIntegration((options: HttpOptions = {}) => {
- const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [404];
+ const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [
+ [401, 404],
+ [300, 399],
+ ];
return {
name: INTEGRATION_NAME,
diff --git a/packages/remix/test/integration/test/server/instrumentation/action.test.ts b/packages/remix/test/integration/test/server/instrumentation/action.test.ts
index 3681e43807b8..bca38429ee29 100644
--- a/packages/remix/test/integration/test/server/instrumentation/action.test.ts
+++ b/packages/remix/test/integration/test/server/instrumentation/action.test.ts
@@ -152,28 +152,15 @@ describe('Remix API Actions', () => {
const envelopes = await env.getMultipleEnvelopeRequest({
url,
- count: 3,
+ count: 2,
method: 'post',
envelopeType: ['transaction', 'event'],
});
- const [transaction_1, transaction_2] = envelopes.filter(envelope => envelope[1].type === 'transaction');
+ const [transaction] = envelopes.filter(envelope => envelope[1].type === 'transaction');
const [event] = envelopes.filter(envelope => envelope[1].type === 'event');
- assertSentryTransaction(transaction_1[2], {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'ok',
- data: {
- 'http.response.status_code': 302,
- },
- },
- },
- transaction: `POST action-json-response/:id`,
- });
-
- assertSentryTransaction(transaction_2[2], {
+ assertSentryTransaction(transaction[2], {
contexts: {
trace: {
op: 'http.server',
diff --git a/packages/remix/test/integration/test/server/instrumentation/loader.test.ts b/packages/remix/test/integration/test/server/instrumentation/loader.test.ts
index eef2a9683813..c90c23d135c8 100644
--- a/packages/remix/test/integration/test/server/instrumentation/loader.test.ts
+++ b/packages/remix/test/integration/test/server/instrumentation/loader.test.ts
@@ -123,27 +123,14 @@ describe('Remix API Loaders', () => {
const envelopes = await env.getMultipleEnvelopeRequest({
url,
- count: 3,
+ count: 2,
envelopeType: ['transaction', 'event'],
});
- const [transaction_1, transaction_2] = envelopes.filter(envelope => envelope[1].type === 'transaction');
+ const [transaction] = envelopes.filter(envelope => envelope[1].type === 'transaction');
const [event] = envelopes.filter(envelope => envelope[1].type === 'event');
- assertSentryTransaction(transaction_1[2], {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'ok',
- data: {
- 'http.response.status_code': 302,
- },
- },
- },
- transaction: `GET loader-json-response/:id`,
- });
-
- assertSentryTransaction(transaction_2[2], {
+ assertSentryTransaction(transaction[2], {
contexts: {
trace: {
op: 'http.server',