Documentation ¶
Overview ¶
`http_logrus` is a HTTP logging middleware for the Logrus logging stack.
It provides both middleware (server-side) and tripperware (client-side) for logging HTTP requests using a user-provided `logrus.Entry`.
Middleware server-side logging ¶
The middleware also embeds a request-field scoped `logrus.Entry` (with fields from `ctxlogrus`) inside the `context.Context` of the `http.Request` that is passed to the executing `http.Handler`. That `logrus.Entry` can be easily extracted using It accepts a user-configured `logrus.Entry` that will be used for logging completed HTTP calls. The same `logrus.Entry` will be used for logging completed gRPC calls, and be populated into the `context.Context` passed into HTTP handler code. To do that, use the `Extract` method (see example below).
The middlewarerequest will be logged at a level indicated by `WithLevels` options, and an example JSON-formatted log message will look like:
{ "@timestamp:" "2006-01-02T15:04:05Z07:00", "@level": "info", "my_custom.my_string": 1337, "custom_tags.string": "something", "http.handler.group": "my_service", "http.host": "something.local", "http.proto_major": 1, "http.request.length_bytes": 0, "http.status": 201, "http.time_ms": 0.095, "http.url.path": "/someurl", "msg": "handled", "peer.address": "127.0.0.1", "peer.port": "59141", "span.kind": "server", "system": "http" }
Tripperware client-side logging ¶
The tripperware uses any `ctxlogrus` to create a request-field scoped `logrus.Entry`. The key one is the `http.call.service` which by default is auto-detected from the domain but can be overwritten by the `ctxlogrus` initialization.
Most requests and responses won't be loged. By default only client-side connectivity and 5** responses cause the outbound requests to be logged, but that can be customized using `WithLevels` and `WithConnectivityError` options. A typical log message for client side will look like:
{ "@timestamp:" "2006-01-02T15:04:05Z07:00", "@level": "debug", "http.call.service": "googleapis", "http.host": "calendar.googleapis.com", "http.proto_major": 1, "http.request.length_bytes": 0, "http.response.length_bytes": 176, "http.status": 201, "http.time_ms": 4.654, "http.url.path": "/someurl", "msg": "request completed", "span.kind": "client", "system": "http" }
You can use `Extract` to log into a request-scoped `logrus.Entry` instance in your handler code. Additional tags to the logger can be added using `ctxlogrus`.
HTTP Library logging ¶
The `http.Server` takes a logger command. You can use the `AsHttpLogger` to take a user-scoped `logrus.Entry` and log connectivity or low-level HTTP errors (e.g. TLS handshake problems, badly formed requests etc).
Please see examples and tests for examples of use.
Index ¶
- Variables
- func AsHttpLogger(logger *logrus.Entry) *log.Logger
- func ContentCaptureMiddleware(entry *logrus.Entry, decider http_logging.ContentCaptureDeciderFunc) httpwares.Middleware
- func ContentCaptureTripperware(entry *logrus.Entry, decider http_logging.ContentCaptureDeciderFunc) httpwares.Tripperware
- func DefaultMiddlewareCodeToLevel(httpStatusCode int) logrus.Level
- func DefaultTripperwareCodeToLevel(httpStatusCode int) logrus.Level
- func Middleware(entry *logrus.Entry, opts ...Option) httpwares.Middleware
- func Tripperware(entry *logrus.Entry, opts ...Option) httpwares.Tripperware
- type CodeToLevel
- type Decider
- type Option
- func WithConnectivityErrorLevel(level logrus.Level) Option
- func WithDecider(f Decider) Option
- func WithLevels(f CodeToLevel) Option
- func WithRequestBodyCapture(deciderFunc func(r *http.Request) bool) Option
- func WithRequestFieldExtractor(f RequestFieldExtractorFunc) Option
- func WithResponseBodyCapture(deciderFunc func(r *http.Request, status int) bool) Option
- func WithResponseFieldExtractor(f ResponseFieldExtractorFunc) Option
- type RequestFieldExtractorFunc
- type ResponseFieldExtractorFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var (
// SystemField is used in every log statement made through http_logrus. Can be overwritten before any initialization code.
SystemField = "http"
)
Functions ¶
func AsHttpLogger ¶
AsHttpLogger returns the given logrus instance as an HTTP logger.
func ContentCaptureMiddleware ¶
func ContentCaptureMiddleware(entry *logrus.Entry, decider http_logging.ContentCaptureDeciderFunc) httpwares.Middleware
ContentCaptureMiddleware is a server-side http ware for logging contents of HTTP requests and responses (body and headers).
Only requests with a set Content-Length will be captured, with no streaming or chunk encoding supported. Only responses with Content-Length set are captured, no gzipped, chunk-encoded responses are supported.
The body will be recorded as a separate log message. Body of `application/json` will be captured as http.request.body_json (in structured JSON form) and others will be captured as http.request.body_raw logrus field (raw base64-encoded value).
This *must* be used together with http_logrus.Middleware, as it relies on the logger provided there. However, you can override the `logrus.Entry` that is used for logging, allowing for logging to a separate backend (e.g. a different file).
func ContentCaptureTripperware ¶
func ContentCaptureTripperware(entry *logrus.Entry, decider http_logging.ContentCaptureDeciderFunc) httpwares.Tripperware
ContentCaptureTripperware is a client-side http ware for logging contents of HTTP requests and responses (body and headers).
Only requests with a set GetBody field will be captured (strings, bytes etc). Only responses with Content-Length are captured, with no support for chunk-encoded responses.
The body will be recorded as a separate log message. Body of `application/json` will be captured as http.request.body_json (in structured JSON form) and others will be captured as http.request.body_raw logrus field (raw base64-encoded value).
func DefaultMiddlewareCodeToLevel ¶
DefaultMiddlewareCodeToLevel is the default of a mapper between HTTP server-side status codes and logrus log levels.
func DefaultTripperwareCodeToLevel ¶
DefaultTripperwareCodeToLevel is the default of a mapper between HTTP client-side status codes and logrus log levels.
func Middleware ¶
Middleware is a server-side http ware for logging using logrus.
All handlers will have a Logrus logger in their context, which can be fetched using `ctxlogrus.Extract`.
Example ¶
h := http.NewServeMux() h.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { ctxlogrus.Extract(r.Context()).Info("logging") }) hm := Middleware(logrus.WithField("test", "abc"))(h) if err := http.ListenAndServe(":8080", hm); err != nil { panic(err) }
Output:
func Tripperware ¶
Tripperware is a server-side http ware for logging using logrus.
This tripperware *does not* propagate a context-based logger, but act as a logger of requests. This includes logging of errors.
Types ¶
type CodeToLevel ¶
CodeToLevel user functions define the mapping between HTTP status codes and logrus log levels.
type Option ¶
type Option func(*options)
func WithConnectivityErrorLevel ¶
WithConnectivityErrorLevel customizes
func WithDecider ¶
WithDecider customizes the function for deciding if the middleware logs at the end of the request.
func WithLevels ¶
func WithLevels(f CodeToLevel) Option
WithLevels customizes the function that maps HTTP client or server side status codes to log levels.
By default `DefaultMiddlewareCodeToLevel` is used for server-side middleware, and `DefaultTripperwareCodeToLevel` is used for client-side tripperware.
func WithRequestBodyCapture ¶
WithRequestBodyCapture enables recording of request body pre-handling/pre-call.
The body will be recorded as a separate log message. Body of `application/json` will be captured as http.request.body_json (in structured JSON form) and others will be captured as http.request.body_raw logrus field (raw base64-encoded value).
For tripperware, only requests with Body of type `bytes.Buffer`, `strings.Reader`, `bytes.Buffer`, or with a specified `GetBody` function will be captured.
For middleware, only requests with a set Content-Length will be captured, with no streaming or chunk encoding supported.
This option creates a copy of the body per request, so please use with care.
func WithRequestFieldExtractor ¶
func WithRequestFieldExtractor(f RequestFieldExtractorFunc) Option
WithRequestFieldExtractor adds a field, allowing you to customize what fields get populated from the request.
Example ¶
Middleware(logrus.WithField("foo", "bar"), WithRequestFieldExtractor(func(req *http.Request) map[string]interface{} { return map[string]interface{}{ "http.request.customFieldA": req.Header.Get("x-custom-header"), "http.request.customFieldB": req.Header.Get("x-another-custom-header"), } }), )
Output:
func WithResponseBodyCapture ¶
WithResponseBodyCapture enables recording of response body post-handling/post-call.
The body will be recorded as a separate log message. Body of `application/json` will be captured as http.response.body_json (in structured JSON form) and others will be captured as http.response.body_raw logrus field (raw base64-encoded value).
Only responses with Content-Length will be captured, with non-default Transfer-Encoding not being supported.
func WithResponseFieldExtractor ¶
func WithResponseFieldExtractor(f ResponseFieldExtractorFunc) Option
WithRequestFieldExtractor adds a field, allowing you to customize what fields get populated from the response.
Example ¶
Middleware(logrus.WithField("foo", "bar"), WithResponseFieldExtractor(func(res httpwares.WrappedResponseWriter) map[string]interface{} { return map[string]interface{}{ "http.response.customFieldC": res.StatusCode(), } }), )
Output:
type RequestFieldExtractorFunc ¶
RequestFieldExtractorFunc is a signature of user-customizable functions for extracting log fields from requests.
type ResponseFieldExtractorFunc ¶
type ResponseFieldExtractorFunc func(res httpwares.WrappedResponseWriter) map[string]interface{}
ResponseFieldExtractorFunc is a signature of user-customizable functions for extracting log fields from responses.