diff --git a/internal/event/bench_test.go b/internal/event/bench_test.go index 8db24e6ece..5df08f5127 100644 --- a/internal/event/bench_test.go +++ b/internal/event/bench_test.go @@ -9,6 +9,7 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/core" "golang.org/x/tools/internal/event/export" + "golang.org/x/tools/internal/event/label" ) type Hooks struct { @@ -147,6 +148,6 @@ func init() { log.SetOutput(ioutil.Discard) } -func noopExporter(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { +func noopExporter(ctx context.Context, ev core.Event, lm label.Map) context.Context { return ctx } diff --git a/internal/event/core/event.go b/internal/event/core/event.go index 109456c386..48286b1028 100644 --- a/internal/event/core/event.go +++ b/internal/event/core/event.go @@ -8,6 +8,8 @@ package core import ( "fmt" "time" + + "golang.org/x/tools/internal/event/label" ) type eventType uint8 @@ -22,27 +24,26 @@ const ( RecordType // a value that should be tracked ) -// sTags is used to hold a small number of tags inside an event whichout -// requiring a separate allocation. -// As tags are often on the stack, this avoids an allocation at all for -// the very common cases of simple events. -// The length needs to be large enough to cope with the majority of events -// but no so large as to cause undue stack pressure. -// A log message with two values will use 3 tags (one for each value and -// one for the message itself). -type sTags [3]Tag - // Event holds the information about an event of note that ocurred. type Event struct { At time.Time - typ eventType - static sTags // inline storage for the first few tags - dynamic []Tag // dynamically sized storage for remaining tags + typ eventType + + // As events are often on the stack, storing the first few labels directly + // in the event can avoid an allocation at all for the very common cases of + // simple events. + // The length needs to be large enough to cope with the majority of events + // but no so large as to cause undue stack pressure. + // A log message with two values will use 3 labels (one for each value and + // one for the message itself). + + static [3]label.Label // inline storage for the first few labels + dynamic []label.Label // dynamically sized storage for remaining labels } -// eventTagMap implements TagMap for a the tags of an Event. -type eventTagMap struct { +// eventLabelMap implements label.Map for a the labels of an Event. +type eventLabelMap struct { event Event } @@ -54,12 +55,12 @@ func (ev Event) IsDetach() bool { return ev.typ == DetachType } func (ev Event) IsRecord() bool { return ev.typ == RecordType } func (ev Event) Format(f fmt.State, r rune) { - tagMap := TagMap(ev) + lm := label.Map(ev) if !ev.At.IsZero() { fmt.Fprint(f, ev.At.Format("2006/01/02 15:04:05 ")) } - msg := Msg.Get(tagMap) - err := Err.Get(tagMap) + msg := Msg.Get(lm) + err := Err.Get(lm) fmt.Fprint(f, msg) if err != nil { if f.Flag('+') { @@ -69,13 +70,13 @@ func (ev Event) Format(f fmt.State, r rune) { } } for index := 0; ev.Valid(index); index++ { - tag := ev.Tag(index) + l := ev.Label(index) // msg and err were both already printed above, so we skip them to avoid // double printing - if !tag.Valid() || tag.Key() == Msg || tag.Key() == Err { + if !l.Valid() || l.Key() == Msg || l.Key() == Err { continue } - fmt.Fprintf(f, "\n\t%v", tag) + fmt.Fprintf(f, "\n\t%v", l) } } @@ -83,31 +84,31 @@ func (ev Event) Valid(index int) bool { return index >= 0 && index < len(ev.static)+len(ev.dynamic) } -func (ev Event) Tag(index int) Tag { +func (ev Event) Label(index int) label.Label { if index < len(ev.static) { return ev.static[index] } return ev.dynamic[index-len(ev.static)] } -func (ev Event) Find(key Key) Tag { - for _, tag := range ev.static { - if tag.Key() == key { - return tag +func (ev Event) Find(key label.Key) label.Label { + for _, l := range ev.static { + if l.Key() == key { + return l } } - for _, tag := range ev.dynamic { - if tag.Key() == key { - return tag + for _, l := range ev.dynamic { + if l.Key() == key { + return l } } - return Tag{} + return label.Label{} } -func MakeEvent(typ eventType, static [3]Tag, tags []Tag) Event { +func MakeEvent(typ eventType, static [3]label.Label, labels []label.Label) Event { return Event{ typ: typ, static: static, - dynamic: tags, + dynamic: labels, } } diff --git a/internal/event/core/export.go b/internal/event/core/export.go index 89783f31ab..f006ed14f6 100644 --- a/internal/event/core/export.go +++ b/internal/event/core/export.go @@ -9,11 +9,13 @@ import ( "sync/atomic" "time" "unsafe" + + "golang.org/x/tools/internal/event/label" ) // Exporter is a function that handles events. // It may return a modified context and event. -type Exporter func(context.Context, Event, TagMap) context.Context +type Exporter func(context.Context, Event, label.Map) context.Context var ( exporter unsafe.Pointer @@ -35,7 +37,7 @@ func SetExporter(e Exporter) { } // deliver is called to deliver an event to the supplied exporter. -// it will fill in the time and generate the basic tag source. +// it will fill in the time. func deliver(ctx context.Context, exporter Exporter, ev Event) context.Context { // add the current time to the event ev.At = time.Now() @@ -56,7 +58,7 @@ func Export(ctx context.Context, ev Event) context.Context { // ExportPair is called to deliver a start event to the supplied exporter. // It also returns a function that will deliver the end event to the same // exporter. -// it will fill in the time and generate the basic tag source. +// It will fill in the time. func ExportPair(ctx context.Context, begin, end Event) (context.Context, func()) { // get the global exporter and abort early if there is not one exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter)) diff --git a/internal/event/core/fast.go b/internal/event/core/fast.go index 427bec3df8..eef372102c 100644 --- a/internal/event/core/fast.go +++ b/internal/event/core/fast.go @@ -6,49 +6,51 @@ package core import ( "context" + + "golang.org/x/tools/internal/event/label" ) -// Log1 takes a message and one tag delivers a log event to the exporter. +// Log1 takes a message and one label delivers a log event to the exporter. // It is a customized version of Print that is faster and does no allocation. -func Log1(ctx context.Context, message string, t1 Tag) { - Export(ctx, MakeEvent(LogType, sTags{Msg.Of(message), t1}, nil)) +func Log1(ctx context.Context, message string, t1 label.Label) { + Export(ctx, MakeEvent(LogType, [3]label.Label{Msg.Of(message), t1}, nil)) } -// Log2 takes a message and two tags and delivers a log event to the exporter. +// Log2 takes a message and two labels and delivers a log event to the exporter. // It is a customized version of Print that is faster and does no allocation. -func Log2(ctx context.Context, message string, t1 Tag, t2 Tag) { - Export(ctx, MakeEvent(LogType, sTags{Msg.Of(message), t1, t2}, nil)) +func Log2(ctx context.Context, message string, t1 label.Label, t2 label.Label) { + Export(ctx, MakeEvent(LogType, [3]label.Label{Msg.Of(message), t1, t2}, nil)) } -// Metric1 sends a label event to the exporter with the supplied tags. -func Metric1(ctx context.Context, t1 Tag) context.Context { - return Export(ctx, MakeEvent(RecordType, sTags{t1}, nil)) +// Metric1 sends a label event to the exporter with the supplied labels. +func Metric1(ctx context.Context, t1 label.Label) context.Context { + return Export(ctx, MakeEvent(RecordType, [3]label.Label{t1}, nil)) } -// Metric2 sends a label event to the exporter with the supplied tags. -func Metric2(ctx context.Context, t1, t2 Tag) context.Context { - return Export(ctx, MakeEvent(RecordType, sTags{t1, t2}, nil)) +// Metric2 sends a label event to the exporter with the supplied labels. +func Metric2(ctx context.Context, t1, t2 label.Label) context.Context { + return Export(ctx, MakeEvent(RecordType, [3]label.Label{t1, t2}, nil)) } -// Metric3 sends a label event to the exporter with the supplied tags. -func Metric3(ctx context.Context, t1, t2, t3 Tag) context.Context { - return Export(ctx, MakeEvent(RecordType, sTags{t1, t2, t3}, nil)) +// Metric3 sends a label event to the exporter with the supplied labels. +func Metric3(ctx context.Context, t1, t2, t3 label.Label) context.Context { + return Export(ctx, MakeEvent(RecordType, [3]label.Label{t1, t2, t3}, nil)) } -// Start1 sends a span start event with the supplied tag list to the exporter. +// Start1 sends a span start event with the supplied label list to the exporter. // It also returns a function that will end the span, which should normally be // deferred. -func Start1(ctx context.Context, name string, t1 Tag) (context.Context, func()) { +func Start1(ctx context.Context, name string, t1 label.Label) (context.Context, func()) { return ExportPair(ctx, - MakeEvent(StartSpanType, sTags{Name.Of(name), t1}, nil), - MakeEvent(EndSpanType, sTags{}, nil)) + MakeEvent(StartSpanType, [3]label.Label{Name.Of(name), t1}, nil), + MakeEvent(EndSpanType, [3]label.Label{}, nil)) } -// Start2 sends a span start event with the supplied tag list to the exporter. +// Start2 sends a span start event with the supplied label list to the exporter. // It also returns a function that will end the span, which should normally be // deferred. -func Start2(ctx context.Context, name string, t1, t2 Tag) (context.Context, func()) { +func Start2(ctx context.Context, name string, t1, t2 label.Label) (context.Context, func()) { return ExportPair(ctx, - MakeEvent(StartSpanType, sTags{Name.Of(name), t1, t2}, nil), - MakeEvent(EndSpanType, sTags{}, nil)) + MakeEvent(StartSpanType, [3]label.Label{Name.Of(name), t1, t2}, nil), + MakeEvent(EndSpanType, [3]label.Label{}, nil)) } diff --git a/internal/event/core/key.go b/internal/event/core/key.go index 6c28fb25c3..788e48b15b 100644 --- a/internal/event/core/key.go +++ b/internal/event/core/key.go @@ -9,33 +9,19 @@ import ( "io" "math" "strconv" + + "golang.org/x/tools/internal/event/label" ) var ( - // Msg is a key used to add message strings to tag lists. + // Msg is a key used to add message strings to label lists. Msg = NewStringKey("message", "a readable message") // Name is used for things like traces that have a name. Name = NewStringKey("name", "an entity name") - // Err is a key used to add error values to tag lists. + // Err is a key used to add error values to label lists. Err = NewErrorKey("error", "an error that occurred") ) -// Key is used as the identity of a Tag. -// Keys are intended to be compared by pointer only, the name should be unique -// for communicating with external systems, but it is not required or enforced. -type Key interface { - // Name returns the key name. - Name() string - // Description returns a string that can be used to describe the value. - Description() string - - // Format is used in formatting to append the value of the tag to the - // supplied buffer. - // The formatter may use the supplied buf as a scratch area to avoid - // allocations. - Format(w io.Writer, buf []byte, tag Tag) -} - // ValueKey represents a key for untyped values. type ValueKey struct { name string @@ -50,23 +36,23 @@ func NewKey(name, description string) *ValueKey { func (k *ValueKey) Name() string { return k.name } func (k *ValueKey) Description() string { return k.description } -func (k *ValueKey) Format(w io.Writer, buf []byte, tag Tag) { - fmt.Fprint(w, k.From(tag)) +func (k *ValueKey) Format(w io.Writer, buf []byte, l label.Label) { + fmt.Fprint(w, k.From(l)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *ValueKey) Get(tags TagMap) interface{} { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *ValueKey) Get(lm label.Map) interface{} { + if t := lm.Find(k); t.Valid() { return k.From(t) } return nil } -// From can be used to get a value from a Tag. -func (k *ValueKey) From(t Tag) interface{} { return t.UnpackValue() } +// From can be used to get a value from a Label. +func (k *ValueKey) From(t label.Label) interface{} { return t.UnpackValue() } -// Of creates a new Tag with this key and the supplied value. -func (k *ValueKey) Of(value interface{}) Tag { return TagOfValue(k, value) } +// Of creates a new Label with this key and the supplied value. +func (k *ValueKey) Of(value interface{}) label.Label { return label.OfValue(k, value) } // IntKey represents a key type IntKey struct { @@ -82,23 +68,23 @@ func NewIntKey(name, description string) *IntKey { func (k *IntKey) Name() string { return k.name } func (k *IntKey) Description() string { return k.description } -func (k *IntKey) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendInt(buf, int64(k.From(tag)), 10)) +func (k *IntKey) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *IntKey) Of(v int) Tag { return TagOf64(k, uint64(v)) } +// Of creates a new Label with this key and the supplied value. +func (k *IntKey) Of(v int) label.Label { return label.Of64(k, uint64(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *IntKey) Get(tags TagMap) int { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *IntKey) Get(lm label.Map) int { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *IntKey) From(t Tag) int { return int(t.Unpack64()) } +// From can be used to get a value from a Label. +func (k *IntKey) From(t label.Label) int { return int(t.Unpack64()) } // Int8Key represents a key type Int8Key struct { @@ -114,23 +100,23 @@ func NewInt8Key(name, description string) *Int8Key { func (k *Int8Key) Name() string { return k.name } func (k *Int8Key) Description() string { return k.description } -func (k *Int8Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendInt(buf, int64(k.From(tag)), 10)) +func (k *Int8Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *Int8Key) Of(v int8) Tag { return TagOf64(k, uint64(v)) } +// Of creates a new Label with this key and the supplied value. +func (k *Int8Key) Of(v int8) label.Label { return label.Of64(k, uint64(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *Int8Key) Get(tags TagMap) int8 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *Int8Key) Get(lm label.Map) int8 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *Int8Key) From(t Tag) int8 { return int8(t.Unpack64()) } +// From can be used to get a value from a Label. +func (k *Int8Key) From(t label.Label) int8 { return int8(t.Unpack64()) } // Int16Key represents a key type Int16Key struct { @@ -146,23 +132,23 @@ func NewInt16Key(name, description string) *Int16Key { func (k *Int16Key) Name() string { return k.name } func (k *Int16Key) Description() string { return k.description } -func (k *Int16Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendInt(buf, int64(k.From(tag)), 10)) +func (k *Int16Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *Int16Key) Of(v int16) Tag { return TagOf64(k, uint64(v)) } +// Of creates a new Label with this key and the supplied value. +func (k *Int16Key) Of(v int16) label.Label { return label.Of64(k, uint64(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *Int16Key) Get(tags TagMap) int16 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *Int16Key) Get(lm label.Map) int16 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *Int16Key) From(t Tag) int16 { return int16(t.Unpack64()) } +// From can be used to get a value from a Label. +func (k *Int16Key) From(t label.Label) int16 { return int16(t.Unpack64()) } // Int32Key represents a key type Int32Key struct { @@ -178,23 +164,23 @@ func NewInt32Key(name, description string) *Int32Key { func (k *Int32Key) Name() string { return k.name } func (k *Int32Key) Description() string { return k.description } -func (k *Int32Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendInt(buf, int64(k.From(tag)), 10)) +func (k *Int32Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *Int32Key) Of(v int32) Tag { return TagOf64(k, uint64(v)) } +// Of creates a new Label with this key and the supplied value. +func (k *Int32Key) Of(v int32) label.Label { return label.Of64(k, uint64(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *Int32Key) Get(tags TagMap) int32 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *Int32Key) Get(lm label.Map) int32 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *Int32Key) From(t Tag) int32 { return int32(t.Unpack64()) } +// From can be used to get a value from a Label. +func (k *Int32Key) From(t label.Label) int32 { return int32(t.Unpack64()) } // Int64Key represents a key type Int64Key struct { @@ -210,23 +196,23 @@ func NewInt64Key(name, description string) *Int64Key { func (k *Int64Key) Name() string { return k.name } func (k *Int64Key) Description() string { return k.description } -func (k *Int64Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendInt(buf, k.From(tag), 10)) +func (k *Int64Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, k.From(l), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *Int64Key) Of(v int64) Tag { return TagOf64(k, uint64(v)) } +// Of creates a new Label with this key and the supplied value. +func (k *Int64Key) Of(v int64) label.Label { return label.Of64(k, uint64(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *Int64Key) Get(tags TagMap) int64 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *Int64Key) Get(lm label.Map) int64 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *Int64Key) From(t Tag) int64 { return int64(t.Unpack64()) } +// From can be used to get a value from a Label. +func (k *Int64Key) From(t label.Label) int64 { return int64(t.Unpack64()) } // UIntKey represents a key type UIntKey struct { @@ -242,23 +228,23 @@ func NewUIntKey(name, description string) *UIntKey { func (k *UIntKey) Name() string { return k.name } func (k *UIntKey) Description() string { return k.description } -func (k *UIntKey) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendUint(buf, uint64(k.From(tag)), 10)) +func (k *UIntKey) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *UIntKey) Of(v uint) Tag { return TagOf64(k, uint64(v)) } +// Of creates a new Label with this key and the supplied value. +func (k *UIntKey) Of(v uint) label.Label { return label.Of64(k, uint64(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *UIntKey) Get(tags TagMap) uint { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *UIntKey) Get(lm label.Map) uint { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *UIntKey) From(t Tag) uint { return uint(t.Unpack64()) } +// From can be used to get a value from a Label. +func (k *UIntKey) From(t label.Label) uint { return uint(t.Unpack64()) } // UInt8Key represents a key type UInt8Key struct { @@ -274,23 +260,23 @@ func NewUInt8Key(name, description string) *UInt8Key { func (k *UInt8Key) Name() string { return k.name } func (k *UInt8Key) Description() string { return k.description } -func (k *UInt8Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendUint(buf, uint64(k.From(tag)), 10)) +func (k *UInt8Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *UInt8Key) Of(v uint8) Tag { return TagOf64(k, uint64(v)) } +// Of creates a new Label with this key and the supplied value. +func (k *UInt8Key) Of(v uint8) label.Label { return label.Of64(k, uint64(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *UInt8Key) Get(tags TagMap) uint8 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *UInt8Key) Get(lm label.Map) uint8 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *UInt8Key) From(t Tag) uint8 { return uint8(t.Unpack64()) } +// From can be used to get a value from a Label. +func (k *UInt8Key) From(t label.Label) uint8 { return uint8(t.Unpack64()) } // UInt16Key represents a key type UInt16Key struct { @@ -306,23 +292,23 @@ func NewUInt16Key(name, description string) *UInt16Key { func (k *UInt16Key) Name() string { return k.name } func (k *UInt16Key) Description() string { return k.description } -func (k *UInt16Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendUint(buf, uint64(k.From(tag)), 10)) +func (k *UInt16Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *UInt16Key) Of(v uint16) Tag { return TagOf64(k, uint64(v)) } +// Of creates a new Label with this key and the supplied value. +func (k *UInt16Key) Of(v uint16) label.Label { return label.Of64(k, uint64(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *UInt16Key) Get(tags TagMap) uint16 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *UInt16Key) Get(lm label.Map) uint16 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *UInt16Key) From(t Tag) uint16 { return uint16(t.Unpack64()) } +// From can be used to get a value from a Label. +func (k *UInt16Key) From(t label.Label) uint16 { return uint16(t.Unpack64()) } // UInt32Key represents a key type UInt32Key struct { @@ -338,23 +324,23 @@ func NewUInt32Key(name, description string) *UInt32Key { func (k *UInt32Key) Name() string { return k.name } func (k *UInt32Key) Description() string { return k.description } -func (k *UInt32Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendUint(buf, uint64(k.From(tag)), 10)) +func (k *UInt32Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *UInt32Key) Of(v uint32) Tag { return TagOf64(k, uint64(v)) } +// Of creates a new Label with this key and the supplied value. +func (k *UInt32Key) Of(v uint32) label.Label { return label.Of64(k, uint64(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *UInt32Key) Get(tags TagMap) uint32 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *UInt32Key) Get(lm label.Map) uint32 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *UInt32Key) From(t Tag) uint32 { return uint32(t.Unpack64()) } +// From can be used to get a value from a Label. +func (k *UInt32Key) From(t label.Label) uint32 { return uint32(t.Unpack64()) } // UInt64Key represents a key type UInt64Key struct { @@ -370,23 +356,23 @@ func NewUInt64Key(name, description string) *UInt64Key { func (k *UInt64Key) Name() string { return k.name } func (k *UInt64Key) Description() string { return k.description } -func (k *UInt64Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendUint(buf, k.From(tag), 10)) +func (k *UInt64Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, k.From(l), 10)) } -// Of creates a new Tag with this key and the supplied value. -func (k *UInt64Key) Of(v uint64) Tag { return TagOf64(k, v) } +// Of creates a new Label with this key and the supplied value. +func (k *UInt64Key) Of(v uint64) label.Label { return label.Of64(k, v) } -// Get can be used to get a tag for the key from a TagMap. -func (k *UInt64Key) Get(tags TagMap) uint64 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *UInt64Key) Get(lm label.Map) uint64 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *UInt64Key) From(t Tag) uint64 { return t.Unpack64() } +// From can be used to get a value from a Label. +func (k *UInt64Key) From(t label.Label) uint64 { return t.Unpack64() } // Float32Key represents a key type Float32Key struct { @@ -402,25 +388,25 @@ func NewFloat32Key(name, description string) *Float32Key { func (k *Float32Key) Name() string { return k.name } func (k *Float32Key) Description() string { return k.description } -func (k *Float32Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendFloat(buf, float64(k.From(tag)), 'E', -1, 32)) +func (k *Float32Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendFloat(buf, float64(k.From(l)), 'E', -1, 32)) } -// Of creates a new Tag with this key and the supplied value. -func (k *Float32Key) Of(v float32) Tag { - return TagOf64(k, uint64(math.Float32bits(v))) +// Of creates a new Label with this key and the supplied value. +func (k *Float32Key) Of(v float32) label.Label { + return label.Of64(k, uint64(math.Float32bits(v))) } -// Get can be used to get a tag for the key from a TagMap. -func (k *Float32Key) Get(tags TagMap) float32 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *Float32Key) Get(lm label.Map) float32 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *Float32Key) From(t Tag) float32 { +// From can be used to get a value from a Label. +func (k *Float32Key) From(t label.Label) float32 { return math.Float32frombits(uint32(t.Unpack64())) } @@ -438,25 +424,25 @@ func NewFloat64Key(name, description string) *Float64Key { func (k *Float64Key) Name() string { return k.name } func (k *Float64Key) Description() string { return k.description } -func (k *Float64Key) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendFloat(buf, k.From(tag), 'E', -1, 64)) +func (k *Float64Key) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendFloat(buf, k.From(l), 'E', -1, 64)) } -// Of creates a new Tag with this key and the supplied value. -func (k *Float64Key) Of(v float64) Tag { - return TagOf64(k, math.Float64bits(v)) +// Of creates a new Label with this key and the supplied value. +func (k *Float64Key) Of(v float64) label.Label { + return label.Of64(k, math.Float64bits(v)) } -// Get can be used to get a tag for the key from a TagMap. -func (k *Float64Key) Get(tags TagMap) float64 { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *Float64Key) Get(lm label.Map) float64 { + if t := lm.Find(k); t.Valid() { return k.From(t) } return 0 } -// From can be used to get a value from a Tag. -func (k *Float64Key) From(t Tag) float64 { +// From can be used to get a value from a Label. +func (k *Float64Key) From(t label.Label) float64 { return math.Float64frombits(t.Unpack64()) } @@ -474,23 +460,23 @@ func NewStringKey(name, description string) *StringKey { func (k *StringKey) Name() string { return k.name } func (k *StringKey) Description() string { return k.description } -func (k *StringKey) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendQuote(buf, k.From(tag))) +func (k *StringKey) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendQuote(buf, k.From(l))) } -// Of creates a new Tag with this key and the supplied value. -func (k *StringKey) Of(v string) Tag { return TagOfString(k, v) } +// Of creates a new Label with this key and the supplied value. +func (k *StringKey) Of(v string) label.Label { return label.OfString(k, v) } -// Get can be used to get a tag for the key from a TagMap. -func (k *StringKey) Get(tags TagMap) string { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *StringKey) Get(lm label.Map) string { + if t := lm.Find(k); t.Valid() { return k.From(t) } return "" } -// From can be used to get a value from a Tag. -func (k *StringKey) From(t Tag) string { return t.UnpackString() } +// From can be used to get a value from a Label. +func (k *StringKey) From(t label.Label) string { return t.UnpackString() } // BooleanKey represents a key type BooleanKey struct { @@ -506,28 +492,28 @@ func NewBooleanKey(name, description string) *BooleanKey { func (k *BooleanKey) Name() string { return k.name } func (k *BooleanKey) Description() string { return k.description } -func (k *BooleanKey) Format(w io.Writer, buf []byte, tag Tag) { - w.Write(strconv.AppendBool(buf, k.From(tag))) +func (k *BooleanKey) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendBool(buf, k.From(l))) } -// Of creates a new Tag with this key and the supplied value. -func (k *BooleanKey) Of(v bool) Tag { +// Of creates a new Label with this key and the supplied value. +func (k *BooleanKey) Of(v bool) label.Label { if v { - return TagOf64(k, 1) + return label.Of64(k, 1) } - return TagOf64(k, 0) + return label.Of64(k, 0) } -// Get can be used to get a tag for the key from a TagMap. -func (k *BooleanKey) Get(tags TagMap) bool { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *BooleanKey) Get(lm label.Map) bool { + if t := lm.Find(k); t.Valid() { return k.From(t) } return false } -// From can be used to get a value from a Tag. -func (k *BooleanKey) From(t Tag) bool { return t.Unpack64() > 0 } +// From can be used to get a value from a Label. +func (k *BooleanKey) From(t label.Label) bool { return t.Unpack64() > 0 } // ErrorKey represents a key type ErrorKey struct { @@ -543,23 +529,23 @@ func NewErrorKey(name, description string) *ErrorKey { func (k *ErrorKey) Name() string { return k.name } func (k *ErrorKey) Description() string { return k.description } -func (k *ErrorKey) Format(w io.Writer, buf []byte, tag Tag) { - io.WriteString(w, k.From(tag).Error()) +func (k *ErrorKey) Format(w io.Writer, buf []byte, l label.Label) { + io.WriteString(w, k.From(l).Error()) } -// Of creates a new Tag with this key and the supplied value. -func (k *ErrorKey) Of(v error) Tag { return TagOfValue(k, v) } +// Of creates a new Label with this key and the supplied value. +func (k *ErrorKey) Of(v error) label.Label { return label.OfValue(k, v) } -// Get can be used to get a tag for the key from a TagMap. -func (k *ErrorKey) Get(tags TagMap) error { - if t := tags.Find(k); t.Valid() { +// Get can be used to get a label for the key from a label.Map. +func (k *ErrorKey) Get(lm label.Map) error { + if t := lm.Find(k); t.Valid() { return k.From(t) } return nil } -// From can be used to get a value from a Tag. -func (k *ErrorKey) From(t Tag) error { +// From can be used to get a value from a Label. +func (k *ErrorKey) From(t label.Label) error { err, _ := t.UnpackValue().(error) return err } diff --git a/internal/event/core/tag.go b/internal/event/core/tag.go deleted file mode 100644 index 57de6ba888..0000000000 --- a/internal/event/core/tag.go +++ /dev/null @@ -1,197 +0,0 @@ -// 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 core - -import ( - "fmt" - "io" - "reflect" - "unsafe" -) - -// Tag holds a key and value pair. -// It is normally used when passing around lists of tags. -type Tag struct { - key Key - packed uint64 - untyped interface{} -} - -// TagMap is the interface to a collection of Tags indexed by key. -type TagMap interface { - // Find returns the tag that matches the supplied key. - Find(key Key) Tag -} - -// TagList is the interface to something that provides an iterable -// list of tags. -// Iteration should start from 0 and continue until Valid returns false. -type TagList interface { - // Valid returns true if the index is within range for the list. - // It does not imply the tag at that index will itself be valid. - Valid(index int) bool - // Tag returns the tag at the given index. - Tag(index int) Tag -} - -// tagList implements TagList for a list of Tags. -type tagList struct { - tags []Tag -} - -// tagFilter wraps a TagList filtering out specific tags. -type tagFilter struct { - keys []Key - underlying TagList -} - -// tagMap implements TagMap for a simple list of tags. -type tagMap struct { - tags []Tag -} - -// tagMapChain implements TagMap for a list of underlying TagMap. -type tagMapChain struct { - maps []TagMap -} - -// TagOfValue creates a new tag from the key and value. -// This method is for implementing new key types, tag creation should -// normally be done with the Of method of the key. -func TagOfValue(k Key, value interface{}) Tag { return Tag{key: k, untyped: value} } - -// UnpackValue assumes the tag was built using TagOfValue and returns the value -// that was passed to that constructor. -// This method is for implementing new key types, for type safety normal -// access should be done with the From method of the key. -func (t Tag) UnpackValue() interface{} { return t.untyped } - -// TagOf64 creates a new tag from a key and a uint64. This is often -// used for non uint64 values that can be packed into a uint64. -// This method is for implementing new key types, tag creation should -// normally be done with the Of method of the key. -func TagOf64(k Key, v uint64) Tag { return Tag{key: k, packed: v} } - -// Unpack64 assumes the tag was built using TagOf64 and returns the value that -// was passed to that constructor. -// This method is for implementing new key types, for type safety normal -// access should be done with the From method of the key. -func (t Tag) Unpack64() uint64 { return t.packed } - -// TagOfString creates a new tag from a key and a string. -// This method is for implementing new key types, tag creation should -// normally be done with the Of method of the key. -func TagOfString(k Key, v string) Tag { - hdr := (*reflect.StringHeader)(unsafe.Pointer(&v)) - return Tag{ - key: k, - packed: uint64(hdr.Len), - untyped: unsafe.Pointer(hdr.Data), - } -} - -// UnpackString assumes the tag was built using TagOfString and returns the -// value that was passed to that constructor. -// This method is for implementing new key types, for type safety normal -// access should be done with the From method of the key. -func (t Tag) UnpackString() string { - var v string - hdr := (*reflect.StringHeader)(unsafe.Pointer(&v)) - hdr.Data = uintptr(t.untyped.(unsafe.Pointer)) - hdr.Len = int(t.packed) - return *(*string)(unsafe.Pointer(hdr)) -} - -// Valid returns true if the Tag is a valid one (it has a key). -func (t Tag) Valid() bool { return t.key != nil } - -// Key returns the key of this Tag. -func (t Tag) Key() Key { return t.key } - -// Format is used for debug printing of tags. -func (t Tag) Format(f fmt.State, r rune) { - if !t.Valid() { - io.WriteString(f, `nil`) - return - } - io.WriteString(f, t.Key().Name()) - io.WriteString(f, "=") - var buf [128]byte - t.Key().Format(f, buf[:0], t) -} - -func (l *tagList) Valid(index int) bool { - return index >= 0 && index < len(l.tags) -} - -func (l *tagList) Tag(index int) Tag { - return l.tags[index] -} - -func (f *tagFilter) Valid(index int) bool { - return f.underlying.Valid(index) -} - -func (f *tagFilter) Tag(index int) Tag { - tag := f.underlying.Tag(index) - for _, f := range f.keys { - if tag.Key() == f { - return Tag{} - } - } - return tag -} - -func (l tagMap) Find(key Key) Tag { - for _, tag := range l.tags { - if tag.Key() == key { - return tag - } - } - return Tag{} -} - -func (c tagMapChain) Find(key Key) Tag { - for _, src := range c.maps { - tag := src.Find(key) - if tag.Valid() { - return tag - } - } - return Tag{} -} - -var emptyList = &tagList{} - -func NewTagList(tags ...Tag) TagList { - if len(tags) == 0 { - return emptyList - } - return &tagList{tags: tags} -} - -func Filter(l TagList, keys ...Key) TagList { - if len(keys) == 0 { - return l - } - return &tagFilter{keys: keys, underlying: l} -} - -func NewTagMap(tags ...Tag) TagMap { - return tagMap{tags: tags} -} - -func MergeTagMaps(srcs ...TagMap) TagMap { - var nonNil []TagMap - for _, src := range srcs { - if src != nil { - nonNil = append(nonNil, src) - } - } - if len(nonNil) == 1 { - return nonNil[0] - } - return tagMapChain{maps: nonNil} -} diff --git a/internal/event/event.go b/internal/event/event.go index 4ae08b38d2..0caeb694a7 100644 --- a/internal/event/event.go +++ b/internal/event/event.go @@ -8,11 +8,12 @@ import ( "context" "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" ) // Exporter is a function that handles events. // It may return a modified context and event. -type Exporter func(context.Context, core.Event, core.TagMap) context.Context +type Exporter func(context.Context, core.Event, label.Map) context.Context // SetExporter sets the global exporter function that handles all events. // The exporter is called synchronously from the event call site, so it should @@ -21,45 +22,47 @@ func SetExporter(e Exporter) { core.SetExporter(core.Exporter(e)) } -// Log takes a message and a tag list and combines them into a single event +// Log takes a message and a label list and combines them into a single event // before delivering them to the exporter. -func Log(ctx context.Context, message string, tags ...core.Tag) { - core.Export(ctx, core.MakeEvent(core.LogType, [3]core.Tag{ +func Log(ctx context.Context, message string, labels ...label.Label) { + core.Export(ctx, core.MakeEvent(core.LogType, [3]label.Label{ core.Msg.Of(message), - }, tags)) + }, labels)) } -// Error takes a message and a tag list and combines them into a single event +// Error takes a message and a label list and combines them into a single event // before delivering them to the exporter. It captures the error in the // delivered event. -func Error(ctx context.Context, message string, err error, tags ...core.Tag) { - core.Export(ctx, core.MakeEvent(core.LogType, [3]core.Tag{ +func Error(ctx context.Context, message string, err error, labels ...label.Label) { + core.Export(ctx, core.MakeEvent(core.LogType, [3]label.Label{ core.Msg.Of(message), core.Err.Of(err), - }, tags)) + }, labels)) } -// Metric sends a label event to the exporter with the supplied tags. -func Metric(ctx context.Context, tags ...core.Tag) { - core.Export(ctx, core.MakeEvent(core.RecordType, [3]core.Tag{}, tags)) +// Metric sends a label event to the exporter with the supplied labels. +func Metric(ctx context.Context, labels ...label.Label) { + core.Export(ctx, core.MakeEvent(core.RecordType, [3]label.Label{}, labels)) } -// Label sends a label event to the exporter with the supplied tags. -func Label(ctx context.Context, tags ...core.Tag) context.Context { - return core.Export(ctx, core.MakeEvent(core.LabelType, [3]core.Tag{}, tags)) +// Label sends a label event to the exporter with the supplied labels. +func Label(ctx context.Context, labels ...label.Label) context.Context { + return core.Export(ctx, core.MakeEvent(core.LabelType, [3]label.Label{}, labels)) } -// Start sends a span start event with the supplied tag list to the exporter. +// Start sends a span start event with the supplied label list to the exporter. // It also returns a function that will end the span, which should normally be // deferred. -func Start(ctx context.Context, name string, tags ...core.Tag) (context.Context, func()) { +func Start(ctx context.Context, name string, labels ...label.Label) (context.Context, func()) { return core.ExportPair(ctx, - core.MakeEvent(core.StartSpanType, [3]core.Tag{core.Name.Of(name)}, tags), - core.MakeEvent(core.EndSpanType, [3]core.Tag{}, nil)) + core.MakeEvent(core.StartSpanType, [3]label.Label{ + core.Name.Of(name), + }, labels), + core.MakeEvent(core.EndSpanType, [3]label.Label{}, nil)) } // Detach returns a context without an associated span. // This allows the creation of spans that are not children of the current span. func Detach(ctx context.Context) context.Context { - return core.Export(ctx, core.MakeEvent(core.DetachType, [3]core.Tag{}, nil)) + return core.Export(ctx, core.MakeEvent(core.DetachType, [3]label.Label{}, nil)) } diff --git a/internal/event/export/eventtest/eventtest.go b/internal/event/export/eventtest/eventtest.go index d0061f7746..9e9da529bd 100644 --- a/internal/event/export/eventtest/eventtest.go +++ b/internal/event/export/eventtest/eventtest.go @@ -24,6 +24,7 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/core" "golang.org/x/tools/internal/event/export" + "golang.org/x/tools/internal/event/label" ) func init() { @@ -48,11 +49,11 @@ type testExporter struct { logger event.Exporter } -func (w *testExporter) processEvent(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { +func (w *testExporter) processEvent(ctx context.Context, ev core.Event, tm label.Map) context.Context { w.mu.Lock() defer w.mu.Unlock() // build our log message in buffer - result := w.logger(ctx, ev, tagMap) + result := w.logger(ctx, ev, tm) v := ctx.Value(testingKey) // get the testing.TB if w.buffer.Len() > 0 && v != nil { diff --git a/internal/event/export/log.go b/internal/event/export/log.go index 22076aafaa..25912c920f 100644 --- a/internal/event/export/log.go +++ b/internal/event/export/log.go @@ -12,6 +12,7 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" ) // LogWriter returns an Exporter that logs events to the supplied writer. @@ -30,10 +31,10 @@ type logWriter struct { onlyErrors bool } -func (w *logWriter) ProcessEvent(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { +func (w *logWriter) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context { switch { case ev.IsLog(): - if w.onlyErrors && core.Err.Get(tagMap) == nil { + if w.onlyErrors && core.Err.Get(lm) == nil { return ctx } w.mu.Lock() @@ -43,21 +44,21 @@ func (w *logWriter) ProcessEvent(ctx context.Context, ev core.Event, tagMap core if !ev.At.IsZero() { w.writer.Write(ev.At.AppendFormat(buf, "2006/01/02 15:04:05 ")) } - msg := core.Msg.Get(tagMap) + msg := core.Msg.Get(lm) io.WriteString(w.writer, msg) - if err := core.Err.Get(tagMap); err != nil { + if err := core.Err.Get(lm); err != nil { io.WriteString(w.writer, ": ") io.WriteString(w.writer, err.Error()) } for index := 0; ev.Valid(index); index++ { - tag := ev.Tag(index) - if !tag.Valid() || tag.Key() == core.Msg || tag.Key() == core.Err { + l := ev.Label(index) + if !l.Valid() || l.Key() == core.Msg || l.Key() == core.Err { continue } io.WriteString(w.writer, "\n\t") - io.WriteString(w.writer, tag.Key().Name()) + io.WriteString(w.writer, l.Key().Name()) io.WriteString(w.writer, "=") - tag.Key().Format(w.writer, buf, tag) + l.Key().Format(w.writer, buf, l) } io.WriteString(w.writer, "\n") diff --git a/internal/event/export/log_test.go b/internal/event/export/log_test.go index 34029b6443..deef2329f6 100644 --- a/internal/event/export/log_test.go +++ b/internal/event/export/log_test.go @@ -13,6 +13,7 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/core" "golang.org/x/tools/internal/event/export" + "golang.org/x/tools/internal/event/label" ) func ExampleLog() { @@ -31,8 +32,8 @@ func ExampleLog() { func timeFixer(output event.Exporter) event.Exporter { at, _ := time.Parse(time.RFC3339Nano, "2020-03-05T14:27:48Z") - return func(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { + return func(ctx context.Context, ev core.Event, lm label.Map) context.Context { ev.At = at - return output(ctx, ev, tagMap) + return output(ctx, ev, lm) } } diff --git a/internal/event/export/metric/data.go b/internal/event/export/metric/data.go index c9603556b8..95582fe391 100644 --- a/internal/event/export/metric/data.go +++ b/internal/event/export/metric/data.go @@ -10,6 +10,7 @@ import ( "time" "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" ) // Data represents a single point in the time series of a metric. @@ -22,7 +23,7 @@ type Data interface { //TODO: rethink the concept of metric handles Handle() string // Groups reports the rows that currently exist for this metric. - Groups() [][]core.Tag + Groups() [][]label.Label } // Int64Data is a concrete implementation of Data for int64 scalar metrics. @@ -36,7 +37,7 @@ type Int64Data struct { // End is the last time this metric was updated. EndTime time.Time - groups [][]core.Tag + groups [][]label.Label key *core.Int64Key } @@ -51,7 +52,7 @@ type Float64Data struct { // End is the last time this metric was updated. EndTime time.Time - groups [][]core.Tag + groups [][]label.Label key *core.Float64Key } @@ -64,7 +65,7 @@ type HistogramInt64Data struct { // End is the last time this metric was updated. EndTime time.Time - groups [][]core.Tag + groups [][]label.Label key *core.Int64Key } @@ -91,7 +92,7 @@ type HistogramFloat64Data struct { // End is the last time this metric was updated. EndTime time.Time - groups [][]core.Tag + groups [][]label.Label key *core.Float64Key } @@ -109,44 +110,44 @@ type HistogramFloat64Row struct { Max float64 } -func tagListEqual(a, b []core.Tag) bool { +func labelListEqual(a, b []label.Label) bool { //TODO: make this more efficient return fmt.Sprint(a) == fmt.Sprint(b) } -func tagListLess(a, b []core.Tag) bool { +func labelListLess(a, b []label.Label) bool { //TODO: make this more efficient return fmt.Sprint(a) < fmt.Sprint(b) } -func getGroup(tagMap core.TagMap, g *[][]core.Tag, keys []core.Key) (int, bool) { - group := make([]core.Tag, len(keys)) +func getGroup(lm label.Map, g *[][]label.Label, keys []label.Key) (int, bool) { + group := make([]label.Label, len(keys)) for i, key := range keys { - tag := tagMap.Find(key) - if tag.Valid() { - group[i] = tag + l := lm.Find(key) + if l.Valid() { + group[i] = l } } old := *g index := sort.Search(len(old), func(i int) bool { - return !tagListLess(old[i], group) + return !labelListLess(old[i], group) }) - if index < len(old) && tagListEqual(group, old[index]) { + if index < len(old) && labelListEqual(group, old[index]) { // not a new group return index, false } - *g = make([][]core.Tag, len(old)+1) + *g = make([][]label.Label, len(old)+1) copy(*g, old[:index]) copy((*g)[index+1:], old[index:]) (*g)[index] = group return index, true } -func (data *Int64Data) Handle() string { return data.Info.Name } -func (data *Int64Data) Groups() [][]core.Tag { return data.groups } +func (data *Int64Data) Handle() string { return data.Info.Name } +func (data *Int64Data) Groups() [][]label.Label { return data.groups } -func (data *Int64Data) modify(at time.Time, tagMap core.TagMap, f func(v int64) int64) Data { - index, insert := getGroup(tagMap, &data.groups, data.Info.Keys) +func (data *Int64Data) modify(at time.Time, lm label.Map, f func(v int64) int64) Data { + index, insert := getGroup(lm, &data.groups, data.Info.Keys) old := data.Rows if insert { data.Rows = make([]int64, len(old)+1) @@ -162,29 +163,29 @@ func (data *Int64Data) modify(at time.Time, tagMap core.TagMap, f func(v int64) return &frozen } -func (data *Int64Data) count(at time.Time, tagMap core.TagMap, tag core.Tag) Data { - return data.modify(at, tagMap, func(v int64) int64 { +func (data *Int64Data) count(at time.Time, lm label.Map, l label.Label) Data { + return data.modify(at, lm, func(v int64) int64 { return v + 1 }) } -func (data *Int64Data) sum(at time.Time, tagMap core.TagMap, tag core.Tag) Data { - return data.modify(at, tagMap, func(v int64) int64 { - return v + data.key.From(tag) +func (data *Int64Data) sum(at time.Time, lm label.Map, l label.Label) Data { + return data.modify(at, lm, func(v int64) int64 { + return v + data.key.From(l) }) } -func (data *Int64Data) latest(at time.Time, tagMap core.TagMap, tag core.Tag) Data { - return data.modify(at, tagMap, func(v int64) int64 { - return data.key.From(tag) +func (data *Int64Data) latest(at time.Time, lm label.Map, l label.Label) Data { + return data.modify(at, lm, func(v int64) int64 { + return data.key.From(l) }) } -func (data *Float64Data) Handle() string { return data.Info.Name } -func (data *Float64Data) Groups() [][]core.Tag { return data.groups } +func (data *Float64Data) Handle() string { return data.Info.Name } +func (data *Float64Data) Groups() [][]label.Label { return data.groups } -func (data *Float64Data) modify(at time.Time, tagMap core.TagMap, f func(v float64) float64) Data { - index, insert := getGroup(tagMap, &data.groups, data.Info.Keys) +func (data *Float64Data) modify(at time.Time, lm label.Map, f func(v float64) float64) Data { + index, insert := getGroup(lm, &data.groups, data.Info.Keys) old := data.Rows if insert { data.Rows = make([]float64, len(old)+1) @@ -200,23 +201,23 @@ func (data *Float64Data) modify(at time.Time, tagMap core.TagMap, f func(v float return &frozen } -func (data *Float64Data) sum(at time.Time, tagMap core.TagMap, tag core.Tag) Data { - return data.modify(at, tagMap, func(v float64) float64 { - return v + data.key.From(tag) +func (data *Float64Data) sum(at time.Time, lm label.Map, l label.Label) Data { + return data.modify(at, lm, func(v float64) float64 { + return v + data.key.From(l) }) } -func (data *Float64Data) latest(at time.Time, tagMap core.TagMap, tag core.Tag) Data { - return data.modify(at, tagMap, func(v float64) float64 { - return data.key.From(tag) +func (data *Float64Data) latest(at time.Time, lm label.Map, l label.Label) Data { + return data.modify(at, lm, func(v float64) float64 { + return data.key.From(l) }) } -func (data *HistogramInt64Data) Handle() string { return data.Info.Name } -func (data *HistogramInt64Data) Groups() [][]core.Tag { return data.groups } +func (data *HistogramInt64Data) Handle() string { return data.Info.Name } +func (data *HistogramInt64Data) Groups() [][]label.Label { return data.groups } -func (data *HistogramInt64Data) modify(at time.Time, tagMap core.TagMap, f func(v *HistogramInt64Row)) Data { - index, insert := getGroup(tagMap, &data.groups, data.Info.Keys) +func (data *HistogramInt64Data) modify(at time.Time, lm label.Map, f func(v *HistogramInt64Row)) Data { + index, insert := getGroup(lm, &data.groups, data.Info.Keys) old := data.Rows var v HistogramInt64Row if insert { @@ -238,9 +239,9 @@ func (data *HistogramInt64Data) modify(at time.Time, tagMap core.TagMap, f func( return &frozen } -func (data *HistogramInt64Data) record(at time.Time, tagMap core.TagMap, tag core.Tag) Data { - return data.modify(at, tagMap, func(v *HistogramInt64Row) { - value := data.key.From(tag) +func (data *HistogramInt64Data) record(at time.Time, lm label.Map, l label.Label) Data { + return data.modify(at, lm, func(v *HistogramInt64Row) { + value := data.key.From(l) v.Sum += value if v.Min > value || v.Count == 0 { v.Min = value @@ -257,11 +258,11 @@ func (data *HistogramInt64Data) record(at time.Time, tagMap core.TagMap, tag cor }) } -func (data *HistogramFloat64Data) Handle() string { return data.Info.Name } -func (data *HistogramFloat64Data) Groups() [][]core.Tag { return data.groups } +func (data *HistogramFloat64Data) Handle() string { return data.Info.Name } +func (data *HistogramFloat64Data) Groups() [][]label.Label { return data.groups } -func (data *HistogramFloat64Data) modify(at time.Time, tagMap core.TagMap, f func(v *HistogramFloat64Row)) Data { - index, insert := getGroup(tagMap, &data.groups, data.Info.Keys) +func (data *HistogramFloat64Data) modify(at time.Time, lm label.Map, f func(v *HistogramFloat64Row)) Data { + index, insert := getGroup(lm, &data.groups, data.Info.Keys) old := data.Rows var v HistogramFloat64Row if insert { @@ -283,9 +284,9 @@ func (data *HistogramFloat64Data) modify(at time.Time, tagMap core.TagMap, f fun return &frozen } -func (data *HistogramFloat64Data) record(at time.Time, tagMap core.TagMap, tag core.Tag) Data { - return data.modify(at, tagMap, func(v *HistogramFloat64Row) { - value := data.key.From(tag) +func (data *HistogramFloat64Data) record(at time.Time, lm label.Map, l label.Label) Data { + return data.modify(at, lm, func(v *HistogramFloat64Row) { + value := data.key.From(l) v.Sum += value if v.Min > value || v.Count == 0 { v.Min = value diff --git a/internal/event/export/metric/exporter.go b/internal/event/export/metric/exporter.go index c3653d98f4..cfcb20797b 100644 --- a/internal/event/export/metric/exporter.go +++ b/internal/event/export/metric/exporter.go @@ -12,6 +12,7 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" ) var Entries = core.NewKey("metric_entries", "The set of metrics calculated for an event") @@ -20,9 +21,9 @@ type Config struct { subscribers map[interface{}][]subscriber } -type subscriber func(time.Time, core.TagMap, core.Tag) Data +type subscriber func(time.Time, label.Map, label.Label) Data -func (e *Config) subscribe(key core.Key, s subscriber) { +func (e *Config) subscribe(key label.Key, s subscriber) { if e.subscribers == nil { e.subscribers = make(map[interface{}][]subscriber) } @@ -31,26 +32,26 @@ func (e *Config) subscribe(key core.Key, s subscriber) { func (e *Config) Exporter(output event.Exporter) event.Exporter { var mu sync.Mutex - return func(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { + return func(ctx context.Context, ev core.Event, lm label.Map) context.Context { if !ev.IsRecord() { - return output(ctx, ev, tagMap) + return output(ctx, ev, lm) } mu.Lock() defer mu.Unlock() var metrics []Data for index := 0; ev.Valid(index); index++ { - tag := ev.Tag(index) - if !tag.Valid() { + l := ev.Label(index) + if !l.Valid() { continue } - id := tag.Key() + id := l.Key() if list := e.subscribers[id]; len(list) > 0 { for _, s := range list { - metrics = append(metrics, s(ev.At, tagMap, tag)) + metrics = append(metrics, s(ev.At, lm, l)) } } } - tagMap = core.MergeTagMaps(core.NewTagMap(Entries.Of(metrics)), tagMap) - return output(ctx, ev, tagMap) + lm = label.MergeMaps(label.NewMap(Entries.Of(metrics)), lm) + return output(ctx, ev, lm) } } diff --git a/internal/event/export/metric/info.go b/internal/event/export/metric/info.go index 2d423d1f5c..ef88d85efc 100644 --- a/internal/event/export/metric/info.go +++ b/internal/event/export/metric/info.go @@ -4,7 +4,10 @@ package metric -import "golang.org/x/tools/internal/event/core" +import ( + "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" +) // Scalar represents the construction information for a scalar metric. type Scalar struct { @@ -12,8 +15,8 @@ type Scalar struct { Name string // Description can be used by observers to describe the metric to users. Description string - // Keys is the set of tags that collectively describe rows of the metric. - Keys []core.Key + // Keys is the set of labels that collectively describe rows of the metric. + Keys []label.Key } // HistogramInt64 represents the construction information for an int64 histogram metric. @@ -22,8 +25,8 @@ type HistogramInt64 struct { Name string // Description can be used by observers to describe the metric to users. Description string - // Keys is the set of tags that collectively describe rows of the metric. - Keys []core.Key + // Keys is the set of labels that collectively describe rows of the metric. + Keys []label.Key // Buckets holds the inclusive upper bound of each bucket in the histogram. Buckets []int64 } @@ -34,8 +37,8 @@ type HistogramFloat64 struct { Name string // Description can be used by observers to describe the metric to users. Description string - // Keys is the set of tags that collectively describe rows of the metric. - Keys []core.Key + // Keys is the set of labels that collectively describe rows of the metric. + Keys []label.Key // Buckets holds the inclusive upper bound of each bucket in the histogram. Buckets []float64 } @@ -43,7 +46,7 @@ type HistogramFloat64 struct { // Count creates a new metric based on the Scalar information that counts // the number of times the supplied int64 measure is set. // Metrics of this type will use Int64Data. -func (info Scalar) Count(e *Config, key core.Key) { +func (info Scalar) Count(e *Config, key label.Key) { data := &Int64Data{Info: &info, key: nil} e.subscribe(key, data.count) } diff --git a/internal/event/export/ocagent/metrics.go b/internal/event/export/ocagent/metrics.go index 3250c4f948..78d65994db 100644 --- a/internal/event/export/ocagent/metrics.go +++ b/internal/event/export/ocagent/metrics.go @@ -7,9 +7,9 @@ package ocagent import ( "time" - "golang.org/x/tools/internal/event/core" "golang.org/x/tools/internal/event/export/metric" "golang.org/x/tools/internal/event/export/ocagent/wire" + "golang.org/x/tools/internal/event/label" ) // dataToMetricDescriptor return a *wire.MetricDescriptor based on data. @@ -201,7 +201,7 @@ func distributionToPoints(counts []int64, count int64, sum float64, bucketBounds // infoKeysToLabelKeys returns an array of *wire.LabelKeys containing the // string values of the elements of labelKeys. -func infoKeysToLabelKeys(infoKeys []core.Key) []*wire.LabelKey { +func infoKeysToLabelKeys(infoKeys []label.Key) []*wire.LabelKey { labelKeys := make([]*wire.LabelKey, 0, len(infoKeys)) for _, key := range infoKeys { labelKeys = append(labelKeys, &wire.LabelKey{ diff --git a/internal/event/export/ocagent/ocagent.go b/internal/event/export/ocagent/ocagent.go index 0f1059260c..fabb7c1abe 100644 --- a/internal/event/export/ocagent/ocagent.go +++ b/internal/event/export/ocagent/ocagent.go @@ -22,6 +22,7 @@ import ( "golang.org/x/tools/internal/event/export" "golang.org/x/tools/internal/event/export/metric" "golang.org/x/tools/internal/event/export/ocagent/wire" + "golang.org/x/tools/internal/event/label" ) type Config struct { @@ -85,7 +86,7 @@ func Connect(config *Config) *Exporter { return exporter } -func (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { +func (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context { switch { case ev.IsEndSpan(): e.mu.Lock() @@ -97,7 +98,7 @@ func (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, tagMap core. case ev.IsRecord(): e.mu.Lock() defer e.mu.Unlock() - data := metric.Entries.Get(tagMap).([]metric.Data) + data := metric.Entries.Get(lm).([]metric.Data) e.metrics = append(e.metrics, data...) } return ctx @@ -200,7 +201,7 @@ func convertSpan(span *export.Span) *wire.Span { Kind: wire.UnspecifiedSpanKind, StartTime: convertTimestamp(span.Start().At), EndTime: convertTimestamp(span.Finish().At), - Attributes: convertAttributes(core.Filter(span.Start(), core.Name)), + Attributes: convertAttributes(label.Filter(span.Start(), core.Name)), TimeEvents: convertEvents(span.Events()), SameProcessAsParentSpan: true, //TODO: StackTrace? @@ -227,68 +228,68 @@ func convertMetric(data metric.Data, start time.Time) *wire.Metric { } } -func skipToValidTag(l core.TagList) (int, core.Tag) { - // skip to the first valid tag - for index := 0; l.Valid(index); index++ { - if tag := l.Tag(index); tag.Valid() { - return index, tag +func skipToValidLabel(list label.List) (int, label.Label) { + // skip to the first valid label + for index := 0; list.Valid(index); index++ { + if l := list.Label(index); l.Valid() { + return index, l } } - return -1, core.Tag{} + return -1, label.Label{} } -func convertAttributes(l core.TagList) *wire.Attributes { - index, tag := skipToValidTag(l) - if !tag.Valid() { +func convertAttributes(list label.List) *wire.Attributes { + index, l := skipToValidLabel(list) + if !l.Valid() { return nil } attributes := make(map[string]wire.Attribute) for { - if tag.Valid() { - attributes[tag.Key().Name()] = convertAttribute(tag) + if l.Valid() { + attributes[l.Key().Name()] = convertAttribute(l) } index++ - if !l.Valid(index) { + if !list.Valid(index) { return &wire.Attributes{AttributeMap: attributes} } - tag = l.Tag(index) + l = list.Label(index) } } -func convertAttribute(tag core.Tag) wire.Attribute { - switch key := tag.Key().(type) { +func convertAttribute(l label.Label) wire.Attribute { + switch key := l.Key().(type) { case *core.IntKey: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.Int8Key: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.Int16Key: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.Int32Key: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.Int64Key: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.UIntKey: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.UInt8Key: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.UInt16Key: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.UInt32Key: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.UInt64Key: - return wire.IntAttribute{IntValue: int64(key.From(tag))} + return wire.IntAttribute{IntValue: int64(key.From(l))} case *core.Float32Key: - return wire.DoubleAttribute{DoubleValue: float64(key.From(tag))} + return wire.DoubleAttribute{DoubleValue: float64(key.From(l))} case *core.Float64Key: - return wire.DoubleAttribute{DoubleValue: key.From(tag)} + return wire.DoubleAttribute{DoubleValue: key.From(l)} case *core.BooleanKey: - return wire.BoolAttribute{BoolValue: key.From(tag)} + return wire.BoolAttribute{BoolValue: key.From(l)} case *core.StringKey: - return wire.StringAttribute{StringValue: toTruncatableString(key.From(tag))} + return wire.StringAttribute{StringValue: toTruncatableString(key.From(l))} case *core.ErrorKey: - return wire.StringAttribute{StringValue: toTruncatableString(key.From(tag).Error())} + return wire.StringAttribute{StringValue: toTruncatableString(key.From(l).Error())} case *core.ValueKey: - return wire.StringAttribute{StringValue: toTruncatableString(fmt.Sprint(key.From(tag)))} + return wire.StringAttribute{StringValue: toTruncatableString(fmt.Sprint(key.From(l)))} default: return wire.StringAttribute{StringValue: toTruncatableString(fmt.Sprintf("%T", key))} } @@ -311,21 +312,21 @@ func convertEvent(ev core.Event) wire.TimeEvent { } func convertAnnotation(ev core.Event) *wire.Annotation { - if _, tag := skipToValidTag(ev); !tag.Valid() { + if _, l := skipToValidLabel(ev); !l.Valid() { return nil } - tagMap := core.TagMap(ev) - description := core.Msg.Get(tagMap) - tags := core.Filter(ev, core.Msg) + lm := label.Map(ev) + description := core.Msg.Get(lm) + labels := label.Filter(ev, core.Msg) if description == "" { - err := core.Err.Get(tagMap) - tags = core.Filter(tags, core.Err) + err := core.Err.Get(lm) + labels = label.Filter(labels, core.Err) if err != nil { description = err.Error() } } return &wire.Annotation{ Description: toTruncatableString(description), - Attributes: convertAttributes(tags), + Attributes: convertAttributes(labels), } } diff --git a/internal/event/export/ocagent/ocagent_test.go b/internal/event/export/ocagent/ocagent_test.go index c1f2f959ff..a4cdafed17 100644 --- a/internal/event/export/ocagent/ocagent_test.go +++ b/internal/event/export/ocagent/ocagent_test.go @@ -20,6 +20,7 @@ import ( "golang.org/x/tools/internal/event/export" "golang.org/x/tools/internal/event/export/metric" "golang.org/x/tools/internal/event/export/ocagent" + "golang.org/x/tools/internal/event/label" ) const testNodeStr = `{ @@ -72,21 +73,21 @@ var ( metricLatency = metric.HistogramFloat64{ Name: "latency_ms", Description: "The latency of calls in milliseconds", - Keys: []core.Key{keyMethod, keyRoute}, + Keys: []label.Key{keyMethod, keyRoute}, Buckets: []float64{0, 5, 10, 25, 50}, } metricBytesIn = metric.HistogramInt64{ Name: "latency_ms", Description: "The latency of calls in milliseconds", - Keys: []core.Key{keyMethod, keyRoute}, + Keys: []label.Key{keyMethod, keyRoute}, Buckets: []int64{0, 10, 50, 100, 500, 1000, 2000}, } metricRecursiveCalls = metric.Scalar{ Name: "latency_ms", Description: "The latency of calls in milliseconds", - Keys: []core.Key{keyMethod, keyRoute}, + Keys: []label.Key{keyMethod, keyRoute}, } ) @@ -125,7 +126,7 @@ func timeFixer(output event.Exporter) event.Exporter { start, _ := time.Parse(time.RFC3339Nano, "1970-01-01T00:00:30Z") at, _ := time.Parse(time.RFC3339Nano, "1970-01-01T00:00:40Z") end, _ := time.Parse(time.RFC3339Nano, "1970-01-01T00:00:50Z") - return func(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { + return func(ctx context.Context, ev core.Event, lm label.Map) context.Context { switch { case ev.IsStartSpan(): ev.At = start @@ -134,17 +135,17 @@ func timeFixer(output event.Exporter) event.Exporter { default: ev.At = at } - return output(ctx, ev, tagMap) + return output(ctx, ev, lm) } } func spanFixer(output event.Exporter) event.Exporter { - return func(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { + return func(ctx context.Context, ev core.Event, lm label.Map) context.Context { if ev.IsStartSpan() { span := export.GetSpan(ctx) span.ID = export.SpanContext{} } - return output(ctx, ev, tagMap) + return output(ctx, ev, lm) } } diff --git a/internal/event/export/ocagent/trace_test.go b/internal/event/export/ocagent/trace_test.go index 0f04bee4d4..f8e9781bef 100644 --- a/internal/event/export/ocagent/trace_test.go +++ b/internal/event/export/ocagent/trace_test.go @@ -11,6 +11,7 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" ) func TestTrace(t *testing.T) { @@ -37,9 +38,9 @@ func TestTrace(t *testing.T) { want string }{ { - name: "no tags", + name: "no labels", run: func(ctx context.Context) { - core.Export(ctx, core.MakeEvent(core.LogType, [3]core.Tag{}, nil)) + core.Export(ctx, core.MakeEvent(core.LogType, [3]label.Label{}, nil)) }, want: prefix + ` "timeEvent":[{"time":"1970-01-01T00:00:40Z"}] diff --git a/internal/event/export/ocagent/wire/common.go b/internal/event/export/ocagent/wire/common.go index 61dbfcd9e7..f22b535654 100644 --- a/internal/event/export/ocagent/wire/common.go +++ b/internal/event/export/ocagent/wire/common.go @@ -45,13 +45,13 @@ type DoubleAttribute struct { } type Attribute interface { - tagAttribute() + labelAttribute() } -func (StringAttribute) tagAttribute() {} -func (IntAttribute) tagAttribute() {} -func (BoolAttribute) tagAttribute() {} -func (DoubleAttribute) tagAttribute() {} +func (StringAttribute) labelAttribute() {} +func (IntAttribute) labelAttribute() {} +func (BoolAttribute) labelAttribute() {} +func (DoubleAttribute) labelAttribute() {} type StackTrace struct { StackFrames *StackFrames `json:"stack_frames,omitempty"` diff --git a/internal/event/export/ocagent/wire/metrics.go b/internal/event/export/ocagent/wire/metrics.go index 1c5cf41eda..4cfdb88bf4 100644 --- a/internal/event/export/ocagent/wire/metrics.go +++ b/internal/event/export/ocagent/wire/metrics.go @@ -122,13 +122,13 @@ type PointSummaryValue struct { } type PointValue interface { - tagPointValue() + labelPointValue() } -func (PointInt64Value) tagPointValue() {} -func (PointDoubleValue) tagPointValue() {} -func (PointDistributionValue) tagPointValue() {} -func (PointSummaryValue) tagPointValue() {} +func (PointInt64Value) labelPointValue() {} +func (PointDoubleValue) labelPointValue() {} +func (PointDistributionValue) labelPointValue() {} +func (PointSummaryValue) labelPointValue() {} type DistributionValue struct { Count int64 `json:"count,omitempty"` @@ -143,10 +143,10 @@ type BucketOptionsExplicit struct { } type BucketOptions interface { - tagBucketOptions() + labelBucketOptions() } -func (*BucketOptionsExplicit) tagBucketOptions() {} +func (*BucketOptionsExplicit) labelBucketOptions() {} var _ BucketOptions = (*BucketOptionsExplicit)(nil) var _ json.Marshaler = (*BucketOptionsExplicit)(nil) diff --git a/internal/event/export/ocagent/wire/trace.go b/internal/event/export/ocagent/wire/trace.go index c1a79a58bb..88856673a1 100644 --- a/internal/event/export/ocagent/wire/trace.go +++ b/internal/event/export/ocagent/wire/trace.go @@ -79,11 +79,11 @@ const ( ) type TimeEventValue interface { - tagTimeEventValue() + labelTimeEventValue() } -func (Annotation) tagTimeEventValue() {} -func (MessageEvent) tagTimeEventValue() {} +func (Annotation) labelTimeEventValue() {} +func (MessageEvent) labelTimeEventValue() {} type Links struct { Link []*Link `json:"link,omitempty"` diff --git a/internal/event/export/prometheus/prometheus.go b/internal/event/export/prometheus/prometheus.go index 129f260767..c8272c71dc 100644 --- a/internal/event/export/prometheus/prometheus.go +++ b/internal/event/export/prometheus/prometheus.go @@ -14,6 +14,7 @@ import ( "golang.org/x/tools/internal/event/core" "golang.org/x/tools/internal/event/export/metric" + "golang.org/x/tools/internal/event/label" ) func New() *Exporter { @@ -25,13 +26,13 @@ type Exporter struct { metrics []metric.Data } -func (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { +func (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, ln label.Map) context.Context { if !ev.IsRecord() { return ctx } e.mu.Lock() defer e.mu.Unlock() - metrics := metric.Entries.Get(tagMap).([]metric.Data) + metrics := metric.Entries.Get(ln).([]metric.Data) for _, data := range metrics { name := data.Handle() // We keep the metrics in name sorted order so the page is stable and easy @@ -64,7 +65,7 @@ func (e *Exporter) header(w http.ResponseWriter, name, description string, isGau fmt.Fprintf(w, "# TYPE %s %s\n", name, kind) } -func (e *Exporter) row(w http.ResponseWriter, name string, group []core.Tag, extra string, value interface{}) { +func (e *Exporter) row(w http.ResponseWriter, name string, group []label.Label, extra string, value interface{}) { fmt.Fprint(w, name) buf := &bytes.Buffer{} fmt.Fprint(buf, group) diff --git a/internal/event/export/tag.go b/internal/event/export/tag.go index bc2ecb4b8f..09a201ac17 100644 --- a/internal/event/export/tag.go +++ b/internal/event/export/tag.go @@ -9,28 +9,29 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" ) // Labels builds an exporter that manipulates the context using the event. -// If the event is type IsTag or IsStartSpan then it returns a context updated -// with tag values from the event. -// For all other event types the event tags will be updated with values from the +// If the event is type IsLabel or IsStartSpan then it returns a context updated +// with label values from the event. +// For all other event types the event labels will be updated with values from the // context if they are missing. func Labels(output event.Exporter) event.Exporter { - return func(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { - stored, _ := ctx.Value(labelContextKey).(core.TagMap) + return func(ctx context.Context, ev core.Event, lm label.Map) context.Context { + stored, _ := ctx.Value(labelContextKey).(label.Map) if ev.IsLabel() || ev.IsStartSpan() { - // update the tag source stored in the context - fromEvent := core.TagMap(ev) + // update the label map stored in the context + fromEvent := label.Map(ev) if stored == nil { stored = fromEvent } else { - stored = core.MergeTagMaps(fromEvent, stored) + stored = label.MergeMaps(fromEvent, stored) } ctx = context.WithValue(ctx, labelContextKey, stored) } - // add the stored tag context to the tag source - tagMap = core.MergeTagMaps(tagMap, stored) - return output(ctx, ev, tagMap) + // add the stored label context to the label map + lm = label.MergeMaps(lm, stored) + return output(ctx, ev, lm) } } diff --git a/internal/event/export/trace.go b/internal/event/export/trace.go index 528fdad82d..aa2b4a6221 100644 --- a/internal/event/export/trace.go +++ b/internal/event/export/trace.go @@ -11,6 +11,7 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" ) type SpanContext struct { @@ -45,11 +46,11 @@ func GetSpan(ctx context.Context) *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. +// It creates new spans on start events, adds events to the current span on +// log or label, and closes the span on end events. // The span structure can then be used by other exporters. func Spans(output event.Exporter) event.Exporter { - return func(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { + return func(ctx context.Context, ev core.Event, lm label.Map) context.Context { switch { case ev.IsLog(), ev.IsLabel(): if span := GetSpan(ctx); span != nil { @@ -59,7 +60,7 @@ func Spans(output event.Exporter) event.Exporter { } case ev.IsStartSpan(): span := &Span{ - Name: core.Name.Get(tagMap), + Name: core.Name.Get(lm), start: ev, } if parent := GetSpan(ctx); parent != nil { @@ -79,7 +80,7 @@ func Spans(output event.Exporter) event.Exporter { case ev.IsDetach(): ctx = context.WithValue(ctx, spanContextKey, nil) } - return output(ctx, ev, tagMap) + return output(ctx, ev, lm) } } diff --git a/internal/event/label/label.go b/internal/event/label/label.go new file mode 100644 index 0000000000..b55c12eb25 --- /dev/null +++ b/internal/event/label/label.go @@ -0,0 +1,213 @@ +// 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 label + +import ( + "fmt" + "io" + "reflect" + "unsafe" +) + +// Key is used as the identity of a Label. +// Keys are intended to be compared by pointer only, the name should be unique +// for communicating with external systems, but it is not required or enforced. +type Key interface { + // Name returns the key name. + Name() string + // Description returns a string that can be used to describe the value. + Description() string + + // Format is used in formatting to append the value of the label to the + // supplied buffer. + // The formatter may use the supplied buf as a scratch area to avoid + // allocations. + Format(w io.Writer, buf []byte, l Label) +} + +// Label holds a key and value pair. +// It is normally used when passing around lists of labels. +type Label struct { + key Key + packed uint64 + untyped interface{} +} + +// Map is the interface to a collection of Labels indexed by key. +type Map interface { + // Find returns the label that matches the supplied key. + Find(key Key) Label +} + +// List is the interface to something that provides an iterable +// list of labels. +// Iteration should start from 0 and continue until Valid returns false. +type List interface { + // Valid returns true if the index is within range for the list. + // It does not imply the label at that index will itself be valid. + Valid(index int) bool + // Label returns the label at the given index. + Label(index int) Label +} + +// list implements LabelList for a list of Labels. +type list struct { + labels []Label +} + +// filter wraps a LabelList filtering out specific labels. +type filter struct { + keys []Key + underlying List +} + +// listMap implements LabelMap for a simple list of labels. +type listMap struct { + labels []Label +} + +// mapChain implements LabelMap for a list of underlying LabelMap. +type mapChain struct { + maps []Map +} + +// OfValue creates a new label from the key and value. +// This method is for implementing new key types, label creation should +// normally be done with the Of method of the key. +func OfValue(k Key, value interface{}) Label { return Label{key: k, untyped: value} } + +// UnpackValue assumes the label was built using LabelOfValue and returns the value +// that was passed to that constructor. +// This method is for implementing new key types, for type safety normal +// access should be done with the From method of the key. +func (t Label) UnpackValue() interface{} { return t.untyped } + +// Of64 creates a new label from a key and a uint64. This is often +// used for non uint64 values that can be packed into a uint64. +// This method is for implementing new key types, label creation should +// normally be done with the Of method of the key. +func Of64(k Key, v uint64) Label { return Label{key: k, packed: v} } + +// Unpack64 assumes the label was built using LabelOf64 and returns the value that +// was passed to that constructor. +// This method is for implementing new key types, for type safety normal +// access should be done with the From method of the key. +func (t Label) Unpack64() uint64 { return t.packed } + +// OfString creates a new label from a key and a string. +// This method is for implementing new key types, label creation should +// normally be done with the Of method of the key. +func OfString(k Key, v string) Label { + hdr := (*reflect.StringHeader)(unsafe.Pointer(&v)) + return Label{ + key: k, + packed: uint64(hdr.Len), + untyped: unsafe.Pointer(hdr.Data), + } +} + +// UnpackString assumes the label was built using LabelOfString and returns the +// value that was passed to that constructor. +// This method is for implementing new key types, for type safety normal +// access should be done with the From method of the key. +func (t Label) UnpackString() string { + var v string + hdr := (*reflect.StringHeader)(unsafe.Pointer(&v)) + hdr.Data = uintptr(t.untyped.(unsafe.Pointer)) + hdr.Len = int(t.packed) + return *(*string)(unsafe.Pointer(hdr)) +} + +// Valid returns true if the Label is a valid one (it has a key). +func (t Label) Valid() bool { return t.key != nil } + +// Key returns the key of this Label. +func (t Label) Key() Key { return t.key } + +// Format is used for debug printing of labels. +func (t Label) Format(f fmt.State, r rune) { + if !t.Valid() { + io.WriteString(f, `nil`) + return + } + io.WriteString(f, t.Key().Name()) + io.WriteString(f, "=") + var buf [128]byte + t.Key().Format(f, buf[:0], t) +} + +func (l *list) Valid(index int) bool { + return index >= 0 && index < len(l.labels) +} + +func (l *list) Label(index int) Label { + return l.labels[index] +} + +func (f *filter) Valid(index int) bool { + return f.underlying.Valid(index) +} + +func (f *filter) Label(index int) Label { + l := f.underlying.Label(index) + for _, f := range f.keys { + if l.Key() == f { + return Label{} + } + } + return l +} + +func (lm listMap) Find(key Key) Label { + for _, l := range lm.labels { + if l.Key() == key { + return l + } + } + return Label{} +} + +func (c mapChain) Find(key Key) Label { + for _, src := range c.maps { + l := src.Find(key) + if l.Valid() { + return l + } + } + return Label{} +} + +var emptyList = &list{} + +func NewList(labels ...Label) List { + if len(labels) == 0 { + return emptyList + } + return &list{labels: labels} +} + +func Filter(l List, keys ...Key) List { + if len(keys) == 0 { + return l + } + return &filter{keys: keys, underlying: l} +} + +func NewMap(labels ...Label) Map { + return listMap{labels: labels} +} + +func MergeMaps(srcs ...Map) Map { + var nonNil []Map + for _, src := range srcs { + if src != nil { + nonNil = append(nonNil, src) + } + } + if len(nonNil) == 1 { + return nonNil[0] + } + return mapChain{maps: nonNil} +} diff --git a/internal/event/core/tag_test.go b/internal/event/label/label_test.go similarity index 54% rename from internal/event/core/tag_test.go rename to internal/event/label/label_test.go index c03b146b53..92b68dc873 100644 --- a/internal/event/core/tag_test.go +++ b/internal/event/label/label_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package core_test +package label_test import ( "bytes" @@ -10,6 +10,7 @@ import ( "testing" "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" ) var ( @@ -19,59 +20,59 @@ var ( A = AKey.Of("a") B = BKey.Of("b") C = CKey.Of("c") - all = []core.Tag{A, B, C} + all = []label.Label{A, B, C} ) -func TestTagList(t *testing.T) { +func TestList(t *testing.T) { for _, test := range []struct { name string - tags []core.Tag + labels []label.Label expect string }{{ name: "empty", }, { name: "single", - tags: []core.Tag{A}, + labels: []label.Label{A}, expect: `A="a"`, }, { name: "invalid", - tags: []core.Tag{{}}, + labels: []label.Label{{}}, expect: ``, }, { name: "two", - tags: []core.Tag{A, B}, + labels: []label.Label{A, B}, expect: `A="a", B="b"`, }, { name: "three", - tags: []core.Tag{A, B, C}, + labels: []label.Label{A, B, C}, expect: `A="a", B="b", C="c"`, }, { name: "missing A", - tags: []core.Tag{{}, B, C}, + labels: []label.Label{{}, B, C}, expect: `B="b", C="c"`, }, { name: "missing B", - tags: []core.Tag{A, {}, C}, + labels: []label.Label{A, {}, C}, expect: `A="a", C="c"`, }, { name: "missing C", - tags: []core.Tag{A, B, {}}, + labels: []label.Label{A, B, {}}, expect: `A="a", B="b"`, }, { name: "missing AB", - tags: []core.Tag{{}, {}, C}, + labels: []label.Label{{}, {}, C}, expect: `C="c"`, }, { name: "missing AC", - tags: []core.Tag{{}, B, {}}, + labels: []label.Label{{}, B, {}}, expect: `B="b"`, }, { name: "missing BC", - tags: []core.Tag{A, {}, {}}, + labels: []label.Label{A, {}, {}}, expect: `A="a"`, }} { t.Run(test.name, func(t *testing.T) { - got := printList(core.NewTagList(test.tags...)) + got := printList(label.NewList(test.labels...)) if got != test.expect { t.Errorf("got %q want %q", got, test.expect) } @@ -79,44 +80,44 @@ func TestTagList(t *testing.T) { } } -func TestTagFilter(t *testing.T) { +func TestFilter(t *testing.T) { for _, test := range []struct { name string - tags []core.Tag - filters []core.Key + labels []label.Label + filters []label.Key expect string }{{ name: "no filters", - tags: all, + labels: all, expect: `A="a", B="b", C="c"`, }, { - name: "no tags", - filters: []core.Key{AKey}, + name: "no labels", + filters: []label.Key{AKey}, expect: ``, }, { name: "filter A", - tags: all, - filters: []core.Key{AKey}, + labels: all, + filters: []label.Key{AKey}, expect: `B="b", C="c"`, }, { name: "filter B", - tags: all, - filters: []core.Key{BKey}, + labels: all, + filters: []label.Key{BKey}, expect: `A="a", C="c"`, }, { name: "filter C", - tags: all, - filters: []core.Key{CKey}, + labels: all, + filters: []label.Key{CKey}, expect: `A="a", B="b"`, }, { name: "filter AC", - tags: all, - filters: []core.Key{AKey, CKey}, + labels: all, + filters: []label.Key{AKey, CKey}, expect: `B="b"`, }} { t.Run(test.name, func(t *testing.T) { - tags := core.NewTagList(test.tags...) - got := printList(core.Filter(tags, test.filters...)) + labels := label.NewList(test.labels...) + got := printList(label.Filter(labels, test.filters...)) if got != test.expect { t.Errorf("got %q want %q", got, test.expect) } @@ -124,55 +125,55 @@ func TestTagFilter(t *testing.T) { } } -func TestTagMap(t *testing.T) { +func TestMap(t *testing.T) { for _, test := range []struct { name string - tags []core.Tag - keys []core.Key + labels []label.Label + keys []label.Key expect string }{{ - name: "no tags", - keys: []core.Key{AKey}, + name: "no labels", + keys: []label.Key{AKey}, expect: `nil`, }, { name: "match A", - tags: all, - keys: []core.Key{AKey}, + labels: all, + keys: []label.Key{AKey}, expect: `A="a"`, }, { name: "match B", - tags: all, - keys: []core.Key{BKey}, + labels: all, + keys: []label.Key{BKey}, expect: `B="b"`, }, { name: "match C", - tags: all, - keys: []core.Key{CKey}, + labels: all, + keys: []label.Key{CKey}, expect: `C="c"`, }, { name: "match ABC", - tags: all, - keys: []core.Key{AKey, BKey, CKey}, + labels: all, + keys: []label.Key{AKey, BKey, CKey}, expect: `A="a", B="b", C="c"`, }, { name: "missing A", - tags: []core.Tag{{}, B, C}, - keys: []core.Key{AKey, BKey, CKey}, + labels: []label.Label{{}, B, C}, + keys: []label.Key{AKey, BKey, CKey}, expect: `nil, B="b", C="c"`, }, { name: "missing B", - tags: []core.Tag{A, {}, C}, - keys: []core.Key{AKey, BKey, CKey}, + labels: []label.Label{A, {}, C}, + keys: []label.Key{AKey, BKey, CKey}, expect: `A="a", nil, C="c"`, }, { name: "missing C", - tags: []core.Tag{A, B, {}}, - keys: []core.Key{AKey, BKey, CKey}, + labels: []label.Label{A, B, {}}, + keys: []label.Key{AKey, BKey, CKey}, expect: `A="a", B="b", nil`, }} { t.Run(test.name, func(t *testing.T) { - tagMap := core.NewTagMap(test.tags...) - got := printTagMap(tagMap, test.keys) + lm := label.NewMap(test.labels...) + got := printMap(lm, test.keys) if got != test.expect { t.Errorf("got %q want %q", got, test.expect) } @@ -180,60 +181,60 @@ func TestTagMap(t *testing.T) { } } -func TestTagMapMerge(t *testing.T) { +func TestMapMerge(t *testing.T) { for _, test := range []struct { name string - maps []core.TagMap - keys []core.Key + maps []label.Map + keys []label.Key expect string }{{ name: "no maps", - keys: []core.Key{AKey}, + keys: []label.Key{AKey}, expect: `nil`, }, { name: "one map", - maps: []core.TagMap{core.NewTagMap(all...)}, - keys: []core.Key{AKey}, + maps: []label.Map{label.NewMap(all...)}, + keys: []label.Key{AKey}, expect: `A="a"`, }, { name: "invalid map", - maps: []core.TagMap{core.NewTagMap()}, - keys: []core.Key{AKey}, + maps: []label.Map{label.NewMap()}, + keys: []label.Key{AKey}, expect: `nil`, }, { name: "two maps", - maps: []core.TagMap{core.NewTagMap(B, C), core.NewTagMap(A)}, - keys: []core.Key{AKey, BKey, CKey}, + maps: []label.Map{label.NewMap(B, C), label.NewMap(A)}, + keys: []label.Key{AKey, BKey, CKey}, expect: `A="a", B="b", C="c"`, }, { name: "invalid start map", - maps: []core.TagMap{core.NewTagMap(), core.NewTagMap(B, C)}, - keys: []core.Key{AKey, BKey, CKey}, + maps: []label.Map{label.NewMap(), label.NewMap(B, C)}, + keys: []label.Key{AKey, BKey, CKey}, expect: `nil, B="b", C="c"`, }, { name: "invalid mid map", - maps: []core.TagMap{core.NewTagMap(A), core.NewTagMap(), core.NewTagMap(C)}, - keys: []core.Key{AKey, BKey, CKey}, + maps: []label.Map{label.NewMap(A), label.NewMap(), label.NewMap(C)}, + keys: []label.Key{AKey, BKey, CKey}, expect: `A="a", nil, C="c"`, }, { name: "invalid end map", - maps: []core.TagMap{core.NewTagMap(A, B), core.NewTagMap()}, - keys: []core.Key{AKey, BKey, CKey}, + maps: []label.Map{label.NewMap(A, B), label.NewMap()}, + keys: []label.Key{AKey, BKey, CKey}, expect: `A="a", B="b", nil`, }, { name: "three maps one nil", - maps: []core.TagMap{core.NewTagMap(A), core.NewTagMap(B), nil}, - keys: []core.Key{AKey, BKey, CKey}, + maps: []label.Map{label.NewMap(A), label.NewMap(B), nil}, + keys: []label.Key{AKey, BKey, CKey}, expect: `A="a", B="b", nil`, }, { name: "two maps one nil", - maps: []core.TagMap{core.NewTagMap(A, B), nil}, - keys: []core.Key{AKey, BKey, CKey}, + maps: []label.Map{label.NewMap(A, B), nil}, + keys: []label.Key{AKey, BKey, CKey}, expect: `A="a", B="b", nil`, }} { t.Run(test.name, func(t *testing.T) { - tagMap := core.MergeTagMaps(test.maps...) - got := printTagMap(tagMap, test.keys) + tagMap := label.MergeMaps(test.maps...) + got := printMap(tagMap, test.keys) if got != test.expect { t.Errorf("got %q want %q", got, test.expect) } @@ -241,28 +242,28 @@ func TestTagMapMerge(t *testing.T) { } } -func printList(l core.TagList) string { +func printList(list label.List) string { buf := &bytes.Buffer{} - for index := 0; l.Valid(index); index++ { - tag := l.Tag(index) - if !tag.Valid() { + for index := 0; list.Valid(index); index++ { + l := list.Label(index) + if !l.Valid() { continue } if buf.Len() > 0 { buf.WriteString(", ") } - fmt.Fprint(buf, tag) + fmt.Fprint(buf, l) } return buf.String() } -func printTagMap(tagMap core.TagMap, keys []core.Key) string { +func printMap(lm label.Map, keys []label.Key) string { buf := &bytes.Buffer{} for _, key := range keys { if buf.Len() > 0 { buf.WriteString(", ") } - fmt.Fprint(buf, tagMap.Find(key)) + fmt.Fprint(buf, lm.Find(key)) } return buf.String() } diff --git a/internal/jsonrpc2/jsonrpc2.go b/internal/jsonrpc2/jsonrpc2.go index 43cfccdb48..88a1f4910a 100644 --- a/internal/jsonrpc2/jsonrpc2.go +++ b/internal/jsonrpc2/jsonrpc2.go @@ -15,7 +15,7 @@ import ( "sync/atomic" "golang.org/x/tools/internal/event" - "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" "golang.org/x/tools/internal/lsp/debug/tag" ) @@ -173,17 +173,17 @@ func (c *Conn) Run(runCtx context.Context, handler Handler) error { } switch msg := msg.(type) { case Request: - tags := []core.Tag{ + labels := []label.Label{ tag.Method.Of(msg.Method()), tag.RPCDirection.Of(tag.Inbound), {}, // reserved for ID if present } if call, ok := msg.(*Call); ok { - tags[len(tags)-1] = tag.RPCID.Of(fmt.Sprintf("%q", call.ID())) + labels[len(labels)-1] = tag.RPCID.Of(fmt.Sprintf("%q", call.ID())) } else { - tags = tags[:len(tags)-1] + labels = labels[:len(labels)-1] } - reqCtx, spanDone := event.Start(runCtx, msg.Method(), tags...) + reqCtx, spanDone := event.Start(runCtx, msg.Method(), labels...) event.Metric(reqCtx, tag.Started.Of(1), tag.ReceivedBytes.Of(n)) diff --git a/internal/lsp/debug/metrics.go b/internal/lsp/debug/metrics.go index 94b582ead0..8efc1d495e 100644 --- a/internal/lsp/debug/metrics.go +++ b/internal/lsp/debug/metrics.go @@ -5,8 +5,8 @@ package debug import ( - "golang.org/x/tools/internal/event/core" "golang.org/x/tools/internal/event/export/metric" + "golang.org/x/tools/internal/event/label" "golang.org/x/tools/internal/lsp/debug/tag" ) @@ -18,34 +18,34 @@ var ( receivedBytes = metric.HistogramInt64{ Name: "received_bytes", Description: "Distribution of received bytes, by method.", - Keys: []core.Key{tag.RPCDirection, tag.Method}, + Keys: []label.Key{tag.RPCDirection, tag.Method}, Buckets: bytesDistribution, } sentBytes = metric.HistogramInt64{ Name: "sent_bytes", Description: "Distribution of sent bytes, by method.", - Keys: []core.Key{tag.RPCDirection, tag.Method}, + Keys: []label.Key{tag.RPCDirection, tag.Method}, Buckets: bytesDistribution, } latency = metric.HistogramFloat64{ Name: "latency", Description: "Distribution of latency in milliseconds, by method.", - Keys: []core.Key{tag.RPCDirection, tag.Method}, + Keys: []label.Key{tag.RPCDirection, tag.Method}, Buckets: millisecondsDistribution, } started = metric.Scalar{ Name: "started", Description: "Count of RPCs started by method.", - Keys: []core.Key{tag.RPCDirection, tag.Method}, + Keys: []label.Key{tag.RPCDirection, tag.Method}, } completed = metric.Scalar{ Name: "completed", Description: "Count of RPCs completed by method and status.", - Keys: []core.Key{tag.RPCDirection, tag.Method, tag.StatusCode}, + Keys: []label.Key{tag.RPCDirection, tag.Method, tag.StatusCode}, } ) diff --git a/internal/lsp/debug/rpc.go b/internal/lsp/debug/rpc.go index 4bbca75dde..de90a6cf32 100644 --- a/internal/lsp/debug/rpc.go +++ b/internal/lsp/debug/rpc.go @@ -15,6 +15,7 @@ import ( "golang.org/x/tools/internal/event/core" "golang.org/x/tools/internal/event/export" + "golang.org/x/tools/internal/event/label" "golang.org/x/tools/internal/lsp/debug/tag" ) @@ -77,7 +78,7 @@ type rpcCodeBucket struct { Count int64 } -func (r *rpcs) ProcessEvent(ctx context.Context, ev core.Event, tagMap core.TagMap) context.Context { +func (r *rpcs) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context { r.mu.Lock() defer r.mu.Unlock() switch { @@ -91,8 +92,8 @@ func (r *rpcs) ProcessEvent(ctx context.Context, ev core.Event, tagMap core.TagM endRPC(ctx, ev, span, stats) } case ev.IsRecord(): - sent := byteUnits(tag.SentBytes.Get(tagMap)) - rec := byteUnits(tag.ReceivedBytes.Get(tagMap)) + sent := byteUnits(tag.SentBytes.Get(lm)) + rec := byteUnits(tag.ReceivedBytes.Get(lm)) if sent != 0 || rec != 0 { if _, stats := r.getRPCSpan(ctx, ev); stats != nil { stats.Sent += sent @@ -161,13 +162,13 @@ func (r *rpcs) getRPCSpan(ctx context.Context, ev core.Event) (*export.Span, *rp return span, r.getRPCStats(span.Start()) } -func (r *rpcs) getRPCStats(tagMap core.TagMap) *rpcStats { - method := tag.Method.Get(tagMap) +func (r *rpcs) getRPCStats(lm label.Map) *rpcStats { + method := tag.Method.Get(lm) if method == "" { return nil } set := &r.Inbound - if tag.RPCDirection.Get(tagMap) != tag.Inbound { + if tag.RPCDirection.Get(lm) != tag.Inbound { set = &r.Outbound } // get the record for this method diff --git a/internal/lsp/debug/serve.go b/internal/lsp/debug/serve.go index 3cdc914ce0..85aeca6ed6 100644 --- a/internal/lsp/debug/serve.go +++ b/internal/lsp/debug/serve.go @@ -32,6 +32,7 @@ import ( "golang.org/x/tools/internal/event/export/metric" "golang.org/x/tools/internal/event/export/ocagent" "golang.org/x/tools/internal/event/export/prometheus" + "golang.org/x/tools/internal/event/label" "golang.org/x/tools/internal/lsp/debug/tag" "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/span" @@ -543,7 +544,7 @@ func (i *Instance) writeMemoryDebug(threshold uint64) error { } func makeGlobalExporter(stderr io.Writer) event.Exporter { - return func(ctx context.Context, ev core.Event, tags core.TagMap) context.Context { + return func(ctx context.Context, ev core.Event, lm label.Map) context.Context { i := GetInstance(ctx) if ev.IsLog() { @@ -556,27 +557,27 @@ func makeGlobalExporter(stderr io.Writer) event.Exporter { fmt.Fprintf(stderr, "%v\n", ev) } } - ctx = protocol.LogEvent(ctx, ev, tags) + ctx = protocol.LogEvent(ctx, ev, lm) if i == nil { return ctx } - return i.exporter(ctx, ev, tags) + return i.exporter(ctx, ev, lm) } } func makeInstanceExporter(i *Instance) event.Exporter { - exporter := func(ctx context.Context, ev core.Event, tags core.TagMap) context.Context { + exporter := func(ctx context.Context, ev core.Event, lm label.Map) context.Context { if i.ocagent != nil { - ctx = i.ocagent.ProcessEvent(ctx, ev, tags) + ctx = i.ocagent.ProcessEvent(ctx, ev, lm) } if i.prometheus != nil { - ctx = i.prometheus.ProcessEvent(ctx, ev, tags) + ctx = i.prometheus.ProcessEvent(ctx, ev, lm) } if i.rpcs != nil { - ctx = i.rpcs.ProcessEvent(ctx, ev, tags) + ctx = i.rpcs.ProcessEvent(ctx, ev, lm) } if i.traces != nil { - ctx = i.traces.ProcessEvent(ctx, ev, tags) + ctx = i.traces.ProcessEvent(ctx, ev, lm) } return ctx } diff --git a/internal/lsp/debug/tag/tag.go b/internal/lsp/debug/tag/tag.go index 4250a1c7b1..43883c5893 100644 --- a/internal/lsp/debug/tag/tag.go +++ b/internal/lsp/debug/tag/tag.go @@ -10,7 +10,7 @@ import ( ) var ( - // create the tag keys we use + // create the label keys we use Method = core.NewStringKey("method", "") StatusCode = core.NewStringKey("status.code", "") StatusMessage = core.NewStringKey("status.message", "") diff --git a/internal/lsp/debug/trace.go b/internal/lsp/debug/trace.go index 2ad2cda7df..8213df758d 100644 --- a/internal/lsp/debug/trace.go +++ b/internal/lsp/debug/trace.go @@ -17,6 +17,7 @@ import ( "golang.org/x/tools/internal/event/core" "golang.org/x/tools/internal/event/export" + "golang.org/x/tools/internal/event/label" ) var traceTmpl = template.Must(template.Must(baseTemplate.Clone()).Parse(` @@ -73,7 +74,7 @@ type traceEvent struct { Tags string } -func (t *traces) ProcessEvent(ctx context.Context, ev core.Event, tags core.TagMap) context.Context { +func (t *traces) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context { t.mu.Lock() defer t.mu.Unlock() span := export.GetSpan(ctx) @@ -94,7 +95,7 @@ func (t *traces) ProcessEvent(ctx context.Context, ev core.Event, tags core.TagM ParentID: span.ParentID, Name: span.Name, Start: span.Start().At, - Tags: renderTags(span.Start()), + Tags: renderLabels(span.Start()), } t.unfinished[span.ID] = td // and wire up parents if we have them @@ -124,7 +125,7 @@ func (t *traces) ProcessEvent(ctx context.Context, ev core.Event, tags core.TagM for i, event := range events { td.Events[i] = traceEvent{ Time: event.At, - Tags: renderTags(event), + Tags: renderLabels(event), } } @@ -170,11 +171,11 @@ func fillOffsets(td *traceData, start time.Time) { } } -func renderTags(tags core.TagList) string { +func renderLabels(labels label.List) string { buf := &bytes.Buffer{} - for index := 0; tags.Valid(index); index++ { - if tag := tags.Tag(index); tag.Valid() { - fmt.Fprintf(buf, "%v ", tag) + for index := 0; labels.Valid(index); index++ { + if l := labels.Label(index); l.Valid() { + fmt.Fprintf(buf, "%v ", l) } } return buf.String() diff --git a/internal/lsp/protocol/context.go b/internal/lsp/protocol/context.go index d526e2cf02..00b8fd81e2 100644 --- a/internal/lsp/protocol/context.go +++ b/internal/lsp/protocol/context.go @@ -5,6 +5,7 @@ import ( "fmt" "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/label" "golang.org/x/tools/internal/xcontext" ) @@ -18,7 +19,7 @@ func WithClient(ctx context.Context, client Client) context.Context { return context.WithValue(ctx, clientKey, client) } -func LogEvent(ctx context.Context, ev core.Event, tags core.TagMap) context.Context { +func LogEvent(ctx context.Context, ev core.Event, tags label.Map) context.Context { if !ev.IsLog() { return ctx } diff --git a/internal/lsp/source/types_format.go b/internal/lsp/source/types_format.go index a536ffd9fd..51c6b9f30c 100644 --- a/internal/lsp/source/types_format.go +++ b/internal/lsp/source/types_format.go @@ -14,9 +14,9 @@ import ( "go/types" "strings" + "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/lsp/debug/tag" "golang.org/x/tools/internal/lsp/protocol" - "golang.org/x/tools/internal/telemetry/event" ) // formatType returns the detail and kind for a types.Type.