Skip to content

Commit c6ae2e6

Browse files
authored
feat(logger): ability to skip logs based on user-defined logic (#3593)
* log skipper * do not call time.now() if logging should be skipped * do not ignore skip func delay in latency calculation * write docs * write test
1 parent a64286a commit c6ae2e6

File tree

3 files changed

+88
-21
lines changed

3 files changed

+88
-21
lines changed

docs/doc.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,44 @@ Sample Output
508508
::1 - [Fri, 07 Dec 2018 17:04:38 JST] "GET /ping HTTP/1.1 200 122.767µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36" "
509509
```
510510

511+
### Skip logging
512+
513+
```go
514+
func main() {
515+
router := gin.New()
516+
517+
// skip logging for desired paths by setting SkipPaths in LoggerConfig
518+
loggerConfig := gin.LoggerConfig{SkipPaths: []string{"/metrics"}}
519+
520+
// skip logging based on your logic by setting Skip func in LoggerConfig
521+
loggerConfig.Skip = func(c *gin.Context) bool {
522+
// as an example skip non server side errors
523+
return c.Writer.Status() < http.StatusInternalServerError
524+
}
525+
526+
engine.Use(gin.LoggerWithConfig(loggerConfig))
527+
router.Use(gin.Recovery())
528+
529+
// skipped
530+
router.GET("/metrics", func(c *gin.Context) {
531+
c.Status(http.StatusNotImplemented)
532+
})
533+
534+
// skipped
535+
router.GET("/ping", func(c *gin.Context) {
536+
c.String(http.StatusOK, "pong")
537+
})
538+
539+
// not skipped
540+
router.GET("/data", func(c *gin.Context) {
541+
c.Status(http.StatusNotImplemented)
542+
})
543+
544+
router.Run(":8080")
545+
}
546+
547+
```
548+
511549
### Controlling Log output coloring
512550

513551
By default, logs output on console should be colorized depending on the detected TTY.

logger.go

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,15 @@ type LoggerConfig struct {
4747
// SkipPaths is an url path array which logs are not written.
4848
// Optional.
4949
SkipPaths []string
50+
51+
// Skip is a Skipper that indicates which logs should not be written.
52+
// Optional.
53+
Skip Skipper
5054
}
5155

56+
// Skipper is a function to skip logs based on provided Context
57+
type Skipper func(c *Context) bool
58+
5259
// LogFormatter gives the signature of the formatter function passed to LoggerWithFormatter
5360
type LogFormatter func(params LogFormatterParams) string
5461

@@ -241,32 +248,34 @@ func LoggerWithConfig(conf LoggerConfig) HandlerFunc {
241248
// Process request
242249
c.Next()
243250

244-
// Log only when path is not being skipped
245-
if _, ok := skip[path]; !ok {
246-
param := LogFormatterParams{
247-
Request: c.Request,
248-
isTerm: isTerm,
249-
Keys: c.Keys,
250-
}
251-
252-
// Stop timer
253-
param.TimeStamp = time.Now()
254-
param.Latency = param.TimeStamp.Sub(start)
251+
// Log only when it is not being skipped
252+
if _, ok := skip[path]; ok || (conf.Skip != nil && conf.Skip(c)) {
253+
return
254+
}
255255

256-
param.ClientIP = c.ClientIP()
257-
param.Method = c.Request.Method
258-
param.StatusCode = c.Writer.Status()
259-
param.ErrorMessage = c.Errors.ByType(ErrorTypePrivate).String()
256+
param := LogFormatterParams{
257+
Request: c.Request,
258+
isTerm: isTerm,
259+
Keys: c.Keys,
260+
}
260261

261-
param.BodySize = c.Writer.Size()
262+
// Stop timer
263+
param.TimeStamp = time.Now()
264+
param.Latency = param.TimeStamp.Sub(start)
262265

263-
if raw != "" {
264-
path = path + "?" + raw
265-
}
266+
param.ClientIP = c.ClientIP()
267+
param.Method = c.Request.Method
268+
param.StatusCode = c.Writer.Status()
269+
param.ErrorMessage = c.Errors.ByType(ErrorTypePrivate).String()
266270

267-
param.Path = path
271+
param.BodySize = c.Writer.Size()
268272

269-
fmt.Fprint(out, formatter(param))
273+
if raw != "" {
274+
path = path + "?" + raw
270275
}
276+
277+
param.Path = path
278+
279+
fmt.Fprint(out, formatter(param))
271280
}
272281
}

logger_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,26 @@ func TestLoggerWithConfigSkippingPaths(t *testing.T) {
415415
assert.Contains(t, buffer.String(), "")
416416
}
417417

418+
func TestLoggerWithConfigSkipper(t *testing.T) {
419+
buffer := new(strings.Builder)
420+
router := New()
421+
router.Use(LoggerWithConfig(LoggerConfig{
422+
Output: buffer,
423+
Skip: func(c *Context) bool {
424+
return c.Writer.Status() == http.StatusNoContent
425+
},
426+
}))
427+
router.GET("/logged", func(c *Context) { c.Status(http.StatusOK) })
428+
router.GET("/skipped", func(c *Context) { c.Status(http.StatusNoContent) })
429+
430+
PerformRequest(router, "GET", "/logged")
431+
assert.Contains(t, buffer.String(), "200")
432+
433+
buffer.Reset()
434+
PerformRequest(router, "GET", "/skipped")
435+
assert.Contains(t, buffer.String(), "")
436+
}
437+
418438
func TestDisableConsoleColor(t *testing.T) {
419439
New()
420440
assert.Equal(t, autoColor, consoleColorMode)

0 commit comments

Comments
 (0)