← Блог

Observability автотестов: почему passed/failed недостаточно

Селективный конвейер тестовых модулей

Observability автотестов, или наблюдаемость автоматизированных проверок, помогает восстановить, что происходило во время выполнения и почему получен конкретный результат. Для этого статус связывают с условиями запуска, историей попыток, логами, трейсами и артефактами. Passed/failed сообщает итог проверки, но не устанавливает причину сбоя и не показывает, какие проверки вообще не состоялись.

Ночной запуск завершился: несколько тестов упали, повтор прошёл, сборка снова зелёная. Утром остался скриншот пустой страницы и знакомое «ожидание элемента превысило таймаут». Это может быть ошибка интерфейса, удалённая тестовая запись, неверный адрес стенда или остановившийся браузер. Статус один, исправления — разные.

Правила повторов и карантина мы разбирали в статье об управлении flaky-тестами. Здесь другой вопрос: какие свидетельства должны пережить запуск, чтобы команда могла отличить дефект продукта от проблемы теста, данных или инфраструктуры. Не перезапустить до успеха, а понять, что именно произошло.

Что показывает статус автотеста и что добавляет наблюдаемость

Статус — вывод тестового фреймворка о конкретном выполнении. Причина — объяснение, которое нужно подтвердить. Если проверка ожидала код ответа 200, а получила 500, известно расхождение. Но пока не известно, ошибся ли сервис, не подготовились ли данные или запрос попал не в тот контур.

Даже расширенный набор статусов не устраняет этот разрыв. В Allure Report различаются Passed, Failed, Broken, Skipped и Unknown; правила разграничения Failed и Broken зависят от интеграции с фреймворком. Это полезная первичная классификация, но не готовое заключение о владельце дефекта. Исключение в подготовке теста может быть вызвано как ошибкой фикстуры, так и отказом сервиса, к которому она обращается.

С зелёным результатом нужна та же точность. Passed означает, что выполнение удовлетворило заложенным проверкам. Он не доказывает, что в тесте есть нужные утверждения, выбрана правильная версия продукта или выполнен весь запланированный набор. Наблюдаемость помогает увидеть условия и ход проверки; силу самих утверждений оценивают при ревью теста, а не по объёму телеметрии.

Почему много логов ещё не означает observability

Наблюдаемость в программных системах опирается на телеметрию, по которой можно исследовать внутреннее поведение. Для автотестов это означает возможность пройти от результата к конкретной попытке, её действиям и ответам зависимостей. Архив на несколько гигабайт без такой связи может оказаться менее полезным, чем короткий журнал с точными идентификаторами.

Отчёт отвечает, чем закончилась проверка. Мониторинг сообщает, что известный показатель вышел за ожидаемые пределы. Наблюдаемость помогает исследовать, какие события и условия за этим стоят. Это разные задачи, которые могут решаться одним набором инструментов, а не три взаимоисключающих подхода.

В практике автоматизации полезно наблюдать две стороны. Тестируемый продукт обрабатывает запросы и меняет состояние. Система выполнения тестов готовит данные, запускает процессы, распределяет работу и сохраняет результаты. Если видна только первая сторона, можно пропустить остановку раннера. Если только вторая — увидеть таймаут, но не медленную операцию внутри сервиса.

Почему отсутствие результата — отдельный сигнал

Допустим, план включал 120 вариантов проверок, а отчёт содержит 100 успешных результатов. Доля успеха среди полученных записей равна 100%, но судьба ещё 20 вариантов неизвестна. Они могли не попасть в отбор, остаться в остановленном процессе или не загрузиться в отчёт. Это учебный пример, а не статистика продукта.

Поэтому до старта полезно сохранять состав выбранного набора, а после — сопоставлять его с результатами. Сверять нужно идентификаторы сценариев и значимые параметры, а не только два счётчика: повторные попытки способны увеличить число записей, не увеличив число выполненных проверок. Пропуск с известной причиной и потерянный результат также требуют разных решений.

Какие данные связывают результат с конкретной попыткой

Основная единица диагностики — попытка выполнения теста в определённой конфигурации. У одного сценария могут быть разные браузеры, наборы данных и повторы. Если всё это склеить по названию, скриншот одной попытки легко окажется рядом с логами другой.

Здесь нужны два вида идентичности. Стабильный идентификатор связывает один тест с его историей. Уникальный идентификатор результата различает выполнения. Например, в формате результатов Allure эти задачи разведены: у результата есть uuid, а для сопоставления истории используются отдельные идентификаторы, включая historyId. Их не следует заменять одним случайным ID, который меняется при каждом запуске.

Что включить в диагностическую запись

Для конкретного проекта состав записи определяется вопросами диагностики. Практический минимум обычно складывается из четырёх групп.

Идентичность: тест, значимый вариант его параметров, запуск CI, джоба, результат и номер попытки. CI — система непрерывной интеграции, в которой выполняется проверка.

Условия: фактически развёрнутая сборка продукта, ревизия кода тестов, конфигурация стенда, исполнительный процесс и версия набора данных. Названия ветки или адреса staging недостаточно: содержимое за ними меняется. Если данные генерируются случайно, полезно сохранять seed — исходное значение генератора; оно помогает воспроизвести входы, но не фиксирует поведение всех внешних зависимостей.

События: начало и завершение этапов, выполненные действия, ожидаемые и фактические значения, тип ошибки, операция, на которой оборвалась проверка.

Свидетельства: логи, снимки состояния, трассировки и ссылки на внешние записи. Каждый артефакт относится к той же попытке и имеет понятный срок хранения.

Ниже — сокращённый пример собственной диагностической записи команды. Это не формат импорта в ТестОпс и не схема OpenTelemetry; названия полей выбраны для объяснения связей.

{
  "testId": "orders.created-order-visible",
  "variantId": "chromium-ru",
  "pipelineRunId": "ci-1842",
  "jobRunId": "ui-shard-2-run-1",
  "resultId": "ci-1842-ui-2-orders-visible-attempt-1",
  "attempt": 1,
  "appBuild": "store-2026.10.23.1",
  "testCommit": "7c9e2a1",
  "environment": "staging-eu",
  "workerId": "worker-7",
  "dataRevision": "orders-fixtures-v3",
  "phase": "test",
  "status": "failed",
  "errorType": "expectation_timeout",
  "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
  "artifacts": ["attempt-1/trace.zip", "attempt-1/events.jsonl"]
}

Значения условные; attempt: 1 здесь означает первое выполнение. У конкретного фреймворка нумерация может быть другой. К этой записи добавляют временные отметки и длительности, а пути к артефактам при публикации связывают с реальным хранилищем.

Как логи, метрики и трейсы дополняют друг друга

Лог фиксирует событие: какой запрос отправили, какой код получили, что произошло при очистке данных. Метрика помогает заметить изменение во множестве выполнений: выросло время ожидания раннера, участились таймауты, увеличилась доля повторов. Трейс связывает операции в цепочку и показывает их длительность. Скриншот или видео дополняют эту картину состоянием интерфейса, но не объясняют самостоятельно, почему он оказался таким.

При проверке взаимодействия микросервисов особенно полезна связь клиентского действия с серверными операциями. Передача контекста OpenTelemetry позволяет переносить идентификаторы трассировки между инструментированными компонентами, в HTTP — например, через traceparent. Отдельные операции представлены спанами: участками работы с началом, завершением и атрибутами.

Наличие traceId в отчёте ещё не создаёт сквозную трассировку. Контекст нужно передать, принять на другой стороне и сохранить вместе со спанами. Если клиент не инструментирован, полезным первым шагом остаётся идентификатор запроса, который сервер возвращает или записывает и который тест сохраняет в результате. Для нескольких запросов одной попытки потребуется несколько таких связей, а не один произвольно выбранный ID.

Не следует путать трейс браузерного теста и распределённый трейс приложения. Первый показывает действия автоматизации и состояние страницы. Второй — путь операции по сервисам. Они отвечают на разные вопросы и становятся полезнее вместе, если привязаны к одной попытке и её запросам.

Почему длительность теста не равна времени ожидания результата

Между постановкой джобы и доступным отчётом есть очередь, подготовка окружения, фикстуры, тело теста, очистка и публикация артефактов. Если растёт очередь раннеров, оптимизация шагов теста не устранит задержку. Если зависает выгрузка результатов, окончание проверки ещё не означает, что команда получила обратную связь.

Этапы нужно измерять раздельно. При параллельном выполнении сумма длительностей тестов показывает объём работы, но не календарное время запуска: часть интервалов перекрывается. Для поиска задержки важны временная шкала и цепочка зависимых операций, которая удерживает завершение всего процесса. Для пайплайнов и их задач существуют семантические соглашения OpenTelemetry; прикладные этапы тестирования всё равно нужно явно инструментировать.

Как отличить дефект продукта от ошибки теста, данных и инфраструктуры

Причину устанавливают по наблюдаемому механизму, а не по цвету результата. Рабочая матрица ниже помогает выбрать следующую проверку. Это диагностические направления: одно падение может иметь несколько связанных причин.

Где искать подтверждение, прежде чем назначать причину
ОбластьЧто могло произойтиЧто проверить
ПродуктСистема нарушила согласованное правило на допустимых данныхОжидаемое и фактическое поведение, входной запрос, серверную обработку и итоговое состояние
АвтотестНеверны локатор, ожидание, утверждение или порядок действийКод и шаг падения, состояние интерфейса, фактически отправленные действия
Тестовые данныеЗапись не подготовлена, изменена соседним тестом или удалена слишком раноСоздание и очистку записей, их принадлежность попытке, параллельные обращения
Конфигурация окруженияНе та сборка, выключенный флаг, несовместимая схема или неверный адрес сервисаФактическую конфигурацию и развёрнутые версии на момент проверки
Инфраструктура выполненияЗавершился процесс, закончилась память, недоступна сеть или очередь исполнителейСостояние раннера, код завершения, события контейнера, ресурсы и сетевые ошибки
Внешняя зависимостьСторонний сервис ограничил запросы, ответил ошибкой или не ответилЗапрос и ответ зависимости, лимиты, таймауты и предусмотренную реакцию продукта

Таймаут не подтверждает инфраструктурную причину: приложение могло попасть в бесконечное ожидание. Ошибка стороннего сервиса тоже не снимает ответственность с продукта, если он должен корректно обработать такой отказ. А совпадение ошибок у нескольких тестов — повод искать общую зависимость, но не доказательство, что все падения вызваны одной проблемой.

Полезно разделять в разборе наблюдение, гипотезу и подтверждённую причину. «Падает только на worker-7» — наблюдение. «На worker-7 не хватает памяти» — гипотеза. Событие завершения нужного контейнера из-за нехватки памяти, совпавшее с обрывом этой попытки, — уже предметное свидетельство, которое можно проверять дальше.

Если данных нет, корректное заключение — «причина не установлена». Это не статус Unknown из отчёта Allure, а состояние расследования. Его нельзя автоматически заменять пометкой flaky: успешный повтор описывает вариативность результата, а не место дефекта.

Пример: как за таймаутом обнаружилась очистка чужих данных

Рассмотрим учебный интернет-магазин. Автотест order_should_be_visible_after_creation создаёт заказ и проверяет, что тот появился в истории пользователя. Для примера команда согласовала ожидание до пяти секунд. Это условие сценария, а не рекомендуемый таймаут для любых тестов.

Первая попытка падает: заказ не найден. Повтор проходит. На скриншоте первой попытки — пустая история. Без дополнительного контекста напрашиваются два решения: увеличить ожидание или записать тест в нестабильные. Ни одно пока не объясняет исчезновение заказа.

Как восстановить последовательность событий

Предположим, тест, сервер и скрипт очистки сохраняют идентификаторы попыток и тестовых объектов. По ним команда собирает следующую картину. Время приведено относительно начала первой попытки; значения условные.

Один результат, несколько источников свидетельств
МоментСобытиеГде найдено подтверждение
0,0 сПопытка A создаёт заказ ORD-DEMO-17 для общей тестовой учётной записиЛог фикстуры с ID попытки и ответ API
0,4 сСервис сохраняет заказ и отвечает 201Трейс запроса и запись о создании объекта
1,2 сОчистка попытки B удаляет все заказы этой учётной записи, включая ORD-DEMO-17Лог cleanup с ID попытки B и журнал удалённых объектов
1,5 сБраузер попытки A получает пустой список заказовСетевой ответ в браузерном трейсе
5,0 сОжидание заказа завершается таймаутомРезультат утверждения и скриншот попытки A

Ключевое свидетельство — не таймаут и даже не пустой ответ, а удаление конкретного объекта чужой очисткой. Лог скрипта связывает операцию с попыткой B, а серверная запись подтверждает её действие над ORD-DEMO-17. Простого совпадения времени для такого вывода было бы недостаточно.

Разбор указывает на дефект изоляции тестовых данных: параллельные проверки используют общий аккаунт, а cleanup удаляет больше, чем создал его владелец. Повтор прошёл без вмешательства соседней очистки. Сценарий не доказывает отсутствие других ошибок продукта — он объясняет именно это наблюдавшееся падение.

Почему исправление следует из свидетельств, а не из статуса

Увеличение таймаута не вернёт удалённую запись. Исправление должно ограничить очистку объектами своей попытки и обеспечить необходимую изоляцию данных. После изменения проверяют совместное выполнение конфликтовавших сценариев, в том числе перекрытие их фаз подготовки и очистки.

У тестовых данных здесь появился ещё один важный атрибут — принадлежность конкретному выполнению. Вместе с версией фикстуры и событиями удаления он помогает объяснить сбой, который по одному сообщению выглядел как проблема интерфейса.

Результат такого разбора можно передать в баг-репорт: приложить последовательность событий, указать нарушенную границу изоляции и связать исправление с воспроизводящим сценарием. Повторный поиск тех же логов больше не должен быть обязательной частью передачи задачи.

Как сохранить свидетельства первой ошибки, а не только успешного повтора

Сбор диагностики нужно проектировать до падения. Если логирование включается лишь после повторного запуска, исходное состояние уже потеряно. Раннер может сменить процесс, заново подготовить данные или попасть на другой узел — повтор оказывается новым наблюдением, а не записью прежнего сбоя.

Например, Playwright Test после падения заменяет worker-процесс и браузер. Поэтому при сравнении попыток важно сохранять не только их номера, но и параметры выполнения, данные и свидетельства каждой ошибки.

Как не перепутать трейс повтора с трейсом падения

В настройках трассировки Playwright режим on-first-retry записывает первую повторную попытку, а не исходное выполнение. Для задачи «разобрать именно первое падение» подходит другая политика: retain-on-failure записывает попытки и удаляет трейсы успешных. Она требует учитывать накладные расходы записи.

Минимальный пример конфигурации:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    trace: 'retain-on-failure',
    screenshot: 'only-on-failure',
  },
});

В существующем проекте эти параметры добавляют в его конфигурацию, сохраняя настройки окружения и проектов. Лимит повторов здесь намеренно не задаётся: политика сохранения свидетельств и решение о допустимых retries — разные настройки.

Браузерный трейс помогает увидеть действия, снимки DOM и сетевые обращения. Серверные спаны он не создаёт. Для нашего примера нужен ещё лог очистки: файл trace.zip попытки A покажет исчезнувший заказ, но без данных попытки B не объяснит, кто его удалил.

Что делать, если тест не успел записать результат

При аварийном завершении процесса обработчик завершения теста может не отработать. Поэтому журнал задания CI, события контейнера и состояние исполнителя должны сохраняться независимо от репортера тестового фреймворка. Внешние журналы особенно важны для остановки по лимиту памяти и принудительного завершения процесса.

Публикацию артефактов организуют так, чтобы она выполнялась и после неуспешной тестовой команды, насколько это допускает CI. При этом ошибка тестов не должна маскироваться успешным шагом загрузки. Ошибка самой загрузки — ещё один результат, который требуется увидеть отдельно.

Файлы разных попыток не должны перезаписывать друг друга. После публикации проверяют не только наличие ссылки в отчёте, но и доступность файла для участников разбора. Ссылка на уже удалённый архив формально существует, диагностической ценности — нет.

Какие метрики нужны кроме общей доли успешных тестов

Метрики полезны, когда показывают, где ухудшился сигнал или увеличилась цена его получения. До расчёта нужно договориться об единице учёта: один сценарий с одним значимым вариантом параметров в выбранном запуске. Повторы этого варианта учитываются как попытки, а не как новые тесты.

Ниже — предлагаемые показатели для завершённых запусков в такой модели. Это не перечень готовых виджетов конкретного инструмента.

Что считать и какую слепую зону устраняет показатель
ПоказательОпределениеНа что обратить внимание
Успех с первой попыткиВарианты с passed при первом выполнении / варианты с известным первым исходом passed, failed или brokenНе смешивать с итоговым успехом после повторов; пропуски и потерянные результаты показывать отдельно
Полнота отчётаЗапланированные варианты с зафиксированным итоговым исходом / все запланированные вариантыСписок допустимых итоговых статусов фиксируется заранее. Запись skipped объясняет судьбу варианта, но не означает выполнения проверки
Ошибки с нужными артефактамиПопытки failed/broken с согласованным набором доступных свидетельств / все попытки failed/brokenНаличие файлов ещё не означает, что они содержат достаточное объяснение
Длительность по этапамРаспределение времени очереди, подготовки, выполнения, очистки и публикацииСравнивать один этап в сопоставимых наборах, окружениях и ресурсах
Время до первичного разбораИнтервал от доступности результата до первой обоснованной классификацииНеразобранные случаи и их возраст учитывать отдельно, иначе метрика улучшится за счёт сложных забытых ошибок

Для долей результат умножают на 100%. Показатель без наблюдений в знаменателе не равен нулю: это отсутствие данных. Коды пропуска, отмены и аварийного завершения тоже нужно сохранять, даже если они не входят в расчёт успеха.

Как зелёная сводка скрывает потерю устойчивости

Учебный расчёт: из 100 вариантов проверок 88 проходят сразу, 12 падают. Все 12 выполняют ещё по одному разу; девять проходят, три снова падают. Пропусков и потерянных записей в этом примере нет.

Итоговая доля успеха — 97%, успех с первой попытки — 88%. Выполнено 112 попыток, но проверяемых вариантов по-прежнему 100. Доля успешных повторов среди первоначальных падений составляет 9 / 12 = 75%; это не доказанная доля flaky-тестов и не доля исправленных дефектов. Причины этих переходов требуют разбора.

Такое разделение позволяет увидеть изменение ещё до того, как начнёт падать весь запуск. Например, итоговый успех сохраняется, а первые попытки становятся менее надёжными и время на повторы растёт. Одной последней зелёной отметки для этого наблюдения недостаточно.

Как не потерять проблему в среднем значении

Длительности полезно смотреть по распределению: медиана описывает типичный случай, P95 — уровень, ниже которого находится примерно 95% наблюдений. У P95 должна быть понятная выборка: длительность какого этапа, каких тестов, на каких исполнителях и за какой период. При малом числе наблюдений отдельные значения часто информативнее одного процентиля.

Увеличение времени выполнения на конкретном образе раннера и увеличение очереди для всех джоб требуют разных действий. Аналогично, средняя доля успеха может скрыть падения одного браузера. Сопоставление сначала строят внутри значимых групп, а уже затем смотрят общую динамику.

Идентификатор попытки полезен в логах и трейсах, но опасен как метка каждого временного ряда. В Prometheus каждая уникальная комбинация labels создаёт отдельный ряд. Неограниченно растущие run_id, trace_id и случайные значения данных лучше оставлять в событиях и артефактах; для метрик выбирать ограниченные группы — набор, тип окружения, этап и класс ошибки.

Как использовать ТестОпс для наблюдаемости результатов автотестов

Система управления тестированием связывает результаты с тест-кейсами, запусками и контекстом. Но сами свидетельства должны появиться в тестах, CI и сервисах. В ТестОпс их можно использовать при разборе; сохранённый статус не восстановит лог, который никогда не записывался.

Границы ответственности здесь практические. Фреймворк фиксирует шаги, проверки и вложения. CI сохраняет обстоятельства задания и передаёт результаты — например, через allurectl. Инструменты наблюдаемости приложения хранят серверные логи и распределённые трейсы. TMS помогает связать тестовую историю и найденную проблему с дальнейшей работой команды. Это схема организации процесса, а не обещание встроенной интеграции любого хранилища с ТестОпс.

Как не склеить разные окружения и не раздробить историю

В карточке результата ТестОпс доступны метаданные теста и переход к связанному тест-кейсу. Окружение задаётся парами «ключ — значение»; результаты в разных окружениях не объединяются. Значения из CI появляются в соответствующих полях после настройки маппинга.

Из этого следует важное правило конфигурации: различать вариант проверки и адрес конкретного выполнения. Браузер или целевая ОС могут определять самостоятельный результат. Случайный traceId или уникальный ID попытки обычно служит для поиска свидетельств. Если без необходимости включить такой ID в различающие окружение поля, каждый повтор станет новой конфигурацией, а история потеряет сопоставимость. Способ хранения технических ID выбирают отдельно — в метаданных, ссылках или вложении результата согласно интеграции.

Для изучения времени в карточке запуска есть временная шкала выполнения и график распределения длительностей. Они помогают увидеть порядок и параллельность тестов, но сами по себе не объясняют ожидание в очереди CI или задержку внутри сервиса: для этих интервалов нужны отдельные данные.

Как использовать вложения и категории, не подменяя ими причину

ТестОпс поддерживает просмотр трейсов Playwright во вложениях результатов автоматизированных тестов. В примечаниях к релизу указаны условия: вложение должно иметь MIME-тип application/vnd.allure.playwright-trace, а доступ к ТестОпс — работать по HTTPS. Запись трейса и его передачу настраивают на стороне тестовой интеграции; одно наличие просмотрщика не включает сбор автоматически.

Категории ошибок позволяют объединять похожие результаты по правилам, в том числе по тексту ошибки. Это уменьшает объём первичного просмотра, но категория «таймаут» остаётся группой симптомов. Внутри неё могут оказаться удалённые данные из нашего примера, медленный сервис и неправильный локатор.

После разбора полезно сохранять подтверждённое объяснение и связь с задачей на исправление. Тогда следующая похожая ошибка сравнивается с известным механизмом, а не автоматически объявляется той же проблемой. При изменении контекста прежняя классификация требует проверки.

С чего начать внедрение наблюдаемости автотестов

Первый шаг — выбрать несколько падений, которые команда регулярно не может объяснить без нового запуска. Для каждого нужно назвать недостающее свидетельство. У одного теста это ответ API перед таймаутом, у другого — версия данных, у третьего — событие завершения раннера. Так объём сбора определяется вопросом, а не желанием записать всё.

Затем вводят общий набор идентификаторов, сохраняют состав запуска и настраивают сбор артефактов для выбранных сценариев. Проверять полезно не только обычное падение утверждения, но и сбой подготовки, остановку процесса и ошибку выгрузки. У каждой ситуации должен остаться понятный след, даже когда полноценного результата теста нет.

Как ограничить стоимость и риски телеметрии

Для всех попыток обычно достаточно компактных метаданных и итогов, а тяжёлую диагностику выбирают по риску и задаче. Ошибки нуждаются в свидетельствах; ограниченная выборка успешных выполнений помогает сравнивать нормальный и проблемный путь. При выборочном сохранении нужно знать правило отбора: отсутствие трейса не доказывает, что операции не было.

Сроки хранения отчёта, логов, видео и серверных трейсов согласуют между собой. Если расследование обычно начинается на следующий рабочий день, артефакт со сроком жизни несколько часов не поможет. Для важных задач на исправление полезно сохранять разрешённый диагностический пакет отдельно от краткоживущего хранилища CI.

Минимизация чувствительных данных относится и к тестовой телеметрии. Заголовки авторизации, cookies, тела запросов, DOM-снимки и видео могут содержать секреты или персональные сведения. Маскирование и ограничение доступа нужно учитывать для каждого формата: очистка текстового лога не очищает скриншот. Собранные данные не должны становиться общедоступными только потому, что относятся к тестовому стенду.

Как проверить, что наблюдаемость действительно появилась

Практическая проверка проста: инженер, не участвовавший в запуске, открывает неуспешный результат и восстанавливает условия, порядок событий и границы неизвестного. Он видит, какое свидетельство подтверждает гипотезу, а какого не хватает. Если для этого снова нужен автор теста или запуск с дополнительным логированием, обнаружен конкретный пробел в диагностике.

Уведомление тоже должно вести к действию: новая группа необъяснённых ошибок, исчезнувшие результаты, рост времени очереди или потеря обязательных артефактов. Универсальный порог для всех наборов не нужен. Нужны согласованные условия реакции, ответственный и данные, по которым он сможет проверить сигнал.

Наблюдаемость не делает каждый автотест надёжным и не превращает успешный прогон в гарантию качества. Она делает результат проверяемым: показывает, что выполнялось, в каких условиях и какие свидетельства остались. Именно это позволяет исправлять причину, а не выбирать между очередным retry и очередным предположением.