Как читать чужие логи и не утонуть
Типичное обращение выглядит так: «у нас ничего не работает, посмотрите». Ни времени, ни запроса, ни описания — только эмоция. Дальше всё зависит от того, в каком порядке ты будешь сужать.
Ниже — порядок, к которому я пришёл. Он скучный, но экономит часы.
Сначала время, потом всё остальное
Первый вопрос всегда один: когда. Не «что случилось», а «во сколько».
Без временного окна поиск по логам превращается в чтение всего подряд. С окном в пять минут — в просмотр сотни строк.
Если пользователь не помнит — привязывайся к косвенным признакам: время последнего успешного действия, время скриншота, время письма. Годится любая точка отсчёта.
Связка идентификаторов
Дальше ищем request_id. В нормально устроенном сервисе он есть в ответе — в заголовке или в теле ошибки:
HTTP/1.1 500 Internal Server Error
content-type: application/json
x-request-id: 7f3a91c4-2b08-4e1d-9a55-c0de12345678
{
"error": {
"code": "internal_error",
"message": "Что-то пошло не так",
"request_id": "7f3a91c4-2b08-4e1d-9a55-c0de12345678"
}
}
Этот идентификатор — вход в лог. По нему находится строка, которая породила ответ:
2026-08-14T09:14:22.881Z ERROR billing-api host=billing-api-04
request_id=7f3a91c4-2b08-4e1d-9a55-c0de12345678
trace_id=b19d0c77aa5e4f02
method=POST path=/v1/orders status=500 duration_ms=8412
msg="upstream timeout" upstream=inventory-service
Здесь есть всё, что нужно для следующего шага:
| Поле | Что говорит |
|---|---|
status=500 |
Ошибка на нашей стороне, не у клиента |
duration_ms=8412 |
Восемь секунд — почти наверняка таймаут, а не логическая ошибка |
upstream=inventory-service |
Виноваты не мы, а сервис ниже по цепочке |
trace_id |
Ключ, по которому видно всю цепочку вызовов |
request_id и trace_id — не одно и то же
Это различие стоит держать в голове, потому что путаница здесь стоит дороже всего.
request_id живёт внутри одного сервиса. Он отвечает на вопрос «что произошло здесь».
trace_id сквозной: он одинаковый у всех сервисов, которые участвовали в обработке. Он отвечает на вопрос «что произошло по всей цепочке».
Поиск по request_id покажет одну строку. Поиск по trace_id — весь путь:
09:14:14.402 INFO api-gateway trace_id=b19d0c77aa5e4f02 POST /v1/orders status=-
09:14:14.418 INFO billing-api trace_id=b19d0c77aa5e4f02 -> inventory-service/reserve
09:14:14.503 INFO inventory-service trace_id=b19d0c77aa5e4f02 acquiring lock sku=A-1187
09:14:22.874 ERROR inventory-service trace_id=b19d0c77aa5e4f02 lock wait timeout after 8000ms
09:14:22.881 ERROR billing-api trace_id=b19d0c77aa5e4f02 upstream timeout status=500
И вот тут картина собирается: дело не в биллинге, который вернул 500. Дело в блокировке на конкретной позиции склада, которую кто-то держал восемь секунд.
Биллинг — жертва, а не причина. Если бы я остановился на первой строке с ERROR, я бы завёл задачу не на ту команду.
Порядок, который работает
- Время. Окно в 5–10 минут вокруг события.
- Идентификатор.
request_idиз ответа или из скриншота. - Цепочка.
trace_id— весь путь запроса. - Первая ошибка по времени, а не первая, которую увидел. Они редко совпадают.
- Сравнение с нормой. Найди такой же успешный запрос рядом по времени и посмотри, чем он отличался.
Пятый шаг пропускают чаще всего, а он самый полезный. Ошибка сама по себе говорит мало. Ошибка рядом с успехом говорит почти всё.
Три ошибки, которые я делал сам
Смотрел на последнюю ошибку вместо первой. В логах ошибки размножаются: одна причина порождает десяток следствий, и следствия часто заметнее. Сортируй по времени по возрастанию.
Верил уровню логирования. ERROR в одном сервисе может быть штатной ситуацией, а WARN в другом — настоящей проблемой. Уровень расставлял человек, у него было своё представление о важности.
Искал по тексту ошибки. «Timeout» найдётся в тысяче строк. Идентификатор — в одной. Всегда, когда есть идентификатор, ищи по нему.
Что делать, если request_id нет
Бывает и так. Тогда сужение идёт по косвенным признакам: аккаунт, эндпоинт, код ответа, время. Это дольше, но работает.
И отдельным пунктом — заводи задачу на то, чтобы идентификатор появился в ответе. Один раз потратить время на это дешевле, чем каждый раз искать вслепую.
Что проверить дальше
Если картина не сошлась:
- посмотри логи балансировщика — часть запросов может не доходить до приложения вообще;
- сравни время на серверах: расхождение в пару минут превращает разбор в гадание;
- проверь, не совпало ли событие с деплоем или миграцией;
- глянь соседние экземпляры сервиса: если ошибка только на одном хосте, причина в нём, а не в коде.
Обновлено 22 августа 2026