Как ИИ помог за 4 часа найти причину зависаний в продакшене: разбор реального инцидента
Введение
30 июня 2026 года, 17:43 по Москве. Клиент пишет в чат: «Приложение очень плохо работает. Отвечает очень долго. Или вообще не отвечает. Активити по таймауту отваливаются».
Речь о приложении для Битрикс24, которое получает реквизиты контрагентов через DaData по ИНН. Работало стабильно, а потом — словно выключатель щёлкнул: первый запрос зависает, второй и последующие отрабатывают моментально. Клиент уже перепробовал всё — переключил активити на новые, отключил стандартизацию ФИО, убрал ключи из настроек. Без толку.
Дальше — четыре часа диагностики. Но за терминалом в это время работал не только человек. Основной объём — чтение логов, запросы к базе, анализ кода — делал ИИ.
Я покажу, как именно: какие команды выполнялись, что нашли логи Docker и база данных, как выстроилась цепочка от симптома к корневой причине. И почему без ИИ это заняло бы на порядок больше времени.
Как устроено приложение — коротко
Чтобы понять, что именно ломалось, нужно представлять архитектуру. Приложение состоит из трёх слоёв.
Первый слой — фронтенд. Интерфейс внутри Битрикс24: страница настроек, слайдеры с результатами, форма запуска роботов. Написан на Nuxt 4 и TypeScript, работает прямо в интерфейсе CRM.
Второй слой — бэкенд. Python/FastAPI. Принимает запросы от Битрикс24, обращается к внешним API (в данном случае DaData), обрабатывает результаты и возвращает их в CRM. Все операции с данными идут через него.
Третий слой — инфраструктура. Docker-контейнеры на боевом сервере: сам бэкенд, PostgreSQL для хранения данных и очереди задач, транспортный слой для обмена сообщениями с Битрикс24.
Ключевой элемент — очередь задач. Когда робот запускается в Битрикс24, CRM отправляет запрос в приложение. Бэкенд не выполняет его сразу — он кладёт задачу в очередь внутри PostgreSQL. Отдельные воркеры разбирают эту очередь и выполняют задачи. Такая архитектура защищает от перегрузок: если один портал шлёт сотни запросов в секунду, очередь не даёт ему забить весь пул воркеров и оставить другие порталы без ответа.
У каждого портала есть лимит одновременных задач и ограничение по частоте запросов. Воркеры по очереди разбирают задачи, отдавая приоритет тем порталам, которые дольше ждали.
Эта архитектура работала стабильно. Но 30 июня что-то пошло не так.
Что показывали симптомы
Клиент описывал поведение чётко:
- Запускаешь робота — тишина. Через минуту активити падает по таймауту.
- Запускаешь второй раз сразу же — отрабатывает за доли секунды.
- Подождал какое-то время — опять «засыпает», первый запрос снова виснет.
- Проблеме примерно неделя, до этого всё работало.
Худший тип багов для техподдержки. Не лежит целиком, не падает с явной ошибкой. Работает, но через раз. И на тестовом стенде не воспроизводится — там нет реальной нагрузки.
Первая гипотеза была — проблема в очереди. Месяцем ранее как раз добавили очередь с защитой от перегрузок. Может, защита слишком агрессивная? Но клиент сообщил, что проблема началась неделю назад, а очередь работает уже месяц. Не сходится.
Дальше началась основная диагностика. И вот тут к работе подключился ИИ.
Хронология отладки
Вот как развивались события. Каждый этап — это фактически сеанс диагностики, где ИИ анализировал логи и данные из базы.
17:43 МСК — обращение клиента. Уточняем: версия приложения, какие роботы виснут, менялись ли настройки.
17:53 МСК — гипотеза об очереди. Клиент подтверждает, что активити переключены на новые.
18:04–19:53 МСК — клиент методично проверяет разные сценарии. Паттерн стабилен: первый запрос висит, повторный — моментально. Интересная деталь: клиент заметил, что если запускать роботов подряд, первый висит, остальные проходят. Но если сделать паузу — всё повторяется.
20:09 МСК — ИИ заходит на боевой сервер. Первый раунд: проверка контейнеров через docker ps, чтение логов бэкенда за последние часы. Контейнеры в порядке, эндпоинт принимает запросы и возвращает подтверждение. Проблема явно глубже — не на уровне доступности сервиса.
20:30 МСК — ИИ идёт в базу данных. Это был ключевой момент. Вместо того чтобы гадать, он напрямую проверяет состояние очереди: сколько задач в ожидании, сколько выполняется, сколько завершилось с ошибкой. Запрашивает статистику за последнюю неделю.
Результат мгновенно проясняет картину. Половина задач выполняется быстрее секунды. Но каждый двадцатый запрос висит под 1000 секунд — больше 16 минут. Разрыв между медианой и 95-м перцентилем — в 1400 раз. Классический признак периодических блокировок.
20:42 МСК — вторая находка. ИИ проверяет состояние слотов портала. У клиента занят слот, хотя видимых активных задач нет. Это значит, что старый процесс-воркер по какой-то причине не освободил слот, и новые задачи не могут его занять.
21:22–21:35 МСК — живая проверка с клиентом. Пять запусков робота подряд. Результат: первый висит 92 секунды, остальные четыре — доли секунды. При этом в логах видно: запросы приходят и встают в очередь за 10–13 миллисекунд. Узкое место — не приём запросов, а их обработка.
21:34 МСК — точная локализация. ИИ находит в логах конкретную операцию, на которой всё зависает: получение настроек приложения. Каждый запуск робота, даже если у него уже есть свои собственные ключи для внешнего API, начинает с того, что запрашивает настройки через транспортный слой. И этот запрос периодически зависает на 1000 секунд — из-за кратковременных проблем на одном из промежуточных звеньев.
22:12–23:38 МСК — серия правок и деплой. После исправлений клиент подтверждает: «Вроде нет задержек теперь. Пока моментально всё».
Что конкретно делал ИИ
Теперь подробнее — без конкретных запросов к базе и внутренних названий, но с реальной механикой работы.
Чтение логов Docker. ИИ выполнял команды вроде docker logs --since 6h и фильтровал вывод по порталу клиента. В логах он искал паттерны: таймауты, ошибки подключения, аномально долгие операции. За минуту он делал то, на что человек потратил бы полчаса ручного просмотра сотен строк.
Среди логов нашлась строка, которая маскировала истинную проблему. Текст ошибки говорил «Ошибка DaData», но ИИ заметил, что в стектрейсе фигурирует не внешний API DaData, а внутренний запрос к настройкам. Код робота просто оборачивал любое исключение в сообщение об ошибке DaData. Без ИИ разработчик мог бы потратить час, проверяя доступность DaData API, хотя проблема была совсем в другом месте.
Логи в Grafana. Помимо прямого доступа к контейнерам, все логи приложения агрегируются в Grafana — единой системе мониторинга. На дашбордах Grafana ИИ видел графики количества запросов, времени ответа и частоты ошибок в реальном времени по каждому порталу. Это позволило сразу заметить аномалию: у клиента периодические всплески времени ответа до 1000 секунд, тогда как остальные порталы работали стабильно. Без централизованного сбора логов пришлось бы вручную собирать данные за неделю из нескольких контейнеров, чтобы увидеть этот паттерн. А когда логи уже в Grafana — ИИ получает готовую визуализацию и находит отклонения за секунды.
Анализ базы данных. ИИ запрашивал агрегированную статистику по порталу за разные периоды: последние 6 часов, последние 7 дней. Он смотрел не на отдельные строки, а на распределение: сколько задач выполняется быстро, сколько медленно, сколько падает. Такой подход — с перцентилями и группировкой по статусам — сразу показал, что проблема не в общей деградации, а в периодических всплесках длительности.
Отдельно ИИ проверил состояние слотов портала — механизма, который ограничивает количество одновременных задач. Оказалось, что слот занят процессом, которого уже нет. Эта находка мгновенно объяснила симптом «первый запрос висит»: новый запрос ждёт освобождения слота, а старый процесс, который его занял, уже не существует.
Проверка runtime-настроек. Прямо из контейнера ИИ получил текущие значения параметров: таймауты блокировок, лимиты параллельных задач, окно ограничения частоты. Оказалось, что таймаут блокировки — 15 минут, а таймаут выполнения задачи — 14 минут. При том что полезная работа (запрос к DaData) занимает доли секунды, а получение настроек должно отрабатывать за десятки миллисекунд. Эти таймауты были неоправданно огромными — наследие ранней версии очереди, где их поставили «с запасом».
Анализ транспортного слоя. ИИ проверил состояние очередей сообщений между приложением и Битрикс24: нет ли заторов, переподключений, потерянных сообщений. Нашёл кратковременные перераспределения нагрузки, которые совпадали по времени с зависаниями. Это подтвердило гипотезу: проблема в получении настроек через транспортный слой, а не в самом внешнем API.
Цепочка от симптома к причине
Вот полная картина, которую собрал ИИ за два часа диагностики:
- Каждый запуск робота начинает с получения настроек приложения. Даже если у робота уже есть все нужные ключи, он всё равно делает этот запрос.
- Запрос настроек идёт через транспортный слой. На пути — несколько звеньев, и на любом может случиться кратковременная задержка.
- При задержке запрос настроек зависает. Таймаут этого запроса — 1000 секунд.
- Пока запрос висит, worker держит слот портала. Остальные задачи этого же портала не могут выполняться.
- Через 15 минут (старый таймаут блокировки) задача освобождает слот и возвращается в очередь.
- Новый запуск робота получает свободный слот. Если на этот раз запрос настроек проходит без задержки — робот отрабатывает за доли секунды.
- Клиент видит ровно то, что описал: первый запрос висит, повторный — моментально.
Красивая, самовоспроизводящаяся проблема. И ровно поэтому человек без инструментов диагностики мог бы искать её днями.
Что исправили
ИИ определил корневые причины и подсказал, что именно нужно менять. Код писал разработчик — но с готовым списком проблем и конкретными рекомендациями. Пять изменений:
1. Кеш настроек в базе данных. Вместо того чтобы каждый запуск робота дёргать настройки через транспортный слой, они сохраняются в быстром кеше внутри PostgreSQL. Последующие запуски читают кеш, а не делают сетевой запрос. При кратковременных проблемах с транспортом используется сохранённая копия — робот не ждёт.
2. Пропуск лишнего запроса. Если робот запущен с собственными ключами (переданы прямо в параметрах), он больше не запрашивает настройки приложения. Раньше делал это в любом случае — даже когда настройки ему не нужны.
3. Снижение таймаутов. Таймаут блокировки уменьшен с 15 минут до полутора минут. Таймаут задачи — с 14 минут до 45 секунд. Stale-задачи перестали держать слоты бесконечно.
4. Ограничение повторов. После двух неудачных попыток задача помечается как завершённая с ошибкой и освобождает слот. Раньше она могла возвращаться в очередь бесконечно.
5. Детальное логирование этапов. Каждый шаг внутри робота — получение настроек, работа с кешем, запрос к внешнему API, отправка результата — получил свой таймаут и запись в лог. Теперь по логам сразу видно, на каком этапе произошло зависание, а не гадать по общему времени.
Все изменения покрыты тестами и задокументированы — разработчик, получив от ИИ точную диагностику и рекомендации, реализовал их за считанные часы.
Сколько заняла бы ручная диагностика
Без ИИ разработчик получает жалобу «робот то работает, то нет» и должен пройти тот же путь вручную.
Понять, куда смотреть. Зайти на сервер, проверить контейнеры, прочитать логи в поисках подозрительных строк. Составить запросы к базе данных — вспомнив или найдя в коде структуру таблиц. Интерпретировать распределение времени выполнения, найти выбросы. Сопоставить статистику с симптомами клиента. Это 3–5 часов — даже если разработчик знает архитектуру.
Найти корневую причину. Увидев, что проблема в получении настроек, нужно понять, на каком звене транспорта происходит задержка. Проверить очереди сообщений, состояние потребителей, корреляцию по времени. Если ошибка плавающая — перебрать гипотезы и исключить ложные следы. Ещё 1–2 часа.
Исправить и не сломать. Кеш, таймауты, логика пропуска запросов — каждое изменение кода требует тестов, проверки обратной совместимости и миграций базы данных. Ещё 2–3 часа.
Итого: 8–12 часов непрерывной работы вручную. С ИИ диагностика заняла 4 часа, из которых большая часть — ожидание ответов клиента в чате. Чистое время анализа и реализации — около 2 часов.
Дело не в том, что ИИ «умнее». Он не забывает структуру кода, не теряет контекст между итерациями и перебирает гипотезы на порядок быстрее человека.
Типичные ошибки при ручной отладке
Эти ошибки видны задним числом, но в моменте — когда клиент ждёт, а проблема плавающая — в них легко провалиться.
Доверие к тексту ошибок. В логах было написано «Ошибка DaData» — человек полез бы проверять внешнее API. ИИ заметил, что в стектрейсе фигурирует внутренний запрос, и пошёл в правильную сторону.
Диагностика «на глаз» вместо агрегаций. Человек склонен смотреть на отдельные строки и делать выводы. ИИ сразу построил распределение времени выполнения за неделю — и паттерн стал очевиден: каждый двадцатый запрос висит по 1000 секунд.
Лечение симптома вместо причины. Увидев, что робот «засыпает», хочется перезапустить контейнеры, увеличить пул воркеров или добавить костыль с повторными попытками. ИИ пошёл по цепочке: что именно ждёт робот → получение настроек → транспорт → кеш вместо прямого вызова.
Пропуск неочевидных данных. Таблица с состоянием слотов портала — не первое, куда посмотрит разработчик, если не трогал этот код пару недель. ИИ методично проверил все связанные сущности и сразу нашёл занятый слот при отсутствии активной задачи.
Боязнь трогать production. ИИ выполнял исключительно read-only операции — ни одного изменения данных на боевом сервере. Человек в стрессе может случайно выполнить не тот запрос.
Сравнение: ручной подход против ИИ-ассистированной диагностики
| Этап | Ручная диагностика | С ИИ |
|---|---|---|
| Проверка контейнеров | docker ps, docker logs, чтение глазами |
Автоматическая фильтрация по порталу, поиск ошибок и аномалий |
| Анализ логов | Сотни строк вручную, поиск паттернов | Мгновенный grep с привязкой к конкретным операциям |
| Запросы к базе | Вспомнить схему, написать 4–5 запросов с агрегациями | Структура данных из кодовой базы, запросы за секунды |
| Статистика | Обычно не делается — слишком трудоёмко | Распределение за неделю — один запрос |
| Интерпретация | Мысленное сопоставление, риск упустить связь | Явная цепочка: симптом → лог → база → причина |
| Код и тесты | Тесты откладываются «на потом» | ИИ подсказал что править — разработчик реализовал и покрыл тестами |
| Документирование | Постфактум или никогда | Обоснование с каждым изменением |
| Общее время | 8–12 часов | 4 часа (из них ~2 часа диагностики и кода) |
Заключение
Этот инцидент — не история про замену разработчика искусственным интеллектом. Разработчик принимал ключевые решения: когда смотреть логи, какую гипотезу проверять следующей, как общаться с клиентом, когда деплоить. ИИ взял на себя рутину — анализ логов, запросы к базе, поиск по коду — и сделал это в 5–10 раз быстрее. А код писал разработчик, вооружённый точной диагностикой.
Самые противные production-баги — те, что плавают и не воспроизводятся стабильно, — идеально ложатся на ИИ-диагностику. Их поиск — это перебор гипотез и анализ больших объёмов логов и статистики. Две сильные стороны LLM, которые освобождают разработчика для главного: принять решение и написать код.
Архитектура приложения здесь принципиальна: Docker-контейнеры, очередь задач в PostgreSQL, транспортный слой — это стандартный стек для интеграционных решений на Битрикс24. ИИ, имея доступ к этому стеку в режиме read-only, способен провести полную диагностику, не меняя ни строчки на боевом сервере.
Если хотите попробовать такой подход: дайте ИИ контекст — исходный код проекта, доступ к логам и базе данных (только на чтение), и ставьте конкретные диагностические вопросы. Не «почему не работает», а «на каком этапе запрос проводит больше всего времени» или «какая доля задач завершается с ошибкой за последнюю неделю».
И тогда 12 часов отладки превращаются в 4, а клиент в полночь пишет: «Пока моментально всё».