diff --git a/otel/span_processor.go b/otel/span_processor.go index 8b64d9dd0..5342bc085 100644 --- a/otel/span_processor.go +++ b/otel/span_processor.go @@ -4,6 +4,7 @@ package sentryotel import ( "context" + semconv "go.opentelemetry.io/otel/semconv/v1.12.0" "time" "github.com/getsentry/sentry-go" @@ -77,6 +78,8 @@ func (ssp *sentrySpanProcessor) OnEnd(s otelSdkTrace.ReadOnlySpan) { return } + processEvents(sentrySpan, s) + if sentrySpan.IsTransaction() { updateTransactionWithOtelData(sentrySpan, s) } else { @@ -101,6 +104,57 @@ func (ssp *sentrySpanProcessor) ForceFlush(ctx context.Context) error { return flushSpanProcessor(ctx) } +func processEvents(sentrySpan *sentry.Span, s otelSdkTrace.ReadOnlySpan) { + ctx := sentrySpan.Context() + + hub := sentry.GetHubFromContext(ctx) + if hub == nil { + hub = sentry.CurrentHub() + } + + for _, event := range s.Events() { + sentryEvent := sentry.NewEvent() + sentryEvent.Timestamp = event.Time + + switch event.Name { + case semconv.ExceptionEventName: + sentryEvent.Level = sentry.LevelError + + var exceptionType string + var exceptionMessage string + //var exceptionStacktrace string + + for _, kv := range event.Attributes { + switch kv.Key { + case semconv.ExceptionTypeKey: + exceptionType = kv.Value.Emit() + case semconv.ExceptionMessageKey: + exceptionMessage = kv.Value.Emit() + // case semconv.ExceptionStacktraceKey: + // exceptionStacktrace = kv.Value.Emit() + } + } + + // todo(vtfr): Parse the exceptionStacktrace into an []sentry.Exception + sentryEvent.Message = exceptionMessage + sentryEvent.Exception = []sentry.Exception{ + { + Type: exceptionType, + Value: exceptionMessage, + }, + } + default: + // todo(vtfr): Check for attributes for setting the level + sentryEvent.Level = sentry.LevelInfo + sentryEvent.Message = event.Name + } + + hub.Client().CaptureEvent(sentryEvent, &sentry.EventHint{ + Context: ctx, + }, nil) + } +} + func flushSpanProcessor(ctx context.Context) error { hub := sentry.GetHubFromContext(ctx) // TODO(michi) should we make this configurable?