diff --git a/debug/trace/default.go b/debug/trace/default.go new file mode 100644 index 00000000..abbf1c15 --- /dev/null +++ b/debug/trace/default.go @@ -0,0 +1,71 @@ +package trace + +import ( + "context" + "time" + + "github.com/google/uuid" + "github.com/micro/go-micro/util/ring" +) + +type trace struct { + opts Options + + // ring buffer of traces + buffer *ring.Buffer +} + +func (t *trace) Read(opts ...ReadOption) ([]*Span, error) { + return []*Span{}, nil +} + +func (t *trace) Start(ctx context.Context, name string) *Span { + span := &Span{ + Name: name, + Trace: uuid.New().String(), + Id: uuid.New().String(), + Started: time.Now(), + Metadata: make(map[string]string), + } + + // return span if no context + if ctx == nil { + return span + } + + s, ok := FromContext(ctx) + if !ok { + return span + } + + // set trace id + span.Trace = s.Trace + // set parent + span.Parent = s.Id + + // return the sapn + return span +} + +func (t *trace) Finish(s *Span) error { + // set finished time + s.Finished = time.Now() + + // save the span + t.buffer.Put(s) + + return nil +} + +func NewTrace(opts ...Option) Trace { + var options Options + for _, o := range opts { + o(&options) + } + + return &trace{ + opts: options, + // the last 64 requests + buffer: ring.New(64), + } +} diff --git a/debug/trace/options.go b/debug/trace/options.go new file mode 100644 index 00000000..d92abad9 --- /dev/null +++ b/debug/trace/options.go @@ -0,0 +1,12 @@ +package trace + +type Options struct{} + +type Option func(o *Options) + +type ReadOptions struct { + // Trace id + Trace string +} + +type ReadOption func(o *ReadOptions) diff --git a/debug/trace/trace.go b/debug/trace/trace.go new file mode 100644 index 00000000..4a4471c3 --- /dev/null +++ b/debug/trace/trace.go @@ -0,0 +1,48 @@ +// Package trace provides an interface for distributed tracing +package trace + +import ( + "context" + "time" +) + +// Trace is an interface for distributed tracing +type Trace interface { + // Start a trace + Start(ctx context.Context, name string) *Span + // Finish the trace + Finish(*Span) error + // Read the traces + Read(...ReadOption) ([]*Span, error) +} + +// Span is used to record an entry +type Span struct { + // Id of the trace + Trace string + // name of the span + Name string + // id of the span + Id string + // parent span id + Parent string + // Start time + Started time.Time + // Finish time + Finished time.Time + // associated data + Metadata map[string]string +} + +type spanKey struct{} + +// FromContext returns a span from context +func FromContext(ctx context.Context) (*Span, bool) { + s, ok := ctx.Value(spanKey{}).(*Span) + return s, ok +} + +// NewContext creates a new context with the span +func NewContext(ctx context.Context, s *Span) context.Context { + return context.WithValue(ctx, spanKey{}, s) +}