为了账号安全,请及时绑定邮箱和手机立即绑定

如何初始化 zap 记录器一次并在其他 Go 文件中重用它?

如何初始化 zap 记录器一次并在其他 Go 文件中重用它?

Go
慕无忌1623718 2023-07-17 16:29:21
我正在尝试从漂亮的 Logrus(对调试非常有帮助)迁移我的应用程序,并引入 Uber 日志框架 Zap。使用 Logrus,我只能初始化记录器一次并从其他 Go 文件中重用它,例如:package mainimport(    // Print filename on log    filename "github.com/onrik/logrus/filename"    // Very nice log library    log "github.com/sirupsen/logrus")func main(){// ==== SET LOGGING    Formatter := new(log.TextFormatter)    Formatter.TimestampFormat = "Jan _2 15:04:05.000000000"    Formatter.FullTimestamp = true    Formatter.ForceColors = true    log.AddHook(filename.NewHook()) // Print filename + line at every log    log.SetFormatter(Formatter)}从其他 Go 文件中,我可以重用该记录器而无需任何其他初始化:// VerifyCommandLineInput is delegated to manage the inputer parameter provide with the input flag from command linefunc VerifyCommandLineInput() datastructures.Configuration {    log.Debug("VerifyCommandLineInput | Init a new configuration from the conf file")    c := flag.String("config", "./conf/test.json", "Specify the configuration file.")    flag.Parse()    if strings.Compare(*c, "") == 0 {        log.Fatal("VerifyCommandLineInput | Call the tool using --config conf/config.json")    }    file, err := os.Open(*c)    if err != nil {        log.Fatal("VerifyCommandLineInput | can't open config file: ", err)    }    defer file.Close()    decoder := json.NewDecoder(file)    cfg := datastructures.Configuration{}    err = decoder.Decode(&cfg)    if err != nil {        log.Fatal("VerifyCommandLineInput | can't decode config JSON: ", err)    }    log.Debug("VerifyCommandLineInput | Conf loaded -> ", cfg)    return cfg}我的问题是:使用 Zap 日志框架,如何在 main 函数中初始化日志并使用其他 Go 文件中的记录器?
查看完整描述

4 回答

?
慕仙森

TA贡献1827条经验 获得超7个赞

用 zaps 的实现替换默认的 go Global 记录器是可能的,但不鼓励。

为什么要包含包全局记录器?由于许多其他日志记录包都包含全局记录器,因此许多应用程序并未设计为接受记录器作为显式参数。更改函数签名通常是一个重大更改,因此 zap 包含全局记录器来简化迁移。

尽可能避免它们。

根据您的需要,您可以在 main 中创建一个记录器并将其传递,或者在每个包中创建一个新的记录器。我选择在 main 中创建一个并将其传递,因为我使用的是 Atomic 记录器,它允许我在应用程序通过 API 调用运行时更改日志级别。有着使用 DI 和整合代码的悠久历史,它确实感觉像代码味道,但显然它对于 zap 如何通过单例或全局传递它的性能明显更高。


查看完整回答
反对 回复 2023-07-17
?
长风秋雁

TA贡献1757条经验 获得超7个赞

您可以在主函数中设置记录器并调用zap.ReplaceGlobals以将其用作默认的全局记录器。

ReplaceGlobals 替换全局 Logger 和 SugaredLogger,并返回一个函数来恢复原始值。并发使用是安全的。


查看完整回答
反对 回复 2023-07-17
?
慕哥6287543

TA贡献1831条经验 获得超10个赞

我认为避免替换默认的 go 记录器是个好主意,我的方法是为 zap 记录器的配置和初始化创建一个单独的包。它还提供了包装函数实现,在将 zap 更改为另一个日志记录工具时非常有用。

package logger

import (

    "go.uber.org/zap"

    "go.uber.org/zap/zapcore"

)


var zapLog *zap.Logger


func init() {

    var err error

    config := zap.NewProductionConfig()

    enccoderConfig := zap.NewProductionEncoderConfig()

    zapcore.TimeEncoderOfLayout("Jan _2 15:04:05.000000000")

    enccoderConfig.StacktraceKey = "" // to hide stacktrace info

    config.EncoderConfig = enccoderConfig


    zapLog, err = config.Build(zap.AddCallerSkip(1))

    if err != nil {

        panic(err)

    }

}


func Info(message string, fields ...zap.Field) {

    zapLog.Info(message, fields...)

}


func Debug(message string, fields ...zap.Field) {

    zapLog.Debug(message, fields...)

}


func Error(message string, fields ...zap.Field) {

    zapLog.Error(message, fields...)

}


func Fatal(message string, fields ...zap.Field) {

    zapLog.Fatal(message, fields...)

}

所以您的项目中的任何其他文件将如下所示


import "github.com/[your_repo_path_here]/logger"


func SomeFunc() datastructures.Configuration {

    logger.Debug("VerifyCommandLineInput | Init a new configuration from the conf file")

    c := flag.String("config", "./conf/test.json", "Specify the configuration file.")

    flag.Parse()if strings.Compare(*c, "") == 0 {

        logger.Fatal("VerifyCommandLineInput | Call the tool using --config conf/config.json")

    }

    file, err := os.Open(*c)

    if err != nil {

        logger.Fatal("VerifyCommandLineInput | can't open config file: ", err)

    }

    defer file.Close()

    decoder := json.NewDecoder(file)

    cfg := datastructures.Configuration{}

    err = decoder.Decode(&cfg)

    if err != nil {

        logger.Fatal("VerifyCommandLineInput | can't decode config JSON: ", err)

    }

    logger.Debug("VerifyCommandLineInput | Conf loaded -> ", cfg)


    return cfg

}


查看完整回答
反对 回复 2023-07-17
?
交互式爱情

TA贡献1712条经验 获得超3个赞

初始化一个新日志并将其设置为全局。


package main


import(

    "go.uber.org/zap"

    "go.uber.org/zap/zapcore"

)


func initZapLog() *zap.Logger {

    config := zap.NewDevelopmentConfig()

    config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder

    config.EncoderConfig.TimeKey = "timestamp"

    config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder

    logger, _ := config.Build()

    return logger

}


func main() {


    loggerMgr := initZapLog()

    zap.ReplaceGlobals(loggerMgr)

    defer loggerMgr.Sync() // flushes buffer, if any

    logger := loggerMgr.Sugar()

    logger.Debug("START!")

    db2.GetToken(`alessio`, `savi`, `pass`)

    datastructure.LoadConfiguration()

}


您可以在其他 Go 文件中使用记录器:


func GetToken(url, user, pass string) string {

    var User datastructure.User

    var data string

    var jsonData []byte


    User.User = user

    User.Pass = pass

    jsonData, err := json.Marshal(User)

    if err != nil {

        zap.S().Errorw("Error during marshalling...", err)

        return ""

    }

    data = string(jsonData)

    zap.S().Info("Data encoded => ", data)

    return ""

}


查看完整回答
反对 回复 2023-07-17
  • 4 回答
  • 0 关注
  • 133 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信