...

Source file src/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go

Documentation: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp

     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  	"net/http"
     9  	"net/http/httptrace"
    10  
    11  	"go.opentelemetry.io/otel"
    12  	"go.opentelemetry.io/otel/metric"
    13  	"go.opentelemetry.io/otel/propagation"
    14  	"go.opentelemetry.io/otel/trace"
    15  )
    16  
    17  // ScopeName is the instrumentation scope name.
    18  const ScopeName = "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
    19  
    20  // config represents the configuration options available for the http.Handler
    21  // and http.Transport types.
    22  type config struct {
    23  	ServerName        string
    24  	Tracer            trace.Tracer
    25  	Meter             metric.Meter
    26  	Propagators       propagation.TextMapPropagator
    27  	SpanStartOptions  []trace.SpanStartOption
    28  	PublicEndpoint    bool
    29  	PublicEndpointFn  func(*http.Request) bool
    30  	ReadEvent         bool
    31  	WriteEvent        bool
    32  	Filters           []Filter
    33  	SpanNameFormatter func(string, *http.Request) string
    34  	ClientTrace       func(context.Context) *httptrace.ClientTrace
    35  
    36  	TracerProvider trace.TracerProvider
    37  	MeterProvider  metric.MeterProvider
    38  }
    39  
    40  // Option interface used for setting optional config properties.
    41  type Option interface {
    42  	apply(*config)
    43  }
    44  
    45  type optionFunc func(*config)
    46  
    47  func (o optionFunc) apply(c *config) {
    48  	o(c)
    49  }
    50  
    51  // newConfig creates a new config struct and applies opts to it.
    52  func newConfig(opts ...Option) *config {
    53  	c := &config{
    54  		Propagators:   otel.GetTextMapPropagator(),
    55  		MeterProvider: otel.GetMeterProvider(),
    56  	}
    57  	for _, opt := range opts {
    58  		opt.apply(c)
    59  	}
    60  
    61  	// Tracer is only initialized if manually specified. Otherwise, can be passed with the tracing context.
    62  	if c.TracerProvider != nil {
    63  		c.Tracer = newTracer(c.TracerProvider)
    64  	}
    65  
    66  	c.Meter = c.MeterProvider.Meter(
    67  		ScopeName,
    68  		metric.WithInstrumentationVersion(Version()),
    69  	)
    70  
    71  	return c
    72  }
    73  
    74  // WithTracerProvider specifies a tracer provider to use for creating a tracer.
    75  // If none is specified, the global provider is used.
    76  func WithTracerProvider(provider trace.TracerProvider) Option {
    77  	return optionFunc(func(cfg *config) {
    78  		if provider != nil {
    79  			cfg.TracerProvider = provider
    80  		}
    81  	})
    82  }
    83  
    84  // WithMeterProvider specifies a meter provider to use for creating a meter.
    85  // If none is specified, the global provider is used.
    86  func WithMeterProvider(provider metric.MeterProvider) Option {
    87  	return optionFunc(func(cfg *config) {
    88  		if provider != nil {
    89  			cfg.MeterProvider = provider
    90  		}
    91  	})
    92  }
    93  
    94  // WithPublicEndpoint configures the Handler to link the span with an incoming
    95  // span context. If this option is not provided, then the association is a child
    96  // association instead of a link.
    97  func WithPublicEndpoint() Option {
    98  	return optionFunc(func(c *config) {
    99  		c.PublicEndpoint = true
   100  	})
   101  }
   102  
   103  // WithPublicEndpointFn runs with every request, and allows conditionnally
   104  // configuring the Handler to link the span with an incoming span context. If
   105  // this option is not provided or returns false, then the association is a
   106  // child association instead of a link.
   107  // Note: WithPublicEndpoint takes precedence over WithPublicEndpointFn.
   108  func WithPublicEndpointFn(fn func(*http.Request) bool) Option {
   109  	return optionFunc(func(c *config) {
   110  		c.PublicEndpointFn = fn
   111  	})
   112  }
   113  
   114  // WithPropagators configures specific propagators. If this
   115  // option isn't specified, then the global TextMapPropagator is used.
   116  func WithPropagators(ps propagation.TextMapPropagator) Option {
   117  	return optionFunc(func(c *config) {
   118  		if ps != nil {
   119  			c.Propagators = ps
   120  		}
   121  	})
   122  }
   123  
   124  // WithSpanOptions configures an additional set of
   125  // trace.SpanOptions, which are applied to each new span.
   126  func WithSpanOptions(opts ...trace.SpanStartOption) Option {
   127  	return optionFunc(func(c *config) {
   128  		c.SpanStartOptions = append(c.SpanStartOptions, opts...)
   129  	})
   130  }
   131  
   132  // WithFilter adds a filter to the list of filters used by the handler.
   133  // If any filter indicates to exclude a request then the request will not be
   134  // traced. All filters must allow a request to be traced for a Span to be created.
   135  // If no filters are provided then all requests are traced.
   136  // Filters will be invoked for each processed request, it is advised to make them
   137  // simple and fast.
   138  func WithFilter(f Filter) Option {
   139  	return optionFunc(func(c *config) {
   140  		c.Filters = append(c.Filters, f)
   141  	})
   142  }
   143  
   144  type event int
   145  
   146  // Different types of events that can be recorded, see WithMessageEvents.
   147  const (
   148  	ReadEvents event = iota
   149  	WriteEvents
   150  )
   151  
   152  // WithMessageEvents configures the Handler to record the specified events
   153  // (span.AddEvent) on spans. By default only summary attributes are added at the
   154  // end of the request.
   155  //
   156  // Valid events are:
   157  //   - ReadEvents: Record the number of bytes read after every http.Request.Body.Read
   158  //     using the ReadBytesKey
   159  //   - WriteEvents: Record the number of bytes written after every http.ResponeWriter.Write
   160  //     using the WriteBytesKey
   161  func WithMessageEvents(events ...event) Option {
   162  	return optionFunc(func(c *config) {
   163  		for _, e := range events {
   164  			switch e {
   165  			case ReadEvents:
   166  				c.ReadEvent = true
   167  			case WriteEvents:
   168  				c.WriteEvent = true
   169  			}
   170  		}
   171  	})
   172  }
   173  
   174  // WithSpanNameFormatter takes a function that will be called on every
   175  // request and the returned string will become the Span Name.
   176  func WithSpanNameFormatter(f func(operation string, r *http.Request) string) Option {
   177  	return optionFunc(func(c *config) {
   178  		c.SpanNameFormatter = f
   179  	})
   180  }
   181  
   182  // WithClientTrace takes a function that returns client trace instance that will be
   183  // applied to the requests sent through the otelhttp Transport.
   184  func WithClientTrace(f func(context.Context) *httptrace.ClientTrace) Option {
   185  	return optionFunc(func(c *config) {
   186  		c.ClientTrace = f
   187  	})
   188  }
   189  
   190  // WithServerName returns an Option that sets the name of the (virtual) server
   191  // handling requests.
   192  func WithServerName(server string) Option {
   193  	return optionFunc(func(c *config) {
   194  		c.ServerName = server
   195  	})
   196  }
   197  

View as plain text