11import type { Context } from '@opentelemetry/api' ;
22import { trace } from '@opentelemetry/api' ;
33import type { Span as OtelSpan , SpanProcessor as OtelSpanProcessor } from '@opentelemetry/sdk-trace-base' ;
4+ import { SemanticAttributes } from '@opentelemetry/semantic-conventions' ;
45import { addGlobalEventProcessor , getCurrentHub } from '@sentry/core' ;
56import { Transaction } from '@sentry/tracing' ;
67import type { DynamicSamplingContext , Span as SentrySpan , TraceparentData , TransactionContext } from '@sentry/types' ;
7- import { logger } from '@sentry/utils' ;
8+ import { isString , logger } from '@sentry/utils' ;
89
910import { SENTRY_DYNAMIC_SAMPLING_CONTEXT_KEY , SENTRY_TRACE_PARENT_CONTEXT_KEY } from './constants' ;
1011import { isSentryRequestSpan } from './utils/is-sentry-request' ;
@@ -93,6 +94,12 @@ export class SentrySpanProcessor implements OtelSpanProcessor {
9394 * @inheritDoc
9495 */
9596 public onEnd ( otelSpan : OtelSpan ) : void {
97+ const hub = getCurrentHub ( ) ;
98+ if ( ! hub ) {
99+ __DEBUG_BUILD__ && logger . error ( 'SentrySpanProcessor has triggered onEnd before a hub has been setup.' ) ;
100+ return ;
101+ }
102+
96103 const otelSpanId = otelSpan . spanContext ( ) . spanId ;
97104 const sentrySpan = SENTRY_SPAN_PROCESSOR_MAP . get ( otelSpanId ) ;
98105
@@ -112,6 +119,46 @@ export class SentrySpanProcessor implements OtelSpanProcessor {
112119 return ;
113120 }
114121
122+ otelSpan . events . forEach ( event => {
123+ if ( event . name !== 'exception' ) {
124+ return ;
125+ }
126+
127+ const attributes = event . attributes ;
128+ if ( ! attributes ) {
129+ return ;
130+ }
131+
132+ const message = attributes [ SemanticAttributes . EXCEPTION_MESSAGE ] ;
133+ const syntheticError = new Error ( message as string | undefined ) ;
134+
135+ const stack = attributes [ SemanticAttributes . EXCEPTION_STACKTRACE ] ;
136+ if ( isString ( stack ) ) {
137+ syntheticError . stack = stack ;
138+ }
139+
140+ const type = attributes [ SemanticAttributes . EXCEPTION_TYPE ] ;
141+ if ( isString ( type ) ) {
142+ syntheticError . name = type ;
143+ }
144+
145+ hub . captureException ( syntheticError , {
146+ captureContext : {
147+ contexts : {
148+ otel : {
149+ attributes : otelSpan . attributes ,
150+ resource : otelSpan . resource . attributes ,
151+ } ,
152+ trace : {
153+ trace_id : otelSpan . spanContext ( ) . traceId ,
154+ span_id : otelSpan . spanContext ( ) . spanId ,
155+ parent_span_id : otelSpan . parentSpanId ,
156+ } ,
157+ } ,
158+ } ,
159+ } ) ;
160+ } ) ;
161+
115162 if ( sentrySpan instanceof Transaction ) {
116163 updateTransactionWithOtelData ( sentrySpan , otelSpan ) ;
117164 } else {
0 commit comments