Зачем нужны уровни логирования: инструмент, а не украшение
Логирование — это не просто запись событий в файл. Это диагностический инструмент, который должен отвечать на вопрос: что сломалось и почему? Если в логах нет ответа, они превращаются в бесполезный шум. Если их слишком много — их невозможно анализировать.
Уровни логирования (debug, info, warn, error, fatal) пытаются разделить события по важности, но важность — понятие относительное. Один и тот же сигнал в разных системах может попасть в разные категории. Например, отсутствие ответа от внешнего сервиса может быть:
- error, если система не может работать без него
- warn, если система может работать с ограничениями
Уровни логирования — это не объективная шкала, а соглашение между разработчиками и эксплуатацией. Их главная задача — отделить сигнал от шума, чтобы в критической ситуации не приходилось продираться через мегабайты отладочных сообщений.
Как устроены уровни: теория и реальность
Стандартные уровни логирования выглядят как лестница, где каждый следующий включает предыдущие:
- Debug — подробности для разработчиков: внутренние состояния, параметры запросов, временные метки
- Info — события, важные для понимания работы, но не сигнализирующие о проблемах
- Warn — потенциальные проблемы, не нарушающие работу
- Error — ошибки, нарушающие работу, но не останавливающие систему
- Fatal — критические ошибки, после которых система не может продолжать работу
На практике эта лестница ломается по двум причинам:
-
Разные системы — разные правила В распределённой архитектуре один и тот же уровень может означать разные вещи. В одном сервисе warn — это потеря части функциональности, в другом — единичный сбой без последствий.
-
Человеческий фактор Разработчики часто выбирают уровень логирования интуитивно. В результате warn может оказаться важнее error, а debug — содержать критические данные.
Что писать в лог, а что — выключить навсегда
Писать обязательно: контекст решает всё
-
Контекст ошибки Недостаточно написать “Ошибка подключения к базе данных”. Нужно добавить:
- Какая именно база данных (адрес, порт, имя сервиса)
- Какой запрос выполнялся (текст запроса, параметры)
- Время выполнения (если оно превысило ожидаемое)
- Трассировку стека (но только в debug)
Пример полезного лога:
[ERROR] Database connection failed: host=db-server, query="SELECT * FROM users WHERE id=?", error="timeout after exceeding expected duration" -
Границы транзакций Если система работает с транзакциями, в логах должны быть метки начала и конца транзакции, а также её статус.
-
Внешние зависимости Для зависимостей от других сервисов в логах должны быть:
- Запросы к внешним API (URL, параметры)
- Ответы от внешних сервисов (код статуса)
- Таймауты и повторные попытки
-
Изменения состояния Переходы системы из одного состояния в другое должны фиксироваться в логах, особенно для систем с очередями и конечных автоматов.
Не писать ни при каких условиях
-
Чувствительные данные Пароли, токены, персональные данные должны маскироваться:
[DEBUG] Request: body={"email": "u***@e***.com"} -
Избыточные отладочные сообщения Вместо логгирования каждого изменения переменной лучше писать одно сообщение с финальным значением.
-
Дубликаты Для повторяющихся ошибок достаточно первого сообщения с контекстом и счётчика повторений.
-
Сообщения без контекста Лог должен отвечать на вопросы: что произошло, где, почему и с какими данными.
Как выбрать уровень логирования: правила вместо догадок
Debug: только для отладки
Debug должен быть выключен в продакшене. Включается только для расследования конкретных проблем. Можно писать:
- Параметры запросов и ответов
- Внутренние состояния системы
- Временные метки и задержки
Но даже в debug не стоит писать всё подряд. Если сообщение не помогает понять проблему, его лучше убрать.
Info: что важно знать
Info — это уровень для событий, важных для понимания работы, но не сигнализирующих о проблемах:
- Старт и остановка сервиса
- Успешное завершение задачи
- Изменения конфигурации
Info должен быть включён в продакшене, но не должен создавать шум.
Warn: потенциальные проблемы
Warn — это уровень для событий, которые могут привести к проблемам, но не нарушают работу:
- Превышение таймаута с автоматическим восстановлением
- Неожиданные ответы от внешних сервисов
- Предупреждения о деградации производительности
Warn не должен срабатывать слишком часто.
Error: ошибки, нарушающие работу
Error — это уровень для ошибок, нарушающих работу, но не останавливающих систему:
- Неудачные запросы к базе данных с повторными попытками
- Ошибки валидации данных
- Превышение лимитов ресурсов
На error должны быть настроены алерты.
Fatal: критические ошибки
Fatal — это уровень для ошибок, после которых система не может продолжать работу:
- Невозможность подключиться к базе данных
- Критические ошибки конфигурации
- Нехватка ресурсов
На fatal должны быть настроены алерты с высоким приоритетом.
Почему логи ломаются именно так
Проблема 1: debug в продакшене
Когда debug включён в продакшене:
- Логи раздуваются до огромных объёмов
- Система замедляется из-за записи данных
- Важные сообщения теряются в шуме
Тупик: разработчики включают debug “на всякий случай”, но это приводит к обратному эффекту.
Решение: debug должен быть выключен по умолчанию и включаться только для расследования проблем.
Проблема 2: warn вместо error
Когда критические ошибки маскируются под warn:
- Алерты не срабатывают
- Проблемы остаются незамеченными
- Система деградирует незаметно
Тупик: разработчики выбирают warn, потому что “система ещё работает”.
Решение: если ошибка нарушает работу — это error.
Проблема 3: отсутствие контекста
Когда логи не содержат контекста:
- Невозможно понять, что произошло
- Расследование инцидентов занимает больше времени
- Логи становятся бесполезными
Тупик: разработчики пишут логи для себя, а не для других.
Решение: каждый лог должен отвечать на вопросы: что, где, почему и с какими данными произошло.
Проблема 4: дубликаты и шум
Когда одна и та же ошибка повторяется многократно:
- Логи становятся нечитаемыми
- Поиск важных сигналов занимает слишком много времени
- Система выглядит более сломанной, чем есть на самом деле
Тупик: разработчики пишут каждое сообщение об ошибке “на всякий случай”.
Решение: для повторяющихся ошибок писать первое сообщение с контекстом и счётчик повторений.
Позиция редакции: как сделать логи полезными
Логирование — это инженерная дисциплина. Уровни логирования должны выбираться по формальным критериям:
- Если ошибка нарушает работу — error
- Если система может работать с ограничениями — warn
- Если событие важно для понимания работы — info
- Если событие нужно только для отладки — debug
Эта позиция неверна, если:
- Система настолько простая, что все логи можно писать на одном уровне
- В системе нет распределённых компонентов
- Логи не используются для расследования инцидентов
Что делать, если логи уже сломаны
-
Провести аудит логов Перераспределить сообщения по правильным уровням.
-
Настроить ротацию логов Убедиться, что логи не раздуваются до огромных объёмов.
-
Настроить алерты Убедиться, что на error и fatal настроены алерты.
-
Убрать debug из продакшена Убедиться, что debug выключен по умолчанию.
Логи — это не просто текстовые файлы. Это инструмент, который помогает поддерживать систему в рабочем состоянии. Если они сломаны, система становится неуправляемой.