Zerolog钩子未注册:日志级别高于警告时钩子不触发
Zerolog自定义AlertHook未触发问题排查
问题描述
实现了自定义AlertHook,期望当日志级别高于WarnLevel时触发alert函数打印内容,但错误日志能正常输出,alert函数无任何打印。
代码片段
Hook定义与日志初始化
type AlertHook struct{} func (t *AlertHook) Run(e *zerolog.Event, level zerolog.Level, message string) { if level > zerolog.WarnLevel { _ = alert(message) } } func alert(msg string) error { fmt.Println(msg) return nil } var once sync.Once var log zerolog.Logger func Get() zerolog.Logger { once.Do(func() { zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack zerolog.TimeFieldFormat = time.RFC3339Nano logLevel, err := strconv.Atoi(os.Getenv("LOG_LEVEL")) if err != nil { logLevel = int(zerolog.InfoLevel) // default to INFO } var output io.Writer = zerolog.ConsoleWriter{ Out: os.Stdout, TimeFormat: time.RFC3339, } if os.Getenv("APP_ENV") != "development" { fileLogger := &lumberjack.Logger{ Filename: "service.log", MaxSize: 5, MaxBackups: 10, MaxAge: 14, Compress: true, } output = zerolog.MultiLevelWriter(os.Stderr, fileLogger) } var gitRevision string buildInfo, ok := debug.ReadBuildInfo() if ok { for _, v := range buildInfo.Settings { if v.Key == "vcs.revision" { gitRevision = v.Value break } } } log = zerolog.New(output). Level(zerolog.Level(logLevel)). With(). Timestamp(). Str("git_revision", gitRevision). Str("go_version", buildInfo.GoVersion). Logger() }) log.Hook(&AlertHook{}) return log }
测试代码
// CreateClientHandler is the handler for creating a new client. // It is used to create a new client. func CreateClientHandler(si *server.ServerInstance) fiber.Handler { return func(c *fiber.Ctx) error { l := logs.Get() l.Error().Msg("test error") // SHOULD TRIGGER HOOK o := new(models.APIClientUser) if err := c.BodyParser(o); err != nil { return c.Status(fiber.StatusBadRequest).JSON(models.NewErrorBadRequest(&err)) } result := si.DB.ORM.Create(&o) if result.Error != nil { return c.Status(fiber.StatusBadRequest).JSON(models.NewErrorBadRequest(&result.Error)) } return c.Status(fiber.StatusCreated).JSON(models.NewSuccessCreated(o)) } }
问题根源
Zerolog的Logger是不可变对象,所有修改Logger配置的方法(包括Hook())都会返回一个新的Logger实例,而非修改原有实例。
在Get()函数中,log.Hook(&AlertHook{})创建了带Hook的新Logger,但你既没有将这个新实例赋值给全局log变量,也没有返回该新实例——最终返回的还是初始化时不带Hook的原log变量,导致Hook从未真正绑定到你使用的Logger上。
修复方案
方案1:初始化时直接添加Hook(推荐)
将Hook整合到初始化流程中,确保全局Logger从一开始就带有Hook:
log = zerolog.New(output). Level(zerolog.Level(logLevel)). With(). Timestamp(). Str("git_revision", gitRevision). Str("go_version", buildInfo.GoVersion). Logger(). Hook(&AlertHook{}) // 在此处添加Hook
方案2:返回带Hook的新实例
如果需要动态添加Hook(不推荐,全局初始化一次即可),需将Hook()返回的新Logger赋值并返回:
once.Do(...) // 创建带Hook的新Logger并返回 return log.Hook(&AlertHook{})
额外验证
你的级别判断level > zerolog.WarnLevel是正确的,Zerolog级别优先级为:TraceLevel < DebugLevel < InfoLevel < WarnLevel < ErrorLevel < FatalLevel < PanicLevel,Error()级别确实满足触发条件。
内容的提问来源于stack exchange,提问作者rak1n
相关产品推荐
相关产品推荐

