httpobs

package
v1.141.0 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package httpobs is what every inbound HTTP request reports (#1889): the route TEMPLATE it matched, its duration under that template, a server span named by it, a counter for every 429 a rate limiter answered, and a WARN line for a request slower than the deployment's threshold.

The template, never the path. A path is the caller's to choose, and a metric label or a span name that carried it would hold a series per invented path and personal data per real one. The template is the pattern the mux matched ("GET /api/v1/assets/{id}"), a closed set in the code.

The template is resolved before any handler runs, and refined by every nested mux the request descends into. An auth layer clones the request before the mux under it matches, so the pattern that mux writes onto its clone never reaches an outer middleware; Routed resolves a nested mux's pattern on the request as it arrives and records it in the scope the middleware installed, through a pointer a clone keeps.

Index

Constants

View Source
const (
	LimiterOAuthToken         = "oauth_token" // #nosec G101 -- a limiter's name, not a credential
	LimiterOAuthRegister      = "oauth_register"
	LimiterPortalViewer       = "portal_viewer"
	LimiterPortalContent      = "portal_content"
	LimiterPortalRefs         = "portal_refs"
	LimiterObservabilityProxy = "observability_proxy"
	LimiterPDFExport          = "pdf_export"
	LimiterWebhook            = "webhook"
	LimiterUnknown            = "unknown"
)

The HTTP rate limiters, as http_rate_limited_total{limiter} names them. A 429 no limiter marked is counted under LimiterUnknown, so an unmarked limiter shows up as a series rather than vanishing.

View Source
const DefaultSlowThreshold = 5 * time.Second

DefaultSlowThreshold is how long a request may take before it is logged as slow when server.slow_request_threshold is unset. The request that opened #1889 took 12 to 30 seconds and left no record of itself.

View Source
const RouteUnmatched = "unmatched"

RouteUnmatched is the route label of a request no registered pattern answered: a 404 or 405 from the mux, a CORS preflight the CORS layer answered before the mux, or a CONNECT (whose mux pattern is the raw path).

Variables

This section is empty.

Functions

func Detached

func Detached(ctx context.Context) context.Context

Detached is ctx without the request's scope, for a handler that serves a second route in-process on the caller's behalf (the PDF routes read their document through the content route beside them). Without it the nested route the re-entry reaches would report itself as the caller's route.

func MarkRateLimited

func MarkRateLimited(r *http.Request, limiter string)

MarkRateLimited records that limiter answered r with a 429, so the middleware counts the refusal under its name. A no-op outside the middleware.

func Middleware

func Middleware(cfg Config) func(http.Handler) http.Handler

Middleware is the outermost layer of a listener: it continues the caller's W3C trace context, opens the server span, installs the scope the handlers below report their template and refusals into, serves, and records what happened under the template. It wraps the CORS layer so a preflight is counted too.

func Routed

func Routed(mux *http.ServeMux, wrap func(http.Handler) http.Handler) http.Handler

Routed serves a nested mux behind wrap (an auth layer; nil for none) and reports the route template the request matched on it, twice over:

  • before wrap runs, the pattern mux would match is resolved and recorded, so a request the auth layer refuses still reports the template it was headed for, and the record survives the clone the auth layer makes;
  • after mux has served, the pattern written onto the request it served is recorded, which is the innermost one: a mux nested under mux again (the audit, knowledge and catalog muxes under the admin mux) serves the same request and overwrites it, and the mount prefix the first pass resolved gives way to the route itself.

A request mux does not match keeps the route an outer mux resolved. Outside the middleware (a handler driven directly in a test) Routed only serves.

Types

type Config

type Config struct {
	// Mux is the mux the wrapped handler serves from. It resolves the
	// template of a request no handler reported one for: a CORS preflight
	// the CORS layer answers before the mux runs. Nil for a listener with a
	// single handler, which names its route in Route.
	Mux *http.ServeMux
	// Route is the fixed template of a listener that serves one handler
	// with no mux (the webhook receiver's own listener, "/hooks/").
	Route string
	// Metrics receives the duration and the 429 count. Nil records nothing.
	Metrics *observability.Metrics
	// SlowThreshold is the duration past which a request is logged at WARN;
	// zero means DefaultSlowThreshold. A GET that opened an event stream is
	// never slow: its duration is how long the client listened. A POST
	// answered as an event stream (a streamable MCP message) is a request
	// and is.
	SlowThreshold time.Duration
}

Config is what the middleware records with.

Jump to

Keyboard shortcuts

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