github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/runtime/pprof/label.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package pprof 6 7 import ( 8 "context" 9 ) 10 11 type label struct { 12 key string 13 value string 14 } 15 16 // LabelSet is a set of labels. 17 type LabelSet struct { 18 list []label 19 } 20 21 // labelContextKey is the type of contextKeys used for profiler labels. 22 type labelContextKey struct{} 23 24 func labelValue(ctx context.Context) labelMap { 25 labels, _ := ctx.Value(labelContextKey{}).(*labelMap) 26 if labels == nil { 27 return labelMap(nil) 28 } 29 return *labels 30 } 31 32 // labelMap is the representation of the label set held in the context type. 33 // This is an initial implementation, but it will be replaced with something 34 // that admits incremental immutable modification more efficiently. 35 type labelMap map[string]string 36 37 // WithLabels returns a new context.Context with the given labels added. 38 // A label overwrites a prior label with the same key. 39 func WithLabels(ctx context.Context, labels LabelSet) context.Context { 40 childLabels := make(labelMap) 41 parentLabels := labelValue(ctx) 42 // TODO(matloob): replace the map implementation with something 43 // more efficient so creating a child context WithLabels doesn't need 44 // to clone the map. 45 for k, v := range parentLabels { 46 childLabels[k] = v 47 } 48 for _, label := range labels.list { 49 childLabels[label.key] = label.value 50 } 51 return context.WithValue(ctx, labelContextKey{}, &childLabels) 52 } 53 54 // Labels takes an even number of strings representing key-value pairs 55 // and makes a LabelSet containing them. 56 // A label overwrites a prior label with the same key. 57 func Labels(args ...string) LabelSet { 58 if len(args)%2 != 0 { 59 panic("uneven number of arguments to pprof.Labels") 60 } 61 labels := LabelSet{} 62 for i := 0; i+1 < len(args); i += 2 { 63 labels.list = append(labels.list, label{key: args[i], value: args[i+1]}) 64 } 65 return labels 66 } 67 68 // Label returns the value of the label with the given key on ctx, and a boolean indicating 69 // whether that label exists. 70 func Label(ctx context.Context, key string) (string, bool) { 71 ctxLabels := labelValue(ctx) 72 v, ok := ctxLabels[key] 73 return v, ok 74 } 75 76 // ForLabels invokes f with each label set on the context. 77 // The function f should return true to continue iteration or false to stop iteration early. 78 func ForLabels(ctx context.Context, f func(key, value string) bool) { 79 ctxLabels := labelValue(ctx) 80 for k, v := range ctxLabels { 81 if !f(k, v) { 82 break 83 } 84 } 85 }