⚙️
Zapを使いginのlogging middlewareを実装する
Zap Logger Middleware
middlewares/logger.go
func Logger(l *zap.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
fmt.Println("starting logger", start)
c.Next()
l.Info("incoming request",
zap.Int("status", c.Writer.Status()),
zap.Int64("content_length", c.Request.ContentLength),
zap.String("method", c.Request.Method),
zap.String("path", c.Request.URL.Path),
zap.String("query", c.Request.URL.RawQuery),
zap.String("ip", c.ClientIP()),
zap.String("user_agent", c.Request.UserAgent()),
zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),
zap.Duration("elapsed", time.Since(start)),
)
}
}
main.go
func main() {
logger, err := zap.NewProduction()
if err != nil {
log.Fatal(err)
}
defer logger.Sync()
r := gin.New()
r.Use(middleware.Logger(logger))
r.GET("/ping", func(c *gin.Context) {
fmt.Println("ping called")
c.JSON(200, "pong")
})
if err := r.Run(); err != nil {
fmt.Println("Failed", err)
}
}
出力結果は以下の通りです。
curl -s 'localhost:8080/ping?test=testing'
"pong"
starting logger 2022-11-30 08:00:32.694792773 +0900 JST m=+44.982572328
ping called
{"level":"info","ts":1669762832.6951628,"caller":"middlewares/logger.go:47","msg":"incoming request","status":200,"content_length":0,"method":"GET","path":"/ping","query":"test=testing","ip":"127.0.0.1","user_agent":"curl/7.64.1","errors":"","elapsed":0.000345985}
解説
start := time.Now()
は処理にかかった時間を計測するために、リクエストの処理を行う前に時刻を保持する。処理が終了したタイミングでtime.Since()
で差分を算出します。logger
ミドルウェアーの実行の処理しか計測できないので、実行順番を考慮して.Use()
を設定しましょう。
c.Next()
次のgin
のhandler
を実行するために.Next()
を呼びます。fmt.Println()
とstdout
の結果でもご覧になれるように、.GET()
で登録されているhandler
が呼ばれています。
以上でzapを使用したgin logger middlewareの実装でした。
Discussion