apm-agent-go: github.com/elastic/apm-agent-go/module/apmhttp Index | Examples | Files

package apmhttp

import "github.com/elastic/apm-agent-go/module/apmhttp"

Package apmhttp provides a tracing middleware http.Handler for servers, and a tracing http.RoundTripper for clients.



Package Files

client.go context.go doc.go handler.go ignorer.go recovery.go requestname.go traceheaders.go


const (
    // TraceparentHeader is the HTTP header for trace propagation.
    // NOTE: at this time, the W3C Trace-Context headers are not finalised.
    // To avoid producing possibly invalid traceparent headers, we will
    // use an alternative name until the format is frozen.
    TraceparentHeader = "Elastic-Apm-Traceparent"

func ClientRequestName Uses

func ClientRequestName(req *http.Request) string

ClientRequestName returns the span name for the client request, req.

func FormatTraceparentHeader Uses

func FormatTraceparentHeader(c apm.TraceContext) string

FormatTraceparentHeader formats the given trace context as a traceparent header.

func IgnoreNone Uses

func IgnoreNone(*http.Request) bool

IgnoreNone is a RequestIgnorerFunc which ignores no requests.

func ParseTraceparentHeader Uses

func ParseTraceparentHeader(h string) (apm.TraceContext, error)

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:


Note that the returned TraceParent'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.

func RequestWithContext Uses

func RequestWithContext(ctx context.Context, req *http.Request) *http.Request

RequestWithContext is equivalent to req.WithContext, except that the URL pointer is copied, rather than the contents.

func ServerRequestName Uses

func ServerRequestName(req *http.Request) string

ServerRequestName returns the transaction name for the server request, req.

func SetContext Uses

func SetContext(ctx *apm.Context, req *http.Request, resp *Response, body *apm.BodyCapturer)

SetContext sets the context for a transaction or error using information from req, resp, and body.

func SetTransactionContext Uses

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 Uses

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.

func StatusCodeResult Uses

func StatusCodeResult(statusCode int) string

StatusCodeResult returns the transaction result value to use for the given status code.

func UnknownRouteRequestName Uses

func UnknownRouteRequestName(req *http.Request) string

UnknownRouteRequestName returns the transaction name for the server request, req, when the route could not be determined.

func Wrap Uses

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 Uses

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.


// 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
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

package main

import (


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 {

        // 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 {
        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 {

    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) {
    if f, ok := w.(http.Flusher); ok {
    time.Sleep(250 * time.Millisecond)

func WrapRoundTripper Uses

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.

type ClientOption Uses

type ClientOption func(*roundTripper)

ClientOption sets options for tracing client requests.

func WithClientRequestName Uses

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.

type RecoveryFunc Uses

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 Uses

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 Uses

type RequestIgnorerFunc func(*http.Request) bool

RequestIgnorerFunc is the type of a function for use in WithServerRequestIgnorer.

func DefaultServerRequestIgnorer Uses

func DefaultServerRequestIgnorer() RequestIgnorerFunc

DefaultServerRequestIgnorer returns the default RequestIgnorer to use in handlers. If ELASTIC_APM_IGNORE_URLS is set, it will be treated as a comma-separated list of wildcard patterns; requests that match any of the patterns will be ignored.

func NewRegexpRequestIgnorer Uses

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.

func NewWildcardPatternsRequestIgnorer Uses

func NewWildcardPatternsRequestIgnorer(matchers wildcard.Matchers) RequestIgnorerFunc

NewWildcardPatternsRequestIgnorer returns a RequestIgnorerFunc which matches requests' URLs against any of the matchers. Note that for server requests, typically only Path and possibly RawQuery will be set, so the wildcard patterns should take this into account.

type RequestNameFunc Uses

type RequestNameFunc func(*http.Request) string

RequestNameFunc is the type of a function for use in WithServerRequestName.

type Response Uses

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 Uses

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 and http.Hijacker if and only if the provided http.ResponseWriter does.

type ServerOption Uses

type ServerOption func(*handler)

ServerOption sets options for tracing server requests.

func WithPanicPropagation Uses

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 Uses

func WithRecovery(r RecoveryFunc) ServerOption

WithRecovery returns a ServerOption which sets r as the recovery function to use for tracing server requests.

func WithServerRequestIgnorer Uses

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 Uses

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 Uses

func WithTracer(t *apm.Tracer) ServerOption

WithTracer returns a ServerOption which sets t as the tracer to use for tracing server requests.

Package apmhttp imports 14 packages (graph). Updated 2019-10-21. Refresh now. Tools for package owners.