В журнале поддержки остался скриншот ошибки, через минуту тот же адрес снова ответил 200. Для редкой 500-й этого недостаточно: случайные ручные повторы почти всегда попадают в исправное окно. Расследование стоит строить вокруг одного проблемного запроса и его следа через CDN, прокси, приложение и зависимости.
Оформите паспорт проблемного запроса
Уточните, какой ответ получил клиент. Нужны точный URL, метод, время с часовым поясом, статус, фрагмент страницы ошибки, длительность и идентификатор запроса, если он выводится в заголовке. Для формы или API запишите тип и размер тела, набор неперсональных параметров и состояние авторизации. Пароли, cookie, токены и полные пользовательские данные в карточку не переносят.
Проверьте исходный код ответа. CDN иногда показывает пользователю свою страницу и меняет 502 или 504 на другой статус. Браузер может отобразить сохранённый документ, а аналитическая система — объединить несколько классов серверных ошибок. Диагностический запрос сохраняют целиком:
curl -sS -D headers.txt -o response.html \
-w '%{http_code} %{time_total}\n' https://example.com/problem-urlУспешный результат означает только текущее состояние. Он не опровергает зафиксированную ошибку. Значение соседних кодов можно сверить с руководством по HTTP-статусам.
Карточка на этом этапе выглядит так:
UTC: 2026-08-14 07:31:42.618
URL/method: POST /api/report
external status: 500
request_id: 7f2…91c
release: unknown
node: unknown
safe condition: report_type=monthly, payload_size=1,8 МБПоля unknown показывают, каких данных сейчас не хватает. Их нельзя заменять предположением.
Восстановите временную линию по request_id
Сверьте часы и часовые пояса на edge, балансировщике, контейнерах приложения, базе и системе трассировки. Затем возьмите короткий интервал вокруг события. Для единичной ошибки обычно достаточно нескольких минут до и после.
Лучший ключ — сквозной request_id или trace_id. Когда его нет, сочетайте время, URL, метод, имя узла и длительность. IP клиента слабее: корпоративный NAT объединяет людей, мобильный адрес меняется, а CDN скрывает исходное соединение.
Запишите последовательность одной строкой на слой:
| Время | Слой | Событие | Длительность | Результат |
|---|---|---|---|---|
| 07:31:42.618 | Edge | Принял POST | 4,9 с | upstream error |
| 07:31:42.641 | Nginx | Передал node-3 | 4,8 с | 500 |
| 07:31:42.650 | App node-3 | Начал отчёт | 4,7 с | exception |
| 07:31:47.301 | DB | Запрос завершён | 4,5 с | pool timeout |
Если вход есть у Nginx и отсутствует в приложении, бизнес-логика пока не является главным направлением. Если приложение завершило запрос 200, а edge отдал 500, нужно исследовать участок после приложения.
Сравните с ближайшим успешным запросом
Найдите ответ того же маршрута с похожими параметрами до или после ошибки. Сравните версию приложения, узел, способ авторизации, вариант эксперимента, регион, размер входа и состояние кэша. Таблица различий быстрее отсекает общие версии:
| Признак | Ошибка | Успех |
|---|---|---|
| Версия | 2026.08.14.3 | 2026.08.14.3 |
| Узел | node-3 | node-1 |
| Размер отчёта | 1,8 МБ | 1,7 МБ |
| Пул БД | ожидание 4,5 с | ожидание 40 мс |
Здесь версия совпадает, а связь с узлом и пулом стоит проверить. Если 17 из 19 ошибок пришли с одного контейнера, гипотеза становится измеримой. Если сбой встречается у всех узлов только для пустого поля, направление смещается к обработке граничных данных.
Не переносите производственную запись целиком в тестовую среду. Воспроизведите минимальные свойства на обезличенных данных: размер, отсутствие поля, число элементов или роль пользователя.
Пройдите журналы снаружи внутрь
Читайте edge или CDN, access/error log прокси, журнал приложения, базу, очередь и внешние API в порядке прохождения запроса. На каждом слое ответьте: поступил ли запрос, куда был передан, сколько заняла обработка и чем она закончилась.
Поиск только по строке 500 пропускает важные события. Приложение может записать тип исключения без HTTP-кода. Прокси способен создать 500 после закрытия соединения процессом. Полезны рестарты контейнера, исчерпание пула, паузы сборщика мусора, ошибки чтения файлов и превышение лимита внешнего API.
График CPU рядом со сбоем остаётся корреляцией, пока не построена цепочка. Подтверждение выглядит конкретно: рост параллельных задач занял все соединения, запрос ждал пул дольше лимита, обработчик получил timeout и вернул 500.
Особенно внимательно сравнивайте лимиты времени. Клиент, CDN, прокси и приложение могут прерывать работу на разных секундах. Короткий внешний тайм-аут оборвёт ответ, пока приложение продолжает занимать ресурс; слишком длинный удержит очередь во время деградации.
Подготовьте телеметрию к следующему случаю
Статус «сейчас не воспроизводится» означает, что наблюдаемости не хватило. Добавьте безопасные поля: сквозной идентификатор, версию релиза, имя узла, структурированный тип исключения, длительности этапов и код ответа зависимости. Не журналируйте содержимое пароля, авторизационные заголовки и тела клиентских форм.
Считайте 5xx по маршрутам, версиям и узлам. Общая доля по сайту скроет один сбой редко вызываемого критичного API. Для каждого алерта сохраняйте безопасный пример request_id и ссылку на временной диапазон логов. Повторы одной причины объединяйте в событие со счётчиком.
Внешний uptime-монитор полезен только для ошибок, попавших в момент его GET-запроса к настроенному URL. Редкие сбои между запусками, POST, другие маршруты и stack trace остаются задачей серверных метрик и журналов.
Требования к устойчивым внешним сигналам подробнее описаны в статье о мониторинге доступности.
Проверяйте одну гипотезу за раз
Сформулируйте её с условием и механизмом: «версия 3 на node-3 возвращает 500 для отчёта больше 1,5 МБ, потому что соединение с базой ожидается дольше четырёх секунд». Для такой фразы понятны тест, необходимые логи и опровержение.
Воспроизводите сочетание условий в тестовой среде или на согласованном диагностическом маршруте. Массовую нагрузку на рабочем сайте без окна не запускают. Допустимы точечный безопасный запрос, чтение журналов и сравнение узлов.
Исправление должно изменить наблюдаемый механизм: обработать отсутствующее поле, ограничить параллелизм, освободить соединение, исправить конфигурацию одного узла или вернуть подходящий 4xx для некорректного запроса. Простое увеличение тайм-аута иногда лишь сдвигает момент отказа.
Перед выпуском запишите базовую частоту, проблемное условие и ожидаемый результат. После выпуска проведите это условие через новую версию и проверьте смежные показатели: успешность, задержку, очередь и количество повторов.
Закройте карточку доказательствами
Для редкой ошибки одного спокойного часа недостаточно. Окно наблюдения выбирают по прежней частоте: событие раз в неделю требует более долгой проверки, чем десятки ошибок в час. В карточке должны остаться:
- подтверждённая причина или честный статус «данных недостаточно»;
- затронутые маршруты, версии и узлы;
- доказательство связи между условием и исключением;
- изменение и способ его проверки;
- период наблюдения после выпуска;
- добавленный сигнал на случай повторения.
Пример финальной строки: Версия 2026.08.15.1 обработала 312 отчётов >1,5 МБ на всех трёх узлах; pool timeout и HTTP 500 не повторились за семь суток; алерт по ожиданию пула включён. Если причина осталась неизвестной, перечислите добавленные поля телеметрии и критерий возобновления расследования.