diff --git a/internal/telemetry/event/event.go b/internal/telemetry/event/event.go index 6028fa6d2b..2b990c5c1e 100644 --- a/internal/telemetry/event/event.go +++ b/internal/telemetry/event/event.go @@ -72,7 +72,7 @@ func (ev Event) Format(f fmt.State, r rune) { tag := ev.Tag(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 !tag.Valid() || tag.Key() == Msg || tag.Key() == Err { continue } fmt.Fprintf(f, "\n\t%v", tag) @@ -90,14 +90,14 @@ func (ev Event) Tag(index int) Tag { return ev.dynamic[index-len(ev.static)] } -func (ev Event) Find(key interface{}) Tag { +func (ev Event) Find(key Key) Tag { for _, tag := range ev.static { - if tag.Key == key { + if tag.Key() == key { return tag } } for _, tag := range ev.dynamic { - if tag.Key == key { + if tag.Key() == key { return tag } } diff --git a/internal/telemetry/event/key.go b/internal/telemetry/event/key.go index 97572c37f1..503ec50dda 100644 --- a/internal/telemetry/event/key.go +++ b/internal/telemetry/event/key.go @@ -17,7 +17,9 @@ var ( Err = NewErrorKey("error", "an error that occurred") ) -// Key is the interface shared by all key implementations. +// 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 @@ -25,14 +27,6 @@ type Key interface { Description() string } -// 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 struct { - name string - description string -} - // ValueKey represents a key for untyped values. type ValueKey struct { name string @@ -56,10 +50,10 @@ func (k *ValueKey) Get(tags TagMap) interface{} { } // From can be used to get a value from a Tag. -func (k *ValueKey) From(t Tag) interface{} { return t.untyped } +func (k *ValueKey) From(t Tag) interface{} { return t.UnpackValue() } // Of creates a new Tag with this key and the supplied value. -func (k *ValueKey) Of(value interface{}) Tag { return Tag{Key: k, untyped: value} } +func (k *ValueKey) Of(value interface{}) Tag { return TagOfValue(k, value) } // IntKey represents a key type IntKey struct { @@ -76,7 +70,7 @@ func (k *IntKey) Name() string { return k.name } func (k *IntKey) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *IntKey) Of(v int) Tag { return Tag{Key: k, packed: uint64(v)} } +func (k *IntKey) Of(v int) Tag { return TagOf64(k, uint64(v)) } // Get can be used to get a tag for the key from a TagMap. func (k *IntKey) Get(tags TagMap) int { @@ -87,7 +81,7 @@ func (k *IntKey) Get(tags TagMap) int { } // From can be used to get a value from a Tag. -func (k *IntKey) From(t Tag) int { return int(t.packed) } +func (k *IntKey) From(t Tag) int { return int(t.Unpack64()) } // Int8Key represents a key type Int8Key struct { @@ -104,7 +98,7 @@ func (k *Int8Key) Name() string { return k.name } func (k *Int8Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *Int8Key) Of(v int8) Tag { return Tag{Key: k, packed: uint64(v)} } +func (k *Int8Key) Of(v int8) Tag { return TagOf64(k, uint64(v)) } // Get can be used to get a tag for the key from a TagMap. func (k *Int8Key) Get(tags TagMap) int8 { @@ -115,7 +109,7 @@ func (k *Int8Key) Get(tags TagMap) int8 { } // From can be used to get a value from a Tag. -func (k *Int8Key) From(t Tag) int8 { return int8(t.packed) } +func (k *Int8Key) From(t Tag) int8 { return int8(t.Unpack64()) } // Int16Key represents a key type Int16Key struct { @@ -132,7 +126,7 @@ func (k *Int16Key) Name() string { return k.name } func (k *Int16Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *Int16Key) Of(v int16) Tag { return Tag{Key: k, packed: uint64(v)} } +func (k *Int16Key) Of(v int16) Tag { return TagOf64(k, uint64(v)) } // Get can be used to get a tag for the key from a TagMap. func (k *Int16Key) Get(tags TagMap) int16 { @@ -143,7 +137,7 @@ func (k *Int16Key) Get(tags TagMap) int16 { } // From can be used to get a value from a Tag. -func (k *Int16Key) From(t Tag) int16 { return int16(t.packed) } +func (k *Int16Key) From(t Tag) int16 { return int16(t.Unpack64()) } // Int32Key represents a key type Int32Key struct { @@ -160,7 +154,7 @@ func (k *Int32Key) Name() string { return k.name } func (k *Int32Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *Int32Key) Of(v int32) Tag { return Tag{Key: k, packed: uint64(v)} } +func (k *Int32Key) Of(v int32) Tag { return TagOf64(k, uint64(v)) } // Get can be used to get a tag for the key from a TagMap. func (k *Int32Key) Get(tags TagMap) int32 { @@ -171,7 +165,7 @@ func (k *Int32Key) Get(tags TagMap) int32 { } // From can be used to get a value from a Tag. -func (k *Int32Key) From(t Tag) int32 { return int32(t.packed) } +func (k *Int32Key) From(t Tag) int32 { return int32(t.Unpack64()) } // Int64Key represents a key type Int64Key struct { @@ -188,7 +182,7 @@ func (k *Int64Key) Name() string { return k.name } func (k *Int64Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *Int64Key) Of(v int64) Tag { return Tag{Key: k, packed: uint64(v)} } +func (k *Int64Key) Of(v int64) Tag { return TagOf64(k, uint64(v)) } // Get can be used to get a tag for the key from a TagMap. func (k *Int64Key) Get(tags TagMap) int64 { @@ -199,7 +193,7 @@ func (k *Int64Key) Get(tags TagMap) int64 { } // From can be used to get a value from a Tag. -func (k *Int64Key) From(t Tag) int64 { return int64(t.packed) } +func (k *Int64Key) From(t Tag) int64 { return int64(t.Unpack64()) } // UIntKey represents a key type UIntKey struct { @@ -216,7 +210,7 @@ func (k *UIntKey) Name() string { return k.name } func (k *UIntKey) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *UIntKey) Of(v uint) Tag { return Tag{Key: k, packed: uint64(v)} } +func (k *UIntKey) Of(v uint) Tag { return TagOf64(k, uint64(v)) } // Get can be used to get a tag for the key from a TagMap. func (k *UIntKey) Get(tags TagMap) uint { @@ -227,7 +221,7 @@ func (k *UIntKey) Get(tags TagMap) uint { } // From can be used to get a value from a Tag. -func (k *UIntKey) From(t Tag) uint { return uint(t.packed) } +func (k *UIntKey) From(t Tag) uint { return uint(t.Unpack64()) } // UInt8Key represents a key type UInt8Key struct { @@ -244,7 +238,7 @@ func (k *UInt8Key) Name() string { return k.name } func (k *UInt8Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *UInt8Key) Of(v uint8) Tag { return Tag{Key: k, packed: uint64(v)} } +func (k *UInt8Key) Of(v uint8) Tag { return TagOf64(k, uint64(v)) } // Get can be used to get a tag for the key from a TagMap. func (k *UInt8Key) Get(tags TagMap) uint8 { @@ -255,7 +249,7 @@ func (k *UInt8Key) Get(tags TagMap) uint8 { } // From can be used to get a value from a Tag. -func (k *UInt8Key) From(t Tag) uint8 { return uint8(t.packed) } +func (k *UInt8Key) From(t Tag) uint8 { return uint8(t.Unpack64()) } // UInt16Key represents a key type UInt16Key struct { @@ -272,7 +266,7 @@ func (k *UInt16Key) Name() string { return k.name } func (k *UInt16Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *UInt16Key) Of(v uint16) Tag { return Tag{Key: k, packed: uint64(v)} } +func (k *UInt16Key) Of(v uint16) Tag { return TagOf64(k, uint64(v)) } // Get can be used to get a tag for the key from a TagMap. func (k *UInt16Key) Get(tags TagMap) uint16 { @@ -283,7 +277,7 @@ func (k *UInt16Key) Get(tags TagMap) uint16 { } // From can be used to get a value from a Tag. -func (k *UInt16Key) From(t Tag) uint16 { return uint16(t.packed) } +func (k *UInt16Key) From(t Tag) uint16 { return uint16(t.Unpack64()) } // UInt32Key represents a key type UInt32Key struct { @@ -300,7 +294,7 @@ func (k *UInt32Key) Name() string { return k.name } func (k *UInt32Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *UInt32Key) Of(v uint32) Tag { return Tag{Key: k, packed: uint64(v)} } +func (k *UInt32Key) Of(v uint32) Tag { return TagOf64(k, uint64(v)) } // Get can be used to get a tag for the key from a TagMap. func (k *UInt32Key) Get(tags TagMap) uint32 { @@ -311,7 +305,7 @@ func (k *UInt32Key) Get(tags TagMap) uint32 { } // From can be used to get a value from a Tag. -func (k *UInt32Key) From(t Tag) uint32 { return uint32(t.packed) } +func (k *UInt32Key) From(t Tag) uint32 { return uint32(t.Unpack64()) } // UInt64Key represents a key type UInt64Key struct { @@ -328,7 +322,7 @@ func (k *UInt64Key) Name() string { return k.name } func (k *UInt64Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *UInt64Key) Of(v uint64) Tag { return Tag{Key: k, packed: v} } +func (k *UInt64Key) Of(v uint64) Tag { return TagOf64(k, v) } // Get can be used to get a tag for the key from a TagMap. func (k *UInt64Key) Get(tags TagMap) uint64 { @@ -339,7 +333,7 @@ func (k *UInt64Key) Get(tags TagMap) uint64 { } // From can be used to get a value from a Tag. -func (k *UInt64Key) From(t Tag) uint64 { return t.packed } +func (k *UInt64Key) From(t Tag) uint64 { return t.Unpack64() } // Float32Key represents a key type Float32Key struct { @@ -357,7 +351,7 @@ func (k *Float32Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. func (k *Float32Key) Of(v float32) Tag { - return Tag{Key: k, packed: uint64(math.Float32bits(v))} + return TagOf64(k, uint64(math.Float32bits(v))) } // Get can be used to get a tag for the key from a TagMap. @@ -370,7 +364,7 @@ func (k *Float32Key) Get(tags TagMap) float32 { // From can be used to get a value from a Tag. func (k *Float32Key) From(t Tag) float32 { - return math.Float32frombits(uint32(t.packed)) + return math.Float32frombits(uint32(t.Unpack64())) } // Float64Key represents a key @@ -389,7 +383,7 @@ func (k *Float64Key) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. func (k *Float64Key) Of(v float64) Tag { - return Tag{Key: k, packed: math.Float64bits(v)} + return TagOf64(k, math.Float64bits(v)) } // Get can be used to get a tag for the key from a TagMap. @@ -402,7 +396,7 @@ func (k *Float64Key) Get(tags TagMap) float64 { // From can be used to get a value from a Tag. func (k *Float64Key) From(t Tag) float64 { - return math.Float64frombits(t.packed) + return math.Float64frombits(t.Unpack64()) } // StringKey represents a key @@ -420,7 +414,7 @@ func (k *StringKey) Name() string { return k.name } func (k *StringKey) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *StringKey) Of(v string) Tag { return Tag{Key: k, str: v} } +func (k *StringKey) Of(v string) Tag { return TagOfString(k, v) } // Get can be used to get a tag for the key from a TagMap. func (k *StringKey) Get(tags TagMap) string { @@ -431,7 +425,7 @@ func (k *StringKey) Get(tags TagMap) string { } // From can be used to get a value from a Tag. -func (k *StringKey) From(t Tag) string { return t.str } +func (k *StringKey) From(t Tag) string { return t.UnpackString() } // BooleanKey represents a key type BooleanKey struct { @@ -449,11 +443,10 @@ func (k *BooleanKey) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. func (k *BooleanKey) Of(v bool) Tag { - t := Tag{Key: k} if v { - t.packed = 1 + return TagOf64(k, 1) } - return t + return TagOf64(k, 0) } // Get can be used to get a tag for the key from a TagMap. @@ -465,7 +458,7 @@ func (k *BooleanKey) Get(tags TagMap) bool { } // From can be used to get a value from a Tag. -func (k *BooleanKey) From(t Tag) bool { return t.packed > 0 } +func (k *BooleanKey) From(t Tag) bool { return t.Unpack64() > 0 } // ErrorKey represents a key type ErrorKey struct { @@ -482,7 +475,7 @@ func (k *ErrorKey) Name() string { return k.name } func (k *ErrorKey) Description() string { return k.description } // Of creates a new Tag with this key and the supplied value. -func (k *ErrorKey) Of(v error) Tag { return Tag{Key: k, untyped: v} } +func (k *ErrorKey) Of(v error) Tag { return TagOfValue(k, v) } // Get can be used to get a tag for the key from a TagMap. func (k *ErrorKey) Get(tags TagMap) error { @@ -494,6 +487,6 @@ func (k *ErrorKey) Get(tags TagMap) error { // From can be used to get a value from a Tag. func (k *ErrorKey) From(t Tag) error { - err, _ := t.untyped.(error) + err, _ := t.UnpackValue().(error) return err } diff --git a/internal/telemetry/event/tag.go b/internal/telemetry/event/tag.go index 5fe40a1e9c..7381cd0b90 100644 --- a/internal/telemetry/event/tag.go +++ b/internal/telemetry/event/tag.go @@ -11,7 +11,7 @@ import ( // Tag holds a key and value pair. // It is normally used when passing around lists of tags. type Tag struct { - Key Key + key Key packed uint64 str string untyped interface{} @@ -20,7 +20,7 @@ type Tag struct { // 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 interface{}) Tag + Find(key Key) Tag } // TagList is the interface to something that provides an iterable @@ -55,8 +55,45 @@ 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 { return Tag{key: k, str: v} } + +// 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 { return t.str } + // Valid returns true if the Tag is a valid one (it has a key). -func (t Tag) Valid() bool { return t.Key != nil } +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) { @@ -64,7 +101,7 @@ func (t Tag) Format(f fmt.State, r rune) { fmt.Fprintf(f, `nil`) return } - switch key := t.Key.(type) { + switch key := t.key.(type) { case *IntKey: fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t)) case *Int8Key: @@ -117,23 +154,23 @@ func (f *tagFilter) Valid(index int) bool { func (f *tagFilter) Tag(index int) Tag { tag := f.underlying.Tag(index) for _, f := range f.keys { - if tag.Key == f { + if tag.Key() == f { return Tag{} } } return tag } -func (l tagMap) Find(key interface{}) Tag { +func (l tagMap) Find(key Key) Tag { for _, tag := range l.tags { - if tag.Key == key { + if tag.Key() == key { return tag } } return Tag{} } -func (c tagMapChain) Find(key interface{}) Tag { +func (c tagMapChain) Find(key Key) Tag { for _, src := range c.maps { tag := src.Find(key) if tag.Valid() { diff --git a/internal/telemetry/export/log.go b/internal/telemetry/export/log.go index f5278eddc3..525c80ef40 100644 --- a/internal/telemetry/export/log.go +++ b/internal/telemetry/export/log.go @@ -51,13 +51,13 @@ func (w *logWriter) ProcessEvent(ctx context.Context, ev event.Event, tagMap eve } for index := 0; ev.Valid(index); index++ { tag := ev.Tag(index) - if !tag.Valid() || tag.Key == event.Msg || tag.Key == event.Err { + if !tag.Valid() || tag.Key() == event.Msg || tag.Key() == event.Err { continue } io.WriteString(w.writer, "\n\t") - io.WriteString(w.writer, tag.Key.Name()) + io.WriteString(w.writer, tag.Key().Name()) io.WriteString(w.writer, "=") - switch key := tag.Key.(type) { + switch key := tag.Key().(type) { case *event.IntKey: w.writer.Write(strconv.AppendInt(buf, int64(key.From(tag)), 10)) case *event.Int8Key: diff --git a/internal/telemetry/export/metric/exporter.go b/internal/telemetry/export/metric/exporter.go index 56b4fa1609..ad3552fb44 100644 --- a/internal/telemetry/export/metric/exporter.go +++ b/internal/telemetry/export/metric/exporter.go @@ -42,7 +42,7 @@ func (e *Config) Exporter(output event.Exporter) event.Exporter { if !tag.Valid() { continue } - id := tag.Key + id := tag.Key() if list := e.subscribers[id]; len(list) > 0 { for _, s := range list { metrics = append(metrics, s(ev.At, tagMap, tag)) diff --git a/internal/telemetry/export/ocagent/ocagent.go b/internal/telemetry/export/ocagent/ocagent.go index 217ce9fb68..0d1af1aa38 100644 --- a/internal/telemetry/export/ocagent/ocagent.go +++ b/internal/telemetry/export/ocagent/ocagent.go @@ -245,7 +245,7 @@ func convertAttributes(l event.TagList) *wire.Attributes { attributes := make(map[string]wire.Attribute) for { if tag.Valid() { - attributes[tag.Key.Name()] = convertAttribute(tag) + attributes[tag.Key().Name()] = convertAttribute(tag) } index++ if !l.Valid(index) { @@ -256,7 +256,7 @@ func convertAttributes(l event.TagList) *wire.Attributes { } func convertAttribute(tag event.Tag) wire.Attribute { - switch key := tag.Key.(type) { + switch key := tag.Key().(type) { case *event.IntKey: return wire.IntAttribute{IntValue: int64(key.From(tag))} case *event.Int8Key: