otelhttptrace

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 5, 2026 License: MIT Imports: 20 Imported by: 0

README

otelhttptrace

OpenTelemetry instrumentation for outgoing net/http requests with net/http/httptrace phase timings.

The package can work in two modes:

  • standalone: wrap an http.RoundTripper, start a client span for each request, and record DNS, TCP connect, TLS handshake, connection reuse, request write, and time-to-first-byte data as span events and attributes;
  • with go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp: record the same httptrace data on the span created by otelhttp.

Usage

client := &http.Client{
    Transport: otelhttptrace.NewTransport(http.DefaultTransport, otelhttptrace.Config{}),
}

resp, err := client.Get("https://example.com")
if err != nil {
    return err
}
defer resp.Body.Close()

Use Config to provide a non-global tracer provider, add default attributes, or customize span names:

client := &http.Client{
    Transport: otelhttptrace.NewTransport(
        nil,
        otelhttptrace.Config{
            TracerProvider: provider,
            Attributes: []attribute.KeyValue{
                attribute.String("service.component", "api-client"),
            },
            SpanNameFormatter: func(req *http.Request) string {
                return req.Method + " " + req.URL.Hostname()
            },
        },
    ),
}

Spans end when the response body is closed. This keeps the span duration aligned with the full response consumption instead of only the header round trip.

Usage with otelhttp

The preferred integration is to let otelhttp own the HTTP client span and pass this package's client trace factory to otelhttp.WithClientTrace:

client := &http.Client{
    Transport: otelhttp.NewTransport(
        http.DefaultTransport,
        otelhttp.WithClientTrace(otelhttptrace.NewClientTrace),
    ),
}

If you need this package to sit in the RoundTripper chain, set Config.SpanFromContext and make it the base transport for otelhttp:

client := &http.Client{
    Transport: otelhttp.NewTransport(
        otelhttptrace.NewTransport(
            http.DefaultTransport,
            otelhttptrace.Config{SpanFromContext: true},
        ),
    ),
}

In this mode otelhttptrace does not create or end a span. It only records httptrace events and timing attributes on the span already active in the request context.

Documentation

Overview

Package otelhttptrace instruments outgoing net/http requests with OpenTelemetry spans enriched by net/http/httptrace timing events.

The package can either wrap an http.RoundTripper and create one client span per request, or provide an httptrace.ClientTrace factory for instrumentation that already owns the HTTP client span. In the standalone mode, construct an http.Client with NewTransport and close each response body to finish the created span.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewClientTrace

func NewClientTrace(ctx context.Context) *httptrace.ClientTrace

NewClientTrace returns an httptrace.ClientTrace that records HTTP client phase events and timing attributes on the span active in ctx.

It is intended for use with instrumentation that already owns the HTTP client span, such as otelhttp.WithClientTrace. If ctx contains no recording span, the returned trace is still valid but records no telemetry.

Types

type Config

type Config struct {
	// TracerProvider creates standalone client spans.
	// If nil, the global OpenTelemetry tracer provider is used.
	TracerProvider trace.TracerProvider

	// Attributes are added to every standalone client span.
	Attributes []attribute.KeyValue

	// SpanNameFormatter formats standalone client span names.
	// If nil, spans are named "METHOD host".
	SpanNameFormatter SpanNameFormatter

	// SpanFromContext records httptrace events on the span already active in the
	// request context instead of starting and ending a standalone client span.
	// Use this when another instrumentation layer, such as otelhttp.Transport,
	// owns the HTTP client span.
	SpanFromContext bool
}

Config configures HTTP client tracing.

The zero value is valid. Call Resolve to apply defaults explicitly, or pass the config to NewTransport and it will be resolved before use.

func (Config) Resolve

func (c Config) Resolve() Config

Resolve returns a copy of c with defaults applied.

Resolve also copies Attributes so later mutations to the original slice do not affect the resolved configuration.

type SpanNameFormatter

type SpanNameFormatter func(*http.Request) string

SpanNameFormatter formats the name of a client span for an outgoing request.

type Transport

type Transport struct {
	// contains filtered or unexported fields
}

Transport instruments outgoing HTTP requests with OpenTelemetry spans and net/http/httptrace timing events.

A Transport may be used concurrently when its base RoundTripper and SpanNameFormatter are safe for concurrent use.

func NewTransport

func NewTransport(base http.RoundTripper, cfg Config) *Transport

NewTransport returns a Transport that records httptrace phases as span events and attributes.

If base is nil, http.DefaultTransport is used. By default the returned Transport creates a client span for each request and ends it when the response body is closed, or immediately when RoundTrip returns an error or a response without a body. If cfg.SpanFromContext is true, it records on the request's active span instead and does not create or end spans.

Example
package main

import (
	"net/http"

	"github.com/skarm/otelhttptrace"
)

func main() {
	client := &http.Client{
		Transport: otelhttptrace.NewTransport(http.DefaultTransport, otelhttptrace.Config{}),
	}

	_ = client
}

func (*Transport) RoundTrip

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip executes req through the base RoundTripper while recording httptrace events on the configured span.

RoundTrip returns an error for a nil request. In standalone mode, errors from the base RoundTripper and response body Close are recorded on the span and the original errors are returned unchanged.

Jump to

Keyboard shortcuts

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