✨
Go Echoでのログ管理プラクティス:標準Loggerからslog連携まで
Echoが標準で提供しているログ管理機能
Logger
✅ 実装例 (実際のコミット)
e.Use(middleware.Logger())
🚀 出力例
⇨ http server started on [::]:1323
{"time":"2025-06-13T05:58:06.15304+09:00","id":"","remote_ip":"::1","host":"localhost:1323","method":"GET","uri":"/","user_agent":"curl/8.7.1","status":200,"error":"","latency":2375,"latency_human":"2.375µs","bytes_in":0,"bytes_out":11}
Loggerの出力をカスタマイズする
✅ 実装例 (実際のコミット例)
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
Format: "method=${method}, uri=${uri}, status=${status}\n",
}))
🚀 出力例
⇨ http server started on [::]:1323
method=GET, uri=/, status=200
RequestLogger
✅ 実装例-1 (実際のコミット)
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)
},
LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
value, _ := c.Get("customValueFromContext").(int)
fmt.Printf("REQUEST: uri: %v, status: %v, custom-value: %v\n", v.URI, v.Status, value)
return nil
},
}))
🚀 出力例 (REQUEST curl localhost:1323/
)
⇨ http server started on [::]:1323
REQUEST: uri: /, status: 200, custom-value: 42
curl localhost:1323/health
へのリクエスト時のログ出力はskip設定されているので、出力されません
✅ 実装例-2 (実際のコミット)
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
LogStatus: true,
LogURI: true,
LogError: true,
HandleError: true, // forwards error to the global error handler, so it can decide appropriate status code
LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
if v.Error == nil {
logger.LogAttrs(context.Background(), slog.LevelInfo, "REQUEST",
slog.String("uri", v.URI),
slog.Int("status", v.Status),
)
} else {
logger.LogAttrs(context.Background(), slog.LevelError, "REQUEST_ERROR",
slog.String("uri", v.URI),
slog.Int("status", v.Status),
slog.String("err", v.Error.Error()),
)
}
return nil
},
}))
🚀 出力例 (REQUEST curl localhost:1323/
)
⇨ http server started on [::]:1323
{"time":"2025-06-13T06:10:15.515028+09:00","level":"INFO","msg":"REQUEST","uri":"/","status":200}
ここで、あえてエラーを出力してみます (エラー検証コミット)
🚀 出力例 (REQUEST curl localhost:1323/error
)
⇨ http server started on [::]:1323
{"time":"2025-06-13T06:15:23.617689+09:00","level":"ERROR","msg":"REQUEST_ERROR","uri":"/error","status":500,"err":"code=500, message=intentional error for testing"}
レベルがエラー ( "level":"ERROR"
) として出力されていることがわかります
まとめ
以上のように、echoで用意されているログ機能では、ログレベルの出力を分けらるように作られていません。
よって、単純なログの場合は Logger
を利用し、エラーログをレベルカスタマイズ等したい場合は RequestLogger
を利用し、3rd partyと組み合わせましょう
Discussion