Skip to content

Commit 6903407

Browse files
authored
fix(deno,cloudflare): Prioritize name from params over name from options (#18800)
I was playing around with #15466 and saw that the span names for the Prisma integration are different than the ones with actual OTel support, such as `@sentry/node`. Cloudflare (no `prisma:client:` prefix): <img width="200" height="978" alt="Screenshot 2026-01-13 at 15 48 41" src="https://github.com/user-attachments/assets/6b70a719-3c62-4799-af9c-cc15fe5aef8e" /> Express / Node (prefix is there): <img width="200" height="917" alt="Screenshot 2026-01-13 at 17 18 05" src="https://github.com/user-attachments/assets/e4677cff-b3d9-4695-871a-e64ad05b4810" /> Within the `@prisma/instrumentation`, which is used for our integration, the name [is added properly](https://github.com/prisma/prisma/blob/d4ec055ee9e13e62351bf72643fc978b3d315ae3/packages/instrumentation/src/ActiveTracingHelper.ts#L83), but the `options` are not updated on purpose, as the source of truth is the `name` itself - OTel also uses the name directly: https://github.com/open-telemetry/opentelemetry-js/blob/87a0b455e5f7f36d9b05b41b6bf11d114dcc854c/packages/opentelemetry-sdk-trace-base/src/Tracer.ts#L149 There is no further explanation in #16714 why [the `name` came before the spreading `options`](https://github.com/getsentry/sentry-javascript/pull/16714/files#diff-595e62985088cbceb347c68deb88b69569b35edee895929d72a7f690ac13ecf7R59). --- With this PR the Prisma integration does work correctly: <img width="200" height="843" alt="Screenshot 2026-01-13 at 17 23 06" src="https://github.com/user-attachments/assets/39fa89a3-9b31-4640-ac0c-a517d6457b62" /> --- Since the same code was copied over to Deno, I also fixed it there.
1 parent d350c81 commit 6903407

File tree

4 files changed

+119
-4
lines changed

4 files changed

+119
-4
lines changed

packages/cloudflare/src/opentelemetry/tracer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ class SentryCloudflareTraceProvider implements TracerProvider {
2727
class SentryCloudflareTracer implements Tracer {
2828
public startSpan(name: string, options?: SpanOptions): Span {
2929
return startInactiveSpan({
30-
name,
3130
...options,
31+
name,
3232
attributes: {
3333
...options?.attributes,
3434
'sentry.cloudflare_tracer': true,
@@ -56,8 +56,8 @@ class SentryCloudflareTracer implements Tracer {
5656
const opts = (typeof options === 'object' && options !== null ? options : {}) as SpanOptions;
5757

5858
const spanOpts = {
59-
name,
6059
...opts,
60+
name,
6161
attributes: {
6262
...opts.attributes,
6363
'sentry.cloudflare_tracer': true,

packages/cloudflare/test/opentelemetry.test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,59 @@ describe('opentelemetry compatibility', () => {
142142
}),
143143
]);
144144
});
145+
146+
test('name parameter should take precedence over options.name in startSpan', async () => {
147+
const transactionEvents: TransactionEvent[] = [];
148+
149+
const client = init({
150+
dsn: 'https://username@domain/123',
151+
tracesSampleRate: 1,
152+
beforeSendTransaction: event => {
153+
transactionEvents.push(event);
154+
return null;
155+
},
156+
});
157+
158+
const tracer = trace.getTracer('test');
159+
160+
// Pass options with a different name property - the first parameter should take precedence
161+
// This is important for integrations like Prisma that add prefixes to span names
162+
const span = tracer.startSpan('prisma:client:operation', { name: 'operation' } as any);
163+
span.end();
164+
165+
await client!.flush();
166+
167+
expect(transactionEvents).toHaveLength(1);
168+
const [transactionEvent] = transactionEvents;
169+
170+
expect(transactionEvent?.transaction).toBe('prisma:client:operation');
171+
});
172+
173+
test('name parameter should take precedence over options.name in startActiveSpan', async () => {
174+
const transactionEvents: TransactionEvent[] = [];
175+
176+
const client = init({
177+
dsn: 'https://username@domain/123',
178+
tracesSampleRate: 1,
179+
beforeSendTransaction: event => {
180+
transactionEvents.push(event);
181+
return null;
182+
},
183+
});
184+
185+
const tracer = trace.getTracer('test');
186+
187+
// Pass options with a different name property - the first parameter should take precedence
188+
// This is important for integrations like Prisma that add prefixes to span names
189+
tracer.startActiveSpan('prisma:client:operation', { name: 'operation' } as any, span => {
190+
span.end();
191+
});
192+
193+
await client!.flush();
194+
195+
expect(transactionEvents).toHaveLength(1);
196+
const [transactionEvent] = transactionEvents;
197+
198+
expect(transactionEvent?.transaction).toBe('prisma:client:operation');
199+
});
145200
});

packages/deno/src/opentelemetry/tracer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ class SentryDenoTracer implements Tracer {
3535
const op = this._mapSpanKindToOp(options?.kind);
3636

3737
return startInactiveSpan({
38-
name,
3938
...options,
39+
name,
4040
attributes: {
4141
...options?.attributes,
4242
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'manual',
@@ -69,8 +69,8 @@ class SentryDenoTracer implements Tracer {
6969
const op = this._mapSpanKindToOp(opts.kind);
7070

7171
const spanOpts = {
72-
name,
7372
...opts,
73+
name,
7474
attributes: {
7575
...opts.attributes,
7676
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'manual',

packages/deno/test/opentelemetry.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,66 @@ Deno.test('should be compatible with native Deno OpenTelemetry', async () => {
178178
await client.flush();
179179
});
180180

181+
// Test that name parameter takes precedence over options.name for both startSpan and startActiveSpan
182+
Deno.test('name parameter should take precedence over options.name in startSpan', async () => {
183+
resetSdk();
184+
const transactionEvents: any[] = [];
185+
186+
const client = init({
187+
dsn: 'https://username@domain/123',
188+
tracesSampleRate: 1,
189+
beforeSendTransaction: event => {
190+
transactionEvents.push(event);
191+
return null;
192+
},
193+
}) as DenoClient;
194+
195+
const tracer = trace.getTracer('test');
196+
197+
// Pass options with a different name property - the first parameter should take precedence
198+
// This is important for integrations like Prisma that add prefixes to span names
199+
const span = tracer.startSpan('prisma:client:operation', { name: 'operation' } as any);
200+
span.end();
201+
202+
await client.flush();
203+
204+
assertEquals(transactionEvents.length, 1);
205+
const [transactionEvent] = transactionEvents;
206+
207+
// The span name should be 'prisma:client:operation', not 'operation'
208+
assertEquals(transactionEvent?.transaction, 'prisma:client:operation');
209+
});
210+
211+
Deno.test('name parameter should take precedence over options.name in startActiveSpan', async () => {
212+
resetSdk();
213+
const transactionEvents: any[] = [];
214+
215+
const client = init({
216+
dsn: 'https://username@domain/123',
217+
tracesSampleRate: 1,
218+
beforeSendTransaction: event => {
219+
transactionEvents.push(event);
220+
return null;
221+
},
222+
}) as DenoClient;
223+
224+
const tracer = trace.getTracer('test');
225+
226+
// Pass options with a different name property - the first parameter should take precedence
227+
// This is important for integrations like Prisma that add prefixes to span names
228+
tracer.startActiveSpan('prisma:client:operation', { name: 'operation' } as any, span => {
229+
span.end();
230+
});
231+
232+
await client.flush();
233+
234+
assertEquals(transactionEvents.length, 1);
235+
const [transactionEvent] = transactionEvents;
236+
237+
// The span name should be 'prisma:client:operation', not 'operation'
238+
assertEquals(transactionEvent?.transaction, 'prisma:client:operation');
239+
});
240+
181241
Deno.test('should verify native Deno OpenTelemetry works when enabled', async () => {
182242
resetSdk();
183243

0 commit comments

Comments
 (0)