labeler.go raw

   1  // Copyright The OpenTelemetry Authors
   2  // SPDX-License-Identifier: Apache-2.0
   3  
   4  package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
   5  
   6  import (
   7  	"context"
   8  	"sync"
   9  
  10  	"go.opentelemetry.io/otel/attribute"
  11  )
  12  
  13  // Labeler is used to allow instrumented HTTP handlers to add custom attributes to
  14  // the metrics recorded by the net/http instrumentation.
  15  type Labeler struct {
  16  	mu         sync.Mutex
  17  	attributes []attribute.KeyValue
  18  }
  19  
  20  // Add attributes to a Labeler.
  21  func (l *Labeler) Add(ls ...attribute.KeyValue) {
  22  	l.mu.Lock()
  23  	defer l.mu.Unlock()
  24  	l.attributes = append(l.attributes, ls...)
  25  }
  26  
  27  // Get returns a copy of the attributes added to the Labeler.
  28  func (l *Labeler) Get() []attribute.KeyValue {
  29  	l.mu.Lock()
  30  	defer l.mu.Unlock()
  31  	ret := make([]attribute.KeyValue, len(l.attributes))
  32  	copy(ret, l.attributes)
  33  	return ret
  34  }
  35  
  36  type labelerContextKeyType int
  37  
  38  const labelerContextKey labelerContextKeyType = 0
  39  
  40  // ContextWithLabeler returns a new context with the provided Labeler instance.
  41  // Attributes added to the specified labeler will be injected into metrics
  42  // emitted by the instrumentation. Only one labeller can be injected into the
  43  // context. Injecting it multiple times will override the previous calls.
  44  func ContextWithLabeler(parent context.Context, l *Labeler) context.Context {
  45  	return context.WithValue(parent, labelerContextKey, l)
  46  }
  47  
  48  // LabelerFromContext retrieves a Labeler instance from the provided context if
  49  // one is available.  If no Labeler was found in the provided context a new, empty
  50  // Labeler is returned and the second return value is false.  In this case it is
  51  // safe to use the Labeler but any attributes added to it will not be used.
  52  func LabelerFromContext(ctx context.Context) (*Labeler, bool) {
  53  	l, ok := ctx.Value(labelerContextKey).(*Labeler)
  54  	if !ok {
  55  		l = &Labeler{}
  56  	}
  57  	return l, ok
  58  }
  59