使用在代码库其他部分的 main 中初始化的记录器

Ala*_*anH 7 logging go

我正在努力了解如何使用zap。在文档中,他们提供了一些有关如何配置记录器以及如何使用预设的示例。但是,我不明白应该如何使用在 中初始化的记录器main.go,该记录器位于cmd/server/server.go. 根据这篇 SO post和其他几篇文章,无法从main包外部的包中导入。那么,根据 Zap 示例,我应该如何使用pkg/endpoint/my_requestspkg与 处于同一级别cmd)中的记录器?我还没有找到任何明确的例子(甚至与 zap 无关)来说明如何完成这样的事情;然而,我确信这是一个非常简单的问题。

hmo*_*ega 7

我个人倾向于将其视为任何其他正常依赖项并将其传递到需要的地方

package foo

type Bar struct {
    Logger logger.Logger
}

func (b *Bar) Something() {
    b.Logger.Debug("starting something")
}

func DoSomething(logger logger.Logger) {
    b := Bar{Logger: logger}
    b.Something()
}

Run Code Online (Sandbox Code Playgroud)

任何涉及 init 函数的东西基本上都是全局变量

我还倾向于对我使用的任何记录器使用抽象,并赋予零值无操作行为(不记录任何内容),在测试时特别有用,缺点是速度有点慢,因为所有方法都不是指针接收者并需要一个副本,并且我必须定义相同的方法(事实上,我抽象了加糖版本,所以我不在我的包上导入 zap)

package logger

import "go.uber.org/zap"

type Logger struct {
    zap *zap.Logger
}

func Must(logger *Logger, err error) *Logger {
    if err != nil {
        panic(err)
    }
    return logger
}

func NewLogger(logFile string) (*Logger, error) {
    zap.NewProductionConfig()
    config := zap.NewProductionConfig()
    config.OutputPaths = []string{"stdout", "./logs/" + logFile}
    logger, err := config.Build(zap.AddCaller())
    if err != nil {
        return nil, err
    }   
    return &Logger{zap: logger}, err
}

func (l Logger) Debug(msg string, fields ...zap.Field) {
    l.writer().Debug(msg, fields...)
}

func (l Logger) Info(msg string, fields ...zap.Field) {
    l.writer().Info(msg, fields...)
}
// define all the methdos

var noOpLogger = zap.NewNop()

func (l Logger) writer() *zap.Logger {
    if l.zap == nil {
        return noOpLogger
    }
    return l.zap
}
Run Code Online (Sandbox Code Playgroud)

零值无操作记录器对于并发使用是安全的,并且记录器在测试期间不再处于中间状态

var b Bar
b.Something() // no panics
Run Code Online (Sandbox Code Playgroud)


Nav*_*pak 4

一个好主意是创建一个负责记录器的包,或者只是创建一个像“config”或“settings”这样的包来处理像记录器这样的全局配置。

我确实在我的项目中使用 zap,并且通常有一个名为 logger 的包,它提供了一个名为 的基本方法,NewLogger当我的包生成大量日志并且它们非常大时,我从其他包中调用该方法来创建特定于包的记录器。在相当小的项目中,我只是在记录器包中初始化记录器并从外部调用它。

// /my-project/pkg/logging/logging.go
func NewLogger(logFile string) *zap.Logger {
    zap.NewProductionConfig()
    config := zap.NewProductionConfig()
    config.OutputPaths = []string{"stdout", "./logs/" + logFile}
    logger, err := config.Build(zap.AddCaller())
    if err != nil {
        panic(err)
    }
    return logger
}
Run Code Online (Sandbox Code Playgroud)

然后在其他包中使用它:

// /my-project/pkg/a/a.go

package a

var logger *zap.Logger

func init() {
    logger = logging.NewLogger("a.log")
}

func MyFunction() {
    logger.Info("log from package a to a.log")
}
Run Code Online (Sandbox Code Playgroud)

另一个包:

// /my-project/pkg/b/b.go

package b

var logger *zap.Logger

func init() {
    logger = logging.NewLogger("b.log")
}

func MyFunction() {
    logger.Info("log from package b to b.log")
}
Run Code Online (Sandbox Code Playgroud)

您还可以直接在包中初始化记录器,但是将记录器放在单独的包中可以帮助您随时更改配置或整个记录器,而无需在各处进行更改。

您还可以向记录器包中添加更多方法和帮助器,以统一您的日志,或者只是让您的记录工作变得更轻松。