1
0
mirror of https://github.com/golang/go synced 2024-11-06 04:16:11 -07:00
go/internal/telemetry/export/trace.go
Ian Cottrell 224c947ce5 internal/telemetry: replace TagSet with TagMap and TagPointer
This separates the concerns of tag collections that have to be iterated
and tag collections that need lookup by key.
Also make it so that events just carry a plain slice of tags.
We pass a TagMap down through the exporters and allow it to be
extended on the way.
We no longer need the event.Query method (or the event type)
We now exclusivley use Key as the identity, and no longer have a
common core implementation but just implement it directly in each
type.
This removes some confusion that was causing the same key through
different paths to end up with a different identity.

Change-Id: I61e47adcb397f4ca83dd90342b021dd8e9571ed3
Reviewed-on: https://go-review.googlesource.com/c/tools/+/224278
Run-TryBot: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
2020-03-25 01:00:44 +00:00

90 lines
2.0 KiB
Go

// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package export
import (
"context"
"fmt"
"golang.org/x/tools/internal/telemetry/event"
)
type SpanContext struct {
TraceID TraceID
SpanID SpanID
}
type Span struct {
Name string
ID SpanContext
ParentID SpanID
Start event.Event
Finish event.Event
Events []event.Event
}
type contextKeyType int
const (
spanContextKey = contextKeyType(iota)
labelContextKey
)
func GetSpan(ctx context.Context) *Span {
v := ctx.Value(spanContextKey)
if v == nil {
return nil
}
return v.(*Span)
}
// Spans creates an exporter that maintains hierarchical span structure in the
// context.
// It creates new spans on EventStartSpan, adds events to the current span on
// EventLog or EventTag, and closes the span on EventEndSpan.
// The span structure can then be used by other exporters.
func Spans(output event.Exporter) event.Exporter {
return func(ctx context.Context, ev event.Event, tagMap event.TagMap) context.Context {
switch {
case ev.IsLog(), ev.IsLabel():
if span := GetSpan(ctx); span != nil {
span.Events = append(span.Events, ev)
}
case ev.IsStartSpan():
span := &Span{
Name: ev.Message,
Start: ev,
}
if parent := GetSpan(ctx); parent != nil {
span.ID.TraceID = parent.ID.TraceID
span.ParentID = parent.ID.SpanID
} else {
span.ID.TraceID = newTraceID()
}
span.ID.SpanID = newSpanID()
ctx = context.WithValue(ctx, spanContextKey, span)
case ev.IsEndSpan():
if span := GetSpan(ctx); span != nil {
span.Finish = ev
}
case ev.IsDetach():
ctx = context.WithValue(ctx, spanContextKey, nil)
}
return output(ctx, ev, tagMap)
}
}
func (s *SpanContext) Format(f fmt.State, r rune) {
fmt.Fprintf(f, "%v:%v", s.TraceID, s.SpanID)
}
func (s *Span) Format(f fmt.State, r rune) {
fmt.Fprintf(f, "%v %v", s.Name, s.ID)
if s.ParentID.IsValid() {
fmt.Fprintf(f, "[%v]", s.ParentID)
}
fmt.Fprintf(f, " %v->%v", s.Start, s.Finish)
}