@@ -4,12 +4,16 @@ import { Resource } from '@opentelemetry/resources';
4
4
import { Span as OtelSpan } from '@opentelemetry/sdk-trace-base' ;
5
5
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node' ;
6
6
import { SemanticAttributes , SemanticResourceAttributes } from '@opentelemetry/semantic-conventions' ;
7
- import { Hub , makeMain } from '@sentry/core' ;
7
+ import { createTransport , Hub , makeMain } from '@sentry/core' ;
8
+ import { NodeClient } from '@sentry/node' ;
8
9
import { addExtensionMethods , Span as SentrySpan , SpanStatusType , Transaction } from '@sentry/tracing' ;
9
10
import { Contexts , Scope } from '@sentry/types' ;
11
+ import { resolvedSyncPromise } from '@sentry/utils' ;
10
12
11
13
import { SENTRY_SPAN_PROCESSOR_MAP , SentrySpanProcessor } from '../src/spanprocessor' ;
12
14
15
+ const SENTRY_DSN = 'https://0@0.ingest.sentry.io/0' ;
16
+
13
17
// Integration Test of SentrySpanProcessor
14
18
15
19
beforeAll ( ( ) => {
@@ -22,7 +26,13 @@ describe('SentrySpanProcessor', () => {
22
26
let spanProcessor : SentrySpanProcessor ;
23
27
24
28
beforeEach ( ( ) => {
25
- hub = new Hub ( ) ;
29
+ const client = new NodeClient ( {
30
+ dsn : SENTRY_DSN ,
31
+ integrations : [ ] ,
32
+ transport : ( ) => createTransport ( { recordDroppedEvent : ( ) => undefined } , _ => resolvedSyncPromise ( { } ) ) ,
33
+ stackParser : ( ) => [ ] ,
34
+ } ) ;
35
+ hub = new Hub ( client ) ;
26
36
makeMain ( hub ) ;
27
37
28
38
spanProcessor = new SentrySpanProcessor ( ) ;
@@ -561,6 +571,106 @@ describe('SentrySpanProcessor', () => {
561
571
} ) ;
562
572
} ) ;
563
573
} ) ;
574
+
575
+ describe ( 'skip sentry requests' , ( ) => {
576
+ it ( 'does not finish transaction for Sentry request' , async ( ) => {
577
+ const otelSpan = provider . getTracer ( 'default' ) . startSpan ( 'POST to sentry' , {
578
+ attributes : {
579
+ [ SemanticAttributes . HTTP_METHOD ] : 'POST' ,
580
+ [ SemanticAttributes . HTTP_URL ] : `${ SENTRY_DSN } /sub/route` ,
581
+ } ,
582
+ } ) as OtelSpan ;
583
+
584
+ const sentrySpanTransaction = getSpanForOtelSpan ( otelSpan ) as Transaction | undefined ;
585
+ expect ( sentrySpanTransaction ) . toBeDefined ( ) ;
586
+
587
+ otelSpan . end ( ) ;
588
+
589
+ expect ( sentrySpanTransaction ?. endTimestamp ) . toBeUndefined ( ) ;
590
+
591
+ // Ensure it is still removed from map!
592
+ expect ( getSpanForOtelSpan ( otelSpan ) ) . toBeUndefined ( ) ;
593
+ } ) ;
594
+
595
+ it ( 'finishes transaction for non-Sentry request' , async ( ) => {
596
+ const otelSpan = provider . getTracer ( 'default' ) . startSpan ( 'POST to sentry' , {
597
+ attributes : {
598
+ [ SemanticAttributes . HTTP_METHOD ] : 'POST' ,
599
+ [ SemanticAttributes . HTTP_URL ] : 'https://other.sentry.io/sub/route' ,
600
+ } ,
601
+ } ) as OtelSpan ;
602
+
603
+ const sentrySpanTransaction = getSpanForOtelSpan ( otelSpan ) as Transaction | undefined ;
604
+ expect ( sentrySpanTransaction ) . toBeDefined ( ) ;
605
+
606
+ otelSpan . end ( ) ;
607
+
608
+ expect ( sentrySpanTransaction ?. endTimestamp ) . toBeDefined ( ) ;
609
+ } ) ;
610
+
611
+ it ( 'does not finish spans for Sentry request' , async ( ) => {
612
+ const tracer = provider . getTracer ( 'default' ) ;
613
+
614
+ tracer . startActiveSpan ( 'GET /users' , ( ) => {
615
+ tracer . startActiveSpan (
616
+ 'SELECT * FROM users;' ,
617
+ {
618
+ attributes : {
619
+ [ SemanticAttributes . HTTP_METHOD ] : 'POST' ,
620
+ [ SemanticAttributes . HTTP_URL ] : `${ SENTRY_DSN } /sub/route` ,
621
+ } ,
622
+ } ,
623
+ child => {
624
+ const childOtelSpan = child as OtelSpan ;
625
+
626
+ const sentrySpan = getSpanForOtelSpan ( childOtelSpan ) ;
627
+ expect ( sentrySpan ) . toBeDefined ( ) ;
628
+
629
+ childOtelSpan . end ( ) ;
630
+
631
+ expect ( sentrySpan ?. endTimestamp ) . toBeUndefined ( ) ;
632
+
633
+ // Ensure it is still removed from map!
634
+ expect ( getSpanForOtelSpan ( childOtelSpan ) ) . toBeUndefined ( ) ;
635
+ } ,
636
+ ) ;
637
+ } ) ;
638
+ } ) ;
639
+
640
+ it ( 'handles child spans of Sentry requests normally' , async ( ) => {
641
+ const tracer = provider . getTracer ( 'default' ) ;
642
+
643
+ tracer . startActiveSpan ( 'GET /users' , ( ) => {
644
+ tracer . startActiveSpan (
645
+ 'SELECT * FROM users;' ,
646
+ {
647
+ attributes : {
648
+ [ SemanticAttributes . HTTP_METHOD ] : 'POST' ,
649
+ [ SemanticAttributes . HTTP_URL ] : `${ SENTRY_DSN } /sub/route` ,
650
+ } ,
651
+ } ,
652
+ child => {
653
+ const childOtelSpan = child as OtelSpan ;
654
+
655
+ const grandchildSpan = tracer . startSpan ( 'child 1' ) ;
656
+
657
+ const sentrySpan = getSpanForOtelSpan ( childOtelSpan ) ;
658
+ expect ( sentrySpan ) . toBeDefined ( ) ;
659
+
660
+ const sentryGrandchildSpan = getSpanForOtelSpan ( grandchildSpan ) ;
661
+ expect ( sentryGrandchildSpan ) . toBeDefined ( ) ;
662
+
663
+ grandchildSpan . end ( ) ;
664
+
665
+ childOtelSpan . end ( ) ;
666
+
667
+ expect ( sentryGrandchildSpan ?. endTimestamp ) . toBeDefined ( ) ;
668
+ expect ( sentrySpan ?. endTimestamp ) . toBeUndefined ( ) ;
669
+ } ,
670
+ ) ;
671
+ } ) ;
672
+ } ) ;
673
+ } ) ;
564
674
} ) ;
565
675
566
676
// OTEL expects a custom date format
0 commit comments