Skip to content

Commit

Permalink
add extended span to traceutils
Browse files Browse the repository at this point in the history
  • Loading branch information
jslching committed Nov 1, 2023
1 parent 83abfb0 commit 66151e1
Showing 1 changed file with 97 additions and 9 deletions.
106 changes: 97 additions & 9 deletions util/traceutil/trace/span.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import (
"context"
"encoding/json"
"sync"
"time"

"github.com/eluv-io/common-go/format/duration"
"github.com/eluv-io/utc-go"

"github.com/eluv-io/common-go/format/duration"
)

// Span represents an operation that is named and timed. It may contain sub-spans, representing nested sub-operations. A
Expand Down Expand Up @@ -41,6 +43,22 @@ type Span interface {

// FindByName returns the first sub span with the given name (depth-first) or nil if not found.
FindByName(name string) Span

// Extended returns the extended representation of the span.
Extended() ExtendedSpan
}

type ExtendedSpan interface {
Span

// StartTime returns the start time of the span.
StartTime() utc.UTC

// EndTime returns the end time of the span.
EndTime() utc.UTC

// Duration returns the duration of the span.
Duration() time.Duration
}

type Event struct {
Expand All @@ -53,6 +71,10 @@ type Event struct {

type NoopSpan struct{}

type NoopExtendedSpan struct {
NoopSpan
}

func (n NoopSpan) Start(ctx context.Context, _ string) (context.Context, Span) {
return ctx, n
}
Expand All @@ -65,14 +87,26 @@ func (n NoopSpan) Json() string { return
func (n NoopSpan) Attributes() map[string]interface{} { return nil }
func (n NoopSpan) Events() []*Event { return nil }
func (n NoopSpan) FindByName(string) Span { return nil }
func (n NoopSpan) Extended() ExtendedSpan { return n }
func (n NoopSpan) StartTime() utc.UTC { return utc.Zero }
func (n NoopSpan) EndTime() utc.UTC { return utc.Zero }
func (n NoopSpan) Duration() time.Duration { return 0 }

// ---------------------------------------------------------------------------------------------------------------------

func newSpan(name string) *RecordingSpan {
s := &RecordingSpan{
StartTime: utc.Now(),
Data: &recordingData{},
}
s.Data.Name = name
s.extended = &recordingExtendedSpan{
RecordingSpan: s,
data: &recordingExtendedData{
recordingData: s.Data,
Start: s.StartTime.String(),
},
}
return s
}

Expand All @@ -81,13 +115,28 @@ type RecordingSpan struct {
Parent Span
StartTime utc.UTC
EndTime utc.UTC
Data struct {
Name string `json:"name"`
Duration duration.Spec `json:"time"`
Attr map[string]interface{} `json:"attr,omitempty"`
Events []*Event `json:"evnt,omitempty"`
Subs []Span `json:"subs,omitempty"`
}
Duration time.Duration
Data *recordingData
extended *recordingExtendedSpan
}

type recordingData struct {
Name string `json:"name"`
Duration duration.Spec `json:"time"`
Attr map[string]interface{} `json:"attr,omitempty"`
Events []*Event `json:"evnt,omitempty"`
Subs []Span `json:"subs,omitempty"`
}

type recordingExtendedSpan struct {
*RecordingSpan
data *recordingExtendedData
}

type recordingExtendedData struct {
*recordingData
Start string `json:"start"`
End string `json:"end"`
}

func (s *RecordingSpan) Start(ctx context.Context, name string) (context.Context, Span) {
Expand All @@ -108,7 +157,9 @@ func (s *RecordingSpan) End() {
return
}
s.EndTime = utc.Now()
s.Data.Duration = duration.Spec(s.EndTime.Sub(s.StartTime)).RoundTo(1)
s.Duration = s.EndTime.Sub(s.StartTime)
s.Data.Duration = duration.Spec(s.Duration).RoundTo(1)
s.extended.data.End = s.EndTime.String()
}

func (s *RecordingSpan) Attribute(name string, val interface{}) {
Expand Down Expand Up @@ -174,6 +225,43 @@ func (s *RecordingSpan) FindByName(name string) Span {
return nil
}

func (s *RecordingSpan) Extended() ExtendedSpan {
return s.extended
}

func (s *RecordingSpan) MarshalJSON() ([]byte, error) {
return json.Marshal(s.Data)
}

func (s *recordingExtendedSpan) StartTime() utc.UTC {
s.RecordingSpan.mutex.Lock()
defer s.RecordingSpan.mutex.Unlock()

return s.RecordingSpan.StartTime
}

func (s *recordingExtendedSpan) EndTime() utc.UTC {
s.RecordingSpan.mutex.Lock()
defer s.RecordingSpan.mutex.Unlock()

return s.RecordingSpan.EndTime
}

func (s *recordingExtendedSpan) Duration() time.Duration {
s.RecordingSpan.mutex.Lock()
defer s.RecordingSpan.mutex.Unlock()

return s.RecordingSpan.Duration
}

func (s *recordingExtendedSpan) Json() string {
res, err := s.MarshalJSON()
if err != nil {
return "failed to marshal span: " + err.Error()
}
return string(res)
}

func (s *recordingExtendedSpan) MarshalJSON() ([]byte, error) {
return json.Marshal(s.data)
}

0 comments on commit 66151e1

Please sign in to comment.