...

Source file src/pkg/runtime/pprof/label.go

     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	// Currently only CPU profile utilizes labels information.
    58	// See https://golang.org/issue/23458 for details.
    59	func Labels(args ...string) LabelSet {
    60		if len(args)%2 != 0 {
    61			panic("uneven number of arguments to pprof.Labels")
    62		}
    63		labels := LabelSet{}
    64		for i := 0; i+1 < len(args); i += 2 {
    65			labels.list = append(labels.list, label{key: args[i], value: args[i+1]})
    66		}
    67		return labels
    68	}
    69	
    70	// Label returns the value of the label with the given key on ctx, and a boolean indicating
    71	// whether that label exists.
    72	func Label(ctx context.Context, key string) (string, bool) {
    73		ctxLabels := labelValue(ctx)
    74		v, ok := ctxLabels[key]
    75		return v, ok
    76	}
    77	
    78	// ForLabels invokes f with each label set on the context.
    79	// The function f should return true to continue iteration or false to stop iteration early.
    80	func ForLabels(ctx context.Context, f func(key, value string) bool) {
    81		ctxLabels := labelValue(ctx)
    82		for k, v := range ctxLabels {
    83			if !f(k, v) {
    84				break
    85			}
    86		}
    87	}
    88	

View as plain text