apmhttp

package module
v1.15.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 8, 2021 License: Apache-2.0 Imports: 16 Imported by: 130

Documentation

Overview

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

Index

Examples

Constants

View Source
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

func ClientRequestName(req *http.Request) string

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

func IgnoreNone(*http.Request) bool

IgnoreNone is a RequestIgnorerFunc which ignores no requests.

func ParseTraceparentHeader

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:

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 added in v1.7.0

func ParseTracestateHeader(h ...string) (apm.TraceState, error)

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

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

func ServerRequestName(req *http.Request) string

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

func SetContext

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 SetHeaders added in v1.14.0

func SetHeaders(req *http.Request, traceContext apm.TraceContext, propagateLegacyHeader bool)

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 added in v1.12.0

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

func StatusCodeResult(statusCode int) string

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

func UnknownRouteRequestName added in v1.4.0

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

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"

	"go.elastic.co/apm/apmtest"
	"go.elastic.co/apm/module/apmhttp"
)

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 added in v1.6.0

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 added in v1.14.0

func WithClientSpanType(spanType string) ClientOption

WithClientSpanType sets the span type for HTTP client requests.

Defaults to "external.http".

func WithClientTrace added in v1.9.0

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

type RequestIgnorerFunc func(*http.Request) bool

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

func DefaultServerRequestIgnorer

func DefaultServerRequestIgnorer() RequestIgnorerFunc

DefaultServerRequestIgnorer returns the default RequestIgnorer to use in handlers. If ELASTIC_APM_TRANSACTION_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.

DEPRECATED. Use NewDynamicServerRequestIgnorer instead

func NewDynamicServerRequestIgnorer added in v1.11.0

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.

func NewWildcardPatternsRequestIgnorer

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

type RequestNameFunc func(*http.Request) string

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 added in v1.6.0

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL