Skip to content

Commit 2fb0ec6

Browse files
committed
Update logger.md
1 parent 7eb5db7 commit 2fb0ec6

File tree

1 file changed

+124
-4
lines changed

1 file changed

+124
-4
lines changed

website/docs/middleware/logger.md

Lines changed: 124 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ Echo has 2 different logger middlewares:
1111
- Older string template based logger [`Logger`](https://github.com/labstack/echo/blob/master/middleware/logger.go) - easy to start with but has limited capabilities
1212
- Newer customizable function based logger [`RequestLogger`](https://github.com/labstack/echo/blob/master/middleware/request_logger.go) - allows developer fully to customize what is logged and how it is logged. Suitable for usage with 3rd party logger libraries.
1313

14+
## Dependencies
15+
```go
16+
import "github.com/labstack/gommon/log"
17+
import "github.com/mattn/go-isatty"
18+
import "github.com/valyala/fasttemplate"
19+
import "github.com/labstack/gommon/color"
20+
```
1421
## Old Logger middleware
1522

1623
## Usage
@@ -21,7 +28,7 @@ e.Use(middleware.Logger())
2128

2229
*Sample output*
2330

24-
```js
31+
```exec
2532
{"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}
2633
```
2734

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

4047
*Sample output*
4148

42-
```sh
49+
```exec
4350
method=GET, uri=/, status=200
4451
```
4552

@@ -110,17 +117,87 @@ DefaultLoggerConfig = LoggerConfig{
110117

111118
RequestLogger middleware allows developer fully to customize what is logged and how it is logged and is more suitable
112119
for usage with 3rd party (structured logging) libraries.
113-
114-
See [`RequestLoggerConfig`](https://github.com/labstack/echo/blob/master/middleware/request_logger.go) structure fields for values that logger knows to extract.
120+
```go
121+
type RequestLoggerConfig struct {
122+
// Skipper defines a function to skip middleware.
123+
Skipper Skipper
124+
125+
// BeforeNextFunc defines a function that is called before next middleware or handler is called in chain.
126+
BeforeNextFunc func(c echo.Context)
127+
// LogValuesFunc defines a function that is called with values extracted by logger from request/response.
128+
// Mandatory.
129+
LogValuesFunc func(c echo.Context, v RequestLoggerValues) error
130+
131+
// HandleError instructs logger to call global error handler when next middleware/handler returns an error.
132+
// This is useful when you have custom error handler that can decide to use different status codes.
133+
//
134+
// A side-effect of calling global error handler is that now Response has been committed and sent to the client
135+
// and middlewares up in chain can not change Response status code or response body.
136+
HandleError bool
137+
138+
// LogLatency instructs logger to record duration it took to execute rest of the handler chain (next(c) call).
139+
LogLatency bool
140+
// LogProtocol instructs logger to extract request protocol (i.e. `HTTP/1.1` or `HTTP/2`)
141+
LogProtocol bool
142+
// LogRemoteIP instructs logger to extract request remote IP. See `echo.Context.RealIP()` for implementation details.
143+
LogRemoteIP bool
144+
// LogHost instructs logger to extract request host value (i.e. `example.com`)
145+
LogHost bool
146+
// LogMethod instructs logger to extract request method value (i.e. `GET` etc)
147+
LogMethod bool
148+
// LogURI instructs logger to extract request URI (i.e. `/list?lang=en&page=1`)
149+
LogURI bool
150+
// LogURIPath instructs logger to extract request URI path part (i.e. `/list`)
151+
LogURIPath bool
152+
// LogRoutePath instructs logger to extract route path part to which request was matched to (i.e. `/user/:id`)
153+
LogRoutePath bool
154+
// LogRequestID instructs logger to extract request ID from request `X-Request-ID` header or response if request did not have value.
155+
LogRequestID bool
156+
// LogReferer instructs logger to extract request referer values.
157+
LogReferer bool
158+
// LogUserAgent instructs logger to extract request user agent values.
159+
LogUserAgent bool
160+
// LogStatus instructs logger to extract response status code. If handler chain returns an echo.HTTPError,
161+
// the status code is extracted from the echo.HTTPError returned
162+
LogStatus bool
163+
// LogError instructs logger to extract error returned from executed handler chain.
164+
LogError bool
165+
// LogContentLength instructs logger to extract content length header value. Note: this value could be different from
166+
// actual request body size as it could be spoofed etc.
167+
LogContentLength bool
168+
// LogResponseSize instructs logger to extract response content length value. Note: when used with Gzip middleware
169+
// this value may not be always correct.
170+
LogResponseSize bool
171+
// LogHeaders instructs logger to extract given list of headers from request. Note: request can contain more than
172+
// one header with same value so slice of values is been logger for each given header.
173+
//
174+
// Note: header values are converted to canonical form with http.CanonicalHeaderKey as this how request parser converts header
175+
// names to. For example, the canonical key for "accept-encoding" is "Accept-Encoding".
176+
LogHeaders []string
177+
// LogQueryParams instructs logger to extract given list of query parameters from request URI. Note: request can
178+
// contain more than one query parameter with same name so slice of values is been logger for each given query param name.
179+
LogQueryParams []string
180+
// LogFormValues instructs logger to extract given list of form values from request body+URI. Note: request can
181+
// contain more than one form value with same name so slice of values is been logger for each given form value name.
182+
LogFormValues []string
183+
184+
timeNow func() time.Time
185+
}
186+
```
115187

116188

117189
### Examples
118190

119191
Example for naive `fmt.Printf`
120192
```go
193+
skipper := func(c echo.Context) bool {
194+
// Skip health check endpoint
195+
return c.Request().URL.Path == "/health"
196+
}
121197
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
122198
LogStatus: true,
123199
LogURI: true,
200+
Skipper: skipper,
124201
BeforeNextFunc: func(c echo.Context) {
125202
c.Set("customValueFromContext", 42)
126203
},
@@ -131,6 +208,12 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
131208
},
132209
}))
133210
```
211+
*Sample output*
212+
213+
```exec
214+
REQUEST: uri: /hello, status: 200, custom-value: 42
215+
```
216+
134217

135218
Example for slog (https://pkg.go.dev/log/slog)
136219
```go
@@ -157,6 +240,10 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
157240
},
158241
}))
159242
```
243+
*Sample output*
244+
```exec
245+
{"time":"2024-12-30T20:55:46.2399999+08:00","level":"INFO","msg":"REQUEST","uri":"/hello","status":200}
246+
```
160247

161248
Example for Zerolog (https://github.com/rs/zerolog)
162249
```go
@@ -174,6 +261,10 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
174261
},
175262
}))
176263
```
264+
*Sample output*
265+
```exec
266+
{"level":"info","URI":"/hello","status":200,"message":"request"}
267+
```
177268

178269
Example for Zap (https://github.com/uber-go/zap)
179270
```go
@@ -191,6 +282,10 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
191282
},
192283
}))
193284
```
285+
*Sample output*
286+
```exec
287+
{"level":"info","ts":1735564026.3197417,"caller":"cmd/main.go:20","msg":"request","URI":"/hello","status":200}
288+
```
194289

195290
Example for Logrus (https://github.com/sirupsen/logrus)
196291
```go
@@ -208,3 +303,28 @@ e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
208303
},
209304
}))
210305
```
306+
*Sample output*
307+
```exec
308+
time="2024-12-30T21:08:49+08:00" level=info msg=request URI=/hello status=200
309+
```
310+
311+
### Troubleshooting Tips
312+
313+
#### 1. Solution for "panic: missing LogValuesFunc callback function for request logger middleware"
314+
This panic arises when the `LogValuesFunc` callback function, which is mandatory for the request logger middleware configuration, is left unset.
315+
316+
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:
317+
318+
```go
319+
func logValues(c echo.Context, v middleware.RequestLoggerValues) error {
320+
fmt.Printf("Request Method: %s, URI: %s\n", v.Method, v.URI)
321+
return nil
322+
}
323+
324+
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
325+
LogValuesFunc: logValues,
326+
}))
327+
```
328+
329+
#### 2. If Parameters in Logs Are Empty
330+
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.

0 commit comments

Comments
 (0)