Начниая с Go 1.21 стало доступно журналирование при помощи slog
из пакета log/slog
.
Чаще slog
используют как обертку над другими пакетами журналирования, но для начала его вполне достаточно.
- Во время разработки нам бы хотелось получать
debug
сообщения журнала в форматеJSON
. На тесте нам уже нужен уровень детализации не нижеinfo
и сообщения в форматеTEXT
. Для этого создадим конструктор, который будет возвращатьlogger
с заданным уровнем детализации в журнале и форматом. - Так как мы принимаем уровень детализации журнала в виде строки (в конфиге корректнее хранить в виде строки), то нам понадобится небольшой парсер для конвертации строки в
slog.Level
.
Создаем парсер
Начнем с парсера, так как он нам понадобится в конструкторе:
// parseLevel takes a string level and returns the log/slog log level constant.
func parseLevel(level string) (slog.Level, error) {
switch strings.ToLower(level) {
case "error":
return slog.LevelError, nil
case "warn", "warning":
return slog.LevelWarn, nil
case "info":
return slog.LevelInfo, nil
case "debug":
return slog.LevelDebug, nil
}
var l slog.Level
return l, fmt.Errorf("not a valid log level: %q", level)
}
Создаем конструктор
Уровень детализации в журнале и формат мы берем из конфигурационного файла
(см. статью Create config using viper package.
) и передаем в конструктор logger
.
В конструкторе используя парсер получаем уровень детализации в виде slog.Level
.
Затем создаем logger
при помощи функции New
, в которую передаем slog.Handler
.
В качестве slog.Handler
мы по умолчанию задаем формат TEXT
используя функцию NewTextHandler
.
Если был передан формат JSON
, то создаем его используя NewJSONHandler
.
В обоих случаях передаем уровень детализации при помощи &slog.HandlerOptions{})
. Полный код конструктора:
func New(level, format string) (*slog.Logger, error) {
var logger *slog.Logger
l, err := parseLevel(level)
if err != nil {
return nil, err
}
logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: l}))
if format == "json" {
logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: l}))
}
return logger, nil
}