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

Это шестая часть цикла «Мастерская разработчика».

1. Четыре прогона по 0,0 секунды

Гоняли воркер прогрева кэша и получили четыре прогона подряд по 0.0s и ноль предупреждений. Выглядело блестяще. На деле прошлый прогон мы сами прервали по таймауту, он оставил замок (транзиент на 3 минуты), и каждый следующий вызов упирался в замок и выходил, не сделав ни одного запроса. Ноль предупреждений — потому что нечего было предупреждать.

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

2. «679 из 679 холодных»

Спросили хранилище кэша, какие ячейки на месте, и получили «холодных 679 из 679» — сразу после выката. Чуть не подняли тревогу о развале кэша. Причина — тип аргумента: функции проверки передали задачи прогрева, а она ждала ключи ячеек (ключ из задачи строит отдельная функция). Ни один ключ не совпал. Правильный вызов — той функцией, которой пользуется сам продукт, — дал ноль холодных.

В другой раз — тот же класс ошибки: «очередь пуста при 1293 холодных ячейках — догрев после выката не работает». Смотрели не ту опцию: очередь называлась иначе, и в ней лежало 1094 задачи. Три замера подряд показали бы 1293 → 1152 → 999 за три минуты — и сняли бы вопрос без единой гипотезы.

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

3. Ноль от собственного разбора вывода

Скрипт выката правила для fail2ban проверял правку утилитой fail2ban-regex и откатывал, если дата в журнале не распознаётся. Он откатил верную правку. Число совпадений мы вытаскивали шаблоном \d+(?= hit), а утилита печатает его в квадратных скобках:

Date template hits:
|- [# of hits] date format
|  [400] "time":"Year-Month-DayT24hour:Minute:Second

Шаблон не совпал → «0» → «дата не распознана» → откат. Дата распознавалась во всех 400 строках.

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

Рядом — ошибка подписи. Замер был подписан «идёт ли поток прямо сейчас, за последние 3 минуты», а считал по tail -300 — последним 300 строкам, что при редком трафике покрывает полчаса. Число 199 выглядело внушительно и не значило ничего. Подпись должна описывать то, что замер делает, а не то, что хотелось измерить: через десять минут сам поверишь подписи.

4. Таймаут — не «порт закрыт»

exec 3<>/dev/tcp/$HOST/$PORT && head -c 60 <&3     # пусто, код 124 — «порт не отвечает»?

Порт отвечал: честный ssh тут же получил Permission denied (publickey). head -c 60 ждёт ровно 60 байт, а приветствие SSH короче — около 40, и больше сервер не пришлёт, пока клиент не поздоровается сам. Зонд повис на добор и был убит таймаутом. Читать построчно:

exec 3<>/dev/tcp/$HOST/$PORT; IFS= read -r -t 6 line <&3; echo "$line"

Если зонд может «не дождаться», а не «получить отказ», таймаут ничего не говорит о доступности. Подтверждать инструментом, который знает протокол: ssh, curl, openssl s_client. Из той же серии: wc -l по /var/log/nginx/access.log внутри официального контейнера nginx висит вечно — это ссылка на /dev/stdout. Журнал читается через docker logs.

5. Символы против байтов

После вставки строки в 18 файлов скрипт отчитался: «20522 → 15045». Похоже на потерю 5 КБ. На деле «до» было в байтах (wc -c), а «после» — len() строки, то есть в символах; кириллица в UTF-8 занимает два байта. Каждый файл вырос ровно на 1039 байт. Единица измерения — часть результата: мерить тем же инструментом, что и «до», а при подозрении на потерю смотреть содержимое, а не только размер.

6. Ручные прогоны подряд — не работа по расписанию

Пять ручных прогонов обхода подряд — ноль предупреждений пула PHP-FPM. Первый же обход по крону — всплеск. Между тиками крона есть паузы, в ручном цикле их нет, и нагрузка ложится иначе. Финальную проверку надо гнать в том режиме, в каком механизм живёт на самом деле, и считать за окно времени, а не «есть/нет».

Вопросы к любому замеру

  • может ли этот замер в принципе вернуть другой ответ?
  • не упёрся ли он в замок, кэш или ранний выход?
  • тот ли аргумент, та ли опция, та ли функция, что у продукта?
  • не круглое ли число — ноль или всё?
  • что значит подпись и что на самом деле посчитано?
  • в той ли единице «до» и «после»?
  • один снимок или динамика?

Мониторинг «зелёный», а пользователи жалуются?

Пришлите, как вы меряете, — найду, где замер отвечает не на тот вопрос.

· полезно?
АЧ
Алексей Чикун веб-разработчик, команда TRIOHEAD

Делаю сайты и сервисы целиком: от вёрстки до сервера. Пишу о том, что проверил на своих проектах.

Комментарии

// загружаю комментарии…

Комментарии публикуются после проверки. Ссылки и HTML не принимаются.