github.com/karrick/go@v0.0.0-20170817181416-d5b0ec858b37/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  }