1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 "golang.org/x/tools/internal/event"
13 "golang.org/x/tools/internal/event/core"
14 "golang.org/x/tools/internal/event/keys"
15 "golang.org/x/tools/internal/event/label"
18 type SpanContext struct {
33 type contextKeyType int
36 spanContextKey = contextKeyType(iota)
40 func GetSpan(ctx context.Context) *Span {
41 v := ctx.Value(spanContextKey)
48 // Spans creates an exporter that maintains hierarchical span structure in the
50 // It creates new spans on start events, adds events to the current span on
51 // log or label, and closes the span on end events.
52 // The span structure can then be used by other exporters.
53 func Spans(output event.Exporter) event.Exporter {
54 return func(ctx context.Context, ev core.Event, lm label.Map) context.Context {
56 case event.IsLog(ev), event.IsLabel(ev):
57 if span := GetSpan(ctx); span != nil {
59 span.events = append(span.events, ev)
62 case event.IsStart(ev):
64 Name: keys.Start.Get(lm),
67 if parent := GetSpan(ctx); parent != nil {
68 span.ID.TraceID = parent.ID.TraceID
69 span.ParentID = parent.ID.SpanID
71 span.ID.TraceID = newTraceID()
73 span.ID.SpanID = newSpanID()
74 ctx = context.WithValue(ctx, spanContextKey, span)
76 if span := GetSpan(ctx); span != nil {
81 case event.IsDetach(ev):
82 ctx = context.WithValue(ctx, spanContextKey, nil)
84 return output(ctx, ev, lm)
88 func (s *SpanContext) Format(f fmt.State, r rune) {
89 fmt.Fprintf(f, "%v:%v", s.TraceID, s.SpanID)
92 func (s *Span) Start() core.Event {
93 // start never changes after construction, so we dont need to hold the mutex
97 func (s *Span) Finish() core.Event {
103 func (s *Span) Events() []core.Event {
109 func (s *Span) Format(f fmt.State, r rune) {
112 fmt.Fprintf(f, "%v %v", s.Name, s.ID)
113 if s.ParentID.IsValid() {
114 fmt.Fprintf(f, "[%v]", s.ParentID)
116 fmt.Fprintf(f, " %v->%v", s.start, s.finish)