Перейти к содержимому
Войти Регистрация

Лучшие правила полезного логирования

Лучшие правила полезного логирования

Логи пишут все, а пользуются ими единицы — потому что в момент аварии в них невозможно ничего найти. Семь правил, после которых разбор инцидента занимает пять минут, а не полночи.

Зачем логи, если есть отладчик

Отладчик работает там, где вы можете воспроизвести проблему. На боевом сервере вы не можете: ошибка случилась ночью, у одного пользователя из тысячи, при стечении обстоятельств, которое вы не повторите. Всё, что от неё осталось, — то, что программа успела записать.

Отсюда простой критерий качества: лог хорош, если по нему можно восстановить, что происходило, не имея доступа к машине и не воспроизводя ситуацию. Всё остальное — детали.

Обратная сторона. Логи стоят денег: место на диске, трафик, хранилище, время на разбор. Писать всё подряд так же плохо, как не писать ничего, — только дороже. В логе на десять гигабайт в сутки нужную строку не найдёт никто.

И ещё одно. Логи — это данные, которые вы вынесли за пределы приложения. К ним имеют доступ администраторы, служба поддержки, внешний сервис сбора. Всё, что туда попало, считайте наполовину опубликованным.

Список семи правил полезного логирования
Первые два правила дают основной эффект: сквозной номер запроса и честные уровни.

Топ 7 правил

Контекст вместо «произошла ошибка»

разница между пятиминутным разбором и бесполезной строкой

Запись «ошибка при обработке заказа» не стоит ничего. Какого заказа, какого пользователя, на каком шаге, что именно не получилось — ничего из этого в ней нет, и найти по ней конкретный случай невозможно.

Минимальный набор. Идентификатор сущности, с которой работали. Идентификатор пользователя — именно идентификатор, а не имя и не почта. Шаг или операция. Причина отказа, а не только факт. И сквозной идентификатор запроса, о котором ниже.

Сквозной идентификатор. На входе каждому запросу присваивается случайный номер, который дальше передаётся во все вызовы и попадает в каждую строку лога. Тогда по одному номеру собирается вся история: что пришло, куда сходили, что ответили. Без этого в логе нагруженного сервиса строки от разных пользователей перемешаны, и распутать их нельзя.

Приятный бонус. Тот же номер можно показывать пользователю на странице ошибки. Человек называет его в поддержке — и вы находите его случай мгновенно, вместо разговора «а во сколько это было примерно».

  • Превращает лог из ленты сообщений в средство расследования
  • Один номер связывает все компоненты системы
  • Резко ускоряет работу поддержки
  • Передачу номера нужно организовать через весь код и все вызовы
  • Легко случайно записать в контекст лишнее — например, всё тело запроса

главное правило · оценка 9,5

Уровни — по требуемой реакции

не «насколько это важно», а «что мне с этим делать»

Уровни превращаются в бесполезную декорацию, когда каждый выбирает их на глаз. Работающий критерий — не важность, а действие, которого запись требует.

Ошибка — сломалось то, что должно было работать, и кто-то должен вмешаться. По этому уровню настраивают оповещения, поэтому в него нельзя класть ожидаемые ситуации.

Предупреждение — всё работает, но происходит что-то ненормальное: сработал повтор, кончается место, чужой сервис отвечает медленно. Смотреть не срочно, но регулярно.

Информация — значимые события бизнес-логики: заказ создан, платёж подтверждён, задача выполнена. То, по чему потом восстанавливают ход событий.

Отладка — подробности для разбора, обычно выключены в проде и включаются на время.

Самая частая порча. Ошибками помечают то, что ошибкой не является: пользователь ввёл неверный пароль, чужой сервис вернул ожидаемый отказ, запись не найдена. Через месяц таких записей тысячи, на оповещения перестают смотреть, и настоящая авария теряется в шуме. Если реакции не требуется — это не ошибка.

  • Позволяет фильтровать и настраивать оповещения осмысленно
  • Уровень отладки можно включать на живой системе точечно
  • Правило простое и не требует обсуждений
  • Требует общей договорённости, иначе каждый ставит по-своему
  • Границу между предупреждением и ошибкой всё равно приходится обсуждать

база · оценка 9,4

Ни секретов, ни персональных данных

лог — это данные, вынесенные наружу

В логи регулярно утекает то, чего там быть не должно: пароли из тела запроса, токены доступа, ключи к чужим сервисам, номера карт, паспортные данные, полные адреса и телефоны. Чаще всего не намеренно, а одной строкой «записать весь запрос целиком, чтобы было понятнее».

Почему это серьёзно. Логи хранятся дольше всего остального, лежат в отдельном хранилище, часто у стороннего сервиса, и доступ к ним обычно шире, чем к базе. Утечка через логи — типовой сценарий, а не экзотика.

Как правильно. Заранее составьте список полей, которые вырезаются или заменяются на маску, и обрабатывайте его централизованно, на уровне библиотеки логирования. Полагаться на внимательность каждого разработчика в каждой строке не выйдет.

Вместо значения — ссылка. Пишите идентификатор пользователя, а не его почту. Идентификатор карты в платёжной системе, а не номер. Признак «телефон указан», а не сам телефон. Для разбора этого достаточно, а для утечки — уже нет.

Проверяйте на входе. Простой поиск по логам своих же тестовых данных — фамилии, номера, слова вроде «пароль» и «токен» — обычно находит что-нибудь в первый же раз. Про общие правила обращения с чувствительными данными у нас есть отдельный материал.

  • Закрывает целый класс утечек одним централизованным фильтром
  • Ничего не стоит, если сделано с самого начала
  • Упрощает жизнь при проверках и разборе инцидентов
  • Вычистить то, что уже записано, почти невозможно
  • Слишком агрессивная маскировка мешает разбирать проблемы

критично · оценка 9,3

Структурные логи вместо склеенных строк

чтобы искать по полям, а не выковыривать регулярными выражениями

Сообщение, собранное склейкой текста и значений, читается человеком и не читается машиной. Как только вам понадобится «все ошибки этого пользователя за час» или «сколько раз сработал повтор», начнётся разбор строк регулярными выражениями — занятие, которое ломается при первой же смене формулировки.

Как правильно. Сообщение — постоянный текст, всё переменное — отдельными полями. Тогда запись превращается в структуру, по которой можно фильтровать, группировать и считать. Большинство библиотек логирования умеют это из коробки, включается настройкой формата.

Компромисс для локальной разработки. В машиночитаемом формате читать логи глазами тяжело. Обычная схема: в проде — структурный вывод, локально — человекочитаемый. Это одна настройка, зависящая от окружения.

Одинаковые имена полей. Если в одном сервисе поле называется одним именем, а в другом иным, сквозной поиск не работает. Договоритесь о наборе базовых имён: идентификатор запроса, пользователь, операция, длительность, код результата.

  • Поиск и подсчёт по полям вместо разбора текста
  • Легко строить сводки и оповещения
  • Формат не ломается при изменении формулировок
  • Читать глазами без инструмента неудобно
  • Записи занимают заметно больше места
  • Требует договорённости об именах полей между сервисами

важно · оценка 9,2

Один поток вывода и сбор в одном месте

искать по десяти машинам вручную — не вариант

Приложение должно писать в стандартный вывод, а не заботиться о файлах, каталогах и правах. Дальше уже среда решает, куда это девать: на локальной машине — на экран, в контейнере — в журнал движка, на сервере — в систему сбора. Так проще всего, и так одинаково работает везде.

Зачем централизованный сбор. Как только сервисов больше одного, а машин больше одной, ручной поиск по файлам перестаёт работать. Нужна одна точка, где лежат логи всех компонентов, с поиском по полям и по времени. Тогда сквозной идентификатор запроса наконец начинает окупаться.

Время — в UTC и с одинаковым форматом. Иначе записи с разных машин не выстраиваются в одну ленту, и в момент разбора аварии приходится пересчитывать смещения в уме. Это ровно тот случай, когда экономия пяти минут при настройке стоит часа в неподходящий момент.

Реалистичная оговорка. Для одного маленького сервиса на одной машине полноценная система сбора избыточна: обычные файлы плюс просмотр в терминале закрывают вопрос. Порог — примерно два сервиса или две машины.

  • Одна точка поиска вместо обхода серверов
  • Приложению не нужно ничего знать про файлы и ротацию
  • Логи не теряются вместе с пересозданным контейнером
  • Система сбора — ещё один компонент, который нужно обслуживать
  • Готовые сервисы стоят денег, и цена растёт с объёмом
  • Отставание доставки мешает в момент горячего разбора

от двух сервисов · оценка 9,1

Сообщение отвечает на вопрос «что и дальше что»

текст пишется для человека, который увидит его ночью

Хорошая запись говорит, что именно произошло и, если это ошибка, что с этим делать. «Ошибка сохранения» — плохо. «Не удалось сохранить заказ: база отклонила запись из-за нарушения уникальности номера» — хорошо: понятно и что случилось, и куда смотреть.

Ошибку записывайте один раз. Типовая беда — исключение перехватили, записали, пробросили выше, там записали снова, и так три раза. В логе три записи об одном событии, и кажется, что проблем больше, чем есть. Правило: пишет тот, кто обработал; кто пробрасывает — не пишет.

Со стеком вызовов. Для настоящих ошибок стек обязателен — без него запись почти бесполезна. А вот для ожидаемых ситуаций он не нужен и только раздувает объём.

Границы операций. Полезно писать начало и конец значимой операции с длительностью и результатом. Это даёт понимание, где именно всё встало, без всякого профилировщика.

Чего не писать. «Вошли в функцию» и «вышли из функции», содержимое циклов построчно, повторяющиеся сообщения без новой информации. Это не логи, а шум, в котором тонет полезное.

  • Разбор ускоряется без всяких инструментов
  • Меньше объём: шума нет, полезное остаётся
  • Помогает не только автору кода, но и дежурному
  • Требует привычки, а не настройки — внедряется медленно
  • Формулировки со временем расходятся между разработчиками

на разработчике · оценка 9,0

Ротация и срок хранения

забитый логами диск — классическая ночная авария

Лог растёт всегда. Без ограничений он однажды займёт весь диск, и сервис ляжет не из-за ошибки в коде, а из-за того, что некуда записать. Это одна из самых частых причин инцидентов на маленьких проектах.

Что настроить. Ротацию по размеру или по времени, сжатие старых файлов, ограничение общего количества и автоматическое удаление. На большинстве систем всё это делает штатный механизм, и настройка занимает несколько минут.

Срок хранения — осознанное решение. Оперативные логи нужны днями и неделями, а не годами. Отдельно стоит выделить записи о значимых действиях с данными: их иногда требуется хранить дольше, но и требования к их защите выше. Хранить всё вечно «на всякий случай» — дорого и рискованно: чем дольше лежат данные, тем больше шансов, что они утекут.

Проверьте, что оно работает. Настроенная, но не проверенная ротация — то же самое, что ненастроенная. Посмотрите каталог с логами через неделю: если старые файлы на месте и не сжаты, значит, настройка не подхватилась.

  • Убирает целый класс аварий с местом на диске
  • Настраивается штатными средствами за минуты
  • Сокращает объём хранимых персональных данных
  • Слишком короткий срок — и данных для разбора уже нет
  • Требования к хранению иногда диктуются не вами
  • Про проверку настройки все забывают

гигиена · оценка 8,8

Инфографика: назначение правила, цена его пропуска и сложность внедрения
Три правила из семи внедряются за минуты или сразу — с них и стоит начинать.

Сравнение по главному

ПравилоЗачемЦена пропускаВнедрить
Контекст и сквозной номерпоиск по инцидентувысокаядень
Уровни по реакциифильтрация и оповещениясредняясразу
Без секретов и личных данныхбезопасностькритичнаясразу
Структурные логипоиск и подсчётсредняядень
Сбор в одном местеодна лента событийвысокаядень
Понятные сообщенияскорость разборасредняяпривычка
Ротация и срок храненияместо на дискевысокаяминуты
Диаграмма оценок семи правил полезного логирования
Оценка — по тому, насколько правило ускоряет разбор реальной аварии.

Что писать в лог, а что нет

Обязательно. Старт и остановка приложения с версией и ключевыми настройками. Входящие запросы: метод, адрес, код ответа, длительность, номер запроса. Обращения к чужим сервисам: адрес, результат, длительность, факт повтора. Фоновые задачи: запуск, итог, число обработанных элементов. Значимые действия с данными: кто, что и когда изменил.

Полезно. Решения бизнес-логики, которые потом придётся объяснять: почему заказ отклонён, по какому правилу выбрана цена, почему сработало ограничение. Именно эти записи спасают в спорах с пользователями и с коллегами.

Не нужно. Вход и выход из каждой функции. Содержимое коллекций построчно. Дублирование одной ошибки на нескольких уровнях. Сообщения без единого идентификатора внутри.

Как читать в терминале. Просмотр в реальном времени с фильтром по уровню закрывает большую часть повседневных задач. Базовых команд для этого нужно всего несколько — они разобраны в материале про команды терминала.

Проверка на практике. Возьмите вчерашнюю ошибку и попробуйте восстановить по логам, что произошло, не открывая код. Если не получилось — вы точно знаете, чего в них не хватает.

Частые вопросы

Сколько логов — это много?

Ориентир не в объёме, а в пользе: если в потоке невозможно найти нужное без сложных фильтров, записей слишком много. Первым делом убирают повторы и отладочные записи, оставшиеся с этапа разработки. Для очень частых однотипных событий применяют выборочную запись — сохраняют часть, а не каждое.

Логи, метрики или трассировка?

Это разные инструменты. Метрики отвечают на вопрос «сколько и как часто» и дешевле в хранении. Логи — на вопрос «что именно случилось в этом конкретном случае». Трассировка показывает путь одного запроса через несколько сервисов. Считать что-то массовое логами дорого и неудобно — для этого есть счётчики.

Что делать, если для разбора нужны личные данные?

Записывать идентификатор, а не значение: по нему в момент разбора можно поднять нужное из базы, имея на это право. Если без значения совсем никак — маскированный вид, короткий срок хранения и ограниченный доступ. И обязательно фиксируйте, кто и зачем смотрел: это защищает в первую очередь вас.

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

Пока сервис один и живёт на одной машине — нет, файлов и терминала достаточно. Порог — второй сервис, вторая машина или контейнеры, которые пересоздаются вместе со своими логами. Начать разумно с самого простого варианта: важнее не выбор инструмента, а то, что все логи оказываются в одном месте и по ним работает поиск.

Итог

Начните с двух вещей: сквозного идентификатора запроса и честных уровней. Первое превращает разрозненные строки в историю, второе возвращает смысл оповещениям. Это работа на день, а эффект виден при первом же инциденте.

Дальше — фильтр секретов и личных данных на уровне библиотеки и настроенная ротация. Обе вещи делаются один раз и защищают от двух самых неприятных сценариев: утечки через логи и упавшего из-за забитого диска сервиса.

0
Оценили 0 читателей

Комментарии

0
Г
Без регистрации можно оставить один комментарий к публикации. Войдите, чтобы участвовать в обсуждении дальше и получать ответы. Ссылки в комментариях скрываются.
Пока нет комментариев

Будьте первым, кто ответит автору.