mirror of
https://github.com/golang/go
synced 2024-11-06 03:16:10 -07:00
cb106d260e
This allows early exporters to adjust the event for later ones. This is used to lookup key values from the context if needed. Also add a Query type event which is intended to perform all event modifications but nothing else, and is used to lookup values from the context. This cleans up a weirdness where the current lookup presumes there will be an exporter with a matching mechanism. Change-Id: I835d1e0b2511553c30f94b7becfe7b7b5462c111 Reviewed-on: https://go-review.googlesource.com/c/tools/+/223657 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
90 lines
2.0 KiB
Go
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"
|
|
"time"
|
|
|
|
"golang.org/x/tools/internal/telemetry/event"
|
|
)
|
|
|
|
type SpanContext struct {
|
|
TraceID TraceID
|
|
SpanID SpanID
|
|
}
|
|
|
|
type Span struct {
|
|
Name string
|
|
ID SpanContext
|
|
ParentID SpanID
|
|
Start time.Time
|
|
Finish time.Time
|
|
Tags event.TagList
|
|
Events []event.Event
|
|
}
|
|
|
|
type contextKeyType int
|
|
|
|
const (
|
|
spanContextKey = contextKeyType(iota)
|
|
)
|
|
|
|
func GetSpan(ctx context.Context) *Span {
|
|
v := ctx.Value(spanContextKey)
|
|
if v == nil {
|
|
return nil
|
|
}
|
|
return v.(*Span)
|
|
}
|
|
|
|
// ContextSpan is 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 ContextSpan(ctx context.Context, ev event.Event) (context.Context, event.Event) {
|
|
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.At,
|
|
Tags: ev.Tags,
|
|
}
|
|
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.At
|
|
}
|
|
case ev.IsDetach():
|
|
return context.WithValue(ctx, spanContextKey, nil), ev
|
|
}
|
|
return ctx, ev
|
|
}
|
|
|
|
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)
|
|
}
|