Conectarea la Go: Choosing a System and Using it

Sunteți relativ nou în limbajul Go. Probabil că îl utilizați pentru a scrie o aplicație web sau un server și trebuie să creați un fișier jurnal. Deci, faceți o căutare rapidă pe web și descoperiți că există o mulțime de opțiuni pentru logare în Go. Cum știi pe care să o alegi? Acest articol vă va echipa pentru a răspunde la această întrebare.

Ne vom uita la pachetul încorporat log și vom determina pentru ce proiecte este potrivit înainte de a explora alte soluții de logare care sunt predominante în ecosistemul Go.

Ce să loghezi

Nu trebuie să vă spun cât de importantă este logarea. Jurnalele sunt folosite de fiecare aplicație web de producție pentru a ajuta dezvoltatorii și operațiile:

  • Scoateți bug-uri în codul aplicației
  • Descoperiți probleme de performanță
  • Faceți analize post-mortem ale întreruperilor și incidentelor de securitate

Datele pe care le înregistrați efectiv vor depinde de tipul de aplicație pe care o construiți. De cele mai multe ori, veți avea o anumită variație a următoarelor:

  • Data temporală pentru momentul în care a avut loc un eveniment sau a fost generat un jurnal
  • Niveluri de jurnal, cum ar fi depanare, eroare sau informații
  • Date contextuale pentru a ajuta la înțelegerea a ceea ce s-a întâmplat și pentru a face posibilă reproducerea cu ușurință a situației

Ce nu trebuie să înregistrați

În general, nu ar trebui să înregistrați nicio formă de date comerciale sensibile sau informații de identificare personală. Acestea includ, dar nu se limitează la:

  • Nume
  • Adrese IP
  • Numere de carduri de credit

Aceste restricții pot face ca jurnalele să fie mai puțin utile din punct de vedere ingineresc, dar fac ca aplicația dumneavoastră să fie mai sigură. În multe cazuri, reglementări precum GDPR și HIPAA pot interzice înregistrarea de date cu caracter personal.

Introducerea pachetului log

Biblioteca standard Go are un pachet încorporat log care oferă cele mai multe caracteristici de bază de logare. Deși nu are niveluri de log (cum ar fi depanare, avertizare sau eroare), totuși oferă tot ceea ce aveți nevoie pentru a configura o strategie de logare de bază.

Iată cel mai de bază exemplu de logare:

package mainimport "log"func main() { log.Println("Hello world!")}

Codul de mai sus tipărește textul „Hello world!” pe eroarea standard, dar include și data și ora, ceea ce este util pentru filtrarea mesajelor de jurnal în funcție de dată.

2019/12/09 17:21:53 Hello world!

În mod implicit, pachetul log tipărește pe fluxul de ieșire eroare standard (stderr), dar îl puteți face să scrie pe fișiere locale sau pe orice destinație care acceptă interfața io.Writer. De asemenea, adaugă un timestamp la mesajul de jurnal fără nici o configurație suplimentară.

Înregistrarea într-un fișier

Dacă aveți nevoie să stocați mesajele de jurnal într-un fișier, puteți face acest lucru creând un fișier nou sau deschizând un fișier existent și stabilindu-l ca ieșire a jurnalului. Iată un exemplu:

package mainimport ( "log" "os")func main() { // If the file doesn't exist, create it or append to the file file, err := os.OpenFile("logs.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666) if err != nil { log.Fatal(err) } log.SetOutput(file) log.Println("Hello world!")}

Când rulăm codul, următoarele sunt scrise în logs.txt.

2019/12/09 17:22:47 Hello world!

După cum am menționat mai devreme, puteți, practic, scoate jurnalele către orice destinație care implementează interfața io.Writer, astfel încât aveți o mare flexibilitate atunci când decideți unde să înregistrați mesajele din aplicația dumneavoastră.

Crearea de loguri personalizate

Deși pachetul log implementează un logger predefinit care scrie în eroarea standard, putem crea tipuri de loguri personalizate folosind metoda log.New().

Când creați un nou logger, trebuie să treceți trei argumente la log.New():

  • out: Orice tip care implementează interfața io.Writer, care este locul în care vor fi scrise datele de jurnal
  • prefix: Un șir care este adăugat la începutul fiecărei linii de jurnal
  • flag: Un set de constante care ne permit să definim ce proprietăți de logare trebuie să fie incluse în fiecare intrare de jurnal generată de logger (mai multe despre acest lucru în secțiunea următoare)

Potem profita de această caracteristică pentru a crea loggere personalizate. Iată un exemplu care implementează loggerii Info, Warning și Error:

package mainimport ( "log" "os")var ( WarningLogger *log.Logger InfoLogger *log.Logger ErrorLogger *log.Logger)func init() { file, err := os.OpenFile("logs.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666) if err != nil { log.Fatal(err) } InfoLogger = log.New(file, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) WarningLogger = log.New(file, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile) ErrorLogger = log.New(file, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)}func main() { InfoLogger.Println("Starting the application...") InfoLogger.Println("Something noteworthy happened") WarningLogger.Println("There is something you should know about") ErrorLogger.Println("Something went wrong")}

După crearea sau deschiderea fișierului logs.txt din partea de sus a funcției init, inițializăm apoi cei trei loggeri definiți, furnizând destinația de ieșire, șirul de prefix și steagurile de log.

În funcția main, loggerii sunt utilizați prin apelarea funcției Println, care scrie o nouă intrare de jurnal în fișierul jurnal. Când rulați acest program, următoarele vor fi scrise în logs.txt.

INFO: 2019/12/09 12:01:06 main.go:26: Starting the application...INFO: 2019/12/09 12:01:06 main.go:27: Something noteworthy happenedWARNING: 2019/12/09 12:01:06 main.go:28: There is something you should know aboutERROR: 2019/12/09 12:01:06 main.go:29: Something went wrong

Rețineți că, în acest exemplu, înregistrăm într-un singur fișier, dar puteți utiliza un fișier separat pentru fiecare logger, trecând un fișier diferit atunci când creați loggerul.

Semnalizatoare de jurnal

Puteți utiliza constantele de semnalizare a jurnalului pentru a îmbogăți un mesaj de jurnal prin furnizarea de informații suplimentare de context, cum ar fi fișierul, numărul liniei, data și ora. De exemplu, trecerea mesajului „Something went wrong” printr-un logger cu o combinație de stegulețe prezentată mai jos:

log.Ldate|log.Ltime|log.Lshortfile

va imprima

2019/12/09 12:01:06 main.go:29: Something went wrong

Din păcate, nu există niciun control asupra ordinii în care apar sau asupra formatului în care sunt prezentate.

Introducerea cadrelor de logare

Utilizarea pachetului log este excelentă pentru dezvoltarea locală, atunci când obținerea unui feedback rapid este mai importantă decât generarea de jurnale bogate și structurate. Dincolo de aceasta, cel mai probabil vă va fi mai bine să folosiți un cadru de logare.

Un avantaj major al utilizării unui cadru de logare este că ajută la standardizarea datelor de logare. Acest lucru înseamnă că:

  • Este mai ușor să citiți și să înțelegeți datele de jurnal.
  • Este mai ușor să adunați jurnalele din mai multe surse și să le alimentați către o platformă centrală pentru a fi analizate.

În plus, logarea este practic o problemă rezolvată. De ce să reinventăm roata?

Salegerea unui cadru de logare

Decizia asupra cadrului de logare poate fi o provocare, deoarece există mai multe opțiuni din care se poate alege.

Cele mai populare două cadre de logare pentru Go par a fi beglog și logrus. Popularitatea lui glog este surprinzătoare, deoarece nu a mai fost actualizat de câțiva ani. logrus este mai bine întreținut și este folosit în proiecte populare precum Docker, așa că ne vom concentra pe el.

Începem cu logrus

Instalarea logrus este la fel de simplă ca și cum ați rula comanda de mai jos în terminalul dvs.:

go get "github.com/Sirupsen/logrus"

Un lucru grozav despre logrus este că este complet compatibil cu pachetul log al bibliotecii standard, așa că puteți înlocui peste tot importurile de log cu log "github.com/sirupsen/logrus" și va funcționa pur și simplu!

Să modificăm exemplul nostru anterior „hello world” care folosea pachetul log și să folosim în schimb logrus:

package mainimport ( log "github.com/sirupsen/logrus")func main() { log.Println("Hello world!")}

Executarea acestui cod produce rezultatul:

INFO Hello world!

Nu putea fi mai ușor de atât!

Logging în JSON

logrus este foarte potrivit pentru logarea structurată în JSON, care – deoarece JSON este un standard bine definit – facilitează analiza jurnalelor dvs. de către serviciile externe și, de asemenea, face ca adăugarea contextului la un mesaj de jurnal să fie relativ simplă prin utilizarea câmpurilor, așa cum se arată mai jos:

package mainimport ( log "github.com/sirupsen/logrus")func main() { log.SetFormatter(&log.JSONFormatter{}) log.WithFields( log.Fields{ "foo": "foo", "bar": "bar", }, ).Info("Something happened")}

Lovitura de jurnal generată va fi un obiect JSON care include mesajul, nivelul de jurnal, marcajul de timp și câmpurile incluse.

{"bar":"bar","foo":"foo","level":"info","msg":"Something happened","time":"2019-12-09T15:55:24+01:00"}

Dacă nu sunteți interesat de ieșirea jurnalelor dvs. sub formă de JSON, fiți conștienți de faptul că există mai mulți formatatori terți pentru logrus, pe care îi puteți vedea pe pagina sa Github. Puteți chiar să vă scrieți propriul formator, dacă preferați.

Niveluri de jurnal

În comparație cu pachetul standard de jurnal, logrus suportă niveluri de jurnal.

logrus are șapte niveluri de jurnal: Trace, Debug, Info, Warn, Warn, Error, Fatal și Panic. Severitatea fiecărui nivel crește pe măsură ce coborâți în listă.

log.Trace("Something very low level.")log.Debug("Useful debugging information.")log.Info("Something noteworthy happened!")log.Warn("You should probably take a look at this.")log.Error("Something failed but I'm not quitting.")// Calls os.Exit(1) after logginglog.Fatal("Bye.")// Calls panic() after logginglog.Panic("I'm bailing.")

Prin setarea unui nivel de logare pe un logger, puteți înregistra doar intrările de care aveți nevoie în funcție de mediul dumneavoastră. În mod implicit, logrus va înregistra tot ceea ce este de nivel Info sau mai sus (Warn, Error, Fatal sau Panic).

package mainimport ( log "github.com/sirupsen/logrus")func main() { log.SetFormatter(&log.JSONFormatter{}) log.Debug("Useful debugging information.") log.Info("Something noteworthy happened!") log.Warn("You should probably take a look at this.") log.Error("Something failed but I'm not quitting.")}

Executarea codului de mai sus va produce următoarea ieșire:

{"level":"info","msg":"Something noteworthy happened!","time":"2019-12-09T16:18:21+01:00"}{"level":"warning","msg":"You should probably take a look at this.","time":"2019-12-09T16:18:21+01:00"}{"level":"error","msg":"Something failed but I'm not quitting.","time":"2019-12-09T16:18:21+01:00"}

Observați că mesajul de nivel Debug nu a fost tipărit. Pentru a-l include în jurnal, setați log.Level să fie egal cu log.DebugLevel:

log.SetLevel(log.DebugLevel)

Încheie

În această postare, am explorat utilizarea pachetului de jurnal încorporat și am stabilit că acesta ar trebui utilizat numai pentru aplicații triviale sau atunci când se construiește un prototip rapid. Pentru orice altceva, utilizarea unui cadru de logare mainstream este o necesitate.

Am analizat, de asemenea, modalități de a ne asigura că informațiile conținute în jurnalele dvs. sunt coerente și ușor de analizat, în special atunci când le agregăm pe o platformă centralizată.

Mulțumim pentru lectură!

.

Leave a Reply