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