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

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

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

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

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

2 ответа

Решение

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

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

import log "github.com/Sirupsen/logrus"

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

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

var log = logrus.New()

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

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

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.)

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

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")
}
Другие вопросы по тегам