Skip to content

Latest commit

 

History

History

logrus

http_logrus

import "github.com/mwitkow/go-httpwares/logging/logrus"

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 http_ctxtags) 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 http_ctxtags 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 http_ctxtags 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 http_ctxtags.

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.

capture_middleware.go capture_tripperware.go context.go doc.go httplogger.go middleware.go noop.go options.go tripperware.go

var (
    // SystemField is used in every log statement made through http_logrus. Can be overwritten before any initialization code.
    SystemField = "http"
)
func AsHttpLogger(logger *logrus.Entry) *log.Logger

AsHttpLogger returns the given logrus instance as an HTTP logger.

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(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(httpStatusCode int) logrus.Level

DefaultMiddlewareCodeToLevel is the default of a mapper between HTTP server-side status codes and logrus log levels.

func DefaultTripperwareCodeToLevel(httpStatusCode int) logrus.Level

DefaultTripperwareCodeToLevel is the default of a mapper between HTTP client-side status codes and logrus log levels.

func Extract(req *http.Request) *logrus.Entry

Extract takes the call-scoped logrus.Entry from grpc_logrus middleware.

The logger will have fields pre-populated using http_ctxtags.

If the http_logrus middleware wasn't used, a no-op logrus.Entry is returned. This makes it safe to use regardless.

Example:

Click to expand code.
package http_logrus_test
	
	import (
	    "net/http"
	
	    "github.com/mwitkow/go-httpwares/logging/logrus"
	    "github.com/mwitkow/go-httpwares/tags"
	)
	
	var handler http.HandlerFunc
	
	// Simple example of a `http.Handler` extracting the `Middleware`-injected logrus logger from the context.
	func ExampleExtract_withCustomTags() {
	    handler = func(resp http.ResponseWriter, req *http.Request) {
	        // Handlers can add extra tags to `http_ctxtags` that will be set in both the extracted loggers *and*
	        // the final log statement.
	        http_ctxtags.ExtractInbound(req).Set("my_custom.my_string", "something").Set("my_custom.my_int", 1337)
	        http_logrus.Extract(req).Warningf("Hello World")
	    }
	}
func ExtractFromContext(ctx context.Context) *logrus.Entry

Extract takes the call-scoped logrus.Entry from grpc_logrus middleware.

The logger will have fields pre-populated using http_ctxtags.

If the http_logrus middleware wasn't used, a no-op logrus.Entry is returned. This makes it safe to use regardless.

func Middleware(entry *logrus.Entry, opts ...Option) httpwares.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 http_logrus.Extract.

func Tripperware(entry *logrus.Entry, opts ...Option) httpwares.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.

type CodeToLevel func(httpStatusCode int) logrus.Level

CodeToLevel user functions define the mapping between HTTP status codes and logrus log levels.

type Option func(*options)
func WithConnectivityErrorLevel(level logrus.Level) Option

WithConnectivityErrorLevel customizes

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(deciderFunc func(r *http.Request) bool) Option

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 WithResponseBodyCapture(deciderFunc func(r *http.Request, status int) bool) Option

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.


Generated by godoc2ghmd