зеркало из https://github.com/golang/tools.git
internal/telemetry: add type safe tag keys
This changes the way keys work, there is still a single internal key implementation for performance reasons, but the public interface is a set of key implementations that have type safe Of and Get methods. This also hides the implemenation of Tag so that we can modify the storage form and find a more efficient storage if needed. Change-Id: I6a39cc75c2824c6a92e52d59f16e82e876f16e9c Reviewed-on: https://go-review.googlesource.com/c/tools/+/223137 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
This commit is contained in:
Родитель
d7fc2cf50e
Коммит
540150da73
|
@ -207,7 +207,7 @@ func runAnalysis(ctx context.Context, fset *token.FileSet, analyzer *analysis.An
|
|||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
event.Print(ctx, fmt.Sprintf("analysis panicked: %s", r), tag.Package.Of(pkg.PkgPath))
|
||||
event.Print(ctx, fmt.Sprintf("analysis panicked: %s", r), tag.Package.Of(pkg.PkgPath()))
|
||||
data.err = errors.Errorf("analysis %s for package %s panicked: %v", analyzer.Name, pkg.PkgPath(), r)
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -143,7 +143,7 @@ func (s *snapshot) buildKey(ctx context.Context, id packageID, mode source.Parse
|
|||
}
|
||||
depHandle, err := s.buildPackageHandle(ctx, depID, mode)
|
||||
if err != nil {
|
||||
event.Error(ctx, "no dep handle", err, tag.Package.Of(depID))
|
||||
event.Error(ctx, "no dep handle", err, tag.Package.Of(string(depID)))
|
||||
|
||||
// One bad dependency should not prevent us from checking the entire package.
|
||||
// Add a special key to mark a bad dependency.
|
||||
|
@ -259,7 +259,7 @@ func (s *snapshot) parseGoHandles(ctx context.Context, files []span.URI, mode so
|
|||
}
|
||||
|
||||
func typeCheck(ctx context.Context, fset *token.FileSet, m *metadata, mode source.ParseMode, goFiles []source.ParseGoHandle, compiledGoFiles []source.ParseGoHandle, deps map[packagePath]*packageHandle) (*pkg, error) {
|
||||
ctx, done := event.StartSpan(ctx, "cache.importer.typeCheck", tag.Package.Of(m.id))
|
||||
ctx, done := event.StartSpan(ctx, "cache.importer.typeCheck", tag.Package.Of(string(m.id)))
|
||||
defer done()
|
||||
|
||||
var rawErrors []error
|
||||
|
|
|
@ -144,7 +144,7 @@ func (s *snapshot) ModHandle(ctx context.Context, fh source.FileHandle) source.M
|
|||
view: folder,
|
||||
}
|
||||
h := s.view.session.cache.store.Bind(key, func(ctx context.Context) interface{} {
|
||||
ctx, done := event.StartSpan(ctx, "cache.ModHandle", tag.File.Of(uri))
|
||||
ctx, done := event.StartSpan(ctx, "cache.ModHandle", tag.URI.Of(uri))
|
||||
defer done()
|
||||
|
||||
contents, _, err := fh.Read(ctx)
|
||||
|
@ -317,7 +317,7 @@ func (s *snapshot) ModTidyHandle(ctx context.Context, realfh source.FileHandle)
|
|||
return &modData{}
|
||||
}
|
||||
|
||||
ctx, done := event.StartSpan(ctx, "cache.ModTidyHandle", tag.File.Of(realURI))
|
||||
ctx, done := event.StartSpan(ctx, "cache.ModTidyHandle", tag.URI.Of(realURI))
|
||||
defer done()
|
||||
|
||||
realContents, _, err := realfh.Read(ctx)
|
||||
|
|
|
@ -151,7 +151,7 @@ func (s *snapshot) PackageHandles(ctx context.Context, fh source.FileHandle) ([]
|
|||
panic("called PackageHandles on a non-Go FileHandle")
|
||||
}
|
||||
|
||||
ctx = event.Label(ctx, tag.File.Of(fh.Identity().URI))
|
||||
ctx = event.Label(ctx, tag.URI.Of(fh.Identity().URI))
|
||||
|
||||
// Check if we should reload metadata for the file. We don't invalidate IDs
|
||||
// (though we should), so the IDs will be a better source of truth than the
|
||||
|
|
|
@ -73,7 +73,7 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
|
|||
// First, add the quick fixes reported by go/analysis.
|
||||
qf, err := quickFixes(ctx, snapshot, fh, diagnostics)
|
||||
if err != nil {
|
||||
event.Error(ctx, "quick fixes failed", err, tag.File.Of(uri))
|
||||
event.Error(ctx, "quick fixes failed", err, tag.URI.Of(uri))
|
||||
}
|
||||
codeActions = append(codeActions, qf...)
|
||||
|
||||
|
@ -97,7 +97,7 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
|
|||
}
|
||||
actions, err := mod.SuggestedGoFixes(ctx, snapshot, fh, diagnostics)
|
||||
if err != nil {
|
||||
event.Error(ctx, "quick fixes failed", err, tag.File.Of(uri))
|
||||
event.Error(ctx, "quick fixes failed", err, tag.URI.Of(uri))
|
||||
}
|
||||
if len(actions) > 0 {
|
||||
codeActions = append(codeActions, actions...)
|
||||
|
|
|
@ -30,7 +30,7 @@ func (s *Server) completion(ctx context.Context, params *protocol.CompletionPara
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
event.Print(ctx, "no completions found", tag.Position.Of(params.Position), event.Err.Of("Failure"))
|
||||
event.Print(ctx, "no completions found", tag.Position.Of(params.Position), event.Err.Of(err))
|
||||
}
|
||||
if candidates == nil {
|
||||
return &protocol.CompletionList{
|
||||
|
|
|
@ -18,33 +18,33 @@ var (
|
|||
receivedBytes = metric.HistogramInt64{
|
||||
Name: "received_bytes",
|
||||
Description: "Distribution of received bytes, by method.",
|
||||
Keys: []*event.Key{tag.RPCDirection, tag.Method},
|
||||
Keys: []event.Key{tag.RPCDirection, tag.Method},
|
||||
Buckets: bytesDistribution,
|
||||
}.Record(tag.ReceivedBytes)
|
||||
|
||||
sentBytes = metric.HistogramInt64{
|
||||
Name: "sent_bytes",
|
||||
Description: "Distribution of sent bytes, by method.",
|
||||
Keys: []*event.Key{tag.RPCDirection, tag.Method},
|
||||
Keys: []event.Key{tag.RPCDirection, tag.Method},
|
||||
Buckets: bytesDistribution,
|
||||
}.Record(tag.SentBytes)
|
||||
|
||||
latency = metric.HistogramFloat64{
|
||||
Name: "latency",
|
||||
Description: "Distribution of latency in milliseconds, by method.",
|
||||
Keys: []*event.Key{tag.RPCDirection, tag.Method},
|
||||
Keys: []event.Key{tag.RPCDirection, tag.Method},
|
||||
Buckets: millisecondsDistribution,
|
||||
}.Record(tag.Latency)
|
||||
|
||||
started = metric.Scalar{
|
||||
Name: "started",
|
||||
Description: "Count of RPCs started by method.",
|
||||
Keys: []*event.Key{tag.RPCDirection, tag.Method},
|
||||
Keys: []event.Key{tag.RPCDirection, tag.Method},
|
||||
}.CountInt64(tag.Started)
|
||||
|
||||
completed = metric.Scalar{
|
||||
Name: "completed",
|
||||
Description: "Count of RPCs completed by method and status.",
|
||||
Keys: []*event.Key{tag.RPCDirection, tag.Method, tag.StatusCode},
|
||||
Keys: []event.Key{tag.RPCDirection, tag.Method, tag.StatusCode},
|
||||
}.CountFloat64(tag.Latency)
|
||||
)
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"sync"
|
||||
|
@ -97,13 +96,10 @@ func (r *rpcs) Metric(ctx context.Context, data event.MetricData) {
|
|||
defer r.mu.Unlock()
|
||||
for i, group := range data.Groups() {
|
||||
set := &r.Inbound
|
||||
if group.Get(tag.RPCDirection) == tag.Outbound {
|
||||
if tag.RPCDirection.Get(group) == tag.Outbound {
|
||||
set = &r.Outbound
|
||||
}
|
||||
method, ok := group.Get(tag.Method).(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
method := tag.Method.Get(group)
|
||||
index := sort.Search(len(*set), func(i int) bool {
|
||||
return (*set)[i].Method >= method
|
||||
})
|
||||
|
@ -119,11 +115,7 @@ func (r *rpcs) Metric(ctx context.Context, data event.MetricData) {
|
|||
case started:
|
||||
stats.Started = data.(*metric.Int64Data).Rows[i]
|
||||
case completed:
|
||||
status, ok := group.Get(tag.StatusCode).(string)
|
||||
if !ok {
|
||||
log.Printf("Not status... %v", group)
|
||||
continue
|
||||
}
|
||||
status := tag.StatusCode.Get(group)
|
||||
var b *rpcCodeBucket
|
||||
for c, entry := range stats.Codes {
|
||||
if entry.Key == status {
|
||||
|
|
|
@ -13,27 +13,27 @@ import (
|
|||
|
||||
var (
|
||||
// create the tag keys we use
|
||||
Method = &event.Key{Name: "method"}
|
||||
StatusCode = &event.Key{Name: "status.code"}
|
||||
StatusMessage = &event.Key{Name: "status.message"}
|
||||
RPCID = &event.Key{Name: "id"}
|
||||
RPCDirection = &event.Key{Name: "direction"}
|
||||
File = &event.Key{Name: "file"}
|
||||
Directory = &event.Key{Name: "directory"}
|
||||
URI = &event.Key{Name: "URI"}
|
||||
Package = &event.Key{Name: "package"}
|
||||
PackagePath = &event.Key{Name: "package_path"}
|
||||
Query = &event.Key{Name: "query"}
|
||||
Snapshot = &event.Key{Name: "snapshot"}
|
||||
Operation = &event.Key{Name: "operation"}
|
||||
Method = event.NewStringKey("method", "")
|
||||
StatusCode = event.NewStringKey("status.code", "")
|
||||
StatusMessage = event.NewStringKey("status.message", "")
|
||||
RPCID = event.NewStringKey("id", "")
|
||||
RPCDirection = event.NewStringKey("direction", "")
|
||||
File = event.NewStringKey("file", "")
|
||||
Directory = event.NewKey("directory", "")
|
||||
URI = event.NewKey("URI", "")
|
||||
Package = event.NewStringKey("package", "")
|
||||
PackagePath = event.NewStringKey("package_path", "")
|
||||
Query = event.NewKey("query", "")
|
||||
Snapshot = event.NewUInt64Key("snapshot", "")
|
||||
Operation = event.NewStringKey("operation", "")
|
||||
|
||||
Position = &event.Key{Name: "position"}
|
||||
Category = &event.Key{Name: "category"}
|
||||
PackageCount = &event.Key{Name: "packages"}
|
||||
Files = &event.Key{Name: "files"}
|
||||
Port = &event.Key{Name: "port"}
|
||||
Type = &event.Key{Name: "type"}
|
||||
HoverKind = &event.Key{Name: "hoverkind"}
|
||||
Position = event.NewKey("position", "")
|
||||
Category = event.NewStringKey("category", "")
|
||||
PackageCount = event.NewIntKey("packages", "")
|
||||
Files = event.NewKey("files", "")
|
||||
Port = event.NewIntKey("port", "")
|
||||
Type = event.NewKey("type", "")
|
||||
HoverKind = event.NewStringKey("hoverkind", "")
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -172,7 +172,7 @@ func fillOffsets(td *traceData, start time.Time) {
|
|||
func renderTags(tags event.TagList) string {
|
||||
buf := &bytes.Buffer{}
|
||||
for _, tag := range tags {
|
||||
fmt.Fprintf(buf, "%v=%q ", tag.Key, tag.Value)
|
||||
fmt.Fprintf(buf, "%s=%q ", tag.Key().Name(), tag.Value())
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ func (h telemetryHandler) Request(ctx context.Context, conn *jsonrpc2.Conn, dire
|
|||
ctx, stats.close = event.StartSpan(ctx, r.Method,
|
||||
tag.Method.Of(r.Method),
|
||||
tag.RPCDirection.Of(mode),
|
||||
tag.RPCID.Of(r.ID),
|
||||
tag.RPCID.Of(r.ID.String()),
|
||||
)
|
||||
tag.Started.Record(ctx, 1)
|
||||
_, stats.delivering = event.StartSpan(ctx, "queued")
|
||||
|
|
|
@ -22,7 +22,7 @@ func CodeLens(ctx context.Context, snapshot source.Snapshot, uri span.URI) ([]pr
|
|||
if uri != realURI {
|
||||
return nil, nil
|
||||
}
|
||||
ctx, done := event.StartSpan(ctx, "mod.CodeLens", tag.File.Of(realURI))
|
||||
ctx, done := event.StartSpan(ctx, "mod.CodeLens", tag.URI.Of(realURI))
|
||||
defer done()
|
||||
|
||||
fh, err := snapshot.GetFile(realURI)
|
||||
|
|
|
@ -27,7 +27,7 @@ func Diagnostics(ctx context.Context, snapshot source.Snapshot) (map[source.File
|
|||
return nil, nil, nil
|
||||
}
|
||||
|
||||
ctx, done := event.StartSpan(ctx, "mod.Diagnostics", tag.File.Of(realURI))
|
||||
ctx, done := event.StartSpan(ctx, "mod.Diagnostics", tag.URI.Of(realURI))
|
||||
defer done()
|
||||
|
||||
realfh, err := snapshot.GetFile(realURI)
|
||||
|
@ -126,7 +126,7 @@ func SuggestedGoFixes(ctx context.Context, snapshot source.Snapshot, gofh source
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
ctx, done := event.StartSpan(ctx, "mod.SuggestedGoFixes", tag.File.Of(realURI))
|
||||
ctx, done := event.StartSpan(ctx, "mod.SuggestedGoFixes", tag.URI.Of(realURI))
|
||||
defer done()
|
||||
|
||||
realfh, err := snapshot.GetFile(realURI)
|
||||
|
|
|
@ -18,8 +18,8 @@ type Hooks struct {
|
|||
}
|
||||
|
||||
var (
|
||||
aValue = &event.Key{Name: "a"}
|
||||
bValue = &event.Key{Name: "b"}
|
||||
aValue = event.NewInt64Key("a", "")
|
||||
bValue = event.NewStringKey("b", "")
|
||||
aCount = stats.Int64("aCount", "Count of time A is called.", unit.Dimensionless)
|
||||
aStat = stats.Int64("aValue", "A value.", unit.Dimensionless)
|
||||
bCount = stats.Int64("B", "Count of time B is called.", unit.Dimensionless)
|
||||
|
@ -51,9 +51,9 @@ var (
|
|||
|
||||
Log = Hooks{
|
||||
A: func(ctx context.Context, a *int) (context.Context, func()) {
|
||||
event.Print(ctx, "start A", aValue.Of(*a))
|
||||
event.Print(ctx, "start A", aValue.Of(int64(*a)))
|
||||
return ctx, func() {
|
||||
event.Print(ctx, "end A", aValue.Of(*a))
|
||||
event.Print(ctx, "end A", aValue.Of(int64(*a)))
|
||||
}
|
||||
},
|
||||
B: func(ctx context.Context, b *string) (context.Context, func()) {
|
||||
|
|
|
@ -49,6 +49,6 @@ func (e Event) Format(f fmt.State, r rune) {
|
|||
}
|
||||
}
|
||||
for _, tag := range e.Tags {
|
||||
fmt.Fprintf(f, "\n\t%s = %v", tag.Key.Name, tag.Value)
|
||||
fmt.Fprintf(f, "\n\t%s = %v", tag.key.name, tag.value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,19 +6,335 @@ package event
|
|||
|
||||
var (
|
||||
// Err is a key used to add error values to tag lists.
|
||||
Err = Key{Name: "error"}
|
||||
Err = NewErrorKey("error", "")
|
||||
)
|
||||
|
||||
// Key is used as the identity of a Tag.
|
||||
// Key is the interface shared by all key implementations.
|
||||
type Key interface {
|
||||
// Identity returns the underlying key identity.
|
||||
Identity() interface{}
|
||||
// Name returns the key name.
|
||||
Name() string
|
||||
// Description returns a string that can be used to describe the value.
|
||||
Description() string
|
||||
// OfValue creates a new Tag with this key and the supplied untyped value.
|
||||
OfValue(interface{}) Tag
|
||||
}
|
||||
|
||||
// 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
|
||||
type key struct {
|
||||
name string
|
||||
description string
|
||||
}
|
||||
|
||||
func newKey(name, description string) *key { return &key{name: name, description: description} }
|
||||
func (k *key) Name() string { return k.name }
|
||||
func (k *key) Description() string { return k.description }
|
||||
func (k *key) Identity() interface{} { return k }
|
||||
func (k *key) OfValue(value interface{}) Tag { return Tag{key: k, value: value} }
|
||||
|
||||
// ValueKey represents a key for untyped values.
|
||||
type ValueKey struct{ *key }
|
||||
|
||||
// NewKey creates a new Key for untyped values.
|
||||
func NewKey(name, description string) ValueKey {
|
||||
return ValueKey{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k ValueKey) Get(tags TagList) interface{} {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
// You can use this when building a tag list.
|
||||
func (k *Key) Of(v interface{}) Tag {
|
||||
return Tag{Key: k, Value: v}
|
||||
func (k ValueKey) Of(value interface{}) Tag { return Tag{key: k.key, value: value} }
|
||||
|
||||
// IntKey represents a key
|
||||
type IntKey struct{ *key }
|
||||
|
||||
// NewIntKey creates a new Key for int values.
|
||||
func NewIntKey(name, description string) IntKey {
|
||||
return IntKey{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k IntKey) Of(v int) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k IntKey) Get(tags TagList) int {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(int)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int8Key represents a key
|
||||
type Int8Key struct{ *key }
|
||||
|
||||
// NewInt8Key creates a new Key for int8 values.
|
||||
func NewInt8Key(name, description string) Int8Key {
|
||||
return Int8Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k Int8Key) Of(v int8) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k Int8Key) Get(tags TagList) int8 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(int8)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int16Key represents a key
|
||||
type Int16Key struct{ *key }
|
||||
|
||||
// NewInt16Key creates a new Key for int16 values.
|
||||
func NewInt16Key(name, description string) Int16Key {
|
||||
return Int16Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k Int16Key) Of(v int16) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k Int16Key) Get(tags TagList) int16 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(int16)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int32Key represents a key
|
||||
type Int32Key struct{ *key }
|
||||
|
||||
// NewInt32Key creates a new Key for int32 values.
|
||||
func NewInt32Key(name, description string) Int32Key {
|
||||
return Int32Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k Int32Key) Of(v int32) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k Int32Key) Get(tags TagList) int32 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(int32)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int64Key represents a key
|
||||
type Int64Key struct{ *key }
|
||||
|
||||
// NewInt64Key creates a new Key for int64 values.
|
||||
func NewInt64Key(name, description string) Int64Key {
|
||||
return Int64Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k Int64Key) Of(v int64) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k Int64Key) Get(tags TagList) int64 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(int64)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// UIntKey represents a key
|
||||
type UIntKey struct{ *key }
|
||||
|
||||
// NewUIntKey creates a new Key for uint values.
|
||||
func NewUIntKey(name, description string) UIntKey {
|
||||
return UIntKey{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k UIntKey) Of(v uint) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k UIntKey) Get(tags TagList) uint {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(uint)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// UInt8Key represents a key
|
||||
type UInt8Key struct{ *key }
|
||||
|
||||
// NewUInt8Key creates a new Key for uint8 values.
|
||||
func NewUInt8Key(name, description string) UInt8Key {
|
||||
return UInt8Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k UInt8Key) Of(v uint8) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k UInt8Key) Get(tags TagList) uint8 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(uint8)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// UInt16Key represents a key
|
||||
type UInt16Key struct{ *key }
|
||||
|
||||
// NewUInt16Key creates a new Key for uint16 values.
|
||||
func NewUInt16Key(name, description string) UInt16Key {
|
||||
return UInt16Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k UInt16Key) Of(v uint16) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k UInt16Key) Get(tags TagList) uint16 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(uint16)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// UInt32Key represents a key
|
||||
type UInt32Key struct{ *key }
|
||||
|
||||
// NewUInt32Key creates a new Key for uint32 values.
|
||||
func NewUInt32Key(name, description string) UInt32Key {
|
||||
return UInt32Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k UInt32Key) Of(v uint32) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k UInt32Key) Get(tags TagList) uint32 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(uint32)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// UInt64Key represents a key
|
||||
type UInt64Key struct{ *key }
|
||||
|
||||
// NewUInt64Key creates a new Key for uint64 values.
|
||||
func NewUInt64Key(name, description string) UInt64Key {
|
||||
return UInt64Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k UInt64Key) Of(v uint64) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k UInt64Key) Get(tags TagList) uint64 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(uint64)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float32Key represents a key
|
||||
type Float32Key struct{ *key }
|
||||
|
||||
// NewFloat32Key creates a new Key for float32 values.
|
||||
func NewFloat32Key(name, description string) Float32Key {
|
||||
return Float32Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k Float32Key) Of(v float32) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k Float32Key) Get(tags TagList) float32 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(float32)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float64Key represents a key
|
||||
type Float64Key struct{ *key }
|
||||
|
||||
// NewFloat64Key creates a new Key for int64 values.
|
||||
func NewFloat64Key(name, description string) Float64Key {
|
||||
return Float64Key{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k Float64Key) Of(v float64) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k Float64Key) Get(tags TagList) float64 {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(float64)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// StringKey represents a key
|
||||
type StringKey struct{ *key }
|
||||
|
||||
// NewStringKey creates a new Key for int64 values.
|
||||
func NewStringKey(name, description string) StringKey {
|
||||
return StringKey{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k StringKey) Of(v string) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k StringKey) Get(tags TagList) string {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// BooleanKey represents a key
|
||||
type BooleanKey struct{ *key }
|
||||
|
||||
// NewBooleanKey creates a new Key for bool values.
|
||||
func NewBooleanKey(name, description string) BooleanKey {
|
||||
return BooleanKey{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k BooleanKey) Of(v bool) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k BooleanKey) Get(tags TagList) bool {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(bool)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ErrorKey represents a key
|
||||
type ErrorKey struct{ *key }
|
||||
|
||||
// NewErrorKey creates a new Key for int64 values.
|
||||
func NewErrorKey(name, description string) ErrorKey {
|
||||
return ErrorKey{newKey(name, description)}
|
||||
}
|
||||
|
||||
// Of creates a new Tag with this key and the supplied value.
|
||||
func (k ErrorKey) Of(v error) Tag { return Tag{key: k.key, value: v} }
|
||||
|
||||
// Get can be used to get a tag for the key from a TagList.
|
||||
func (k ErrorKey) Get(tags TagList) error {
|
||||
if t := tags.find(k.key); t.key != nil {
|
||||
return t.value.(error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@ func Label(ctx context.Context, tags ...Tag) context.Context {
|
|||
|
||||
// Query sends a query event to the exporter with the supplied keys.
|
||||
// The returned tags will have up to date values if the exporter supports it.
|
||||
func Query(ctx context.Context, keys ...*Key) TagList {
|
||||
func Query(ctx context.Context, keys ...Key) TagList {
|
||||
tags := make(TagList, len(keys))
|
||||
for i, k := range keys {
|
||||
tags[i].Key = k
|
||||
tags[i] = k.OfValue(nil)
|
||||
}
|
||||
_, ev := ProcessEvent(ctx, Event{
|
||||
Type: QueryType,
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
// Tag holds a key and value pair.
|
||||
// It is normally used when passing around lists of tags.
|
||||
type Tag struct {
|
||||
Key *Key
|
||||
Value interface{}
|
||||
key *key
|
||||
value interface{}
|
||||
}
|
||||
|
||||
// TagList is a way of passing around a collection of key value pairs.
|
||||
|
@ -20,19 +20,39 @@ type Tag struct {
|
|||
// maps.
|
||||
type TagList []Tag
|
||||
|
||||
// Key returns the key for this Tag.
|
||||
func (t Tag) Key() Key { return t.key }
|
||||
|
||||
// Value returns the value for this Tag.
|
||||
func (t Tag) Value() interface{} { return t.value }
|
||||
|
||||
// Format is used for debug printing of tags.
|
||||
func (t Tag) Format(f fmt.State, r rune) {
|
||||
fmt.Fprintf(f, `%v="%v"`, t.Key.Name, t.Value)
|
||||
if t.key == nil {
|
||||
fmt.Fprintf(f, `nil`)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(f, `%v="%v"`, t.key.name, t.value)
|
||||
}
|
||||
|
||||
// Get will get a single key's value from the list.
|
||||
func (l TagList) Get(k interface{}) interface{} {
|
||||
// FindAll returns corresponding tags for each key in keys.
|
||||
// If no tag is found for a key, the Tag at its corresponding
|
||||
// index will be of the zero value.
|
||||
func (l TagList) FindAll(keys []Key) TagList {
|
||||
tags := make(TagList, len(keys))
|
||||
for i, key := range keys {
|
||||
tags[i] = l.find(key.Identity())
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
func (l TagList) find(key interface{}) Tag {
|
||||
for _, t := range l {
|
||||
if t.Key == k {
|
||||
return t.Value
|
||||
if t.key == key {
|
||||
return t
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return Tag{}
|
||||
}
|
||||
|
||||
// Format pretty prints a list.
|
||||
|
@ -40,7 +60,7 @@ func (l TagList) Get(k interface{}) interface{} {
|
|||
func (l TagList) Format(f fmt.State, r rune) {
|
||||
printed := false
|
||||
for _, t := range l {
|
||||
if t.Value == nil {
|
||||
if t.value == nil {
|
||||
continue
|
||||
}
|
||||
if printed {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
package ocagent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"golang.org/x/tools/internal/telemetry/event"
|
||||
|
@ -202,11 +201,11 @@ 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 []*event.Key) []*wire.LabelKey {
|
||||
func infoKeysToLabelKeys(infoKeys []event.Key) []*wire.LabelKey {
|
||||
labelKeys := make([]*wire.LabelKey, 0, len(infoKeys))
|
||||
for _, key := range infoKeys {
|
||||
labelKeys = append(labelKeys, &wire.LabelKey{
|
||||
Key: fmt.Sprintf("%v", key.Name),
|
||||
Key: key.Name(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ func TestEncodeMetric(t *testing.T) {
|
|||
Info: &metric.Scalar{
|
||||
Name: "int",
|
||||
Description: "int metric",
|
||||
Keys: []*event.Key{keyHello},
|
||||
Keys: []event.Key{keyHello},
|
||||
},
|
||||
Rows: []int64{
|
||||
1,
|
||||
|
@ -91,7 +91,7 @@ func TestEncodeMetric(t *testing.T) {
|
|||
Info: &metric.Scalar{
|
||||
Name: "int-gauge",
|
||||
Description: "int metric gauge",
|
||||
Keys: []*event.Key{keyHello},
|
||||
Keys: []event.Key{keyHello},
|
||||
},
|
||||
IsGauge: true,
|
||||
})
|
||||
|
@ -116,7 +116,7 @@ func TestEncodeMetric(t *testing.T) {
|
|||
Info: &metric.Scalar{
|
||||
Name: "float",
|
||||
Description: "float metric",
|
||||
Keys: []*event.Key{keyWorld},
|
||||
Keys: []event.Key{keyWorld},
|
||||
},
|
||||
Rows: []float64{
|
||||
1.5,
|
||||
|
@ -165,7 +165,7 @@ func TestEncodeMetric(t *testing.T) {
|
|||
Info: &metric.Scalar{
|
||||
Name: "float-gauge",
|
||||
Description: "float metric gauge",
|
||||
Keys: []*event.Key{keyWorld},
|
||||
Keys: []event.Key{keyWorld},
|
||||
},
|
||||
IsGauge: true,
|
||||
})
|
||||
|
@ -190,7 +190,7 @@ func TestEncodeMetric(t *testing.T) {
|
|||
Info: &metric.HistogramInt64{
|
||||
Name: "histogram int",
|
||||
Description: "histogram int metric",
|
||||
Keys: []*event.Key{keyHello},
|
||||
Keys: []event.Key{keyHello},
|
||||
Buckets: []int64{
|
||||
0, 5, 10,
|
||||
},
|
||||
|
@ -263,7 +263,7 @@ func TestEncodeMetric(t *testing.T) {
|
|||
Info: &metric.HistogramFloat64{
|
||||
Name: "histogram float",
|
||||
Description: "histogram float metric",
|
||||
Keys: []*event.Key{keyHello},
|
||||
Keys: []event.Key{keyHello},
|
||||
Buckets: []float64{
|
||||
0, 5,
|
||||
},
|
||||
|
|
|
@ -233,7 +233,7 @@ func convertAttributes(tags event.TagList) *wire.Attributes {
|
|||
}
|
||||
attributes := make(map[string]wire.Attribute)
|
||||
for _, tag := range tags {
|
||||
attributes[tag.Key.Name] = convertAttribute(tag.Value)
|
||||
attributes[tag.Key().Name()] = convertAttribute(tag.Value())
|
||||
}
|
||||
return &wire.Attributes{AttributeMap: attributes}
|
||||
}
|
||||
|
|
|
@ -39,30 +39,30 @@ const testNodeStr = `{
|
|||
},`
|
||||
|
||||
var (
|
||||
keyDB = &event.Key{Name: "db"}
|
||||
keyHello = &event.Key{Name: "hello"}
|
||||
keyWorld = &event.Key{Name: "world"}
|
||||
keyDB = event.NewStringKey("db", "the database name")
|
||||
keyHello = event.NewStringKey("hello", "a metric grouping key")
|
||||
keyWorld = event.NewStringKey("world", "another metric grouping key")
|
||||
|
||||
key1DB = &event.Key{Name: "1_db"}
|
||||
key1DB = event.NewStringKey("1_db", "A test string key")
|
||||
|
||||
key2aAge = &event.Key{Name: "2a_age"}
|
||||
key2bTTL = &event.Key{Name: "2b_ttl"}
|
||||
key2cExpiryMS = &event.Key{Name: "2c_expiry_ms"}
|
||||
key2aAge = event.NewFloat64Key("2a_age", "A test float64 key")
|
||||
key2bTTL = event.NewFloat32Key("2b_ttl", "A test float32 key")
|
||||
key2cExpiryMS = event.NewFloat64Key("2c_expiry_ms", "A test float64 key")
|
||||
|
||||
key3aRetry = &event.Key{Name: "3a_retry"}
|
||||
key3bStale = &event.Key{Name: "3b_stale"}
|
||||
key3aRetry = event.NewBooleanKey("3a_retry", "A test boolean key")
|
||||
key3bStale = event.NewBooleanKey("3b_stale", "Another test boolean key")
|
||||
|
||||
key4aMax = &event.Key{Name: "4a_max"}
|
||||
key4bOpcode = &event.Key{Name: "4b_opcode"}
|
||||
key4cBase = &event.Key{Name: "4c_base"}
|
||||
key4eChecksum = &event.Key{Name: "4e_checksum"}
|
||||
key4fMode = &event.Key{Name: "4f_mode"}
|
||||
key4aMax = event.NewIntKey("4a_max", "A test int key")
|
||||
key4bOpcode = event.NewInt8Key("4b_opcode", "A test int8 key")
|
||||
key4cBase = event.NewInt16Key("4c_base", "A test int16 key")
|
||||
key4eChecksum = event.NewInt32Key("4e_checksum", "A test int32 key")
|
||||
key4fMode = event.NewInt64Key("4f_mode", "A test int64 key")
|
||||
|
||||
key5aMin = &event.Key{Name: "5a_min"}
|
||||
key5bMix = &event.Key{Name: "5b_mix"}
|
||||
key5cPort = &event.Key{Name: "5c_port"}
|
||||
key5dMinHops = &event.Key{Name: "5d_min_hops"}
|
||||
key5eMaxHops = &event.Key{Name: "5e_max_hops"}
|
||||
key5aMin = event.NewUIntKey("5a_min", "A test uint key")
|
||||
key5bMix = event.NewUInt8Key("5b_mix", "A test uint8 key")
|
||||
key5cPort = event.NewUInt16Key("5c_port", "A test uint16 key")
|
||||
key5dMinHops = event.NewUInt32Key("5d_min_hops", "A test uint32 key")
|
||||
key5eMaxHops = event.NewUInt64Key("5e_max_hops", "A test uint64 key")
|
||||
)
|
||||
|
||||
type testExporter struct {
|
||||
|
|
|
@ -21,13 +21,14 @@ func Tag(ctx context.Context, ev event.Event) (context.Context, event.Event) {
|
|||
switch {
|
||||
case ev.IsLabel(), ev.IsStartSpan():
|
||||
for _, t := range ev.Tags {
|
||||
ctx = context.WithValue(ctx, t.Key, t.Value)
|
||||
ctx = context.WithValue(ctx, t.Key(), t.Value())
|
||||
}
|
||||
default:
|
||||
// all other types want the tags filled in if needed
|
||||
for i := range ev.Tags {
|
||||
if ev.Tags[i].Value == nil {
|
||||
ev.Tags[i].Value = ctx.Value(ev.Tags[i].Key)
|
||||
if ev.Tags[i].Value() == nil {
|
||||
key := ev.Tags[i].Key()
|
||||
ev.Tags[i] = key.OfValue(ctx.Value(key.Identity()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ type Scalar struct {
|
|||
// 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 []*event.Key
|
||||
Keys []event.Key
|
||||
}
|
||||
|
||||
// HistogramInt64 represents the construction information for an int64 histogram metric.
|
||||
|
@ -31,7 +31,7 @@ type HistogramInt64 struct {
|
|||
// 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 []*event.Key
|
||||
Keys []event.Key
|
||||
// Buckets holds the inclusive upper bound of each bucket in the histogram.
|
||||
Buckets []int64
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ type HistogramFloat64 struct {
|
|||
// 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 []*event.Key
|
||||
Keys []event.Key
|
||||
// Buckets holds the inclusive upper bound of each bucket in the histogram.
|
||||
Buckets []float64
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ type HistogramFloat64Row struct {
|
|||
Max float64
|
||||
}
|
||||
|
||||
func getGroup(ctx context.Context, g *[]event.TagList, keys []*event.Key) (int, bool) {
|
||||
func getGroup(ctx context.Context, g *[]event.TagList, keys []event.Key) (int, bool) {
|
||||
group := event.Query(ctx, keys...)
|
||||
old := *g
|
||||
index := sort.Search(len(old), func(i int) bool {
|
||||
|
|
Загрузка…
Ссылка в новой задаче