Skip to content

Часто задаваемые вопросы

Базовое использование

В чём разница между глобальным логгером и пользовательским логгером?

Глобальный логгер используется через пакетные функции dd.Info() и т.д., подходит для простых сценариев. Пользовательский логгер создаётся через dd.New(), поддерживает независимую конфигурацию и управление жизненным циклом.

go
// Глобальный логгер
dd.Info("Глобальный лог")

// Пользовательский логгер
logger, _ := dd.New(dd.JSONConfig())
logger.Info("Независимый лог")

Как инициализировать глобальный логгер при запуске программы?

go
func init() {
    err := dd.InitDefault(dd.JSONConfig())
    if err != nil {
        log.Fatal(err)
    }
}

Или через SetDefault:

go
logger, _ := dd.New(dd.Config{
    Format: dd.FormatJSON,
    Targets: []dd.OutputTarget{
        dd.ConsoleOutput(),
        dd.FileOutput("logs/app.json"),
    },
})
dd.SetDefault(logger)

Что происходит при уровне Fatal?

Fatal / Fatalf / FatalWith вызывают os.Exit(1) после вывода лога (defer-выражения не выполняются; внутренне сначала попытается Close() сбросить отложенные логи, ожидая максимум 5 секунд). Поведение выхода можно настроить через FatalHandler; если требуется очистка ресурсов, используйте ErrorWith + явный Shutdown(ctx).

Конфигурация

Как одновременно выводить в консоль и файл?

go
logger, _ := dd.New(dd.Config{
    Targets: []dd.OutputTarget{
        dd.ConsoleOutput(),
        dd.FileOutput("logs/app.log"),
    },
})
// Или в формате JSON
logger, _ := dd.New(dd.Config{
    Format: dd.FormatJSON,
    Targets: []dd.OutputTarget{
        dd.ConsoleOutput(),
        dd.FileOutput("logs/app.json"),
    },
})

Как динамически изменить уровень логирования?

go
_ = logger.SetLevel(dd.LevelDebug)  // Изменение во время выполнения (возвращает error)
_ = dd.SetLevel(dd.LevelDebug)      // Изменение уровня глобального логгера

Как настроить стратегию ротации файлов?

Через конфигурацию FileWriter:

go
fw, _ := dd.NewFileWriter("logs/app.log",
    dd.DefaultFileWriterConfig(),  // 100МБ, 30 дней, 10 резервных копий
)

Производительность

Влияет ли логирование на производительность программы?

DD разработан для высокой производительности:

  • Низкоаллокационная оптимизация на горячих путях
  • Атомарная проверка уровня, без блокировок
  • Фильтрация конфиденциальных данных для больших входных данных (≥10КБ) выполняется в отдельной goroutine с защитой по таймауту; малые входные данные обрабатываются синхронно
  • Опциональная буферизованная запись для уменьшения I/O

Как оптимизировать в сценариях с высокой пропускной способностью?

  1. Используйте BufferedWriter для уменьшения I/O
  2. Проверяйте уровень перед конструированием полей
  3. Рассмотрите возможность включения сэмплирования логов
  4. Избегайте использования поля Any на высокочастотных путях

Подробнее в Оптимизация производительности.

Безопасность

Как работает фильтрация конфиденциальных данных?

SensitiveDataFilter использует regex-сопоставление шаблонов для автоматической замены конфиденциальных значений на [REDACTED] перед записью лога. Малые входные данные обрабатываются синхронно, большие — в отдельной goroutine с защитой по таймауту, не блокируя запись логов.

Как добавить пользовательские шаблоны конфиденциальных данных?

go
filter, _ := dd.NewCustomSensitiveDataFilter(
    `(?i)my_secret_field\s*[:=]\s*\S+`,
)

Как убедиться, что логи не были подделаны?

Используйте IntegritySigner для HMAC-подписи логов:

go
cfg, _ := dd.DefaultIntegrityConfigSafe()
signer, _ := dd.NewIntegritySigner(cfg)
sig := signer.Sign(logMessage)
// Проверка: signer.Verify(signedEntry)

Обработка ошибок

Почему AddWriter возвращает ошибку?

Возможные причины:

  • ErrNilWriter -- передан nil Writer
  • ErrLoggerClosed -- логгер закрыт
  • ErrMaxWritersExceeded -- превышено количество Writer

Как обработать ошибку записи?

go
logger.SetWriteErrorHandler(func(w io.Writer, err error) {
    // Пользовательская обработка
    metrics.WriteErrors.Inc()
})

Тестирование

Как перехватить логи в тестах?

Используйте LoggerRecorder:

go
rec := dd.NewLoggerRecorder()
logger, _ := rec.NewLogger()

logger.Info("test")

if !rec.ContainsMessage("test") {
    t.Error("Ожидаемый лог не найден")
}

Подробнее в Тестовые утилиты.

Следующие шаги