Go на примерах: Логирование

Стандартная библиотека Go предоставляет простые инструменты для вывода логов из программ Go: пакет log для свободного вывода и пакет log/slog для структурированного вывода.

package main
import (
    "bytes"
    "fmt"
    "log"
    "os"
    "log/slog"
)
func main() {

Простой вызов функций вроде Println из пакета log использует стандартный логгер, который уже предварительно настроен для разумного вывода логов в os.Stderr. Дополнительные методы вроде Fatal* или Panic* завершат программу после логирования.

    log.Println("standard logger")

Логгеры можно настраивать с помощью флагов для установки формата вывода. По умолчанию стандартный логгер имеет установленные флаги log.Ldate и log.Ltime, которые собраны в log.LstdFlags. Можно изменить флаги, чтобы выводить время с микросекундной точностью, например.

    log.SetFlags(log.LstdFlags | log.Lmicroseconds)
    log.Println("with micro")

Также поддерживается вывод имени файла и строки, из которой вызвана функция log.

    log.SetFlags(log.LstdFlags | log.Lshortfile)
    log.Println("with file/line")

Может быть полезно создать пользовательский логгер и передавать его. При создании нового логгера можно установить префикс, чтобы отличать его вывод от других логгеров.

    mylog := log.New(os.Stdout, "my:", log.LstdFlags)
    mylog.Println("from mylog")

Можно установить префикс на существующих логгерах (включая стандартный) с помощью метода SetPrefix.

    mylog.SetPrefix("ohmy:")
    mylog.Println("from mylog")

Логгеры могут иметь пользовательские цели вывода; подойдёт любой io.Writer.

    var buf bytes.Buffer
    buflog := log.New(&buf, "buf:", log.LstdFlags)

Этот вызов записывает вывод лога в buf.

    buflog.Println("привет")

Это фактически покажет его в стандартном выводе.

    fmt.Print("from buflog:", buf.String())

Пакет slog предоставляет структурированный вывод логов. Например, логирование в формате JSON делается просто.

    jsonHandler := slog.NewJSONHandler(os.Stderr, nil)
    myslog := slog.New(jsonHandler)
    myslog.Info("привет")

Помимо сообщения, вывод slog может содержать произвольное количество пар key=value.

    myslog.Info("снова привет", "key", "val", "age", 25)
}

Пример вывода; дата и время зависят от того, когда был запущен пример.

$ go run logging.go
2023/08/22 10:45:16 standard logger
2023/08/22 10:45:16.904141 with micro
2023/08/22 10:45:16 logging.go:40: with file/line
my:2023/08/22 10:45:16 from mylog
ohmy:2023/08/22 10:45:16 from mylog
from buflog:buf:2023/08/22 10:45:16 привет

Эти строки разбиты для наглядности на сайте; на самом деле они выводятся в одну строку.

{"time":"2023-08-22T10:45:16.904166391-07:00",
 "level":"INFO","msg":"привет"}
{"time":"2023-08-22T10:45:16.904178985-07:00",
    "level":"INFO","msg":"снова привет",
    "key":"val","age":25}

Далее: .