Documentation ¶
Overview ¶
Package othttp provides a http.Handler and functions that are intended to be used to add tracing by wrapping existing handlers (with Handler) and routes WithRouteTag.
Index ¶
- Constants
- func NewHandler(handler http.Handler, operation string, opts ...Option) http.Handler
- func WithRouteTag(route string, h http.Handler) http.Handler
- type Config
- type Filter
- type Handler
- type Option
- func WithFilter(f Filter) Option
- func WithMessageEvents(events ...event) Option
- func WithPropagators(ps propagation.Propagators) Option
- func WithPublicEndpoint() Option
- func WithSpanNameFormatter(f func(operation string, r *http.Request) string) Option
- func WithSpanOptions(opts ...trace.StartOption) Option
- func WithTracer(tracer trace.Tracer) Option
- type OptionFunc
- type Transport
Examples ¶
Constants ¶
const ( HostKey = kv.Key("http.host") // the HTTP host (http.Request.Host) MethodKey = kv.Key("http.method") // the HTTP method (http.Request.Method) PathKey = kv.Key("http.path") // the HTTP path (http.Request.URL.Path) URLKey = kv.Key("http.url") // the HTTP URL (http.Request.URL.String()) UserAgentKey = kv.Key("http.user_agent") // the HTTP user agent (http.Request.UserAgent()) RouteKey = kv.Key("http.route") // the HTTP route (ex: /users/:id) RemoteAddrKey = kv.Key("http.remote_addr") // the network address of the client that sent the HTTP request (http.Request.RemoteAddr) StatusCodeKey = kv.Key("http.status_code") // if set, the HTTP status ReadBytesKey = kv.Key("http.read_bytes") // if anything was read from the request body, the total number of bytes read ReadErrorKey = kv.Key("http.read_error") // If an error occurred while reading a request, the string of the error (io.EOF is not recorded) WroteBytesKey = kv.Key("http.wrote_bytes") // if anything was written to the response writer, the total number of bytes written WriteErrorKey = kv.Key("http.write_error") // if an error occurred while writing a reply, the string of the error (io.EOF is not recorded) )
Attribute keys that can be added to a span.
const ( ReadEvents event = iota WriteEvents )
Different types of events that can be recorded, see WithMessageEvents
Variables ¶
This section is empty.
Functions ¶
func NewHandler ¶
NewHandler wraps the passed handler, functioning like middleware, in a span named after the operation and with any provided Options.
Example ¶
package main import ( "context" "fmt" "io" "io/ioutil" "log" "net/http" "strings" "go.opentelemetry.io/otel/api/kv" "go.opentelemetry.io/otel/api/global" "go.opentelemetry.io/otel/api/trace" "go.opentelemetry.io/otel/exporters/trace/stdout" "go.opentelemetry.io/otel/plugin/othttp" sdktrace "go.opentelemetry.io/otel/sdk/trace" ) func main() { /* curl -v -d "a painting" http://localhost:7777/hello/bob/ross ... * upload completely sent off: 10 out of 10 bytes < HTTP/1.1 200 OK < Traceparent: 00-76ae040ee5753f38edf1c2bd9bd128bd-dd394138cfd7a3dc-01 < Date: Fri, 04 Oct 2019 02:33:08 GMT < Content-Length: 45 < Content-Type: text/plain; charset=utf-8 < Hello, bob/ross! You sent me this: a painting */ // Write spans to stdout exporter, err := stdout.NewExporter(stdout.Options{PrettyPrint: true}) if err != nil { log.Fatal(err) } tp, err := sdktrace.NewProvider(sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}), sdktrace.WithSyncer(exporter)) if err != nil { log.Fatal(err) } global.SetTraceProvider(tp) figureOutName := func(ctx context.Context, s string) (string, error) { pp := strings.SplitN(s, "/", 2) var err error switch pp[1] { case "": err = fmt.Errorf("expected /hello/:name in %q", s) default: trace.SpanFromContext(ctx).SetAttributes(kv.String("name", pp[1])) } return pp[1], err } var mux http.ServeMux mux.Handle("/hello/", othttp.WithRouteTag("/hello/:name", http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var name string // Wrap another function in its own span if err := trace.SpanFromContext(ctx).Tracer().WithSpan(ctx, "figureOutName", func(ctx context.Context) error { var err error name, err = figureOutName(ctx, r.URL.Path[1:]) return err }); err != nil { log.Println("error figuring out name: ", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } d, err := ioutil.ReadAll(r.Body) if err != nil { log.Println("error reading body: ", err) w.WriteHeader(http.StatusBadRequest) return } n, err := io.WriteString(w, "Hello, "+name+"!\nYou sent me this:\n"+string(d)) if err != nil { log.Printf("error writing reply after %d bytes: %s", n, err) } }), ), ) if err := http.ListenAndServe(":7777", othttp.NewHandler(&mux, "server", othttp.WithMessageEvents(othttp.ReadEvents, othttp.WriteEvents), ), ); err != nil { log.Fatal(err) } }
Output:
Types ¶
type Config ¶ added in v0.5.0
type Config struct { Tracer trace.Tracer Propagators propagation.Propagators SpanStartOptions []trace.StartOption ReadEvent bool WriteEvent bool Filters []Filter SpanNameFormatter func(string, *http.Request) string }
Config represents the configuration options available for the othttp.Handler and othttp.Transport types.
type Filter ¶ added in v0.3.0
Filter is a predicate used to determine whether a given http.request should be traced. A Filter must return true if the request should be traced.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler is http middleware that corresponds to the http.Handler interface and is designed to wrap a http.Mux (or equivalent), while individual routes on the mux are wrapped with WithRouteTag. A Handler will add various attributes to the span using the kv.Keys defined in this package.
type Option ¶
type Option interface {
Apply(*Config)
}
Option Interface used for setting *optional* Config properties
func WithFilter ¶ added in v0.3.0
WithFilter adds a filter to the list of filters used by the handler. If any filter indicates to exclude a request then the request will not be traced. All filters must allow a request to be traced for a Span to be created. If no filters are provided then all requests are traced. Filters will be invoked for each processed request, it is advised to make them simple and fast.
func WithMessageEvents ¶
func WithMessageEvents(events ...event) Option
WithMessageEvents configures the Handler to record the specified events (span.AddEvent) on spans. By default only summary attributes are added at the end of the request.
Valid events are:
- ReadEvents: Record the number of bytes read after every http.Request.Body.Read using the ReadBytesKey
- WriteEvents: Record the number of bytes written after every http.ResponeWriter.Write using the WriteBytesKey
func WithPropagators ¶ added in v0.2.2
func WithPropagators(ps propagation.Propagators) Option
WithPropagators configures specific propagators. If this option isn't specified then go.opentelemetry.io/otel/api/global.Propagators are used.
func WithPublicEndpoint ¶
func WithPublicEndpoint() Option
WithPublicEndpoint configures the Handler to link the span with an incoming span context. If this option is not provided, then the association is a child association instead of a link.
func WithSpanNameFormatter ¶ added in v0.4.3
WithSpanNameFormatter takes a function that will be called on every request and the returned string will become the Span Name
func WithSpanOptions ¶
func WithSpanOptions(opts ...trace.StartOption) Option
WithSpanOptions configures an additional set of trace.StartOptions, which are applied to each new span.
func WithTracer ¶
WithTracer configures a specific tracer. If this option isn't specified then the global tracer is used.
type OptionFunc ¶ added in v0.5.0
type OptionFunc func(*Config)
OptionFunc provides a convenience wrapper for simple Options that can be represented as functions.
func (OptionFunc) Apply ¶ added in v0.5.0
func (o OptionFunc) Apply(c *Config)
type Transport ¶ added in v0.5.0
type Transport struct {
// contains filtered or unexported fields
}
Transport implements the http.RoundTripper interface and wraps outbound HTTP(S) requests with a span.
func NewTransport ¶ added in v0.5.0
func NewTransport(base http.RoundTripper, opts ...Option) *Transport
NewTransport wraps the provided http.RoundTripper with one that starts a span and injects the span context into the outbound request headers.
Example ¶
// Start with a working trace provider tp, err := sdktrace.NewProvider(sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()})) if err != nil { log.Fatal(err) } global.SetTraceProvider(tp) // Create an http.Client that uses the othttp.Transport // wrapped around the http.DefaultTransport client := http.Client{ Transport: NewTransport(http.DefaultTransport), } // Make a request with our tracing client response, err := client.Get("https://postman-echo.com/get") if err != nil { log.Fatal(err) } // Read the whole body and close it. The span created by the // othttp.Transport does not end until a read from the response // body returns io.EOF or the response body is closed. body, err := ioutil.ReadAll(response.Body) response.Body.Close() if err != nil { log.Fatal(err) } fmt.Printf("%s", body) // body should look like this, with a different "traceparent" value: // {"args":{},"headers":{"x-forwarded-proto":"https","host":"postman-echo.com","accept-encoding":"gzip","traceparent":"00-fb1d6775b94db561d9b51adbb3640de5-919c41073ec08f50-01","user-agent":"Go-http-client/1.1","x-forwarded-port":"443"},"url":"https://postman-echo.com/get"}
Output:
func (*Transport) RoundTrip ¶ added in v0.5.0
RoundTrip creates a Span and propagates its context via the provided request's headers before handing the request to the configured base RoundTripper. The created span will end when the response body is closed or when a read from the body returns io.EOF.