Skip to content

Commit

Permalink
Implement specification compliant trace status handling
Browse files Browse the repository at this point in the history
  • Loading branch information
wdullaer committed Sep 21, 2022
1 parent 038248b commit 38abca3
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

- The metric portion of the OpenCensus bridge (`go.opentelemetry.io/otel/bridge/opencensus`) has been reintroduced. (#3192)

### Changed
- `span.SetStatus` has been updated to comply with the OpenTelemetry specification.
Calls that lower the status are now noops. (#3214)

## [0.32.0] Revised Metric SDK (Alpha) - 2022-09-18

### Changed
Expand Down
7 changes: 5 additions & 2 deletions sdk/trace/span.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,18 @@ func (s *recordingSpan) SetStatus(code codes.Code, description string) {
if !s.IsRecording() {
return
}
s.mu.Lock()
defer s.mu.Unlock()
if s.status.Code > code {
return
}

status := Status{Code: code}
if code == codes.Error {
status.Description = description
}

s.mu.Lock()
s.status = status
s.mu.Unlock()
}

// SetAttributes sets attributes of this span.
Expand Down
76 changes: 76 additions & 0 deletions sdk/trace/span_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,84 @@ import (
"github.com/stretchr/testify/assert"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
)

func TestSetStatus(t *testing.T) {
tests := []struct {
name string
span recordingSpan
code codes.Code
description string
expected Status
}{
{
"Error and description should overwrite Unset",
recordingSpan{},
codes.Error,
"description",
Status{Code: codes.Error, Description: "description"},
},
{
"Ok should overwrite Unset and ignore description",
recordingSpan{},
codes.Ok,
"description",
Status{Code: codes.Ok},
},
{
"Error and description should return error and overwrite description",
recordingSpan{status: Status{Code: codes.Error, Description: "d1"}},
codes.Error,
"d2",
Status{Code: codes.Error, Description: "d2"},
},
{
"Ok should overwrite error and remove description",
recordingSpan{status: Status{Code: codes.Error, Description: "d1"}},
codes.Ok,
"d2",
Status{Code: codes.Ok},
},
{
"Error and description should be ignored when already Ok",
recordingSpan{status: Status{Code: codes.Ok}},
codes.Error,
"d2",
Status{Code: codes.Ok},
},
{
"Ok should be noop when already Ok",
recordingSpan{status: Status{Code: codes.Ok}},
codes.Ok,
"d2",
Status{Code: codes.Ok},
},
{
"Unset should be noop when already Ok",
recordingSpan{status: Status{Code: codes.Ok}},
codes.Unset,
"d2",
Status{Code: codes.Ok},
},
{
"Unset should be noop when already Error",
recordingSpan{status: Status{Code: codes.Error, Description: "d1"}},
codes.Unset,
"d2",
Status{Code: codes.Error, Description: "d1"},
},
}

for i := range tests {
tc := &tests[i]
t.Run(tc.name, func(t *testing.T) {
tc.span.SetStatus(tc.code, tc.description)
assert.Equal(t, tc.expected, tc.span.status)
})
}
}

func TestTruncateAttr(t *testing.T) {
const key = "key"

Expand Down
4 changes: 2 additions & 2 deletions trace/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,8 @@ type Span interface {
SpanContext() SpanContext

// SetStatus sets the status of the Span in the form of a code and a
// description, overriding previous values set. The description is only
// included in a status when the code is for an error.
// description. The description is only included in a status when the code
// is for an error.
SetStatus(code codes.Code, description string)

// SetName sets the Span name.
Expand Down

0 comments on commit 38abca3

Please sign in to comment.