Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ body:
- '@sentry/nestjs'
- '@sentry/nextjs'
- '@sentry/nuxt'
- '@sentry/pino-transport'
- '@sentry/react'
- '@sentry/react-router'
- '@sentry/remix'
Expand Down
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,44 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

## 10.18.0

### Important Changes

- **feat(node): `pino` integration ([#17584](https://github.com/getsentry/sentry-javascript/pull/17584))**

This release adds a new `pino` integration for Node.js, enabling Sentry to capture logs from the Pino logging library.

- **feat: Remove @sentry/pino-transport package ([#17851](https://github.com/getsentry/sentry-javascript/pull/17851))**

The `@sentry/pino-transport` package has been removed. Please use the new `pino` integration in `@sentry/node` instead.

- **feat(node-core): Extend onnhandledrejection with ignore errors option ([#17736](https://github.com/getsentry/sentry-javascript/pull/17736))**

Added support for selectively suppressing specific errors with configurable logging control in onnhandledrejection integration.

### Other Changes

- feat(core): Rename vercelai.schema to gen_ai.request.schema ([#17850](https://github.com/getsentry/sentry-javascript/pull/17850))
- feat(core): Support stream responses and tool calls for Google GenAI ([#17664](https://github.com/getsentry/sentry-javascript/pull/17664))
- feat(nextjs): Attach headers using client hook ([#17831](https://github.com/getsentry/sentry-javascript/pull/17831))
- fix(core): Keep all property values in baggage header ([#17847](https://github.com/getsentry/sentry-javascript/pull/17847))
- fix(nestjs): Add support for Symbol as event name ([#17785](https://github.com/getsentry/sentry-javascript/pull/17785))
- fix(nuxt): include `sentry.client.config.ts` in nuxt app types ([#17830](https://github.com/getsentry/sentry-javascript/pull/17830))
- fix(react-router): Fix type for `OriginalHandleRequest` with middleware ([#17870](https://github.com/getsentry/sentry-javascript/pull/17870))

<details>
<summary> <strong>Internal Changes</strong> </summary>

- chore: Add external contributor to CHANGELOG.md ([#17866](https://github.com/getsentry/sentry-javascript/pull/17866))
- chore(deps): Bump @sentry/cli from 2.53.0 to 2.56.0 ([#17819](https://github.com/getsentry/sentry-javascript/pull/17819))
- chore(deps): Bump axios in browser integration tests ([#17839](https://github.com/getsentry/sentry-javascript/pull/17839))
- chore(deps): Bump nestjs in integration tests ([#17840](https://github.com/getsentry/sentry-javascript/pull/17840))

</details>

Work in this release was contributed by @stefanvanderwolf. Thank you for your contribution!

## 10.17.0

### Important Changes
Expand Down
2 changes: 1 addition & 1 deletion dev-packages/browser-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"@sentry-internal/rrweb": "2.34.0",
"@sentry/browser": "10.17.0",
"@supabase/supabase-js": "2.49.3",
"axios": "1.8.2",
"axios": "^1.12.2",
"babel-loader": "^8.2.2",
"fflate": "0.8.2",
"html-webpack-plugin": "^5.5.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fetchButton.addEventListener('click', () => {
// W3C spec example: property values can contain = signs
// See: https://www.w3.org/TR/baggage/#example
fetch('http://sentry-test-site.example/fetch-test', {
headers: {
baggage: 'key1=value1;property1;property2,key2=value2,key3=value3; propertyKey=propertyValue',
},
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fetch Baggage Property Values Test</title>
</head>
<body>
<button id="fetchButton">Make Fetch Request</button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { expect } from '@playwright/test';
import { TRACEPARENT_REGEXP } from '@sentry/core';
import { sentryTest } from '../../../../utils/fixtures';
import { shouldSkipTracingTest } from '../../../../utils/helpers';

sentryTest(
'preserves baggage property values with equal signs in fetch requests',
async ({ getLocalTestUrl, page }) => {
if (shouldSkipTracingTest()) {
sentryTest.skip();
}

const url = await getLocalTestUrl({ testDir: __dirname });

const requestPromise = page.waitForRequest('http://sentry-test-site.example/fetch-test');

await page.goto(url);
await page.click('#fetchButton');

const request = await requestPromise;

const requestHeaders = request.headers();

expect(requestHeaders).toMatchObject({
'sentry-trace': expect.stringMatching(TRACEPARENT_REGEXP),
});

const baggageHeader = requestHeaders.baggage;
expect(baggageHeader).toBeDefined();

const baggageItems = baggageHeader.split(',').map(item => decodeURIComponent(item.trim()));

// Verify property values with = signs are preserved
expect(baggageItems).toContainEqual(expect.stringContaining('key1=value1;property1;property2'));
expect(baggageItems).toContainEqual(expect.stringContaining('key2=value2'));
expect(baggageItems).toContainEqual(expect.stringContaining('key3=value3; propertyKey=propertyValue'));

// Verify Sentry baggage is also present
expect(baggageHeader).toMatch(/sentry-/);
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const xhr = new XMLHttpRequest();

xhr.open('GET', 'http://sentry-test-site.example/1');
// W3C spec example: property values can contain = signs
// See: https://www.w3.org/TR/baggage/#example
xhr.setRequestHeader('baggage', 'key1=value1;property1;property2,key2=value2,key3=value3; propertyKey=propertyValue');

xhr.send();
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { expect } from '@playwright/test';
import { TRACEPARENT_REGEXP } from '@sentry/core';
import { sentryTest } from '../../../../utils/fixtures';
import { shouldSkipTracingTest } from '../../../../utils/helpers';

sentryTest('preserves baggage property values with equal signs in XHR requests', async ({ getLocalTestUrl, page }) => {
if (shouldSkipTracingTest()) {
sentryTest.skip();
}

const url = await getLocalTestUrl({ testDir: __dirname });

const requestPromise = page.waitForRequest('http://sentry-test-site.example/1');

await page.goto(url);

const request = await requestPromise;

const requestHeaders = request.headers();

expect(requestHeaders).toMatchObject({
'sentry-trace': expect.stringMatching(TRACEPARENT_REGEXP),
});

const baggageHeader = requestHeaders.baggage;
expect(baggageHeader).toBeDefined();
const baggageItems = baggageHeader.split(',').map(item => decodeURIComponent(item.trim()));

// Verify property values with = signs are preserved
expect(baggageItems).toContainEqual(expect.stringContaining('key1=value1;property1;property2'));
expect(baggageItems).toContainEqual(expect.stringContaining('key2=value2'));
expect(baggageItems).toContainEqual(expect.stringContaining('key3=value3; propertyKey=propertyValue'));

// Verify Sentry baggage is also present
expect(baggageHeader).toMatch(/sentry-/);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { NextResponse } from 'next/server';

export const runtime = 'edge';
export const dynamic = 'force-dynamic';

export async function GET() {
return NextResponse.json({ message: 'Hello Edge Route Handler' });
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { NextResponse } from 'next/server';

export const dynamic = 'force-dynamic';

export async function GET() {
return NextResponse.json({ message: 'Hello Node Route Handler' });
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ test('App router transactions should be attached to the pageload request span',
});

test('extracts HTTP request headers as span attributes', async ({ baseURL }) => {
test.skip(
process.env.TEST_ENV === 'prod-turbopack' || process.env.TEST_ENV === 'dev-turbopack',
'Incoming fetch request headers are not added as span attributes when Turbopack is enabled (addHeadersAsAttributes)',
);

const serverTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
return transactionEvent?.transaction === 'GET /pageload-tracing';
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import test, { expect } from '@playwright/test';
import { waitForTransaction } from '@sentry-internal/test-utils';

test('Should create a transaction for node route handlers', async ({ request }) => {
const routehandlerTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
console.log(transactionEvent?.transaction);
return transactionEvent?.transaction === 'GET /route-handler/[xoxo]/node';
});

const response = await request.get('/route-handler/123/node', { headers: { 'x-charly': 'gomez' } });
expect(await response.json()).toStrictEqual({ message: 'Hello Node Route Handler' });

const routehandlerTransaction = await routehandlerTransactionPromise;

expect(routehandlerTransaction.contexts?.trace?.status).toBe('ok');
expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');

// This is flaking on dev mode
if (process.env.TEST_ENV !== 'development' && process.env.TEST_ENV !== 'dev-turbopack') {
expect(routehandlerTransaction.contexts?.trace?.data?.['http.request.header.x_charly']).toBe('gomez');
}
});

test('Should create a transaction for edge route handlers', async ({ request }) => {
// This test only works for webpack builds on non-async param extraction
// todo: check if we can set request headers for edge on sdkProcessingMetadata
test.skip();
const routehandlerTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
return transactionEvent?.transaction === 'GET /route-handler/[xoxo]/edge';
});

const response = await request.get('/route-handler/123/edge', { headers: { 'x-charly': 'gomez' } });
expect(await response.json()).toStrictEqual({ message: 'Hello Edge Route Handler' });

const routehandlerTransaction = await routehandlerTransactionPromise;

expect(routehandlerTransaction.contexts?.trace?.status).toBe('ok');
expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
expect(routehandlerTransaction.contexts?.trace?.data?.['http.request.header.x_charly']).toBe('gomez');
});
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const DEPENDENTS: Dependent[] = [
'NODE_VERSION',
'childProcessIntegration',
'systemErrorIntegration',
'pinoIntegration',
],
},
{
Expand Down
6 changes: 0 additions & 6 deletions dev-packages/e2e-tests/verdaccio-config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,6 @@ packages:
unpublish: $all
# proxy: npmjs # Don't proxy for E2E tests!

'@sentry/pino-transport':
access: $all
publish: $all
unpublish: $all
# proxy: npmjs # Don't proxy for E2E tests!

'@sentry/profiling-node':
access: $all
publish: $all
Expand Down
6 changes: 3 additions & 3 deletions dev-packages/node-core-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
"test:watch": "yarn test --watch"
},
"dependencies": {
"@nestjs/common": "11.0.16",
"@nestjs/core": "10.4.6",
"@nestjs/platform-express": "10.4.6",
"@nestjs/common": "^11",
"@nestjs/core": "^11",
"@nestjs/platform-express": "^11",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^2.1.0",
"@opentelemetry/core": "^2.1.0",
Expand Down
8 changes: 5 additions & 3 deletions dev-packages/node-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
"@google/genai": "^1.20.0",
"@hapi/hapi": "^21.3.10",
"@hono/node-server": "^1.19.4",
"@nestjs/common": "11.1.3",
"@nestjs/core": "11.1.3",
"@nestjs/platform-express": "11.1.3",
"@nestjs/common": "^11",
"@nestjs/core": "^11",
"@nestjs/platform-express": "^11",
"@prisma/client": "6.15.0",
"@sentry/aws-serverless": "10.17.0",
"@sentry/core": "10.17.0",
Expand Down Expand Up @@ -66,6 +66,8 @@
"node-schedule": "^2.1.1",
"openai": "5.18.1",
"pg": "8.16.0",
"pino": "9.9.4",
"pino-next": "npm:pino@^9.12.0",
"postgres": "^3.4.7",
"prisma": "6.15.0",
"proxy": "^2.1.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as Sentry from '@sentry/node';
import { loggingTransport, startExpressServerAndSendPortToRunner } from '@sentry-internal/node-integration-tests';

export type TestAPIResponse = { test_data: { host: string; 'sentry-trace': string; baggage: string } };

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
environment: 'prod',
// disable requests to /express
tracePropagationTargets: [/^(?!.*express).*$/],
tracesSampleRate: 1.0,
transport: loggingTransport,
});

import cors from 'cors';
import express from 'express';
import http from 'http';

const app = express();

app.use(cors());

app.get('/test/express-property-values', (req, res) => {
const incomingBaggage = req.headers.baggage;

// Forward the incoming baggage (which contains property values) to the outgoing request
// This tests that property values with = signs are preserved during parsing and re-serialization
const headers = http.get({ hostname: 'somewhere.not.sentry', headers: { baggage: incomingBaggage } }).getHeaders();

// Responding with the headers outgoing request headers back to the assertions.
res.send({ test_data: headers });
});

Sentry.setupExpressErrorHandler(app);

startExpressServerAndSendPortToRunner(app);
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { afterAll, expect, test } from 'vitest';
import { cleanupChildProcesses, createRunner } from '../../../../utils/runner';
import type { TestAPIResponse } from './server';

afterAll(() => {
cleanupChildProcesses();
});

test('should preserve baggage property values with equal signs (W3C spec compliance)', async () => {
const runner = createRunner(__dirname, 'server.ts').start();

// W3C spec example: https://www.w3.org/TR/baggage/#example
const response = await runner.makeRequest<TestAPIResponse>('get', '/test/express-property-values', {
headers: {
'sentry-trace': '12312012123120121231201212312012-1121201211212012-1',
baggage: 'key1=value1;property1;property2,key2=value2,key3=value3; propertyKey=propertyValue',
},
});

expect(response).toBeDefined();

// The baggage should be parsed and re-serialized, preserving property values with = signs
const baggageItems = response?.test_data.baggage?.split(',').map(item => decodeURIComponent(item.trim()));

expect(baggageItems).toContain('key1=value1;property1;property2');
expect(baggageItems).toContain('key2=value2');
expect(baggageItems).toContain('key3=value3; propertyKey=propertyValue');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as Sentry from '@sentry/node';

Sentry.init({
dsn: process.env.SENTRY_DSN,
release: '1.0',
enableLogs: true,
integrations: [Sentry.pinoIntegration({ error: { levels: ['error', 'fatal'] } })],
});
18 changes: 18 additions & 0 deletions dev-packages/node-integration-tests/suites/pino/scenario-next.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as Sentry from '@sentry/node';
import pino from 'pino-next';

const logger = pino({});

Sentry.withIsolationScope(() => {
Sentry.startSpan({ name: 'startup' }, () => {
logger.info({ user: 'user-id', something: { more: 3, complex: 'nope' } }, 'hello world');
});
});

setTimeout(() => {
Sentry.withIsolationScope(() => {
Sentry.startSpan({ name: 'later' }, () => {
logger.error(new Error('oh no'));
});
});
}, 1000);
Loading
Loading