Примеры ошибок, которые хорошо логировать
Что проверяют
Понимаете ли вы разницу между ошибкой, которую надо чинить, и ожидаемым исходом. Вопрос про меру: лог, где записано всё подряд, читать невозможно, а запись без контекста бесполезна.
Как отвечать
Логировать стоит то, по чему потом принимают решение:
- отказы зависимостей: база, брокер, соседний сервис, таймауты и исчерпанные повторы;
panic, перехваченная вrecover, вместе со стеком: это всегда баг;- нарушение инварианта: невозможная ветка
switch, рассогласованное состояние; - отказ фоновой обработки: задача из очереди не выполнена, синхронизация не прошла;
- заметная деградация: сработал предохранитель, включился запасной путь, часть данных отброшена;
- события безопасности: неуспешный вход, отказ в доступе, обращение к чужому ресурсу.
Не пишите на уровне ошибки то, что является нормальным исходом: запись не найдена, ввод не прошёл валидацию, клиент отменил запрос (context.Canceled). Это ответ клиенту и метрика, максимум уровень debug.
Формат важнее списка: структурная запись с полями, а не склейка строки. В стандартной библиотеке для этого есть log/slog:
slog.ErrorContext(ctx, "не удалось списать средства",
"err", err, "order_id", id, "attempt", n)Ошибку по пути заворачивайте через %w, а пишите один раз, наверху, где принято решение. log.Fatal в сервисе почти всегда ошибка: он вызывает os.Exit, отложенные функции не отработают и соединения не закроются.
Где спотыкаются
Логируют одну ошибку на каждом уровне стека. Одна проблема превращается в пять записей, и в общем потоке непонятно, это одно событие или пять. Ниже оборачиваем контекстом и возвращаем, пишем однажды на верхнем уровне.
Кладут в лог секреты и персональные данные: целиком тело запроса, заголовок с токеном, номер карты. Логи уезжают в общий сборщик, доступ к нему обычно шире, чем к базе, и удалить оттуда запись задним числом получается не всегда.
Пишут сообщение без опознавательных знаков. По строке «ошибка обработки» нельзя понять, чей это запрос. В записи нужны идентификатор трассировки, ключ сущности и, если есть, номер попытки: связать лог с жалобой пользователя иначе не выйдет.