Как один раз инициализировать zap-логгер и повторно использовать его в других файлах Go?

Я пытаюсь перенести свое приложение с прекрасного Логруса (очень полезно для отладки) и внедряю фреймворк журнала Uber Zap.

С Logrus я могу инициализировать регистратор только один раз и использовать его повторно из другого файла Go, пример:

package main
import(
    // 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 line
func 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, как я могу инициализировать журнал в основной функции и использовать этот регистратор из другого файла Go?


person alessiosavi    schedule 01.09.2019    source источник


Ответы (3)


Вы можете настроить регистратор в основной функции и вызвать https://godoc.org/go.uber.org/zap#ReplaceGlobals, чтобы использовать его в качестве глобального регистратора по умолчанию.

person Mikhail    schedule 01.09.2019

Замена стандартного go Global logger на реализацию zaps возможна, но не рекомендуется.

Согласно их FAQ.

Зачем включать глобальные регистраторы пакетов? Поскольку многие другие пакеты протоколирования включают глобальный регистратор, многие приложения не предназначены для приема регистраторов в качестве явных параметров. Изменение сигнатур функций часто является критическим изменением, поэтому zap включает глобальные регистраторы для упрощения миграции.

По возможности избегайте их.

В зависимости от ваших потребностей, вы можете создать логгер в основном и передавать его другим или создавать новый логгер в каждом пакете. Я решил создать один в основном и передать его, так как я использую регистратор Atomic, который позволяет мне изменять уровни журнала, пока мое приложение работает через вызов API. С долгой историей использования DI и консолидации кода в целом это действительно похоже на запах кода, но, по-видимому, гораздо более производительно то, как работает zap, чтобы передать его через синглтон или глобальный.

person ammills01    schedule 02.01.2020

Ответ @alessiosavi, изначально опубликованный в вопросе.


Инициализируйте новый журнал и установите его как глобальный, как указано @Mikhail.

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 ""
}
person Community    schedule 22.07.2021