...

Source file src/runtime/pprof/label.go

Documentation: runtime/pprof

		 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  	"fmt"
		10  	"sort"
		11  	"strings"
		12  )
		13  
		14  type label struct {
		15  	key	 string
		16  	value string
		17  }
		18  
		19  // LabelSet is a set of labels.
		20  type LabelSet struct {
		21  	list []label
		22  }
		23  
		24  // labelContextKey is the type of contextKeys used for profiler labels.
		25  type labelContextKey struct{}
		26  
		27  func labelValue(ctx context.Context) labelMap {
		28  	labels, _ := ctx.Value(labelContextKey{}).(*labelMap)
		29  	if labels == nil {
		30  		return labelMap(nil)
		31  	}
		32  	return *labels
		33  }
		34  
		35  // labelMap is the representation of the label set held in the context type.
		36  // This is an initial implementation, but it will be replaced with something
		37  // that admits incremental immutable modification more efficiently.
		38  type labelMap map[string]string
		39  
		40  // String statisfies Stringer and returns key, value pairs in a consistent
		41  // order.
		42  func (l *labelMap) String() string {
		43  	if l == nil {
		44  		return ""
		45  	}
		46  	keyVals := make([]string, 0, len(*l))
		47  
		48  	for k, v := range *l {
		49  		keyVals = append(keyVals, fmt.Sprintf("%q:%q", k, v))
		50  	}
		51  
		52  	sort.Strings(keyVals)
		53  
		54  	return "{" + strings.Join(keyVals, ", ") + "}"
		55  }
		56  
		57  // WithLabels returns a new context.Context with the given labels added.
		58  // A label overwrites a prior label with the same key.
		59  func WithLabels(ctx context.Context, labels LabelSet) context.Context {
		60  	childLabels := make(labelMap)
		61  	parentLabels := labelValue(ctx)
		62  	// TODO(matloob): replace the map implementation with something
		63  	// more efficient so creating a child context WithLabels doesn't need
		64  	// to clone the map.
		65  	for k, v := range parentLabels {
		66  		childLabels[k] = v
		67  	}
		68  	for _, label := range labels.list {
		69  		childLabels[label.key] = label.value
		70  	}
		71  	return context.WithValue(ctx, labelContextKey{}, &childLabels)
		72  }
		73  
		74  // Labels takes an even number of strings representing key-value pairs
		75  // and makes a LabelSet containing them.
		76  // A label overwrites a prior label with the same key.
		77  // Currently only the CPU and goroutine profiles utilize any labels
		78  // information.
		79  // See https://golang.org/issue/23458 for details.
		80  func Labels(args ...string) LabelSet {
		81  	if len(args)%2 != 0 {
		82  		panic("uneven number of arguments to pprof.Labels")
		83  	}
		84  	list := make([]label, 0, len(args)/2)
		85  	for i := 0; i+1 < len(args); i += 2 {
		86  		list = append(list, label{key: args[i], value: args[i+1]})
		87  	}
		88  	return LabelSet{list: list}
		89  }
		90  
		91  // Label returns the value of the label with the given key on ctx, and a boolean indicating
		92  // whether that label exists.
		93  func Label(ctx context.Context, key string) (string, bool) {
		94  	ctxLabels := labelValue(ctx)
		95  	v, ok := ctxLabels[key]
		96  	return v, ok
		97  }
		98  
		99  // ForLabels invokes f with each label set on the context.
	 100  // The function f should return true to continue iteration or false to stop iteration early.
	 101  func ForLabels(ctx context.Context, f func(key, value string) bool) {
	 102  	ctxLabels := labelValue(ctx)
	 103  	for k, v := range ctxLabels {
	 104  		if !f(k, v) {
	 105  			break
	 106  		}
	 107  	}
	 108  }
	 109  

View as plain text