Documentation
¶
Overview ¶
Package loghttp provides HTTP middleware that derives a per-request logger from a base loglayer.LogLayer and stores it in the request context, so downstream handlers can log with request-scoped fields automatically.
Drop the middleware in once at server setup; every handler downstream gets a logger pre-populated with the request ID, method, and path.
mux := http.NewServeMux()
mux.HandleFunc("/users", handler)
http.ListenAndServe(":8080", loghttp.Middleware(log, loghttp.Config{})(mux))
func handler(w http.ResponseWriter, r *http.Request) {
log := loghttp.FromRequest(r)
log.Info("doing work") // includes requestId/method/path
}
Mirrors the role that hlog.NewHandler plays for zerolog.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FromRequest ¶
FromRequest returns the per-request logger stored in r's context, or nil if the middleware was not applied. Equivalent to loglayer.FromContext(r.Context()).
func Middleware ¶
Middleware returns an HTTP middleware that derives a per-request logger from log and stores it in the request context. Emits a "request completed" log line at the end of every request, with status code, bytes written, and duration in metadata. The base log is never mutated.
Pass a zero-value Config (loglayer.Config{}) to take the defaults; only set the fields you want to override.
func MustFromRequest ¶
MustFromRequest is FromRequest but panics if no logger is attached. Use it in handlers that always sit behind the middleware.
Types ¶
type Config ¶
type Config struct {
// RequestIDHeader is the HTTP header read for an incoming request ID.
// Defaults to "X-Request-ID".
RequestIDHeader string
// RequestIDGenerator is called when no incoming request-ID header is
// present. Defaults to 8 random bytes hex-encoded.
RequestIDGenerator func() string
// FieldNames overrides the keys used in the emitted logs. Empty
// fields here fall back to defaults; the middleware always emits all
// six.
FieldNames FieldNames
// StartLog emits a "request started" line at the beginning of every
// request, in addition to the "request completed" line at the end.
// Defaults to false to keep log volume low. Ignored when
// ShouldStartLog is non-nil.
StartLog bool
// ShouldStartLog, when non-nil, is consulted per request to decide
// whether to emit the "request started" line. Use it for sampling
// (e.g. log 1% of requests) or conditional logging (e.g. only when
// a debug header is set). Returning true emits the start line;
// false skips it. The "request completed" line still emits
// regardless. When ShouldStartLog is set, StartLog is ignored.
ShouldStartLog func(r *http.Request) bool
// StatusLevels picks a log level for the "request completed" line
// based on the response status code. Defaults to:
//
// - 5xx → LogLevelError
// - 4xx → LogLevelWarn
// - else → LogLevelInfo
StatusLevels func(status int) loglayer.LogLevel
// ExtraFields, if set, is called once per request to attach extra
// fields to the per-request logger. Useful for tenant/user/trace IDs
// extracted from the request.
ExtraFields func(*http.Request) loglayer.Fields
}
Config holds middleware configuration. All fields are optional; the zero-value Config gives you sensible defaults (X-Request-ID header, random fallback IDs, the standard six field names, no start-log, status → level mapping for 4xx/5xx).
type FieldNames ¶
type FieldNames struct {
RequestID string // default "requestId"
Method string // default "method"
Path string // default "path"
Status string // default "status"
DurationMs string // default "durationMs"
Bytes string // default "bytes"
}
FieldNames customizes the keys emitted by the middleware. Empty values fall back to the default for that field.