Logrus日志格式化不符合预期,请求排查配置问题
Logrus日志格式不符合官方样式的问题解决
问题描述
使用Logrus库进行日志记录,期望日志格式与官方样式一致,但实际生成的日志格式不符。按官方文档示例配置后无效果,相关中间件代码如下:
package middleware import ( _ "fmt" "net/http" "time" "github.com/labstack/echo/v4" log "github.com/sirupsen/logrus" ) func MakeLogEntry(echo echo.Context) *log.Entry { log.SetFormatter(&log.TextFormatter{ FullTimestamp: true, DisableColors: true, }) if echo == nil { return log.WithFields( log.Fields{ "at": time.Now().Format("2006-01-02 15:04:05"), }, ) } return log.WithFields( log.Fields{ "at": time.Now().Format("2006-01-02 15:04:05"), "method": echo.Request().Method, "uri": echo.Request().URL.String(), "ip": echo.Request().RemoteAddr, }, ) } func LoggingRequest(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { MakeLogEntry(c).Info("Incoming request") return next(c) } } func ErrorHandler(err error, c echo.Context) { report, ok := err.(*echo.HTTPError) if ok { report.Message = map[string]interface{}{ "error": "HTTP Error", "message": report.Message, "status code": report.Code, } } else { report = echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } MakeLogEntry(c).Error(report.Message) c.JSON(report.Code, report.Message.(map[string]interface{})) }
问题原因
- 重复配置Formatter:每次调用
MakeLogEntry都执行log.SetFormatter,不仅冗余,还可能因并发调用导致配置被覆盖,且初始化时机不正确。Logrus全局配置应在程序启动时一次性完成,而非每次生成日志条目时重复设置。 - 手动设置时间戳字段:自行添加的
"at"字段与Logrus TextFormatter自动生成的timestamp字段重复,导致格式偏离官方样式——官方样式的时间戳由Formatter自动处理,无需手动添加。 - 错误日志参数类型问题:
ErrorHandler中直接将map类型作为Error方法的参数,Logrus对复杂类型的格式化处理会偏离官方样式,应将错误信息转为字符串或通过Fields传递结构化数据。
解决方案
1. 全局初始化Logrus配置
在程序启动时(比如main.go的init函数或启动逻辑中)一次性配置Logrus:
package main import ( "your-project-path/middleware" log "github.com/sirupsen/logrus" "github.com/labstack/echo/v4" ) func init() { // 全局配置Logrus格式,只需执行一次 log.SetFormatter(&log.TextFormatter{ FullTimestamp: true, DisableColors: true, TimestampFormat: "2006-01-02 15:04:05", // 可选:指定时间戳格式匹配需求 }) } func main() { e := echo.New() e.Use(middleware.LoggingRequest) e.HTTPErrorHandler = middleware.ErrorHandler // 其他启动逻辑... e.Start(":8080") }
2. 修改MakeLogEntry函数
移除手动设置的"at"字段,去掉重复的Formatter配置:
package middleware import ( "net/http" "github.com/labstack/echo/v4" log "github.com/sirupsen/logrus" ) func MakeLogEntry(c echo.Context) *log.Entry { if c == nil { return log.WithFields(log.Fields{}) } return log.WithFields(log.Fields{ "method": c.Request().Method, "uri": c.Request().URL.String(), "ip": c.Request().RemoteAddr, }) }
3. 修正ErrorHandler的日志输出
将结构化错误信息通过Fields传递,确保日志格式符合官方样式:
func ErrorHandler(err error, c echo.Context) { report, ok := err.(*echo.HTTPError) var errFields log.Fields if ok { errFields = log.Fields{ "error": "HTTP Error", "message": report.Message, "status code": report.Code, } } else { report = echo.NewHTTPError(http.StatusInternalServerError, err.Error()) errFields = log.Fields{ "error": "Internal Server Error", "message": err.Error(), } } // 通过WithFields传递结构化数据,再输出错误信息 MakeLogEntry(c).WithFields(errFields).Error("Request failed") c.JSON(report.Code, errFields) }
修改后效果
修改后的日志会自动包含官方样式的时间戳,字段格式与Logrus默认TextFormatter一致,例如:
INFO[2024-05-20 14:30:00] Incoming request ip=127.0.0.1:54321 method=GET uri=/api/test ERROR[2024-05-20 14:30:05] Request failed error=HTTP Error ip=127.0.0.1:54321 message="Not Found" method=GET status code=404 uri=/api/notfound
内容的提问来源于stack exchange,提问作者Haru-Kazumoto
相关产品推荐
相关产品推荐

