# README
http_logrus
import "github.com/improbable-eng/go-httpwares/logging/logrus"
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.
Imported Packages
- github.com/improbable-eng/go-httpwares
- github.com/improbable-eng/go-httpwares/logging
- github.com/improbable-eng/go-httpwares/logging/logrus/ctxlogrus
- github.com/sirupsen/logrus
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
Package files
capture_middleware.go capture_tripperware.go doc.go get_body_go18.go httplogger.go middleware.go options.go tripperware.go
Variables
var (
// SystemField is used in every log statement made through http_logrus. Can be overwritten before any initialization code.
SystemField = "http"
)
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:
Click to expand code.
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)
}
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.
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:
Click to expand code.
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"),
}
}),
)
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:
Click to expand code.
Middleware(logrus.WithField("foo", "bar"),
WithResponseFieldExtractor(func(res httpwares.WrappedResponseWriter) map[string]interface{} {
return map[string]interface{}{
"http.response.customFieldC": res.StatusCode(),
}
}),
)
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.
Generated by godoc2ghmd