Skip to content

feat!: Bump to OpenTelemetry v2 #16872

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Jul 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
50dc02f
feat: Bump to OpenTelemetry v2
andreiborza Jul 9, 2025
1ddb268
Replace instrumentation-redis-4 with instrumentation-redis
andreiborza Jul 9, 2025
5fa46a3
Address breaking changes for Resource and TracerProvider
andreiborza Jul 9, 2025
21d1b94
Bump node-core-integration-tests OTel deps
andreiborza Jul 9, 2025
0e9b936
Fix nestjs isWrapped import
andreiborza Jul 9, 2025
5f3b902
Adjust @sentry/opentelemetry unit tests for v2
andreiborza Jul 9, 2025
3411e30
Remove dev-packages/opentelemetry-v2-tests
andreiborza Jul 9, 2025
83f642a
Adjust @sentry/node unit tests
andreiborza Jul 9, 2025
b8a3d44
Adjust @sentry/node-core unit tests
andreiborza Jul 9, 2025
67a8d2b
Bump OTel in e2e tests
andreiborza Jul 10, 2025
60d3837
Remove vendored express v5 instrumentation
andreiborza Jul 10, 2025
925773e
Avoid casting to any in tests
andreiborza Jul 10, 2025
7fc54d1
Fix e2e/node-express transactions tests
andreiborza Jul 10, 2025
05e621a
Make OTel core and sdk-trace-base direct deps of vercel-edge
andreiborza Jul 10, 2025
748ace8
Fix e2e/node-express-cjs-preload tests
andreiborza Jul 10, 2025
dafd0b4
Fix e2e/node-express-esm-loader tests
andreiborza Jul 10, 2025
2278ab2
Fix e2e/node-express-esm-preload tests
andreiborza Jul 10, 2025
857beff
Fix e2e/node-otel tests
andreiborza Jul 10, 2025
386d674
Fix e2e/node-otel-custom-sampler tests
andreiborza Jul 10, 2025
4ddff1c
Fix e2e/node-otel-sdk-node tests
andreiborza Jul 10, 2025
19cae7c
Fix e2e/node-otel-without-tracing tests
andreiborza Jul 10, 2025
81f51d7
Add node-core to .size-limit.js and adjust node's size limit
andreiborza Jul 10, 2025
8acb292
Fix e2e/nextjs-app-dir tests by keeping @opentelemetry/sdk-trace-base…
andreiborza Jul 10, 2025
f55a0e7
Try moving deps back to devDeps
andreiborza Jul 11, 2025
b7e098c
Try different deps shuffling
andreiborza Jul 11, 2025
9ea45b6
Try polyfilling nodejs util
andreiborza Jul 11, 2025
c091efb
Adjust tests to look at trace continuation via request handler spans
andreiborza Jul 13, 2025
01628ed
Extend root route handling integration test, see #16375 for details
andreiborza Jul 16, 2025
f3fcd27
Bump to 0.203.0 and all instrumentations
andreiborza Jul 17, 2025
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
11 changes: 10 additions & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,23 @@ module.exports = [
gzip: true,
limit: '41 KB',
},
// Node-Core SDK (ESM)
{
name: '@sentry/node-core',
path: 'packages/node-core/build/esm/index.js',
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '116 KB',
},
// Node SDK (ESM)
{
name: '@sentry/node',
path: 'packages/node/build/esm/index.js',
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '170 KB',
limit: '144 KB',
},
{
name: '@sentry/node - without tracing',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^2.0.0",
"@opentelemetry/core": "^2.0.0",
"@opentelemetry/instrumentation": "^0.202.0",
"@opentelemetry/instrumentation-http": "^0.202.0",
"@opentelemetry/instrumentation": "^0.203.0",
"@opentelemetry/instrumentation-http": "^0.203.0",
"@opentelemetry/resources": "^2.0.0",
"@opentelemetry/sdk-trace-node": "^2.0.0",
"@opentelemetry/semantic-conventions": "^1.30.0",
"@opentelemetry/semantic-conventions": "^1.34.0",
"@types/express": "^4.17.21",
"@types/node": "^18.19.1",
"express": "^4.21.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ test('Should record a transaction for route with parameters', async ({ request }
data: {
'express.name': 'query',
'express.type': 'middleware',
'http.route': '/',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logaf-l but our of curiosity: why was this attribute removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The express instrumentation doesn't add it anymore to middleware spans, I didn't find anything in their changelog regarding this tho so it's more of an observation after running it 😅.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this likely came from open-telemetry/opentelemetry-js-contrib#2843. Looks like it might be a bug in the instrumentation now because these spans are not for a 404 route..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@s1gr1d could you take a look at that please?

Copy link
Member

@s1gr1d s1gr1d Jul 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a bug before, as it was always attaching http.route. http.route should not be included when no route was matched (on 404).

The matched route, that is, the path template in the format used by the respective server framework.

Semantic Convention Docs: https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/


But in this case it's not a 404 route 🤔

Copy link
Member

@s1gr1d s1gr1d Jul 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checked: Middleware spans might not include the http.route attribute when it's not yet known at the time the middleware runs. And 'http.route': '/' is only added when there is an explicitly defined root route AND when when the route resolution is already done (middleware might run before that).

And why it was added before: Previously, the attribute ALWAYS defaulted to / but this was wrong. https://github.com/open-telemetry/opentelemetry-js-contrib/pull/2843/files#diff-81c3e13c3dac53e0dd6aabf6dc165305350eb522a85a2561f9ee51d9249011e7L198

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks so much for investigating and fixing this upstream @s1gr1d :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, no attribute sounds better than a wrong attribute. Thanks for the explanation!

'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
},
Expand All @@ -84,7 +83,6 @@ test('Should record a transaction for route with parameters', async ({ request }
data: {
'express.name': 'expressInit',
'express.type': 'middleware',
'http.route': '/',
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ test('Should record a transaction for route with parameters', async ({ request }
data: {
'express.name': 'query',
'express.type': 'middleware',
'http.route': '/',
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
},
Expand All @@ -84,7 +83,6 @@ test('Should record a transaction for route with parameters', async ({ request }
data: {
'express.name': 'expressInit',
'express.type': 'middleware',
'http.route': '/',
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ test('Should record a transaction for route with parameters', async ({ request }
data: {
'express.name': 'query',
'express.type': 'middleware',
'http.route': '/',
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
},
Expand All @@ -84,7 +83,6 @@ test('Should record a transaction for route with parameters', async ({ request }
data: {
'express.name': 'expressInit',
'express.type': 'middleware',
'http.route': '/',
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ test('Sends an API route transaction', async ({ baseURL }) => {
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'query',
'express.type': 'middleware',
},
Expand All @@ -85,7 +84,6 @@ test('Sends an API route transaction', async ({ baseURL }) => {
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'expressInit',
'express.type': 'middleware',
},
Expand Down Expand Up @@ -144,7 +142,6 @@ test('Sends an API route transaction for an errored route', async ({ baseURL })
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'query',
'express.type': 'middleware',
},
Expand All @@ -163,7 +160,6 @@ test('Sends an API route transaction for an errored route', async ({ baseURL })
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'expressInit',
'express.type': 'middleware',
},
Expand Down Expand Up @@ -192,8 +188,9 @@ test('Sends an API route transaction for an errored route', async ({ baseURL })
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
span_id: expect.stringMatching(/[a-f0-9]{16}/),
start_timestamp: expect.any(Number),
status: 'ok',
status: 'unknown_error',
timestamp: expect.any(Number),
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
measurements: {},
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"dependencies": {
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/sdk-trace-node": "^1.25.1",
"@opentelemetry/sdk-trace-node": "^2.0.0",
"@sentry/node": "latest || *",
"@sentry/opentelemetry": "latest || *",
"@types/express": "4.17.17",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ Sentry.init({

const provider = new NodeTracerProvider({
sampler: new CustomSampler(),
spanProcessors: [new SentrySpanProcessor()],
});

provider.addSpanProcessor(new SentrySpanProcessor());

provider.register({
propagator: new SentryPropagator(),
contextManager: new Sentry.SentryContextManager(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ test('Sends a sampled API route transaction', async ({ baseURL }) => {
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'query',
'express.type': 'middleware',
},
Expand All @@ -69,7 +68,6 @@ test('Sends a sampled API route transaction', async ({ baseURL }) => {
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'expressInit',
'express.type': 'middleware',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"test:assert": "pnpm test"
},
"dependencies": {
"@opentelemetry/sdk-node": "0.52.1",
"@opentelemetry/exporter-trace-otlp-http": "0.52.1",
"@opentelemetry/sdk-node": "0.203.0",
"@opentelemetry/exporter-trace-otlp-http": "0.203.0",
"@sentry/node": "latest || *",
"@types/express": "4.17.17",
"@types/node": "^18.19.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ test('Sends an API route transaction', async ({ baseURL }) => {
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'query',
'express.type': 'middleware',
},
Expand All @@ -93,7 +92,6 @@ test('Sends an API route transaction', async ({ baseURL }) => {
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'expressInit',
'express.type': 'middleware',
},
Expand Down Expand Up @@ -152,7 +150,6 @@ test('Sends an API route transaction for an errored route', async ({ baseURL })
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'query',
'express.type': 'middleware',
},
Expand All @@ -171,7 +168,6 @@ test('Sends an API route transaction for an errored route', async ({ baseURL })
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'expressInit',
'express.type': 'middleware',
},
Expand Down Expand Up @@ -200,8 +196,9 @@ test('Sends an API route transaction for an errored route', async ({ baseURL })
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
span_id: expect.stringMatching(/[a-f0-9]{16}/),
start_timestamp: expect.any(Number),
status: 'ok',
status: 'unknown_error',
timestamp: expect.any(Number),
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
measurements: {},
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
"test:assert": "pnpm test"
},
"dependencies": {
"@opentelemetry/sdk-trace-node": "1.26.0",
"@opentelemetry/exporter-trace-otlp-http": "0.53.0",
"@opentelemetry/instrumentation-undici": "0.6.0",
"@opentelemetry/instrumentation-http": "0.53.0",
"@opentelemetry/instrumentation": "0.53.0",
"@opentelemetry/sdk-trace-node": "2.0.0",
"@opentelemetry/exporter-trace-otlp-http": "0.203.0",
"@opentelemetry/instrumentation-undici": "0.13.2",
"@opentelemetry/instrumentation-http": "0.203.0",
"@opentelemetry/instrumentation": "0.203.0",
"@sentry/node": "latest || *",
"@types/express": "4.17.17",
"@types/node": "^18.19.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ Sentry.init({
});

// Create and configure NodeTracerProvider
const provider = new NodeTracerProvider({});

provider.addSpanProcessor(
new BatchSpanProcessor(
new OTLPTraceExporter({
url: 'http://localhost:3032/',
}),
),
);
const provider = new NodeTracerProvider({
spanProcessors: [
new BatchSpanProcessor(
new OTLPTraceExporter({
url: 'http://localhost:3032/',
}),
),
],
});

// Initialize the provider
provider.register({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"test:assert": "pnpm test"
},
"dependencies": {
"@opentelemetry/sdk-node": "0.52.1",
"@opentelemetry/exporter-trace-otlp-http": "0.52.1",
"@opentelemetry/sdk-node": "0.203.0",
"@opentelemetry/exporter-trace-otlp-http": "0.203.0",
"@sentry/node": "latest || *",
"@types/express": "4.17.17",
"@types/node": "^18.19.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ test('Sends an API route transaction', async ({ baseURL }) => {
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'query',
'express.type': 'middleware',
},
Expand All @@ -93,7 +92,6 @@ test('Sends an API route transaction', async ({ baseURL }) => {
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'expressInit',
'express.type': 'middleware',
},
Expand Down Expand Up @@ -152,7 +150,6 @@ test('Sends an API route transaction for an errored route', async ({ baseURL })
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'query',
'express.type': 'middleware',
},
Expand All @@ -171,7 +168,6 @@ test('Sends an API route transaction for an errored route', async ({ baseURL })
data: {
'sentry.origin': 'auto.http.otel.express',
'sentry.op': 'middleware.express',
'http.route': '/',
'express.name': 'expressInit',
'express.type': 'middleware',
},
Expand Down Expand Up @@ -200,8 +196,9 @@ test('Sends an API route transaction for an errored route', async ({ baseURL })
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
span_id: expect.stringMatching(/[a-f0-9]{16}/),
start_timestamp: expect.any(Number),
status: 'ok',
status: 'unknown_error',
timestamp: expect.any(Number),
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
measurements: {},
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ test.describe('Trace propagation', () => {
const clientTx = await clientTxPromise;

expect(clientTx.contexts?.trace?.trace_id).toEqual(serverTx.contexts?.trace?.trace_id);
expect(clientTx.contexts?.trace?.parent_span_id).toBe(serverTx.contexts?.trace?.span_id);

const requestHandlerSpan = serverTx.spans?.find(span => span.op === 'request_handler.express');

expect(requestHandlerSpan).toBeDefined();
expect(clientTx.contexts?.trace?.parent_span_id).toBe(requestHandlerSpan?.span_id);
});

test('should not have trace connection for prerendered pages', async ({ page }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ test.describe('Trace propagation', () => {
const clientTx = await clientTxPromise;

expect(clientTx.contexts?.trace?.trace_id).toEqual(serverTx.contexts?.trace?.trace_id);
expect(clientTx.contexts?.trace?.parent_span_id).toBe(serverTx.contexts?.trace?.span_id);

const requestHandlerSpan = serverTx.spans?.find(span => span.op === 'request_handler.express');

expect(requestHandlerSpan).toBeDefined();
expect(clientTx.contexts?.trace?.parent_span_id).toBe(requestHandlerSpan?.span_id);
});

test('should not have trace connection for prerendered pages', async ({ page }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ test.describe('Trace propagation', () => {
const clientTx = await clientTxPromise;

expect(clientTx.contexts?.trace?.trace_id).toEqual(serverTx.contexts?.trace?.trace_id);
expect(clientTx.contexts?.trace?.parent_span_id).toBe(serverTx.contexts?.trace?.span_id);

const requestHandlerSpan = serverTx.spans?.find(span => span.op === 'request_handler.express');

expect(requestHandlerSpan).toBeDefined();
expect(clientTx.contexts?.trace?.parent_span_id).toBe(requestHandlerSpan?.span_id);
});

test('should not have trace connection for prerendered pages', async ({ page }) => {
Expand Down
12 changes: 6 additions & 6 deletions dev-packages/node-core-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
"@nestjs/core": "10.4.6",
"@nestjs/platform-express": "10.4.6",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^1.30.1",
"@opentelemetry/core": "^1.30.1",
"@opentelemetry/instrumentation": "^0.57.2",
"@opentelemetry/instrumentation-http": "0.57.2",
"@opentelemetry/resources": "^1.30.1",
"@opentelemetry/sdk-trace-base": "^1.30.1",
"@opentelemetry/context-async-hooks": "^2.0.0",
"@opentelemetry/core": "^2.0.0",
"@opentelemetry/instrumentation": "^0.203.0",
"@opentelemetry/instrumentation-http": "0.203.0",
"@opentelemetry/resources": "^2.0.0",
"@opentelemetry/sdk-trace-base": "^2.0.0",
"@opentelemetry/semantic-conventions": "^1.34.0",
"@sentry/core": "9.40.0",
"@sentry/node-core": "9.40.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const EXPECTED_TRANSCATION = {
'rpc.system': 'aws-api',
'rpc.method': 'PutObject',
'rpc.service': 'S3',
'aws.region': 'us-east-1',
'cloud.region': 'us-east-1',
'aws.s3.bucket': 'ot-demo-test',
'otel.kind': 'CLIENT',
}),
Expand Down
Loading
Loading