import (
"context"
+ "fmt"
+ "sort"
+ "strings"
)
type label struct {
// that admits incremental immutable modification more efficiently.
type labelMap map[string]string
-// WithLabels returns a new context.Context with the given labels added.
+// String satisfies Stringer and returns key, value pairs in a consistent
+// order.
+func (l *labelMap) String() string {
+ if l == nil {
+ return ""
+ }
+ keyVals := make([]string, 0, len(*l))
+
+ for k, v := range *l {
+ keyVals = append(keyVals, fmt.Sprintf("%q:%q", k, v))
+ }
+
+ sort.Strings(keyVals)
+
+ return "{" + strings.Join(keyVals, ", ") + "}"
+}
+
+// WithLabels returns a new [context.Context] with the given labels added.
// A label overwrites a prior label with the same key.
func WithLabels(ctx context.Context, labels LabelSet) context.Context {
- childLabels := make(labelMap)
parentLabels := labelValue(ctx)
+ childLabels := make(labelMap, len(parentLabels))
// TODO(matloob): replace the map implementation with something
// more efficient so creating a child context WithLabels doesn't need
// to clone the map.
}
// Labels takes an even number of strings representing key-value pairs
-// and makes a LabelList containing them.
+// and makes a [LabelSet] containing them.
// A label overwrites a prior label with the same key.
+// Currently only the CPU and goroutine profiles utilize any labels
+// information.
+// See https://golang.org/issue/23458 for details.
func Labels(args ...string) LabelSet {
if len(args)%2 != 0 {
panic("uneven number of arguments to pprof.Labels")
}
- labels := LabelSet{}
+ list := make([]label, 0, len(args)/2)
for i := 0; i+1 < len(args); i += 2 {
- labels.list = append(labels.list, label{key: args[i], value: args[i+1]})
+ list = append(list, label{key: args[i], value: args[i+1]})
}
- return labels
+ return LabelSet{list: list}
}
// Label returns the value of the label with the given key on ctx, and a boolean indicating