Skip to content

Commit ef1f86b

Browse files
authored
Merge pull request #16234 from getsentry/prepare-release/9.17.0
meta(changelog): Update changelog for 9.17.0
2 parents 47f8bc6 + 16af311 commit ef1f86b

File tree

43 files changed

+1775
-323
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1775
-323
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010

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

13+
## 9.17.0
14+
15+
- feat(node): Migrate to `@fastify/otel` ([#15542](https://github.com/getsentry/sentry-javascript/pull/15542))
16+
1317
## 9.16.1
1418

1519
- fix(core): Make sure logs get flushed in server-runtime-client ([#16222](https://github.com/getsentry/sentry-javascript/pull/16222))

dev-packages/e2e-tests/test-applications/nestjs-fastify/tests/transactions.test.ts

+16-11
Original file line numberDiff line numberDiff line change
@@ -53,34 +53,39 @@ test('Sends an API route transaction', async ({ baseURL }) => {
5353
span_id: expect.stringMatching(/[a-f0-9]{16}/),
5454
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
5555
data: {
56-
'sentry.origin': 'manual',
57-
'fastify.type': 'middleware',
58-
'plugin.name': 'fastify -> @fastify/middie',
59-
'hook.name': 'onRequest',
56+
'sentry.origin': 'auto.http.otel.fastify',
57+
'sentry.op': 'hook.fastify',
58+
'service.name': 'fastify',
59+
'hook.name': 'fastify -> @fastify/otel -> @fastify/middie - onRequest',
60+
'fastify.type': 'hook',
61+
'hook.callback.name': 'runMiddie',
6062
},
61-
description: 'middleware - runMiddie',
63+
description: '@fastify/middie - onRequest',
64+
op: 'hook.fastify',
6265
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
6366
start_timestamp: expect.any(Number),
6467
timestamp: expect.any(Number),
6568
status: 'ok',
66-
origin: 'manual',
69+
origin: 'auto.http.otel.fastify',
6770
},
6871
{
6972
span_id: expect.stringMatching(/[a-f0-9]{16}/),
7073
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
7174
data: {
7275
'sentry.origin': 'auto.http.otel.fastify',
73-
'sentry.op': 'request_handler.fastify',
74-
'plugin.name': 'fastify -> @fastify/middie',
75-
'fastify.type': 'request_handler',
76+
'sentry.op': 'request-handler.fastify',
77+
'service.name': 'fastify',
78+
'hook.name': 'fastify -> @fastify/otel -> @fastify/middie - route-handler',
79+
'fastify.type': 'request-handler',
7680
'http.route': '/test-transaction',
81+
'hook.callback.name': 'anonymous',
7782
},
78-
description: '@fastify/middie',
83+
description: '@fastify/middie - route-handler',
84+
op: 'request-handler.fastify',
7985
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
8086
start_timestamp: expect.any(Number),
8187
timestamp: expect.any(Number),
8288
status: 'ok',
83-
op: 'request_handler.fastify',
8489
origin: 'auto.http.otel.fastify',
8590
},
8691
{

dev-packages/e2e-tests/test-applications/node-connect/tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"esModuleInterop": true,
55
"lib": ["dom", "dom.iterable", "esnext"],
66
"strict": true,
7-
"noEmit": true
7+
"noEmit": true,
8+
"skipLibCheck": true
89
},
910
"include": ["src/*.ts"]
1011
}

dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"esModuleInterop": true,
55
"lib": ["es2018"],
66
"strict": true,
7-
"outDir": "dist"
7+
"outDir": "dist",
8+
"skipLibCheck": true
89
},
910
"include": ["src/**/*.ts"]
1011
}

dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"esModuleInterop": true,
55
"lib": ["es2018"],
66
"strict": true,
7-
"outDir": "dist"
7+
"outDir": "dist",
8+
"skipLibCheck": true
89
},
910
"include": ["src/**/*.ts"]
1011
}

dev-packages/e2e-tests/test-applications/node-fastify/package.json renamed to dev-packages/e2e-tests/test-applications/node-fastify-3/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "node-fastify",
2+
"name": "node-fastify-3",
33
"version": "1.0.0",
44
"private": true,
55
"scripts": {
@@ -15,7 +15,7 @@
1515
"@sentry/core": "latest || *",
1616
"@sentry/opentelemetry": "latest || *",
1717
"@types/node": "^18.19.1",
18-
"fastify": "4.23.2",
18+
"fastify": "3.29.5",
1919
"typescript": "~5.0.0",
2020
"ts-node": "10.9.1"
2121
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import type * as S from '@sentry/node';
2+
const Sentry = require('@sentry/node') as typeof S;
3+
4+
// We wrap console.warn to find out if a warning is incorrectly logged
5+
console.warn = new Proxy(console.warn, {
6+
apply: function (target, thisArg, argumentsList) {
7+
const msg = argumentsList[0];
8+
if (typeof msg === 'string' && msg.startsWith('[Sentry]')) {
9+
console.error(`Sentry warning was triggered: ${msg}`);
10+
process.exit(1);
11+
}
12+
13+
return target.apply(thisArg, argumentsList);
14+
},
15+
});
16+
17+
Sentry.init({
18+
environment: 'qa', // dynamic sampling bias to keep transactions
19+
dsn: process.env.E2E_TEST_DSN,
20+
integrations: [],
21+
tracesSampleRate: 1,
22+
tunnel: 'http://localhost:3031/', // proxy server
23+
tracePropagationTargets: ['http://localhost:3030', '/external-allowed'],
24+
});
25+
26+
import type * as H from 'http';
27+
import type * as F from 'fastify';
28+
29+
// Make sure fastify is imported after Sentry is initialized
30+
const { fastify } = require('fastify') as typeof F;
31+
const http = require('http') as typeof H;
32+
33+
const app = fastify();
34+
const port = 3030;
35+
const port2 = 3040;
36+
37+
Sentry.setupFastifyErrorHandler(app);
38+
39+
app.get('/test-success', function (_req, res) {
40+
res.send({ version: 'v1' });
41+
});
42+
43+
app.get<{ Params: { param: string } }>('/test-param/:param', function (req, res) {
44+
res.send({ paramWas: req.params.param });
45+
});
46+
47+
app.get<{ Params: { id: string } }>('/test-inbound-headers/:id', function (req, res) {
48+
const headers = req.headers;
49+
50+
res.send({ headers, id: req.params.id });
51+
});
52+
53+
app.get<{ Params: { id: string } }>('/test-outgoing-http/:id', async function (req, res) {
54+
const id = req.params.id;
55+
const data = await makeHttpRequest(`http://localhost:3030/test-inbound-headers/${id}`);
56+
57+
res.send(data);
58+
});
59+
60+
app.get<{ Params: { id: string } }>('/test-outgoing-fetch/:id', async function (req, res) {
61+
const id = req.params.id;
62+
const response = await fetch(`http://localhost:3030/test-inbound-headers/${id}`);
63+
const data = await response.json();
64+
65+
res.send(data);
66+
});
67+
68+
app.get('/test-transaction', async function (req, res) {
69+
Sentry.startSpan({ name: 'test-span' }, () => {
70+
Sentry.startSpan({ name: 'child-span' }, () => {});
71+
});
72+
73+
res.send({});
74+
});
75+
76+
app.get('/test-error', async function (req, res) {
77+
const exceptionId = Sentry.captureException(new Error('This is an error'));
78+
79+
await Sentry.flush(2000);
80+
81+
res.send({ exceptionId });
82+
});
83+
84+
app.get<{ Params: { id: string } }>('/test-exception/:id', async function (req, res) {
85+
throw new Error(`This is an exception with id ${req.params.id}`);
86+
});
87+
88+
app.get('/test-outgoing-fetch-external-allowed', async function (req, res) {
89+
const fetchResponse = await fetch(`http://localhost:${port2}/external-allowed`);
90+
const data = await fetchResponse.json();
91+
92+
res.send(data);
93+
});
94+
95+
app.get('/test-outgoing-fetch-external-disallowed', async function (req, res) {
96+
const fetchResponse = await fetch(`http://localhost:${port2}/external-disallowed`);
97+
const data = await fetchResponse.json();
98+
99+
res.send(data);
100+
});
101+
102+
app.get('/test-outgoing-http-external-allowed', async function (req, res) {
103+
const data = await makeHttpRequest(`http://localhost:${port2}/external-allowed`);
104+
res.send(data);
105+
});
106+
107+
app.get('/test-outgoing-http-external-disallowed', async function (req, res) {
108+
const data = await makeHttpRequest(`http://localhost:${port2}/external-disallowed`);
109+
res.send(data);
110+
});
111+
112+
app.post('/test-post', function (req, res) {
113+
res.send({ status: 'ok', body: req.body });
114+
});
115+
116+
app.listen({ port: port });
117+
118+
// A second app so we can test header propagation between external URLs
119+
const app2 = fastify();
120+
app2.get('/external-allowed', function (req, res) {
121+
const headers = req.headers;
122+
123+
res.send({ headers, route: '/external-allowed' });
124+
});
125+
126+
app2.get('/external-disallowed', function (req, res) {
127+
const headers = req.headers;
128+
129+
res.send({ headers, route: '/external-disallowed' });
130+
});
131+
132+
app2.listen({ port: port2 });
133+
134+
function makeHttpRequest(url: string) {
135+
return new Promise(resolve => {
136+
const data: any[] = [];
137+
138+
http
139+
.request(url, httpRes => {
140+
httpRes.on('data', chunk => {
141+
data.push(chunk);
142+
});
143+
httpRes.on('error', error => {
144+
resolve({ error: error.message, url });
145+
});
146+
httpRes.on('end', () => {
147+
try {
148+
const json = JSON.parse(Buffer.concat(data).toString());
149+
resolve(json);
150+
} catch {
151+
resolve({ data: Buffer.concat(data).toString(), url });
152+
}
153+
});
154+
})
155+
.end();
156+
});
157+
}

dev-packages/e2e-tests/test-applications/node-fastify/start-event-proxy.mjs renamed to dev-packages/e2e-tests/test-applications/node-fastify-3/start-event-proxy.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ import { startEventProxyServer } from '@sentry-internal/test-utils';
22

33
startEventProxyServer({
44
port: 3031,
5-
proxyServerName: 'node-fastify',
5+
proxyServerName: 'node-fastify-3',
66
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { expect, test } from '@playwright/test';
2+
import { waitForError } from '@sentry-internal/test-utils';
3+
4+
test('Sends correct error event', async ({ baseURL }) => {
5+
const errorEventPromise = waitForError('node-fastify-3', event => {
6+
return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 123';
7+
});
8+
9+
await fetch(`${baseURL}/test-exception/123`);
10+
11+
const errorEvent = await errorEventPromise;
12+
13+
expect(errorEvent.exception?.values).toHaveLength(1);
14+
expect(errorEvent.exception?.values?.[0]?.value).toBe('This is an exception with id 123');
15+
16+
expect(errorEvent.request).toEqual({
17+
method: 'GET',
18+
cookies: {},
19+
headers: expect.any(Object),
20+
url: 'http://localhost:3030/test-exception/123',
21+
});
22+
23+
expect(errorEvent.transaction).toEqual('GET /test-exception/:id');
24+
25+
expect(errorEvent.contexts?.trace).toEqual({
26+
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
27+
span_id: expect.stringMatching(/[a-f0-9]{16}/),
28+
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
29+
});
30+
});

dev-packages/e2e-tests/test-applications/node-fastify/tests/propagation.test.ts renamed to dev-packages/e2e-tests/test-applications/node-fastify-3/tests/propagation.test.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import { SpanJSON } from '@sentry/core';
66
test('Propagates trace for outgoing http requests', async ({ baseURL }) => {
77
const id = crypto.randomUUID();
88

9-
const inboundTransactionPromise = waitForTransaction('node-fastify', transactionEvent => {
9+
const inboundTransactionPromise = waitForTransaction('node-fastify-3', transactionEvent => {
1010
return (
1111
transactionEvent.contexts?.trace?.op === 'http.server' &&
1212
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-inbound-headers/${id}`
1313
);
1414
});
1515

16-
const outboundTransactionPromise = waitForTransaction('node-fastify', transactionEvent => {
16+
const outboundTransactionPromise = waitForTransaction('node-fastify-3', transactionEvent => {
1717
return (
1818
transactionEvent.contexts?.trace?.op === 'http.server' &&
1919
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-http/${id}`
@@ -120,14 +120,14 @@ test('Propagates trace for outgoing http requests', async ({ baseURL }) => {
120120
test('Propagates trace for outgoing fetch requests', async ({ baseURL }) => {
121121
const id = crypto.randomUUID();
122122

123-
const inboundTransactionPromise = waitForTransaction('node-fastify', transactionEvent => {
123+
const inboundTransactionPromise = waitForTransaction('node-fastify-3', transactionEvent => {
124124
return (
125125
transactionEvent?.contexts?.trace?.op === 'http.server' &&
126126
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-inbound-headers/${id}`
127127
);
128128
});
129129

130-
const outboundTransactionPromise = waitForTransaction('node-fastify', transactionEvent => {
130+
const outboundTransactionPromise = waitForTransaction('node-fastify-3', transactionEvent => {
131131
return (
132132
transactionEvent?.contexts?.trace?.op === 'http.server' &&
133133
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-fetch/${id}`
@@ -232,7 +232,7 @@ test('Propagates trace for outgoing fetch requests', async ({ baseURL }) => {
232232
});
233233

234234
test('Propagates trace for outgoing external http requests', async ({ baseURL }) => {
235-
const inboundTransactionPromise = waitForTransaction('node-fastify', transactionEvent => {
235+
const inboundTransactionPromise = waitForTransaction('node-fastify-3', transactionEvent => {
236236
return (
237237
transactionEvent?.contexts?.trace?.op === 'http.server' &&
238238
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-http-external-allowed`
@@ -269,7 +269,7 @@ test('Propagates trace for outgoing external http requests', async ({ baseURL })
269269
});
270270

271271
test('Does not propagate outgoing http requests not covered by tracePropagationTargets', async ({ baseURL }) => {
272-
const inboundTransactionPromise = waitForTransaction('node-fastify', transactionEvent => {
272+
const inboundTransactionPromise = waitForTransaction('node-fastify-3', transactionEvent => {
273273
return (
274274
transactionEvent?.contexts?.trace?.op === 'http.server' &&
275275
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-http-external-disallowed`
@@ -293,7 +293,7 @@ test('Does not propagate outgoing http requests not covered by tracePropagationT
293293
});
294294

295295
test('Propagates trace for outgoing external fetch requests', async ({ baseURL }) => {
296-
const inboundTransactionPromise = waitForTransaction('node-fastify', transactionEvent => {
296+
const inboundTransactionPromise = waitForTransaction('node-fastify-3', transactionEvent => {
297297
return (
298298
transactionEvent?.contexts?.trace?.op === 'http.server' &&
299299
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-fetch-external-allowed`
@@ -330,7 +330,7 @@ test('Propagates trace for outgoing external fetch requests', async ({ baseURL }
330330
});
331331

332332
test('Does not propagate outgoing fetch requests not covered by tracePropagationTargets', async ({ baseURL }) => {
333-
const inboundTransactionPromise = waitForTransaction('node-fastify', transactionEvent => {
333+
const inboundTransactionPromise = waitForTransaction('node-fastify-3', transactionEvent => {
334334
return (
335335
transactionEvent?.contexts?.trace?.op === 'http.server' &&
336336
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-fetch-external-disallowed`

0 commit comments

Comments
 (0)