|
8 | 8 | import io.opentelemetry.sdk.trace.ReadWriteSpan; |
9 | 9 | import io.opentelemetry.sdk.trace.ReadableSpan; |
10 | 10 | import io.opentelemetry.sdk.trace.SpanProcessor; |
| 11 | +import io.opentelemetry.sdk.trace.data.EventData; |
| 12 | +import io.opentelemetry.sdk.trace.data.ExceptionEventData; |
11 | 13 | import io.sentry.Baggage; |
| 14 | +import io.sentry.DateUtils; |
12 | 15 | import io.sentry.IScopes; |
13 | 16 | import io.sentry.PropagationContext; |
14 | 17 | import io.sentry.ScopesAdapter; |
15 | 18 | import io.sentry.Sentry; |
16 | 19 | import io.sentry.SentryDate; |
| 20 | +import io.sentry.SentryEvent; |
17 | 21 | import io.sentry.SentryLevel; |
18 | 22 | import io.sentry.SentryLongDate; |
19 | 23 | import io.sentry.SentryTraceHeader; |
20 | 24 | import io.sentry.SpanId; |
21 | 25 | import io.sentry.TracesSamplingDecision; |
| 26 | +import io.sentry.exception.ExceptionMechanismException; |
| 27 | +import io.sentry.protocol.Mechanism; |
22 | 28 | import io.sentry.protocol.SentryId; |
| 29 | +import java.util.List; |
23 | 30 | import org.jetbrains.annotations.NotNull; |
24 | 31 | import org.jetbrains.annotations.Nullable; |
25 | 32 |
|
@@ -143,9 +150,46 @@ public void onEnd(final @NotNull ReadableSpan spanBeingEnded) { |
143 | 150 | final @NotNull SentryDate finishDate = |
144 | 151 | new SentryLongDate(spanBeingEnded.toSpanData().getEndEpochNanos()); |
145 | 152 | sentrySpan.updateEndDate(finishDate); |
| 153 | + |
| 154 | + maybeCaptureSpanEventsAsExceptions(spanBeingEnded, sentrySpan); |
146 | 155 | } |
147 | 156 | } |
148 | 157 |
|
| 158 | + private void maybeCaptureSpanEventsAsExceptions( |
| 159 | + final @NotNull ReadableSpan spanBeingEnded, final @NotNull IOtelSpanWrapper sentrySpan) { |
| 160 | + final @NotNull IScopes spanScopes = sentrySpan.getScopes(); |
| 161 | + if (spanScopes.getOptions().isCaptureOpenTelemetryEvents()) { |
| 162 | + final @NotNull List<EventData> events = spanBeingEnded.toSpanData().getEvents(); |
| 163 | + for (EventData event : events) { |
| 164 | + if (event instanceof ExceptionEventData) { |
| 165 | + final @NotNull ExceptionEventData exceptionEvent = (ExceptionEventData) event; |
| 166 | + captureException(spanScopes, exceptionEvent, sentrySpan); |
| 167 | + } |
| 168 | + } |
| 169 | + } |
| 170 | + } |
| 171 | + |
| 172 | + private void captureException( |
| 173 | + final @NotNull IScopes scopes, |
| 174 | + final @NotNull ExceptionEventData exceptionEvent, |
| 175 | + final @NotNull IOtelSpanWrapper sentrySpan) { |
| 176 | + final @NotNull Throwable exception = exceptionEvent.getException(); |
| 177 | + final Mechanism mechanism = new Mechanism(); |
| 178 | + mechanism.setType("OpenTelemetrySpanEvent"); |
| 179 | + mechanism.setHandled(true); |
| 180 | + // This is potentially the wrong Thread as it's the current thread meaning the thread where |
| 181 | + // the span is being ended on. This may not match the thread where the exception occurred. |
| 182 | + final Throwable mechanismException = |
| 183 | + new ExceptionMechanismException(mechanism, exception, Thread.currentThread()); |
| 184 | + |
| 185 | + final SentryEvent event = new SentryEvent(mechanismException); |
| 186 | + event.setTimestamp(DateUtils.nanosToDate(exceptionEvent.getEpochNanos())); |
| 187 | + event.setLevel(SentryLevel.ERROR); |
| 188 | + event.getContexts().setTrace(sentrySpan.getSpanContext()); |
| 189 | + |
| 190 | + scopes.captureEvent(event); |
| 191 | + } |
| 192 | + |
149 | 193 | @Override |
150 | 194 | public boolean isEndRequired() { |
151 | 195 | return true; |
|
0 commit comments