@@ -99,7 +99,7 @@ describe('Integration | Transactions', () => {
99
99
environment : 'production' ,
100
100
event_id : expect . any ( String ) ,
101
101
platform : 'node' ,
102
- sdkProcessingMetadata : {
102
+ sdkProcessingMetadata : expect . objectContaining ( {
103
103
dynamicSamplingContext : expect . objectContaining ( {
104
104
environment : 'production' ,
105
105
public_key : expect . any ( String ) ,
@@ -112,7 +112,7 @@ describe('Integration | Transactions', () => {
112
112
source : 'task' ,
113
113
spanMetadata : expect . any ( Object ) ,
114
114
requestPath : 'test-path' ,
115
- } ,
115
+ } ) ,
116
116
server_name : expect . any ( String ) ,
117
117
// spans are circular (they have a reference to the transaction), which leads to jest choking on this
118
118
// instead we compare them in detail below
@@ -329,6 +329,159 @@ describe('Integration | Transactions', () => {
329
329
) ;
330
330
} ) ;
331
331
332
+ it ( 'correctly creates concurrent transaction & spans when using native OTEL tracer' , async ( ) => {
333
+ const beforeSendTransaction = jest . fn ( ( ) => null ) ;
334
+
335
+ mockSdkInit ( { enableTracing : true , beforeSendTransaction } ) ;
336
+
337
+ const client = Sentry . getClient < NodeExperimentalClient > ( ) ;
338
+
339
+ Sentry . addBreadcrumb ( { message : 'test breadcrumb 1' , timestamp : 123456 } ) ;
340
+
341
+ Sentry . withIsolationScope ( ( ) => {
342
+ client . tracer . startActiveSpan ( 'test name' , span => {
343
+ Sentry . addBreadcrumb ( { message : 'test breadcrumb 2' , timestamp : 123456 } ) ;
344
+
345
+ span . setAttributes ( {
346
+ 'test.outer' : 'test value' ,
347
+ } ) ;
348
+
349
+ const subSpan = Sentry . startInactiveSpan ( { name : 'inner span 1' } ) ;
350
+ subSpan . end ( ) ;
351
+
352
+ Sentry . setTag ( 'test.tag' , 'test value' ) ;
353
+
354
+ client . tracer . startActiveSpan ( 'inner span 2' , innerSpan => {
355
+ Sentry . addBreadcrumb ( { message : 'test breadcrumb 3' , timestamp : 123456 } ) ;
356
+
357
+ innerSpan . setAttributes ( {
358
+ 'test.inner' : 'test value' ,
359
+ } ) ;
360
+
361
+ innerSpan . end ( ) ;
362
+ } ) ;
363
+
364
+ span . end ( ) ;
365
+ } ) ;
366
+ } ) ;
367
+
368
+ Sentry . withIsolationScope ( ( ) => {
369
+ client . tracer . startActiveSpan ( 'test name b' , span => {
370
+ Sentry . addBreadcrumb ( { message : 'test breadcrumb 2b' , timestamp : 123456 } ) ;
371
+
372
+ span . setAttributes ( {
373
+ 'test.outer' : 'test value b' ,
374
+ } ) ;
375
+
376
+ const subSpan = Sentry . startInactiveSpan ( { name : 'inner span 1b' } ) ;
377
+ subSpan . end ( ) ;
378
+
379
+ Sentry . setTag ( 'test.tag' , 'test value b' ) ;
380
+
381
+ client . tracer . startActiveSpan ( 'inner span 2b' , innerSpan => {
382
+ Sentry . addBreadcrumb ( { message : 'test breadcrumb 3b' , timestamp : 123456 } ) ;
383
+
384
+ innerSpan . setAttributes ( {
385
+ 'test.inner' : 'test value b' ,
386
+ } ) ;
387
+
388
+ innerSpan . end ( ) ;
389
+ } ) ;
390
+
391
+ span . end ( ) ;
392
+ } ) ;
393
+ } ) ;
394
+
395
+ await client . flush ( ) ;
396
+
397
+ expect ( beforeSendTransaction ) . toHaveBeenCalledTimes ( 2 ) ;
398
+ expect ( beforeSendTransaction ) . toHaveBeenCalledWith (
399
+ expect . objectContaining ( {
400
+ breadcrumbs : [
401
+ { message : 'test breadcrumb 1' , timestamp : 123456 } ,
402
+ { message : 'test breadcrumb 2' , timestamp : 123456 } ,
403
+ { message : 'test breadcrumb 3' , timestamp : 123456 } ,
404
+ ] ,
405
+ contexts : expect . objectContaining ( {
406
+ otel : expect . objectContaining ( {
407
+ attributes : {
408
+ 'test.outer' : 'test value' ,
409
+ } ,
410
+ } ) ,
411
+ trace : {
412
+ data : {
413
+ 'otel.kind' : 'INTERNAL' ,
414
+ 'sentry.origin' : 'manual' ,
415
+ } ,
416
+ span_id : expect . any ( String ) ,
417
+ status : 'ok' ,
418
+ trace_id : expect . any ( String ) ,
419
+ origin : 'manual' ,
420
+ } ,
421
+ } ) ,
422
+ spans : [
423
+ expect . objectContaining ( {
424
+ description : 'inner span 1' ,
425
+ } ) ,
426
+ expect . objectContaining ( {
427
+ description : 'inner span 2' ,
428
+ } ) ,
429
+ ] ,
430
+ start_timestamp : expect . any ( Number ) ,
431
+ tags : { 'test.tag' : 'test value' } ,
432
+ timestamp : expect . any ( Number ) ,
433
+ transaction : 'test name' ,
434
+ type : 'transaction' ,
435
+ } ) ,
436
+ {
437
+ event_id : expect . any ( String ) ,
438
+ } ,
439
+ ) ;
440
+
441
+ expect ( beforeSendTransaction ) . toHaveBeenCalledWith (
442
+ expect . objectContaining ( {
443
+ breadcrumbs : [
444
+ { message : 'test breadcrumb 1' , timestamp : 123456 } ,
445
+ { message : 'test breadcrumb 2b' , timestamp : 123456 } ,
446
+ { message : 'test breadcrumb 3b' , timestamp : 123456 } ,
447
+ ] ,
448
+ contexts : expect . objectContaining ( {
449
+ otel : expect . objectContaining ( {
450
+ attributes : {
451
+ 'test.outer' : 'test value b' ,
452
+ } ,
453
+ } ) ,
454
+ trace : {
455
+ data : {
456
+ 'otel.kind' : 'INTERNAL' ,
457
+ 'sentry.origin' : 'manual' ,
458
+ } ,
459
+ span_id : expect . any ( String ) ,
460
+ status : 'ok' ,
461
+ trace_id : expect . any ( String ) ,
462
+ origin : 'manual' ,
463
+ } ,
464
+ } ) ,
465
+ spans : [
466
+ expect . objectContaining ( {
467
+ description : 'inner span 1b' ,
468
+ } ) ,
469
+ expect . objectContaining ( {
470
+ description : 'inner span 2b' ,
471
+ } ) ,
472
+ ] ,
473
+ start_timestamp : expect . any ( Number ) ,
474
+ tags : { 'test.tag' : 'test value b' } ,
475
+ timestamp : expect . any ( Number ) ,
476
+ transaction : 'test name b' ,
477
+ type : 'transaction' ,
478
+ } ) ,
479
+ {
480
+ event_id : expect . any ( String ) ,
481
+ } ,
482
+ ) ;
483
+ } ) ;
484
+
332
485
it ( 'correctly creates transaction & spans with a trace header data' , async ( ) => {
333
486
const beforeSendTransaction = jest . fn ( ( ) => null ) ;
334
487
0 commit comments