Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update logger.md #361

Merged
merged 2 commits into from
Jan 2, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 117 additions & 3 deletions website/docs/middleware/logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ e.Use(middleware.Logger())

*Sample output*

```js
```exec
{"time":"2017-01-12T08:58:07.372015644-08:00","remote_ip":"::1","host":"localhost:1323","method":"GET","uri":"/","status":200,"error":"","latency":14743,"latency_human":"14.743µs","bytes_in":0,"bytes_out":2}
```

Expand All @@ -39,7 +39,7 @@ Example above uses a `Format` which logs request method and request URI.

*Sample output*

```sh
```exec
method=GET, uri=/, status=200
```

Expand Down Expand Up @@ -111,16 +111,87 @@ DefaultLoggerConfig = LoggerConfig{
RequestLogger middleware allows developer fully to customize what is logged and how it is logged and is more suitable
for usage with 3rd party (structured logging) libraries.

See [`RequestLoggerConfig`](https://github.com/labstack/echo/blob/master/middleware/request_logger.go) structure fields for values that logger knows to extract.
You can quickly acquaint yourself with the values that the logger knows to extract by referring to the fields of the [`RequestLoggerConfig`](https://github.com/labstack/echo/blob/master/middleware/request_logger.go) structure below. Or click the link to view the most up-to-date details.
```go
type RequestLoggerConfig struct {
// Skipper defines a function to skip middleware.
Skipper Skipper

// BeforeNextFunc defines a function that is called before next middleware or handler is called in chain.
BeforeNextFunc func(c echo.Context)
// LogValuesFunc defines a function that is called with values extracted by logger from request/response.
// Mandatory.
LogValuesFunc func(c echo.Context, v RequestLoggerValues) error

// HandleError instructs logger to call global error handler when next middleware/handler returns an error.
// This is useful when you have custom error handler that can decide to use different status codes.
//
// A side-effect of calling global error handler is that now Response has been committed and sent to the client
// and middlewares up in chain can not change Response status code or response body.
HandleError bool

// LogLatency instructs logger to record duration it took to execute rest of the handler chain (next(c) call).
LogLatency bool
// LogProtocol instructs logger to extract request protocol (i.e. `HTTP/1.1` or `HTTP/2`)
LogProtocol bool
// LogRemoteIP instructs logger to extract request remote IP. See `echo.Context.RealIP()` for implementation details.
LogRemoteIP bool
// LogHost instructs logger to extract request host value (i.e. `example.com`)
LogHost bool
// LogMethod instructs logger to extract request method value (i.e. `GET` etc)
LogMethod bool
// LogURI instructs logger to extract request URI (i.e. `/list?lang=en&page=1`)
LogURI bool
// LogURIPath instructs logger to extract request URI path part (i.e. `/list`)
LogURIPath bool
// LogRoutePath instructs logger to extract route path part to which request was matched to (i.e. `/user/:id`)
LogRoutePath bool
// LogRequestID instructs logger to extract request ID from request `X-Request-ID` header or response if request did not have value.
LogRequestID bool
// LogReferer instructs logger to extract request referer values.
LogReferer bool
// LogUserAgent instructs logger to extract request user agent values.
LogUserAgent bool
// LogStatus instructs logger to extract response status code. If handler chain returns an echo.HTTPError,
// the status code is extracted from the echo.HTTPError returned
LogStatus bool
// LogError instructs logger to extract error returned from executed handler chain.
LogError bool
// LogContentLength instructs logger to extract content length header value. Note: this value could be different from
// actual request body size as it could be spoofed etc.
LogContentLength bool
// LogResponseSize instructs logger to extract response content length value. Note: when used with Gzip middleware
// this value may not be always correct.
LogResponseSize bool
// LogHeaders instructs logger to extract given list of headers from request. Note: request can contain more than
// one header with same value so slice of values is been logger for each given header.
//
// Note: header values are converted to canonical form with http.CanonicalHeaderKey as this how request parser converts header
// names to. For example, the canonical key for "accept-encoding" is "Accept-Encoding".
LogHeaders []string
// LogQueryParams instructs logger to extract given list of query parameters from request URI. Note: request can
// contain more than one query parameter with same name so slice of values is been logger for each given query param name.
LogQueryParams []string
// LogFormValues instructs logger to extract given list of form values from request body+URI. Note: request can
// contain more than one form value with same name so slice of values is been logger for each given form value name.
LogFormValues []string

}
```


### Examples

Example for naive `fmt.Printf`
```go
skipper := func(c echo.Context) bool {
// Skip health check endpoint
return c.Request().URL.Path == "/health"
}
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
LogStatus: true,
LogURI: true,
Skipper: skipper,
BeforeNextFunc: func(c echo.Context) {
c.Set("customValueFromContext", 42)
},
Expand All @@ -131,6 +202,12 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
},
}))
```
*Sample output*

```exec
REQUEST: uri: /hello, status: 200, custom-value: 42
```


Example for slog (https://pkg.go.dev/log/slog)
```go
Expand All @@ -157,6 +234,10 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
},
}))
```
*Sample output*
```exec
{"time":"2024-12-30T20:55:46.2399999+08:00","level":"INFO","msg":"REQUEST","uri":"/hello","status":200}
```

Example for Zerolog (https://github.com/rs/zerolog)
```go
Expand All @@ -174,6 +255,10 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
},
}))
```
*Sample output*
```exec
{"level":"info","URI":"/hello","status":200,"message":"request"}
```

Example for Zap (https://github.com/uber-go/zap)
```go
Expand All @@ -191,6 +276,10 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
},
}))
```
*Sample output*
```exec
{"level":"info","ts":1735564026.3197417,"caller":"cmd/main.go:20","msg":"request","URI":"/hello","status":200}
```

Example for Logrus (https://github.com/sirupsen/logrus)
```go
Expand All @@ -208,3 +297,28 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
},
}))
```
*Sample output*
```exec
time="2024-12-30T21:08:49+08:00" level=info msg=request URI=/hello status=200
```

### Troubleshooting Tips

#### 1. Solution for "panic: missing LogValuesFunc callback function for request logger middleware"
This panic arises when the `LogValuesFunc` callback function, which is mandatory for the request logger middleware configuration, is left unset.

To address this, you must define a suitable function that adheres to the `LogValuesFunc` specifications and then assign it within the middleware configuration. Consider the following straightforward illustration:

```go
func logValues(c echo.Context, v middleware.RequestLoggerValues) error {
fmt.Printf("Request Method: %s, URI: %s\n", v.Method, v.URI)
return nil
}

e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
LogValuesFunc: logValues,
}))
```

#### 2. If Parameters in Logs Are Empty
When investigating logging-related glitches, if you notice that certain parameters like `v.URI` and `v.Status` within the `LogValuesFunc` function produce empty outputs, your focus should shift to validating the relevant configuration elements. Specifically, check whether the corresponding items (such as `LogStatus`, `LogURI`, etc.) in `e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{...}))` have been erroneously set to `false` or failed to activate properly due to miscellaneous factors. Ensure these configuration particulars are accurately configured so that the pertinent request and response data can be precisely logged.
Loading