// 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 tag provides support for telemetry tagging. // This package is a thin shim over contexts with the main addition being the // the ability to observe when contexts get tagged with new values. package tag import ( "context" "time" "golang.org/x/tools/internal/telemetry" "golang.org/x/tools/internal/telemetry/export" ) //TODO: Do we need to do something more efficient than just store tags //TODO: directly on the context? // Tagger is the interface to something that returns a Tag given a context. // Both Tag itself and Key support this interface, allowing methods that can // take either (and other implementations as well) type Tagger interface { // Tag returns a Tag potentially using information from the Context. Tag(context.Context) telemetry.Tag } // With is roughly equivalent to context.WithValue except that it also notifies // registered observers. // Unlike WithValue, it takes a list of tags so that you can set many values // at once if needed. Each call to With results in one invocation of each // observer. func With(ctx context.Context, tags ...telemetry.Tag) context.Context { at := time.Now() for _, t := range tags { ctx = context.WithValue(ctx, t.Key, t.Value) } export.Tag(ctx, at, tags) return ctx } // Get collects a set of values from the context and returns them as a tag list. func Get(ctx context.Context, keys ...interface{}) telemetry.TagList { tags := make(telemetry.TagList, len(keys)) for i, key := range keys { tags[i] = telemetry.Tag{Key: key, Value: ctx.Value(key)} } return tags } // Tags collects a list of tags for the taggers from the context. func Tags(ctx context.Context, taggers ...Tagger) telemetry.TagList { tags := make(telemetry.TagList, len(taggers)) for i, t := range taggers { tags[i] = t.Tag(ctx) } return tags }