2013-08-21 12 views
65

Jaki jest wzór rejestrowania aplikacji w Go? Jeśli mam na przykład 5 goryn, z których muszę się logować, powinienem ...Prawidłowe podejście do globalnego rejestrowania w Golang

  • Utworzyć pojedynczy log.Logger i przekazać go dalej?
  • Przepuścić wskaźnik do tego log.Logger?
  • Czy każda goroutyna lub funkcja powinna tworzyć rejestrator?
  • Czy powinienem utworzyć rejestrator jako zmienną globalną?

Odpowiedz

31
  • Utworzyć pojedynczy log.Logger i przekazać go?

To jest możliwe. A log.Logger może być używany jednocześnie z wieloma goroutinami.

  • Przepuścić wskaźnik do tego logu.Logger?

log.New zwraca *Logger który jest zwykle oznaką, że należy przekazać obiekt wokół jako wskaźnik. Przekazanie go jako wartości utworzyłoby kopię struktury (tj. Kopię Loggera), a następnie wiele goroutinów mogłoby jednocześnie pisać do tego samego io.Writer. To może być poważny problem, w zależności od implementacji pisarza.

  • Gdyby każdy goroutine lub funkcja tworzenia rejestratora?

Nie stworzyłem osobnego programu rejestrującego dla każdej funkcji lub goroutine. Goroutines (i funkcje) są używane do bardzo lekkich zadań, które nie usprawiedliwiają utrzymania oddzielnego rejestratora. Dobrym pomysłem jest utworzenie rejestratora dla każdego większego komponentu projektu. Na przykład, jeśli projekt wykorzystuje usługę SMTP do wysyłania wiadomości e-mail, utworzenie osobnego programu rejestrującego dla usługi pocztowej brzmi jak dobry pomysł, aby można było filtrować i oddzielnie wyłączać dane wyjściowe.

  • Czy należy utworzyć rejestrator jako zmienną globalną?

To zależy od pakietu. W poprzednim przykładzie usługi pocztowej dobrym pomysłem byłoby posiadanie jednego programu rejestrującego dla każdej instancji usługi, aby użytkownicy mogli rejestrować awarie podczas korzystania z usługi poczty Gmail w inny sposób niż błędy występujące podczas używania lokalnego MTA (np. Sendmail).

+0

Twoja odpowiedź była całkiem jasna, dzięki – deFreitas

31

W prostych przypadkach w dzienniku zdefiniowano globalny program rejestrujący, log.Logger. Ten globalny program rejestrujący można skonfigurować za pomocą log.SetFlags.

Następnie można po prostu wywołać funkcje najwyższego poziomu pakietu dziennika, takie jak log.Printf i log.Fatalf, które używają tej globalnej instancji.

+0

myśli można ustawić flagi nie można użyć niestandardowego rejestratora. – 0xcaff

+0

@caffinatedmonkey faktycznie, możesz użyć własnych rejestratorów, jeśli implementują interfejs 'io.Writer' i zmieniasz wyjście domyślnego rejestratora przez' SetOutput() '. – congusbongus

5

Wiem, że to pytanie jest trochę stare, ale jeśli, tak jak ja, twoje projekty składają się z wielu mniejszych plików, zagłosuję na czwartą opcję - Stworzyłem logger.go, który jest częścią pakietu głównego. Ten plik go tworzy rejestrator, przypisuje go do pliku i dostarcza go do reszty głównej. Zauważ, że nie mają pochodzić z wdzięcznym sposobem zamknięcia errorlog ...

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

Aby uzyskać pełne zamknięcie, możesz prawdopodobnie odroczyć errorlog.Close() 'na końcu wykonywania lub, aby lepiej zapewnić jego zamknięte, skonfigurowane procedury obsługi sygnału za pomocą pakietu sygnałów GO https: // golang.org/pkg/os/signal/ – AJPennster

2

Znalazłem pakiet domyślny dziennika (https://golang.org/pkg/log/) nieco ograniczający. Na przykład brak obsługi dzienników informacji i debugowania.
Po pewnym poklepaniu się, postanowiłem użyć https://github.com/golang/glog. To wydaje się być portem https://github.com/google/glog i zapewnia przyzwoitą elastyczność w rejestrowaniu. Na przykład przy uruchamianiu aplikacji lokalnie możesz chcieć logować poziom DEBUG, ale możesz chcieć uruchomić tylko na poziomie INFO/ERROR w produkcji. Lista pełni funkcje/przewodnika jest tutaj https://google-glog.googlecode.com/svn/trunk/doc/glog.html (ITS dla modułu C++, ale dla najbardziej część przekłada się na porcie golang)

3

Jest to starsza pytanie, ale chciałbym zasugerować użycie http://github.com/romana/rlog (który opracowaliśmy). Jest on konfigurowany za pomocą zmiennych środowiskowych, obiekt rejestratora jest tworzony i inicjowany po zaimportowaniu protokołu rlog. Dlatego nie trzeba omijać rejestratora.

rlog ma sporo cech:

  • pełni konfigurowalny znaczków data/czas
  • Jednoczesne wyjście do stdout lub stderr jak plik.
  • Standardowe poziomy dziennika (debugowanie, informacje itp.) Oraz dowolnie konfigurowalne rejestrowanie wielopoziomowe.
  • Rejestrowanie na żądanie informacji o dzwoniącym (plik, numer linii, funkcja).
  • Możliwość ustawiania różnych poziomów logowania dla różnych plików źródłowych.

Jest bardzo mały, nie ma zewnętrznych zależności, z wyjątkiem standardowej biblioteki Golang i jest aktywnie rozwijany. Przykłady znajdują się w repozytorium.

+2

Dziękujemy za ujawnienie powiązania z produktem, który polecasz! To jest doceniane. –

3

Jest to prosty rejestrator

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

Można go używać w ten sposób

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") 
} 
Powiązane problemy