2013-08-21 12 views
65

Qual è lo schema per la registrazione dell'applicazione in Go? Se ho, diciamo, 5 goroutines mi devi effettuare il login da, dovrei ...Corretto approccio al log globale in Golang

  • Creare un unico log.Logger e passarlo in giro?
  • Passare un puntatore a quello log.Logger?
  • Ogni goroutine o funzione dovrebbe creare un logger?
  • Devo creare il logger come variabile globale?

risposta

31
  • Creare un singolo log.Logger e passarlo in giro?

Ciò è possibile. A log.Logger può essere utilizzato contemporaneamente da più goroutine.

  • Passare un puntatore a quel log.Logger?

log.New restituisce una *Logger che di solito è un'indicazione che si dovrebbe passare l'oggetto intorno come un puntatore. Passando come valore si creerebbe una copia della struttura (ad esempio una copia del Logger) e quindi più goroutine potrebbero scrivere allo stesso io.Writer contemporaneamente. Questo potrebbe essere un problema serio, a seconda dell'implementazione dello scrittore.

  • caso ogni goroutine o la funzione di creare un logger?

non vorrei creare un logger separato per ogni funzione o goroutine. Goroutine (e funzioni) sono usate per compiti molto leggeri che non giustificano la manutenzione di un logger separato. Probabilmente è una buona idea creare un logger per ogni componente più grande del tuo progetto. Ad esempio, se il progetto utilizza un servizio SMTP per l'invio di posta, creare un logger separato per il servizio di posta suona come una buona idea in modo da poter filtrare e disattivare l'output separatamente.

  • Devo creare il logger come variabile globale?

Dipende dal pacchetto. Nell'esempio precedente del servizio di posta, sarebbe probabilmente una buona idea disporre di un logger per ogni istanza del servizio, in modo che gli utenti possano registrare errori durante l'utilizzo del servizio di posta Gmail in modo diverso rispetto agli errori verificatisi durante l'utilizzo dell'MTA locale (ad esempio sendmail).

+0

La tua risposta è stata abbastanza chiara, grazie – deFreitas

31

Per casi semplici, nel pacchetto di registro è definito un logger globale, log.Logger. Questo logger globale può essere configurato tramite log.SetFlags.

Successivamente è possibile chiamare le funzioni di livello superiore del pacchetto di registro come log.Printf e log.Fatalf, che utilizzano tale istanza globale.

+0

pensiero è possibile impostare i flag non è possibile utilizzare un logger personalizzato. – 0xcaff

+0

@caffinatedmonkey, in realtà, è possibile utilizzare i logger personalizzati se implementano l'interfaccia 'io.Writer' e si modifica l'output del logger predefinito tramite' SetOutput() '. – congusbongus

5

So che questa domanda è un po 'vecchia, ma se, come me, i tuoi progetti sono costituiti da più file più piccoli, voto per la tua quarta opzione: ho creato uno logger.go che fa parte del pacchetto principale. Questo file go crea il logger, lo assegna a un file e lo fornisce al resto del main. Nota io non sono venuto con un modo elegante per chiudere log degli errori ...

package main 

import (
    "fmt" 
    "log" 
    "os" 
) 

var errorlog *os.File 
var logger *log.Logger 

func init() { 
    errorlog, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) 
    if err != nil { 
     fmt.Printf("error opening file: %v", err) 
     os.Exit(1) 
    } 

    logger = log.New(errorlog, "applog: ", log.Lshortfile|log.LstdFlags) 
} 
+5

Per la chiusura regolare, potresti probabilmente "rimandare errorlog.Close()" alla fine dell'esecuzione, o per assicurarne la chiusura, impostare i gestori di segnale usando il pacchetto di segnali di Go https: // golang.org/pkg/os/signal/ – AJPennster

2

ho trovato il pacchetto di registro predefinito (https://golang.org/pkg/log/) un po 'limitante. Ad esempio, nessun supporto per i log info e debug.
Dopo un po 'di tentativi, si è deciso di usare https://github.com/golang/glog. Questa sembra essere una porta di https://github.com/google/glog e offre una discreta flessibilità nella registrazione. Ad esempio, quando si esegue un'applicazione localmente, è possibile che si desideri il registro di livello DEBUG, ma potrebbe essere necessario eseguire solo in INFO/ERRORE di livello in produzione. L'elenco delle caratteristiche complete/guida è, qui https://google-glog.googlecode.com/svn/trunk/doc/glog.html (È per il modulo C++, ma per la maggior parte si traduce nella porta golang)

3

Questa è una domanda precedente, ma vorrei suggerire l'uso di http://github.com/romana/rlog (che abbiamo sviluppato). È configurato tramite variabili di ambiente, l'oggetto logger viene creato e inizializzato quando viene importato rlog. Pertanto, non è necessario passare attorno a un logger.

rlog ha alcune caratteristiche:

  • Completamente configurabili data/ora francobolli
  • uscita simultanea a stderr o stdout così come file.
  • Livelli di registro standard (Debug, Info, ecc.) Nonché registrazione multilivello liberamente configurabile.
  • Registrazione su richiesta delle informazioni sul chiamante (file, numero di riga, funzione).
  • Possibilità di impostare diversi livelli di registro per diversi file sorgente.

È molto piccolo, non ha dipendenze esterne, tranne la libreria standard di Golang ed è in fase di sviluppo. Gli esempi sono forniti nel repository.

+2

Grazie per aver rivelato la tua affiliazione con il prodotto che stai raccomandando! È apprezzato –

3

Questo è un semplice registratore

package customlogger 

import (
    "log" 
    "os" 
    "sync" 
) 

type logger struct { 
    filename string 
    *log.Logger 
} 

var logger *logger 
var once sync.Once 

// start loggeando 
func GetInstance() *logger { 
    once.Do(func() { 
     logger = createLogger("mylogger.log") 
    }) 
    return logger 
} 

func createLogger(fname string) *logger { 
    file, _ := os.OpenFile(fname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777) 

    return &logger{ 
     filename: fname, 
     Logger: log.New(file, "My app Name ", log.Lshortfile), 
    } 
} 

Si può usare in questo modo

package main 

import (
    "customlogger" 
    "fmt" 
    "net/http" 
) 

func main() { 
    logger := customlogger.GetInstance() 
    logger.Println("Starting") 

    http.HandleFunc("/", sroot) 
    http.ListenAndServe(":8080", nil) 
} 

func sroot(w http.ResponseWriter, r *http.Request) { 
    logger := customlogger.GetInstance() 

    fmt.Fprintf(w, "welcome") 
    logger.Println("Starting") 
} 
Problemi correlati