В шестой части замеры не мерили ничего. Здесь другой класс ошибок: замер честно что-то мерит, но не то, что происходит у пользователя. Проверка шла другим путём, другим объёмом, из другой сети или в другом режиме — и говорила «работает», пока у людей не работало.
Это седьмая, заключительная часть цикла «Мастерская разработчика».
Пустой лог ошибок ничего не доказывает сам по себе
После выката исправления: «за 25 минут в журнале PHP ни одного предупреждения». Может быть, исправление работает. А может быть, за эти 25 минут никто не открыл страницу, где предупреждение живёт. Рядом всегда нужно второе число — что трафик был:
docker logs site-nginx-1 --since 25m 2>&1 | grep -c 'katalog/traktory' # 929
docker logs site-nginx-1 --since 25m 2>&1 | wc -l # 3802
929 запросов к нужному разделу и ни одного предупреждения — это уже вывод. На тестовой копии, где живого трафика нет, «нет предупреждений» доказывается принудительным рендером шаблона — и проверкой, что он действительно что-то отрендерил (длина HTML, число карточек), а не вышел на первом условии.
Трафик идёт — не значит «работает»
Сторож канала до внешнего сервиса судил о здоровье по приросту переданных байт и показывал 2000–4000 КБ за такт: «жив, просто медленный». Канал был мёртв. Байты были повторными попытками: один телефон сделал 254 соединения за три минуты. Система всё видела, всё записывала и ничего не делала.
Отказавший канал порождает больше трафика, чем рабочий — за счёт повторов. Судить надо по тому, доходят ли данные, а не по тому, сколько их идёт. Проверка — действие: скачать килобайт-другой тем же путём, которым ходит пользователь.
Рядом — обратная ошибка. Через тот же сломанный канал маленький запрос (узнать свой IP) отвечал нормально, а передача файла шла на 0 КБ/с. Пробы «отвечает ли» слепы к такой поломке. Если жалоба на отправку картинки, проверять надо передачей мегабайтов, а не пингом.
Ошибка в журнале — ещё не причина
В том же разборе в журнале прокси нашлась ошибка «не найден доступный выход», и её сразу объявили причиной. Оказалось, через этот выход шли восемь других доменов, а пострадавший трафик маршрутизировался иначе. Вопрос, который надо задать первым: проходит ли пострадавший трафик через то, что ругается? Ответ ищется по правилам маршрутизации, а не по совпадению во времени.
Детектор, проверенный не на той аварии
Для этого канала написали детектор: тревога, если больше 12 соединений за такт. В реальной аварии их было 7–19 в минуту, то есть около шести за такт — детектор проспал бы именно её. Спасло то, что новое правило прогнали по журналу самой аварии.
Вторая ошибка того же детектора проявилась только в живом прогоне. Соединения он считал за 60 секунд, а байты — за 25. На здоровом канале один провал до 34 КБ втянул в окно 16 соединений из соседних тактов, где шло по 12 МБ, — и детектор объявил живой канал мёртвым.
- порог проверять на исторических данных того события, ради которого он делается;
- признаки, которые сравниваются, — в одном окне;
- после калибровки гонять на здоровом объекте и смотреть, не срабатывает ли впустую.
Зонд из другой сети
Правка сетевых правил на сервере потеряла одну метку, и у машин домашней сети на 2,5 часа отвалились два сервиса. Все проверки говорили «здорово»: конфиг прошёл проверку, контейнер поднялся, в журнале шли сотни соединений, пробник через тот же узел отвечал 200. Пробник жил в отдельном Docker-контейнере, и правила перехвата трафика хоста на него не действовали. Он проверял, что жив узел, а сломан был путь до узла у людей.
В той ли я сети, с тем ли адресом, под теми ли правилами, что и пользователь? Если инструмента, который ходит путём людей, нет, — спросить человека прямо: «проверьте, открывается ли», а не докладывать «работает» по зонду из другого контекста.
Обратный случай. После примерно десяти сессий headless-браузера за пять минут сайт «перестал отвечать»: TCP-соединение на 443 открывалось, данные не шли. Проверка с внешнего сервиса показала 200 — посетители не пострадали: какой-то фильтр на пути к серверу резал только наш адрес и через 15 минут отпустил сам. Домашний тестовый сервер, кстати, выходит в интернет с того же адреса — проверка «с другой машины» из той же сети ничего не дала бы. «Сайт лежит» — сначала проверять с независимой точки.
Верхняя граница вместо факта
Считали, сколько времени начислено задаче за вечер. Точных данных не было, считали границами — и скрипт напечатал «как минимум 1:39:19». Для вычитания взяли верхнюю границу дневной доли. Правильная нижняя граница оказалась девять минут — разница в десять раз, и неверное число успели отправить.
Если величина известна только интервалом, каждый вывод помечается, из какой границы он получен. «Не меньше X» считается из нижней границы уменьшаемого и верхней границы вычитаемого, и в ответе остаются обе границы, а не одна красивая.
Проверил одну ветку из четырёх
Правку выгрузки отчётов проверили на одном виде — он прошёл. Два других отдавали 500: у них была строка-шапка, у проверенного — нет. Там же страховку по типу значения поставили в сборку xlsx и забыли в csv, хотя ошибка в данных была общая. Есть у кода режимы — проверять все. Чинится ошибка в данных — чинить во всех местах, где эти данные выводятся.
Итог цикла
Бот, сервер обновлений, зонд на CDP, скрипты правки — инструменты, которые экономят часы. Но каждый из них отвечает на свой вопрос, и самая дорогая ошибка в этом цикле — принять ответ на соседний вопрос за ответ на свой.
Проверки зелёные, а у людей не работает?
Опишите, что видят пользователи, — найду, чем путь проверки отличается от их пути.
// загружаю комментарии…