Как улучшить логирование статусов в сервисе
Что проверяют
Умеете ли вы превратить логи из потока текста в инструмент, по которому за минуту находится история конкретной заявки. Следом обычно спрашивают, как связать записи одного запроса, который проходит через несколько сервисов.
Как отвечать
- фасад и реализация: в коде только SLF4J, под ним Logback (по умолчанию в Spring Boot) или Log4j2. Сообщения с плейсхолдерами
log.info("Order {} moved to {}", id, status), без склейки строк: при выключенном уровне строка не собирается; - уровни по смыслу:
ERRORдля того, на что нужно реагировать,WARNдля сбоев с восстановлением (ретрай, фолбэк),INFOдля смены статуса бизнес-объекта,DEBUGдля деталей, выключенных на проде. Уровень меняется без рестарта через/actuator/loggers; - структура: смена статуса пишется одним событием с полями
orderId,from,to,reason,durationMs. Вывод в JSON: в Spring Boot начиная с 3.4 есть встроенное структурированное логирование черезlogging.structured.format.console(форматыecs,logstash), раньше бралиlogstash-logback-encoder; - корреляция:
traceIdв MDC, чтобы он попадал в каждую строку. Micrometer Tracing с OpenTelemetry кладёт его туда сам, а при@Asyncи своих пулах потоков контекст нужно передавать явно; - аудит отдельно: если историю статусов читают люди или поддержка, её лучше хранить таблицей в базе, а лог оставить для диагностики;
- сбор и алерты: логи уходят в Loki, Elasticsearch или OpenSearch, а алерты строятся на метриках, например на счётчике переходов в
FAILEDчерез Micrometer и Prometheus, а не на поиске строк в логах.
Где спотыкаются
Логируют каждый шаг на INFO и ловят с записью одно исключение на каждом уровне стека. Одна ошибка оставляет пять одинаковых трейсов, а объём логов растёт кратно.
Пишут log.error("Ошибка: " + e.getMessage()) и теряют стектрейс. Исключение передаётся последним аргументом, тогда SLF4J выведет его целиком.
Забывают про персональные данные: в лог попадают токены, номера карт и телефоны целиком. Такие поля маскируют до записи, а не надеются на фильтры в системе сбора логов.