web-dev-qa-db-fra.com

Golang logrus - comment faire une configuration centralisée?

J'utilise logrus dans une application Go. Je pense que cette question est également applicable à tout autre logiciel de journalisation (qui ne propose pas de configuration basée sur un fichier externe).

logrus fournit des fonctions permettant de configurer diverses configurations, par exemple: SetOutput, SetLevel etc.

Comme toute autre application dont j'ai besoin pour me connecter à partir de plusieurs fichiers/packages source, il semble que vous deviez configurer ces options dans chaque fichier avec logrus.

Est-il possible de configurer ces options une fois quelque part dans un endroit central pour les partager dans toute l'application? Ainsi, si je dois modifier le niveau de journalisation, je peux le faire à un endroit et s’applique à tous les composants de l’application.

16
Dipen Bhikadya

Vous n'avez pas besoin de définir ces options dans chaque fichier avec Logrus.

Vous pouvez importer Logrus en tant que log:

import log "github.com/Sirupsen/logrus"

Ensuite, les fonctions telles que log.SetOutput() ne sont que des fonctions. Elles modifient le journal global et s’appliquent à tout fichier contenant cette importation.

Vous pouvez créer une variable globale log de package:

var log = logrus.New()

Ensuite, les fonctions telles que log.SetOutput() sont des méthodes et modifient votre paquet global. C'est un peu gênant pour OMI si vous avez plusieurs packages dans votre programme, car chacun d'entre eux possède un enregistreur différent avec des paramètres différents (mais c'est peut-être bon pour certains cas d'utilisation). Je n’apprécie pas non plus cette approche car elle confond goimports (qui voudra insérer log dans votre liste d’importations).

Ou vous pouvez créer votre propre wrapper (c'est ce que je fais). J'ai mon propre paquet log avec son propre logger var:

var logger = logrus.New()

Ensuite, je crée des fonctions de haut niveau pour envelopper Logrus:

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

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

C'est un peu fastidieux, mais cela me permet d'ajouter des fonctions spécifiques à mon programme:

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

Je peux donc faire des choses comme:

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

(Je prévois à l'avenir d'encapsuler logrus.Entry dans mon propre type afin de mieux les chaîner; pour l'instant, je ne peux pas appeler log.WithConn(c).WithRequest(r).Error(...) car je ne peux pas ajouter WithRequest() à logrus.Entry.)

20
Rob Napier

C’est la solution à laquelle j’ai abouti pour mon application et qui permet d’ajouter des champs au contexte de journalisation. Cela a un faible impact sur les performances en raison de la copie des champs de base de contexte. 

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")
}
1
hurdlea