Zjistěte, jak se přihlásit k Go

Dokončeno

Protokoly hrají významnou roli v programu, protože se stanou zdrojem informací, které můžete zkontrolovat, kdy se něco nepovede. Obvykle, když dojde k chybě, koncoví uživatelé vidí jenom zprávu, která indikuje problém s programem. Z pohledu vývojáře potřebujeme více informací než jednoduchou chybovou zprávu. To je hlavně proto, že chceme problém reprodukovat, abychom napsali správnou opravu. V tomto modulu se dozvíte, jak funguje protokolování v Go. Dozvíte se také několik postupů, které byste měli vždy implementovat.

Balíček log

Pro začátek go nabízí jednoduchý standardní balíček pro práci s protokoly. Můžete ho použít tak, jak balíček používáte fmt . Standardní balíček neposkytuje úrovně protokolů a neumožňuje konfigurovat samostatné protokolovací nástroje pro každý balíček. Pokud potřebujete psát složitější konfigurace protokolování, můžete to udělat pomocí architektury protokolování. Rozhraní protokolování probereme později.

Tady je nejjednodušší způsob, jak používat protokoly:

import (
    "log"
)

func main() {
    log.Print("Hey, I'm a log!")
}

Při spuštění předchozího kódu získáte tento výstup:

2020/12/19 13:39:17 Hey, I'm a log!

Ve výchozím nastavení log.Print() funkce jako předponu zprávy protokolu obsahuje datum a čas. Stejné chování můžete získat pomocí fmt.Print(), ale s balíčkem můžete dělat další věci log , jako je odesílání protokolů do souboru. Později se podíváme na další log funkce balíčků.

Pomocí funkce můžete log.Fatal() protokolovat chybu a ukončit program, jako byste použili os.Exit(1). Abychom to vyzkoušeli, použijeme tento fragment kódu:

package main

import (
    "fmt"
    "log"
)

func main() {
    log.Fatal("Hey, I'm an error log!")
    fmt.Print("Can you see me?")
}

Při spuštění předchozího kódu získáte tento výstup:

2020/12/19 13:53:19  Hey, I'm an error log!
exit status 1

Všimněte si, fmt.Print("Can you see me?")že poslední řádek se nespustí. Je to proto, že log.Fatal() volání funkce program zastaví. Podobné chování získáte při použití log.Panic() funkce, která také volá panic() funkci, například takto:

package main

import (
    "fmt"
    "log"
)

func main() {
    log.Panic("Hey, I'm an error log!")
    fmt.Print("Can you see me?")
}

Při spuštění předchozího kódu získáte tento výstup:

2020/12/19 13:53:19  Hey, I'm an error log!
panic: Hey, I'm an error log!

goroutine 1 [running]:
log.Panic(0xc000060f58, 0x1, 0x1)
        /usr/local/Cellar/go/1.15.5/libexec/src/log/log.go:351 +0xae
main.main()
        /Users/christian/go/src/helloworld/logs.go:9 +0x65
exit status 2

Stále se zobrazuje zpráva protokolu, ale teď se zobrazí také trasování zásobníku chyb.

Další základní funkcí je log.SetPrefix(). Můžete ho použít k přidání předpony do zpráv protokolu programu. Můžete například použít tento fragment kódu:

package main

import (
    "log"
)

func main() {
    log.SetPrefix("main(): ")
    log.Print("Hey, I'm a log!")
    log.Fatal("Hey, I'm an error log!")
}

Při spuštění předchozího kódu získáte tento výstup:

main(): 2021/01/05 13:59:58 Hey, I'm a log!
main(): 2021/01/05 13:59:58 Hey, I'm an error log!
exit status 1

Předponu nastavíte jednou a protokoly budou obsahovat informace, jako je název funkce, ze které protokol přišel.

Na webu Go můžete prozkoumat další funkce.

Protokolování do souboru

Kromě tisku protokolů do konzoly můžete chtít protokoly odeslat do souboru, abyste je mohli později nebo v reálném čase zpracovat.

Proč chcete odeslat protokoly do souboru? Nejprve můžete chtít skrýt konkrétní informace od koncových uživatelů. Nemusí vás zajímat nebo byste mohli odhalit citlivé informace. Pokud máte protokoly v souborech, můžete všechny protokoly centralizovat do jednoho umístění a korelovat je s jinými událostmi. Tento vzor je typický: mít distribuované aplikace, které mohou být dočasné, jako jsou kontejnery.

K otestování odesílání protokolů do souboru použijeme následující kód:

package main

import (
    "log"
    "os"
)

func main() {
    file, err := os.OpenFile("info.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
    if err != nil {
        log.Fatal(err)
    }

    defer file.Close()

    log.SetOutput(file)
    log.Print("Hey, I'm a log!")
}

Když spustíte předchozí kód, v konzole se nic nezobrazí. V adresáři by se měl zobrazit nový soubor s názvem info.log, který obsahuje protokoly, které jste odeslali pomocí log.Print() funkce. Všimněte si, že musíte začít vytvořením nebo otevřením souboru a následnou konfigurací log balíčku tak, aby se všechny výstupy odesílaly do souboru. Pak můžete funkci dál používat log.Print() stejně, jako obvykle.

Protokolování rozhraní

A konečně může docházet k tomu, že log funkce balíčku nestačí. Místo psaní vlastních knihoven může být užitečné použít protokolovací architekturu. Několik rozhraní protokolování pro Go jsou Logrus, zerolog, zap a Apex.

Pojďme se podívat, co můžeme dělat s nullogem.

Nejprve musíte balíček nainstalovat. Pokud pracujete v této sérii, pravděpodobně už používáte moduly Go, takže nemusíte nic dělat. Pro případ, že byste na pracovní stanici mohli spustit tento příkaz a nainstalovat knihovny zerologu:

go get -u github.com/rs/zerolog/log

Teď ho pomocí tohoto fragmentu kódu vyzkoušejte:

package main

import (
    "github.com/rs/zerolog"
    "github.com/rs/zerolog/log"
)

func main() {
    zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
    log.Print("Hey! I'm a log message!")
}

Při spuštění předchozího kódu získáte tento výstup:

{"level":"debug","time":1609855453,"message":"Hey! I'm a log message!"}

Všimnětesichm funkcím.log.Print() Všimněte si také, jak se výstup změní ve formátu JSON. Json je užitečný formát pro protokoly při spouštění hledání v centralizované lokalitě.

Další užitečnou funkcí je, že můžete rychle zahrnout kontextová data, například takto:

package main

import (
    "github.com/rs/zerolog"
    "github.com/rs/zerolog/log"
)

func main() {
    zerolog.TimeFieldFormat = zerolog.TimeFormatUnix

    log.Debug().
        Int("EmployeeID", 1001).
        Msg("Getting employee information")

    log.Debug().
        Str("Name", "John").
        Send()
}

Při spuštění předchozího kódu získáte tento výstup:

{"level":"debug","EmployeeID":1001,"time":1609855731,"message":"Getting employee information"}
{"level":"debug","Name":"John","time":1609855731}

Všimněte si, jak jsme přidali jako kontext ID zaměstnance. Stane se součástí logline jako další vlastnost. Je také důležité zdůraznit, že pole, která zahrnete, jsou silně napsaná.

Pomocí trasování formátovaného zásobníku a více než jedné instance protokolovacího nástroje můžete implementovat další funkce s nulovým protokolem, jako je protokolování vyrovnání, a ke správě různých výstupů můžete použít více než jednu instanci protokolovacího modulu. Další informace najdete na webu GitHubu.