-
Notifications
You must be signed in to change notification settings - Fork 492
Description
Tracer Version(s)
all versions <= v2.0.1
Go Version(s)
go1.24.3 darwin/arm64
Bug Report
We’re using the Datadog OpenTelemetry bridge with the OpenTelemetry Go SDK. We noticed that when we manually set error.message, error.type, and error.stack, these fields are overwritten during span.End() if the span status is set to Error.
dd-trace-go/ddtrace/opentelemetry/span.go
Lines 85 to 88 in fe9272d
| if s.statusInfo.code == otelcodes.Error { | |
| s.DD.SetTag(ext.ErrorMsg, s.statusInfo.description) | |
| opts = append(opts, tracer.WithError(errors.New(s.statusInfo.description))) | |
| } |
dd-trace-go/ddtrace/tracer/span.go
Lines 424 to 432 in fe9272d
| case error: | |
| // if anyone sets an error value as the tag, be nice here | |
| // and provide all the benefits. | |
| setError(true) | |
| s.setMeta(ext.ErrorMsg, v.Error()) | |
| s.setMeta(ext.ErrorType, reflect.TypeOf(v).String()) | |
| if !cfg.noDebugStack { | |
| s.setMeta(ext.ErrorStack, takeStacktrace(cfg.stackFrames, cfg.stackSkip)) | |
| } |
This behavior causes our manually attached error metadata to be lost — most notably error.stack, which gets replaced by a stack trace pointing to internal middleware like interceptors or gRPC handlers, rather than our application’s actual error context.
Stack trace example
Here is a sample where you can see the overwritten stack trace originating from middleware:
gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.(*span).setTagError
/go/pkg/mod/gopkg.in/!data!dog/[email protected]/ddtrace/tracer/span.go:332
gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.(*span).Finish
/go/pkg/mod/gopkg.in/!data!dog/[email protected]/ddtrace/tracer/span.go:477
gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentelemetry.(*span).End
/go/pkg/mod/gopkg.in/!data!dog/[email protected]/ddtrace/opentelemetry/span.go:103
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc.(*config).handleRPC
/go/pkg/mod/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/[email protected]/stats_handler.go:204
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc.(*serverHandler).HandleRPC
/go/pkg/mod/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/[email protected]/stats_handler.go:81
google.golang.org/grpc.(*Server).processUnaryRPC.func1
/go/pkg/mod/google.golang.org/[email protected]/server.go:1262
google.golang.org/grpc.(*Server).processUnaryRPC
/go/pkg/mod/google.golang.org/[email protected]/server.go:1427
google.golang.org/grpc.(*Server).handleStream
/go/pkg/mod/google.golang.org/[email protected]/server.go:1802
google.golang.org/grpc.(*Server).serveStreams.func2.1
/go/pkg/mod/google.golang.org/[email protected]/server.go:1030
runtime.goexit
/usr/local/go/src/runtime/asm_amd64.s:1700
This is not helpful when trying to debug real issues from user code.
Expected behavior
If a user has already set error.message, error.type, or error.stack, the tracer should not overwrite them. These fields should be treated as user-defined and preserved.
Actual behavior
When a span ends with status code = Error, the ddotel implementation internally creates a new error using the statusInfo.description, and calls tracer.WithError(...). This leads to:
- Overwriting
error.messagewith the statusInfo.description - Overwriting
error.typeusingreflect.TypeOf(error) - Overwriting
error.stackwith a new stack trace — which, in our case, only includes internal tracing layers, not the actual error origin
We are currently using [email protected]. I also checked the [email protected] — while we haven’t tested it in our setup yet, the codebase appears to follow the same logic, so the issue likely persists in v2 as well.
This issue appears to be related to #3424, which highlights a similar problem regarding error field overwriting.
Reproduction Code
No response
Error Logs
No response
Go Env Output
No response