1
1
import type { Context } from '@opentelemetry/api' ;
2
2
import { trace } from '@opentelemetry/api' ;
3
3
import type { Span as OtelSpan , SpanProcessor as OtelSpanProcessor } from '@opentelemetry/sdk-trace-base' ;
4
+ import { SemanticAttributes } from '@opentelemetry/semantic-conventions' ;
4
5
import { addGlobalEventProcessor , getCurrentHub } from '@sentry/core' ;
5
6
import { Transaction } from '@sentry/tracing' ;
6
7
import type { DynamicSamplingContext , Span as SentrySpan , TraceparentData , TransactionContext } from '@sentry/types' ;
7
- import { logger } from '@sentry/utils' ;
8
+ import { isString , logger } from '@sentry/utils' ;
8
9
9
10
import { SENTRY_DYNAMIC_SAMPLING_CONTEXT_KEY , SENTRY_TRACE_PARENT_CONTEXT_KEY } from './constants' ;
10
11
import { isSentryRequestSpan } from './utils/is-sentry-request' ;
@@ -93,6 +94,12 @@ export class SentrySpanProcessor implements OtelSpanProcessor {
93
94
* @inheritDoc
94
95
*/
95
96
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
+
96
103
const otelSpanId = otelSpan . spanContext ( ) . spanId ;
97
104
const sentrySpan = SENTRY_SPAN_PROCESSOR_MAP . get ( otelSpanId ) ;
98
105
@@ -112,6 +119,46 @@ export class SentrySpanProcessor implements OtelSpanProcessor {
112
119
return ;
113
120
}
114
121
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
+
115
162
if ( sentrySpan instanceof Transaction ) {
116
163
updateTransactionWithOtelData ( sentrySpan , otelSpan ) ;
117
164
} else {
0 commit comments