diff --git a/ddtrace/tracer/span.go b/ddtrace/tracer/span.go index 9ce8835191..96e8805855 100644 --- a/ddtrace/tracer/span.go +++ b/ddtrace/tracer/span.go @@ -102,7 +102,9 @@ func (s *span) SetTag(key string, value interface{}) { } switch key { case ext.Error: - s.setTagError(value, &errorConfig{}) + s.setTagError(value, errorConfig{ + noDebugStack: s.noDebugStack, + }) return } if v, ok := value.(bool); ok { @@ -127,7 +129,7 @@ func (s *span) SetTag(key string, value interface{}) { // setTagError sets the error tag. It accounts for various valid scenarios. // This method is not safe for concurrent use. -func (s *span) setTagError(value interface{}, cfg *errorConfig) { +func (s *span) setTagError(value interface{}, cfg errorConfig) { if s.finished { return } @@ -145,6 +147,7 @@ func (s *span) setTagError(value interface{}, cfg *errorConfig) { s.Error = 1 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)) } @@ -280,7 +283,7 @@ func (s *span) Finish(opts ...ddtrace.FinishOption) { } if cfg.Error != nil { s.Lock() - s.setTagError(cfg.Error, &errorConfig{ + s.setTagError(cfg.Error, errorConfig{ noDebugStack: cfg.NoDebugStack, stackFrames: cfg.StackFrames, stackSkip: cfg.SkipStackFrames, diff --git a/ddtrace/tracer/span_test.go b/ddtrace/tracer/span_test.go index 9b68cff0d1..b86a8acc8b 100644 --- a/ddtrace/tracer/span_test.go +++ b/ddtrace/tracer/span_test.go @@ -204,6 +204,22 @@ func TestSpanSetTag(t *testing.T) { assert.Equal("false", span.Meta["some.other.bool"]) } +func TestSpanSetTagErrorNoTrace(t *testing.T) { + assert := assert.New(t) + span := newBasicSpan("web.request") + + span.setTagError(errors.New("error value with no trace"), errorConfig{noDebugStack: true}) + assert.Empty(span.Meta[ext.ErrorStack]) +} + +func TestSpanSetTagErrorWithTrace(t *testing.T) { + assert := assert.New(t) + span := newBasicSpan("web.request") + + span.setTagError(errors.New("error value with trace"), errorConfig{noDebugStack: false}) + assert.NotEmpty(span.Meta[ext.ErrorStack]) +} + func TestSpanSetDatadogTags(t *testing.T) { assert := assert.New(t) diff --git a/ddtrace/tracer/tracer_test.go b/ddtrace/tracer/tracer_test.go index 11e5953942..71ec50d1b4 100644 --- a/ddtrace/tracer/tracer_test.go +++ b/ddtrace/tracer/tracer_test.go @@ -451,16 +451,21 @@ func TestTracerSpanGlobalTags(t *testing.T) { assert.Equal("value", child.Meta["key"]) } -func TestTracerNoDebugStack(t *testing.T) { +func TestTracerNoDebugStackFinish(t *testing.T) { assert := assert.New(t) tracer := newTracer(WithDebugStack(false)) s := tracer.StartSpan("web.request").(*span) err := errors.New("test error") s.Finish(WithError(err)) + assert.Empty(s.Meta[ext.ErrorStack]) +} - assert.Equal(int32(1), s.Error) - assert.Equal("test error", s.Meta[ext.ErrorMsg]) - assert.Equal("*errors.errorString", s.Meta[ext.ErrorType]) +func TestTracerNoDebugStackFinishSetTag(t *testing.T) { + assert := assert.New(t) + tracer := newTracer(WithDebugStack(false)) + s := tracer.StartSpan("web.request").(*span) + err := errors.New("error value with no trace") + s.SetTag(ext.Error, err) assert.Empty(s.Meta[ext.ErrorStack]) }