Подтвердить что ты не робот

Golang logrus - как сделать централизованную конфигурацию?

Я использую logrus в приложении Go. Я считаю, что этот вопрос применим к любому другому протоколу регистрации (который также не предлагает внешнюю конфигурацию на основе файлов).

logrus предоставляет функции для настройки различной конфигурации, например. SetOutput, SetLevel и т.д.

Как и любое другое приложение, мне нужно выполнить ведение журнала из нескольких исходных файлов/пакетов, кажется, вам нужно настроить эти параметры в каждом файле с логрусом.

Можно ли каким-либо образом настроить эти параметры где-то в центральном месте для совместного использования по всему приложению. Таким образом, если мне нужно изменить уровень ведения журнала, я могу сделать это в одном месте и применимо ко всем компонентам приложения.

4b9b3361

Ответ 1

Вам не нужно устанавливать эти параметры в каждом файле с помощью Logrus.

Вы можете импортировать Logrus как log:

import log "github.com/Sirupsen/logrus"

Затем такие функции, как log.SetOutput(), являются просто функциями и изменяют глобальный регистратор и применяются к любому файлу, который включает этот импорт.

Вы можете создать глобальную переменную log пакета:

var log = logrus.New()

Тогда функции типа log.SetOutput() являются методами и изменяют ваш пакет глобальным. Это неудобно ИМО, если в вашей программе есть несколько пакетов, потому что у каждого из них есть другой регистратор с разными настройками (но, возможно, это хорошо для некоторых случаев использования). Мне тоже не нравится этот подход, потому что он смущает goimports (который захочет вставить log в ваш список импорта).

Или вы можете создать свою собственную оболочку (что я и делаю). У меня есть собственный log пакет со своим logger var:

var logger = logrus.New()

Затем я делаю функции верхнего уровня для переноса Logrus:

func Info(args ...interface{}) {
    logger.Info(args...)
}

func Debug(args ...interface{}) {
    logger.Debug(args...)
}

Это немного утомительно, но позволяет добавлять функции, специфичные для моей программы:

func WithConn(conn net.Conn) *logrus.Entry {
    var addr string = "unknown"
    if conn != nil {
        addr = conn.RemoteAddr().String()
    }
    return logger.WithField("addr", addr)
}

func WithRequest(req *http.Request) *logrus.Entry {
    return logger.WithFields(RequestFields(req))
}

Итак, я могу делать такие вещи, как:

log.WithConn(c).Info("Connected")

(Я планирую в будущем обернуть logrus.Entry в свой собственный тип, чтобы я мог лучше их связать; в настоящее время я не могу вызвать log.WithConn(c).WithRequest(r).Error(...), потому что я не могу добавить WithRequest() в logrus.Entry.)

Ответ 2

Это решение, к которому я пришел для своего приложения, которое позволяет добавлять поля в контекст ведения журнала. Он имеет небольшое влияние на производительность из-за копирования полей контекстной базы.

package logging

import (
    log "github.com/Sirupsen/logrus"
)

func NewContextLogger(c log.Fields) func(f log.Fields) *log.Entry {
    return func(f log.Fields) *log.Entry {
        for k, v := range c {
            f[k] = v
        }
        return log.WithFields(f)
    }
}

package main

import (
    "logging"
)

func main {
    app.Logger = logging.NewContextLogger(log.Fields{
        "module":    "app",
        "id":   event.Id,
    })
    app.Logger(log.Fields{
        "startTime": event.StartTime,
        "endTime":   event.EndTime,
        "title":     event.Name,
    }).Info("Starting process")
}