Documentation ¶
Overview ¶
Package apmhttp provides a tracing middleware http.Handler for servers, and a tracing http.RoundTripper for clients.
Index ¶
- Constants
- func ClientRequestName(req *http.Request) string
- func FormatTraceparentHeader(c apm.TraceContext) string
- func IgnoreNone(*http.Request) bool
- func ParseTraceparentHeader(h string) (apm.TraceContext, error)
- func ParseTracestateHeader(h ...string) (apm.TraceState, error)
- func RequestWithContext(ctx context.Context, req *http.Request) *http.Request
- func ServerRequestName(req *http.Request) string
- func SetContext(ctx *apm.Context, req *http.Request, resp *Response, body *apm.BodyCapturer)
- func SetHeaders(req *http.Request, traceContext apm.TraceContext, propagateLegacyHeader bool)
- func SetTransactionContext(tx *apm.Transaction, req *http.Request, resp *Response, body *apm.BodyCapturer)
- func StartTransaction(tracer *apm.Tracer, name string, req *http.Request) (*apm.Transaction, *http.Request)
- func StartTransactionWithBody(tracer *apm.Tracer, name string, req *http.Request) (*apm.Transaction, *apm.BodyCapturer, *http.Request)
- func StatusCodeResult(statusCode int) string
- func UnknownRouteRequestName(req *http.Request) string
- func Wrap(h http.Handler, o ...ServerOption) http.Handler
- func WrapClient(c *http.Client, o ...ClientOption) *http.Client
- func WrapRoundTripper(r http.RoundTripper, o ...ClientOption) http.RoundTripper
- type ClientOption
- type RecoveryFunc
- type RequestIgnorerFunc
- type RequestNameFunc
- type Response
- type ServerOption
Examples ¶
Constants ¶
const ( // TraceparentHeader is the HTTP header for trace propagation. // // For backwards compatibility, this is currently an alias for // for ElasticTraceparentHeader, but the more specific constants // below should be preferred. In a future version this will be // replaced by the standard W3C header. TraceparentHeader = ElasticTraceparentHeader // ElasticTraceparentHeader is the legacy HTTP header for trace propagation, // maintained for backwards compatibility with older agents. ElasticTraceparentHeader = "Elastic-Apm-Traceparent" // W3CTraceparentHeader is the standard W3C Trace-Context HTTP // header for trace propagation. W3CTraceparentHeader = "Traceparent" // TracestateHeader is the standard W3C Trace-Context HTTP header // for vendor-specific trace propagation. TracestateHeader = "Tracestate" )
Variables ¶
This section is empty.
Functions ¶
func ClientRequestName ¶
ClientRequestName returns the span name for the client request, req.
func FormatTraceparentHeader ¶
func FormatTraceparentHeader(c apm.TraceContext) string
FormatTraceparentHeader formats the given trace context as a traceparent header.
func IgnoreNone ¶
IgnoreNone is a RequestIgnorerFunc which ignores no requests.
func ParseTraceparentHeader ¶
ParseTraceparentHeader parses the given header, which is expected to be in the W3C Trace-Context traceparent format according to W3C Editor's Draft 23 May 2018:
https://w3c.github.io/trace-context/#traceparent-field
Note that the returned TraceContext's Trace and Span fields are not necessarily valid. The caller must decide whether or not it wishes to disregard invalid trace/span IDs, and validate them as required using their provided Validate methods.
The returned TraceContext's TraceState field will be the empty value. Use ParseTracestateHeader to parse that separately.
func ParseTracestateHeader ¶
ParseTracestateHeader parses the given header, which is expected to be in the W3C Trace-Context tracestate format according to W3C Editor's Draft 18 Nov 2019:
https://w3c.github.io/trace-context/#tracestate-header
Note that the returned TraceState is not necessarily valid. The caller must decide whether or not it wishes to disregard invalid tracestate entries, and validate them as required using their provided Validate methods.
Multiple header values may be presented, in which case they will be treated as if they are concatenated together with commas.
func RequestWithContext ¶
RequestWithContext is equivalent to req.WithContext, except that the URL pointer is copied, rather than the contents.
func ServerRequestName ¶
ServerRequestName returns the transaction name for the server request, req.
func SetContext ¶
SetContext sets the context for a transaction or error using information from req, resp, and body.
func SetHeaders ¶
SetHeaders sets traceparent and tracestate headers on an http request.
func SetTransactionContext ¶
func SetTransactionContext(tx *apm.Transaction, req *http.Request, resp *Response, body *apm.BodyCapturer)
SetTransactionContext sets tx.Result and, if the transaction is being sampled, sets tx.Context with information from req, resp, and body.
func StartTransaction ¶
func StartTransaction(tracer *apm.Tracer, name string, req *http.Request) (*apm.Transaction, *http.Request)
StartTransaction returns a new Transaction with name, created with tracer, and taking trace context from req.
If the transaction is not ignored, the request will be returned with the transaction added to its context.
DEPRECATED. Use StartTransactionWithBody instead.
func StartTransactionWithBody ¶
func StartTransactionWithBody(tracer *apm.Tracer, name string, req *http.Request) (*apm.Transaction, *apm.BodyCapturer, *http.Request)
StartTransactionWithBody returns a new Transaction with name, created with tracer, and taking trace context from req.
If the transaction is not ignored, the request and the request body capturer will be returned with the transaction added to its context.
func StatusCodeResult ¶
StatusCodeResult returns the transaction result value to use for the given status code.
func UnknownRouteRequestName ¶
UnknownRouteRequestName returns the transaction name for the server request, req, when the route could not be determined.
func Wrap ¶
func Wrap(h http.Handler, o ...ServerOption) http.Handler
Wrap returns an http.Handler wrapping h, reporting each request as a transaction to Elastic APM.
By default, the returned Handler will use apm.DefaultTracer(). Use WithTracer to specify an alternative tracer.
By default, the returned Handler will recover panics, reporting them to the configured tracer. To override this behaviour, use WithRecovery.
func WrapClient ¶
func WrapClient(c *http.Client, o ...ClientOption) *http.Client
WrapClient returns a new *http.Client with all fields copied across, and the Transport field wrapped with WrapRoundTripper such that client requests are reported as spans to Elastic APM if their context contains a sampled transaction.
Spans are started just before the request is sent, and ended immediately if the request returned an error (e.g. due to socket timeout, but not a valid response with a non-200 status code), or otherwise when the response body is fully consumed or closed.
If c is nil, then http.DefaultClient is wrapped.
Example ¶
// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package main import ( "context" "fmt" "io/ioutil" "log" "net/http" "net/http/httptest" "time" "github.com/waldiirawan/apm-agent-go/module/apmhttp/v2" "github.com/waldiirawan/apm-agent-go/v2/apmtest" ) func main() { mux := http.NewServeMux() mux.HandleFunc("/slow", serveSlowly) server := httptest.NewServer(mux) defer server.Close() // Wrap the HTTP client with apmhttp.WrapClient. When using the // wrapped client, any request whose context contains a transaction // will have a span reported. client := apmhttp.WrapClient(http.DefaultClient) slowReq, _ := http.NewRequest("GET", server.URL+"/slow", nil) errorReq, _ := http.NewRequest("GET", "http://testing.invalid", nil) _, spans, _ := apmtest.WithTransaction(func(ctx context.Context) { // Propagate context with the outgoing request. req := slowReq.WithContext(ctx) resp, err := client.Do(req) if err != nil { log.Fatal(err) } // In the case where the request succeeds (i.e. no error // was returned above; unrelated to the HTTP status code), // the span is not ended until the body is consumed. body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Printf("response: %s\n", body) // Send a request to a URL with an unresolvable host. This // will cause the entire request to fail, immediately // ending the span. resp, err = client.Do(errorReq.WithContext(ctx)) if err != nil { fmt.Println("error occurred") } else { resp.Body.Close() } }) if len(spans) != 2 { fmt.Println(len(spans), "spans") } else { for i, span := range spans { const expectedFloor = 250 * time.Millisecond if time.Duration(span.Duration*float64(time.Millisecond)) >= expectedFloor { // This is the expected case (see output below). As noted // previously, the span is only ended once the response body // has been consumed (or closed). fmt.Printf("span #%d duration >= %s\n", i+1, expectedFloor) } else { fmt.Printf("span #%d duration < %s\n", i+1, expectedFloor) } } } } func serveSlowly(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusTeapot) if f, ok := w.(http.Flusher); ok { f.Flush() } time.Sleep(250 * time.Millisecond) w.Write([]byte("*yawn*")) }
Output: response: *yawn* error occurred span #1 duration >= 250ms span #2 duration < 250ms
func WrapRoundTripper ¶
func WrapRoundTripper(r http.RoundTripper, o ...ClientOption) http.RoundTripper
WrapRoundTripper returns an http.RoundTripper wrapping r, reporting each request as a span to Elastic APM, if the request's context contains a sampled transaction.
If r is nil, then http.DefaultTransport is wrapped.
Types ¶
type ClientOption ¶
type ClientOption func(*roundTripper)
ClientOption sets options for tracing client requests.
func WithClientRequestName ¶
func WithClientRequestName(r RequestNameFunc) ClientOption
WithClientRequestName returns a ClientOption which sets r as the function to use to obtain the span name for the given http request.
func WithClientSpanType ¶
func WithClientSpanType(spanType string) ClientOption
WithClientSpanType sets the span type for HTTP client requests.
Defaults to "external.http".
func WithClientTrace ¶
func WithClientTrace() ClientOption
WithClientTrace returns a ClientOption for tracing events within HTTP client requests.
type RecoveryFunc ¶
type RecoveryFunc func( w http.ResponseWriter, req *http.Request, resp *Response, body *apm.BodyCapturer, tx *apm.Transaction, recovered interface{}, )
RecoveryFunc is the type of a function for use in WithRecovery.
func NewTraceRecovery ¶
func NewTraceRecovery(t *apm.Tracer) RecoveryFunc
NewTraceRecovery returns a RecoveryFunc for use in WithRecovery.
The returned RecoveryFunc will report recovered error to Elastic APM using the given Tracer, or apm.DefaultTracer() if t is nil. The error will be linked to the given transaction.
If headers have not already been written, a 500 response will be sent.
type RequestIgnorerFunc ¶
RequestIgnorerFunc is the type of a function for use in WithServerRequestIgnorer.
func NewDynamicServerRequestIgnorer ¶
func NewDynamicServerRequestIgnorer(t *apm.Tracer) RequestIgnorerFunc
NewDynamicServerRequestIgnorer returns the RequestIgnorer to use in handlers. The list of wildcard patterns comes from central config
func NewRegexpRequestIgnorer ¶
func NewRegexpRequestIgnorer(re *regexp.Regexp) RequestIgnorerFunc
NewRegexpRequestIgnorer returns a RequestIgnorerFunc which matches requests' URLs against re. Note that for server requests, typically only Path and possibly RawQuery will be set, so the regular expression should take this into account.
type RequestNameFunc ¶
RequestNameFunc is the type of a function for use in WithServerRequestName.
type Response ¶
type Response struct { // StatusCode records the HTTP status code set via WriteHeader. StatusCode int // Headers holds the headers set in the ResponseWriter. Headers http.Header }
Response records details of the HTTP response.
func WrapResponseWriter ¶
func WrapResponseWriter(w http.ResponseWriter) (http.ResponseWriter, *Response)
WrapResponseWriter wraps an http.ResponseWriter and returns the wrapped value along with a *Response which will be filled in when the handler is called. The *Response value must not be inspected until after the request has been handled, to avoid data races. If neither of the ResponseWriter's Write or WriteHeader methods are called, then the response's StatusCode field will be zero.
The returned http.ResponseWriter implements http.Pusher, http.Hijacker, and io.ReaderFrom if and only if the provided http.ResponseWriter does.
type ServerOption ¶
type ServerOption func(*handler)
ServerOption sets options for tracing server requests.
func WithPanicPropagation ¶
func WithPanicPropagation() ServerOption
WithPanicPropagation returns a ServerOption which enable panic propagation. Any panic will be recovered and recorded as an error in a transaction, then panic will be caused again.
func WithRecovery ¶
func WithRecovery(r RecoveryFunc) ServerOption
WithRecovery returns a ServerOption which sets r as the recovery function to use for tracing server requests.
func WithServerRequestIgnorer ¶
func WithServerRequestIgnorer(r RequestIgnorerFunc) ServerOption
WithServerRequestIgnorer returns a ServerOption which sets r as the function to use to determine whether or not a server request should be ignored. If r is nil, all requests will be reported.
func WithServerRequestName ¶
func WithServerRequestName(r RequestNameFunc) ServerOption
WithServerRequestName returns a ServerOption which sets r as the function to use to obtain the transaction name for the given server request.
func WithTracer ¶
func WithTracer(t *apm.Tracer) ServerOption
WithTracer returns a ServerOption which sets t as the tracer to use for tracing server requests.