tracking

package
v0.37.0 Latest Latest
Warning

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

Go to latest
Published: May 27, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecActiveRequests

func DecActiveRequests(ctx context.Context, peer, method, addr string)

DecActiveRequests decrements the http.client.active_requests counter. Call this after the request completes (in a defer alongside IncActiveRequests). addr is the server hostname (server.address, omitted when empty).

func EndHTTPClientSpan

func EndHTTPClientSpan(span trace.Span, statusCode int, errType string, responseBytes int, err error)

EndHTTPClientSpan applies the final response/error attributes and the status mapping, then ends the span. statusCode == 0 signals a transport error (no response received).

Status mapping (OTel HTTP client semantic conventions):

  • 100-499 (incl. 4xx) without err → status unset (default OK).
  • 500-599 → codes.Error, message "HTTP {code}".
  • transport error (statusCode == 0) → codes.Error, message = error.type.
  • any err != nil regardless of statusCode → RecordError(err) + error.type attribute. Without this, callers that pass (status, errType, err) for non-transport failures (e.g. response interceptor errors on an HTTP 200, or HTTPError wrappers on a final 5xx) would lose the error attribution that the parallel metric path records — see RecordHTTPClientMetrics.

The 4xx-as-OK rule is the OTel *client* convention — a 4xx without a transport/interceptor error is a normal flow-control response from the server, not a client-side fault. A 4xx with err (e.g. a build-failure classified as interceptor_failed) does take the error path so the failure surfaces in the span.

On nil-or-no-op span, the call is a zero-cost no-op.

func IncActiveRequests

func IncActiveRequests(ctx context.Context, peer, method, addr string)

IncActiveRequests increments the http.client.active_requests counter. Call this immediately before sending a request. peer is the peer.service value (omitted when empty); method is the HTTP method; addr is the server hostname (server.address, omitted when empty).

func IncRetry

func IncRetry(ctx context.Context, peer, method, reason string)

IncRetry increments the http.client.retries.total counter. peer is the peer.service value (omitted when empty); method is the HTTP method (normalized via canonicalMethod); reason should be one of: "timeout", "5xx", "network", "build_response".

func InitHTTPMeter

func InitHTTPMeter()

InitHTTPMeter initializes the HTTP client meter idempotently. Subsequent calls after the first are no-ops. Holds meterInitMu so that concurrent calls and ResetMeterForTesting cannot race on meterOnce.

func InitHTTPTracer

func InitHTTPTracer()

InitHTTPTracer initializes the HTTP client tracer idempotently. Subsequent calls after the first are no-ops. Holds tracerInitMu so concurrent calls and ResetTracerForTesting cannot race on tracerOnce.

func RecordHTTPClientMetrics

func RecordHTTPClientMetrics(ctx context.Context, m *HTTPClientMeasurement)

RecordHTTPClientMetrics records all per-request OTel metrics after a request completes. It emits:

  • http.client.request.duration (seconds)
  • http.client.request.body.size (bytes, when > 0)
  • http.client.response.body.size (bytes, when > 0)

func ResetMeterForTesting

func ResetMeterForTesting()

ResetMeterForTesting resets the package-level meter state so each test starts with a fresh meter. This is intended for use by httpclient package tests that cannot access the unexported meter state directly. Safe to call concurrently with InitHTTPMeter — the mutex serializes both paths.

func ResetTracerForTesting

func ResetTracerForTesting()

ResetTracerForTesting resets the package-level tracer state so each test starts with a fresh tracer. Mirrors ResetMeterForTesting. Safe to call concurrently with InitHTTPTracer — the mutex serialises both paths.

func StartHTTPClientSpan

func StartHTTPClientSpan(ctx context.Context, info *HTTPSpanInfo) (context.Context, trace.Span)

StartHTTPClientSpan opens a CLIENT-kind span as a child of any active span on ctx. Returns the new context (with the span attached) and the span itself.

When the global tracer provider is a no-op (observability.enabled: false), `otel.Tracer(...)` returns a no-op tracer and the returned span is non-recording — every span method becomes a no-op and the per-request cost reduces to one cached lookup.

The same function serves both the parent "Do" span (info.ResendCount = 0) and per-attempt spans (info.ResendCount = attempt index). Caller decides by passing the appropriate context and info.

Note: we deliberately do NOT fall back to `trace.SpanFromContext(ctx)` even if httpTracer were nil — that would return whatever upstream span lives on ctx (e.g. the surrounding server-request span), and the caller's subsequent `EndHTTPClientSpan` would erroneously call `.End()` on that parent, corrupting its lifecycle. `otel.Tracer()` is documented to never return nil, so init is always sufficient; the only nil-safety we keep is on the returned span via `EndHTTPClientSpan`'s `span == nil` guard, which covers callers passing a literal nil (not relevant here but cheap to keep).

Types

type HTTPClientMeasurement

type HTTPClientMeasurement struct {
	// PeerName is the logical peer service name (peer.service). Omitted when empty.
	PeerName string
	// Method is the HTTP method (uppercase canonical; unknown methods → "_OTHER").
	Method string
	// URL is the request URL, used to extract server.address, server.port, and url.scheme.
	URL *url.URL
	// StatusCode is the HTTP response status code. 0 means a transport error (no response).
	StatusCode int
	// ErrorType is the OTel error.type enum value. Empty string on success.
	ErrorType string
	// ResendCount is the number of prior attempts (0 = first attempt).
	ResendCount int
	// Elapsed is the total request duration, recorded as seconds in the histogram.
	Elapsed time.Duration
	// RequestBytes is the request body size in bytes. Skipped when 0.
	RequestBytes int
	// ResponseBytes is the response body size in bytes. Skipped when 0.
	ResponseBytes int
}

HTTPClientMeasurement carries all per-request data needed to emit OTel metrics.

type HTTPSpanInfo

type HTTPSpanInfo struct {
	// PeerName is the logical peer service name (peer.service). Omitted when empty.
	PeerName string
	// Method is the HTTP method (canonicalised to uppercase; "_OTHER" for non-standard).
	Method string
	// URL provides server.address, server.port, url.scheme, and url.path.
	URL *url.URL
	// ResendCount is the number of prior attempts (0 = first). Omitted when 0,
	// and always omitted on the parent "Do" span (the logical rollup).
	ResendCount int
}

HTTPSpanInfo carries the per-span data needed to construct a CLIENT-kind span for an outbound HTTP call. It is the span-side twin of HTTPClientMeasurement; every span-eligible field on the measurement also lives here.

Jump to

Keyboard shortcuts

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