Когда сценарий перестаёт работать, первое желание — открыть его и читать узлы сверху вниз. Это самый долгий путь из возможных: логика почти всегда цела, потому что вчера она работала. Меняется не сценарий, а мир вокруг него — ответ чужого API, срок жизни токена, содержимое поля, наличие вебхука. Поэтому диагностика идёт снаружи внутрь, а не наоборот.
Правильный порядок укладывается в шесть шагов и в тридцать минут. Неправильный занимает от трёх часов и обычно заканчивается вызовом подрядчика, потому что человек, который собирал сценарий, к третьему часу уже не помнит, что он проверил, а что нет. Разница в деньгах на одном случае — 9 450 ₽, на парке из 30 сценариев за год — 56 700 ₽.
Ниже — сам порядок, семь типовых причин с признаком каждой, способ повторить прогон, не трогая боевые записи, и правило, по которому решают: останавливать сценарий целиком или пропускать сбойные записи.
Шесть шагов: от последнего успешного прогона к источнику
Шаги идут строго по порядку, и каждый следующий имеет смысл только после того, как предыдущий не дал ответа. Смысл порядка в том, что он сужает круг быстрее всего: первые два шага в половине случаев уже называют причину.
- 1Шаг 1. Найти последний успешный прогон и первый неуспешный
Открывается журнал прогонов и фиксируются две отметки времени. Между ними — окно, в котором что-то изменилось. Если между последним успешным и первым неуспешным прошло несколько дней, а сценарий должен запускаться ежечасно, — вы уже нашли главное: он не падал, он не запускался. Это другой класс поломки, и дальше идти надо в шаг 6, а не в шаг 2.
- 2Шаг 2. Спросить, что изменилось в это окно
Три вопроса подряд: обновлялась ли чужая система, менял ли кто-то сценарий, менялось ли что-то в правах и ключах. Ответ на второй вопрос даёт суточный экспорт парка — по нему видно, какие именно узлы изменились и когда; как он настраивается, мы описывали в материале про версионирование и документирование сценариев. В компаниях без экспорта этот шаг превращается в опрос коллег и занимает больше времени, чем все остальные пять.
- 3Шаг 3. Посмотреть на текст ошибки, а не на её наличие
Красная отметка на узле — не диагноз. Диагноз — код ответа и его тело. Отказ в доступе, превышение лимита, неверный формат данных и недоступность сервиса выглядят в интерфейсе одинаково, а лечатся по-разному. Тело ответа чужой системы почти всегда содержит прямое указание на причину, и его достаточно прочитать целиком.
- 4Шаг 4. Проверить вход упавшего узла
Что пришло на вход именно в этом прогоне: все ли поля на месте, тот ли тип данных, не пустая ли строка там, где ожидалось число. Половина ошибок «неверный формат» — это не смена формата на той стороне, а одна запись с незаполненным полем, которая раньше не встречалась. Здесь же проверяется, не пришло ли на вход в сотни раз больше данных, чем обычно.
- 5Шаг 5. Повторить прогон вручную на той же записи
Берётся конкретный проблемный вход и прогоняется через копию сценария в безопасном режиме. Если ошибка повторяется — причина внутри и она воспроизводима, дальше это обычная инженерная работа. Если не повторяется — причина внешняя и временная: сервис был недоступен, лимит был исчерпан, сеть моргнула. Разные выводы, разные действия.
- 6Шаг 6. Дойти до внешнего источника
Последний шаг для случая «сценарий не запускался». Проверяется, доходит ли событие вообще: жив ли вебхук на стороне отправителя, не отключил ли его сам отправитель после серии неудачных доставок, работает ли расписание, не выключен ли сценарий кем-то из коллег. Отключённый после серии ошибок вебхук — самая частая находка этого шага и самая незаметная.
Схема-воронка из шести горизонтальных полос, сужающихся сверху вниз. Полоса 1 «Последний успешный и первый неуспешный прогон» с ответвлением вправо: «разрыв больше интервала запуска → сразу шаг 6». Полоса 2 «Что изменилось в это окно: чужая система, сценарий, ключи». Полоса 3 «Код ответа и тело ошибки, а не красная отметка». Полоса 4 «Вход упавшего узла: поля, типы, объём». Полоса 5 «Повтор прогона на той же записи в безопасном режиме» с двумя выходами вправо: «повторилось — причина внутри», «не повторилось — причина внешняя и временная». Полоса 6 «Внешний источник: жив ли вебхук, работает ли расписание». Слева от воронки вертикальная шкала времени с отметками «5 минут», «10 минут», «30 минут». Чертёжный стиль, подписи по-русски.
Семь причин и признак каждой
Эти семь закрывают подавляющее большинство случаев в парке любой компании. Ценность таблицы не в перечне, а в столбце «признак»: по нему причина отсеивается за минуту, без чтения логики сценария.
| Причина | Признак, по которому узнаётся | Что делать сейчас | Что сделать, чтобы не повторилось |
|---|---|---|---|
| Изменился формат ответа чужой системы | Падают все прогоны разом, начиная с определённого часа; узел разбора данных не находит поле | Сравнить ответ с сохранённым в журнале до сбоя, поправить разбор | Подписаться на уведомления о версиях API поставщика и держать проверку структуры ответа |
| Исчерпан лимит тарифа или лимит чужого API | Прогоны останавливаются в середине дня и возобновляются после полуночи или после расчётного периода | Проверить остаток лимита, снизить частоту опроса, отложить неприоритетные сценарии | Алерт на 80 % лимита в общий рабочий канал, а не на личную почту автора |
| Просрочен или отозван токен доступа | Единственный узел падает с отказом в доступе, остальные работают; сбой начался ровно в круглую дату | Выпустить новый ключ, подставить его ссылкой, проверить прогон | Календарное напоминание за две недели до истечения и смена ключа с перекрытием |
| Часовой пояс | Данные приезжают, но не те: смена дат на границе суток, пустая выборка «за вчера», сдвиг на 3 часа | Привести все отметки времени к одной зоне в одном узле на входе | Зафиксировать зону хранения в паспорте сценария и не полагаться на настройку площадки |
| Пустое обязательное поле | Падает один прогон из сотни, остальные идут; в журнале видно, что поле не заполнено | Обработать пустое значение явно: подставить значение по умолчанию или отправить запись человеку | Проверка входа первым узлом и отдельная ветка для неполных записей |
| Дубль записи | Ошибок нет вовсе, но в системе-приёмнике появились две одинаковые записи | Найти обе, склеить, разобраться, был ли это повтор после обрыва связи | Ключ операции: повтор едет с тем же ключом, приёмник отвечает «уже создано» |
| Тихий вебхук: сценарий не запускался | Ошибок нет, красных отметок нет, журнал прогонов просто пуст с определённого момента | Проверить, доходит ли событие до площадки, и жива ли подписка у отправителя | Сигнал молчания: алерт, если сценарий не отработал ни разу за отведённый интервал |
Мониторинг ошибок ловит шесть причин из семи и полностью слеп к последней. Сценарий, который не запустился, не даёт ни ошибки, ни алерта — он просто отсутствует в журнале. Обнаруживается это либо через неделю по жалобе клиента, либо сразу — суточной сверкой «сколько событий пришло, сколько обработано, сколько лежит в очереди». Сверка настраивается один раз и стоит несколько часов работы; без неё любой мониторинг остаётся частичным.
Как повторить прогон, не трогая боевые записи
Пятый шаг — самый полезный и самый рискованный: чтобы понять, воспроизводится ли ошибка, надо запустить сценарий ещё раз на тех же данных. Сделать это на боевом контуре означает создать второй документ, отправить второе письмо клиенту или второй раз снять остаток. Три приёма позволяют повторить прогон безопасно, и все три доступны без отдельного тестового сервера.
- 1Копия сценария с отключёнными узлами записи. Дублируется весь сценарий, у всех узлов, которые куда-то пишут или что-то отправляют, действие заменяется на запись в отдельную таблицу. Логика при этом отрабатывает полностью, а внешний мир ничего не замечает. Проверка перед запуском обязательна и делается по списку: каждый узел записи открывается и подтверждается глазами.
- 2Вход из журнала, а не из живого события. Берётся сохранённое тело запроса того самого прогона и подставляется на вход вручную. Это единственный способ разобрать сбой, который случился три дня назад и больше не повторяется: живое событие с теми же данными вы уже не получите.
- 3Тестовый получатель вместо боевого. Там, где отключить запись нельзя — например, надо проверить, примет ли чужая система документ, — используется песочница поставщика или технический контрагент с пометкой в названии. Технические записи заводятся с одним и тем же префиксом, чтобы потом их можно было найти и удалить одним отбором.
У всех трёх приёмов общее требование: тело запроса и ответа должно храниться в журнале. Без него повторить прогон нечем, и диагностика превращается в реконструкцию по памяти. Что именно писать в журнал, чтобы он был полезен, мы разбирали на примере журнала обменов — те же шесть полей работают и для сценариев.
Что писать в лог, чтобы разбор занимал минуты
Штатный журнал прогонов площадки отвечает на вопрос «упало или нет» и почти не помогает с вопросом «почему». Разницу делают четыре добавления, каждое из которых — один узел в начале и в конце сценария.
- Сквозной идентификатор. Один номер, присвоенный записи в самом начале пути и проходящий через все узлы и все системы. Без него поиск «где эта заявка» превращается в сопоставление по времени и сумме, а с ним занимает один запрос.
- Тело входа и тело ответа целиком. Не «ошибка при обращении», а что именно отправили и что именно получили. Это то, из чего собирается повторный прогон. Персональные данные в журнале маскируются, ключи доступа не пишутся в него никогда.
- Номер попытки и итоговый статус. Видно, был ли это первый заход или четвёртый повтор, и чем всё закончилось: обработано, ушло в очередь, отправлено человеку. Иначе повторы неотличимы от новых событий, и картина сбоя искажается.
- Отметка времени с часовым поясом. Без указания зоны журналы двух систем невозможно сопоставить, а именно сопоставление и требуется в споре «мы отправили — вы не получали». Одна и та же зона во всех логах — правило, которое ничего не стоит и экономит часы.
Час простоя в 1 800 ₽ здесь взят для сценария приёма заявок в модельной компании — это не абстрактная цифра, а недошедшие заявки за час. Мы считали её отдельно в разборе стоимости владения парком сценариев. Для сценария, который раз в сутки складывает отчёт в папку, цена часа простоя близка к нулю, и весь этот расчёт для него не работает — что и определяет, на какие сценарии тратить 36 000 ₽, а на какие нет.
Сравнение двух горизонтальных полос равной шкалы времени. Верхняя полоса «Без порядка», разбита на три отрезка с подписями: «обнаружение 1,5 часа», «поиск причины 2,5 часа», «починка 1 час»; справа итог «13 700 ₽». Нижняя полоса «С алертом, журналом и порядком шагов»: «обнаружение 10 минут», «поиск причины 30 минут», «починка 1 час»; справа итог «4 250 ₽». Отрезок «починка» в обеих полосах одинаковой длины и выделен одинаковой штриховкой с подписью «не сокращается». Под полосами строка: «6 отказов в год — 56 700 ₽ разницы; вложение 36 000 ₽ возвращается за 7,6 месяца». Чертёжный стиль, подписи по-русски.
Останавливать сценарий или пропускать сбойные записи
Это решение принимается в первые минуты разбора и определяет, будет ли у вас одна проблема или две. Правило простое и зависит от того, что делает сценарий с данными.
| Тип сценария | Что делать при сбое | Почему так |
|---|---|---|
| Пишет документы, деньги или остатки | Остановить целиком до выяснения причины | Частично отработавший сценарий оставляет несогласованное состояние в двух системах; разбирать его дороже, чем простой |
| Принимает заявки и обращения | Не останавливать: складывать сбойные записи в очередь и разбирать после починки | Остановка означает потерянные заявки, а очередь — только задержку; ни одна запись при этом не теряется |
| Уведомляет и рассылает | Остановить, если сбой массовый; пропускать, если единичный | Массовый сбой рассылки при повторе превращается в дублирующие сообщения клиентам — это дороже пропущенного уведомления |
| Собирает отчёты и складывает файлы | Пропускать и чинить в рабочем порядке | Цена часа простоя близка к нулю; остановка ради такого сценария создаёт больше суеты, чем пользы |
И общее правило поверх таблицы: если сценарий сбоит, а вы не знаете почему, повторные запуски делать нельзя. Три-четыре ручных перезапуска «а вдруг проедет» при исчерпанном лимите продлевают блокировку, а при обрыве связи после отправки создают ровно столько дублей, сколько было попыток. Как настроенные повторы превращаются в машину по сжиганию лимита, мы считали в материале про лимиты и тарификацию операций.
Когда искать причину не надо
Разбор сбоя — работа с ценой, и не каждая поломка её оправдывает. Четыре случая, в которых честнее закрыть вопрос иначе.
- Сбой единичный и не повторяется третьи сутки. Чужой сервис был недоступен полторы минуты — это событие, а не причина. Записи из очереди дообработаны, потерь нет, искать больше нечего. Тратить на это три часа значит менять 2 450 ₽ на ноль информации.
- Сценарий и так собирались выключать. Если процесс меняется в ближайший месяц, чинить надо не сценарий, а расписание работ. Разбор ради двух недель жизни — это оплаченная археология.
- Причина известна и это чужая сторона. Поставщик выкатил обновление и сам об этом написал. Здесь работа не диагностическая, а инженерная: поправить разбор ответа и поставить проверку структуры. Искать «настоящую причину» в своих узлах не нужно, её там нет.
- Сценарий не имеет владельца и никто не помнит, зачем он. Тогда правильный ход — не чинить, а выключить и подождать неделю: если никто не заметит, сценарий был мёртвый. В модельной инвентаризации такими оказываются около трети парка, и починка каждого из них — деньги, потраченные в пустоту.
Логика сценария вчера работала. Ищите то, что изменилось снаружи, а не то, что написано внутри.
