http_logrus

package
v0.0.0-...-a464bf5 Latest Latest
Warning

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

Go to latest
Published: Nov 19, 2023 License: Apache-2.0 Imports: 15 Imported by: 0

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

Examples

Constants

This section is empty.

Variables

View Source
var (
	// SystemField is used in every log statement made through http_logrus. Can be overwritten before any initialization code.
	SystemField = "http"
)

Functions

func AsHttpLogger

func AsHttpLogger(logger *logrus.Entry) *log.Logger

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

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

func DefaultTripperwareCodeToLevel(httpStatusCode int) logrus.Level

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

func Middleware

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 `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

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.

Types

type CodeToLevel

type CodeToLevel func(httpStatusCode int) logrus.Level

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

type Decider

type Decider func(w httpwares.WrappedResponseWriter, r *http.Request) bool

Decider function defines rules for suppressing any interceptor logs

type Option

type Option func(*options)

func WithConnectivityErrorLevel

func WithConnectivityErrorLevel(level logrus.Level) Option

WithConnectivityErrorLevel customizes

func WithDecider

func WithDecider(f Decider) Option

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

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 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

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.

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

type RequestFieldExtractorFunc func(req *http.Request) map[string]interface{}

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.

Directories

Path Synopsis
ctxlogrus allows you to store or extract a logrus logger from the context.
ctxlogrus allows you to store or extract a logrus logger from the context.

Jump to

Keyboard shortcuts

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