Skip to content

Commit

Permalink
implement span processor's OnEnding
Browse files Browse the repository at this point in the history
  • Loading branch information
dmathieu committed Aug 30, 2024
1 parent e47618f commit 440d0b1
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
17 changes: 13 additions & 4 deletions sdk/trace/span.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ type recordingSpan struct {
// value of time.Time until the span is ended.
endTime time.Time

// hasEnded records whether the span is fully ended.
hasEnded bool

// status is the status of this span.
status Status

Expand Down Expand Up @@ -171,10 +174,8 @@ func (s *recordingSpan) IsRecording() bool {
if s == nil {
return false
}
s.mu.Lock()
defer s.mu.Unlock()

return s.endTime.IsZero()
return !s.hasEnded
}

// SetStatus sets the status of the Span in the form of a code and a
Expand Down Expand Up @@ -417,7 +418,6 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) {
}

s.mu.Lock()
// Setting endTime to non-zero marks the span as ended and not recording.
if config.Timestamp().IsZero() {
s.endTime = et
} else {
Expand All @@ -426,6 +426,15 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) {
s.mu.Unlock()

sps := s.tracer.provider.getSpanProcessors()
for _, sp := range sps {
if oesp, ok := sp.sp.(OnEndingSpanProcessor); ok {
oesp.OnEnding(s)
}
}
s.mu.Lock()
s.hasEnded = true
s.mu.Unlock()

if len(sps) == 0 {
return
}
Expand Down
11 changes: 11 additions & 0 deletions sdk/trace/span_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ type SpanProcessor interface {
// must never be done outside of a new major release.
}

// OnEndingSpanProcessor represents span processors that allow mutating spans
// just before they are ended and made immutable.
//
// NOT STABLE: This interface still has a status of "development", and may have
// breaking changes.
type OnEndingSpanProcessor interface {
// OnEnding is called while the span is finished, and while spans are still
// mutable. It is called synchronously and cannot block.
OnEnding(ReadWriteSpan)
}

type spanProcessorState struct {
sp SpanProcessor
state sync.Once
Expand Down
21 changes: 21 additions & 0 deletions sdk/trace/span_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ func (t *testSpanProcessor) OnStart(parent context.Context, s sdktrace.ReadWrite
t.spansStarted = append(t.spansStarted, s)
}

func (t *testSpanProcessor) OnEnding(s sdktrace.ReadWriteSpan) {
if t == nil {
return
}
s.SetAttributes(attribute.Bool("OnEnding", true))
}

func (t *testSpanProcessor) OnEnd(s sdktrace.ReadOnlySpan) {
if t == nil {
return
Expand Down Expand Up @@ -130,6 +137,17 @@ func TestRegisterSpanProcessor(t *testing.T) {
}
}
}

onEndingOK := false
for _, kv := range sp.spansEnded[0].Attributes() {
switch kv.Key {
case "OnEnding":
onEndingOK = true
default:
continue
}
}

if c != len(spNames) {
t.Errorf("%s: expected attributes(SpanProcessorName): got %d, want %d\n", name, c, len(spNames))
}
Expand All @@ -139,6 +157,9 @@ func TestRegisterSpanProcessor(t *testing.T) {
if !sidOK {
t.Errorf("%s: expected attributes(ParentSpanID)\n", name)
}
if !onEndingOK {
t.Errorf("%s: expected attributes(OnEnding)\n", name)
}
}
}

Expand Down

0 comments on commit 440d0b1

Please sign in to comment.