Documentation ¶
Overview ¶
Package middleware has HTTP server middleware that provides access to a shared logger and simplifies writing canonical log lines with a shared entry per request. It also automates basic request parameter logging.
NewHTTPServer binds a logger to an HTTP server so that it will be present in every request context:
// Create a logger. logger, err := log.Open("zerolog", nil) // Generate a new HTTP server with the logger. srv, logCloser = middleware.NewHTTPServer(logger, log.INFO) defer logCloser.Close() // Now every request will have access to the logger in the context. srv.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { logger := log.LoggerFromCtx(r.Context()) }) srv.ListenAndServe()
NewHTTPRequestMiddleware injects an entry into the context of the the request that it writes after the succeeding handlers process it. This entry has certain aspects of the request logged by default, but can be configured to include more. Subsequent handlers can also extract the entry and update it to allow for canonical log line logging.
// Create a logger. logger, err := log.Open("zerolog", nil) // Define request attributes to log. attrs := middleware.HTTPRequestLogAttributes{ Headers: []string{"X-Trace-Id", "X-Request-Id"}, Synthetics: map[string]func(*http.Request) string{ "req.unmod-uri": func(r *http.Request) string { return r.RequestURI }, }, } // Generate the middleware and then wrap subsequent handlers. middlewareFn := middleware.NewHTTPRequestMiddleware(logger, log.INFO, attrs) handler := middlewareFn(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) handler.ServeHTTP(resp, req)
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewHTTPRequestMiddleware ¶
func NewHTTPRequestMiddleware(logger log.Logger, lvl log.Level, attrs *HTTPRequestLogAttributes) func(http.Handler) http.Handler
NewHTTPRequestMiddleware returns net/http compatible middleware for logging requests that pass through it at the provided level. It will also insert an Async log.Entry into the request context such that downstream handlers can use it. It will call entry.Send when done, and capture panics. If lvl is invalid, the default level will be used.
func NewHTTPServer ¶
NewHTTPServer returns an http.Server with its BaseContext set to logger as its value. If srvLvl is valid then the http.Server's ErrorLog field will also be set, in which case the returned io.Closer should be closed when finished.
Types ¶
type HTTPRequestLogAttributes ¶
type HTTPRequestLogAttributes struct { Headers []string Synthetics map[string]func(*http.Request) string SyntheticsResponse map[string]func(ResponseWriter) string SkipDuration bool SkipMethod bool SkipPath bool SkipRemoteAddr bool }
HTTPRequestLogAttributes allows us to inject two different ways to automatically log aspects of a request: headers and synthetics. Headers is a list of header names that will be set as fields in the log if they are present in the request; synthetics are fields generated from some combination or process applied to the request.
If desired, the default attributes may also be skipped.
type ResponseWriter ¶ added in v1.1.0
type ResponseWriter interface { http.ResponseWriter // StatusCode returns the status code of the response. If not written // yet, this returns 0. StatusCode() int // Status returns the HTTP/1.1-standard name for the status code. If // not written yet, this returns "". Status() string // BodySize returns the size of the response body. BodySize() int }
ResponseWriter implements an interface that allows logging middleware access to standard information about the underlying response that is unattainable in the default http.ResponseWriter interface.
In order not to break basic net/http interfaces that are commonly implemented (http.Flusher, http.Hijacker, and http.Pusher), we handle these as well, passing to the underlying response writer if it implements them in turn.
One issue is that the available implementations will always fulfill http.Flusher if any of the above "alternate" interfaces is implemented. Even when the underlying response writer is only http.Hijacker or http.Pusher, the wrapper implements http.Flusher. While this mirrors the most common types (the standard HTTP/1.1 and HTTP/2 response writers, eg, all implement flusher), it may lead to false positive http.Flusher type assertions. Since an unimplemented call to Flush is a no-op, this can be regarded as a minor issue.
Does not hold a separate response body buffer. Log in the application for this sort of data.
func NewResponseWriter ¶ added in v1.1.0
func NewResponseWriter(w http.ResponseWriter) ResponseWriter
NewResponseWriter returns a logging-specific ResponseWriter that wraps an http.ResponseWriter, for use in logging middleware.