2015-05-15 11 views
13

Sto utilizzando logrus in un'app Go. Credo che questa domanda sia applicabile a qualsiasi altro pacchetto di registrazione (che non offre una configurazione esterna basata su file).Golang logro - come fare una configurazione centralizzata?

logrus fornisce funzioni per configurare varie configurazioni, ad es. SetOutput, SetLevel ecc.

Come qualsiasi altra applicazione, ho bisogno di fare il log da più file sorgente/pacchetti, sembra che sia necessario impostare queste opzioni in ogni file con logrus.

C'è un modo per configurare queste opzioni una volta da qualche parte in un punto centrale da condividere su tutta l'applicazione. In questo modo, se devo modificare il livello di registrazione, posso farlo in un unico posto e si applica a tutti i componenti dell'app.

risposta

13

Non è necessario impostare queste opzioni in ciascun file con Logrus.

È possibile importare Logrus come log:

import log "github.com/Sirupsen/logrus" 

Poi funzioni come log.SetOutput() sono solo le funzioni e modificare il logger globale e si applicano a qualsiasi tipo di file che include questa importazione.

è possibile creare una variabile del pacchetto globale log:

var log = logrus.New() 

Poi funzioni come log.SetOutput() sono metodi e modificare il pacchetto globale. Questo è IMO imbarazzante se si hanno più pacchetti nel programma, poiché ognuno di essi ha un registratore diverso con impostazioni diverse (ma forse è buono per alcuni casi d'uso). Anche questo approccio non mi piace perché confonde lo goimports (che vorrebbe inserire log nell'elenco delle importazioni).

Oppure è possibile creare il proprio wrapper (che è quello che faccio). Ho il mio pacchetto log con il proprio logger var:

var logger = logrus.New() 

poi faccio funzioni di primo livello per avvolgere Logrus:

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

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

Questo è un po 'noioso, ma mi permette di aggiungere funzioni specifiche per il mio programma:

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

modo che io possa poi fare cose come:

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

(Ho in programma in futuro di avvolgere logrus.Entry nel mio tipo in modo da poter concatenarli meglio; Al momento non posso chiamare log.WithConn(c).WithRequest(r).Error(...) perché non posso aggiungere WithRequest() a logrus.Entry.)

+1

Grazie per una spiegazione ben dettagliata! In precedenza ho utilizzato anche i miei wrapper di log con altre lingue, ma molte volte li ho trovati non necessari e un sovraccarico. Penso che renderebbe la sostituzione del provider di registro più facile però. –

1

Questa è la soluzione che sono arrivato a per il mio programma che permette l'aggiunta di campi al contesto di registrazione. Ha un impatto ridotto sulle prestazioni a causa della copia dei campi di base del contesto.

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") 
} 
Problemi correlati