Начниая с 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
}