Collectors record the result of every source (schema v3, table source_status); /health reports failing sources (failures in a row >= source_failure_threshold) and turns degraded; GET /sources shows the full state; runs end with a summary log line instead of "data saved". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7.4 KiB
План: наблюдаемость (сбои источников, здоровье, логи)
Источник: docs/analysis-2026-09-21.md (наблюдения 2 и 5, риск «сбои RIPE/DNS не видны»), пункт 2 рекомендуемого порядка. Метрики Prometheus (/metrics) в этот план не входят (решение пользователя); всё, что описано ниже, доступно через /health, /sources, лог и базу.
Проблема
Недоступный RIPEstat или DNS пишется только в лог: задание считается успешным, /health показывает ok, а данные источника не обновляются (до истечения TTL - 90 дней). Сбой одного из шести ASN невидим, пока адреса не начнут пропадать. В логе после каждого запуска стоит «data saved» даже без изменений, а итог запуска по источникам не сводится.
Дизайн
1. Состояние источников (SQLite, схема версии 3)
- Таблица
source_status(kind, source, last_attempt, last_success, failures, error_kind), ключ(kind, source). Хранится в базе, а не вstatus.json: переживает перезапуск демона, пишется в той же транзакции, что и данные, попадает в резервные копии. Миграция 2 -> 3 автоматическая (как 1 -> 2), данные не затрагиваются. - Сборщик записывает результат по каждому источнику при каждом запуске: успех -
last_success = last_attempt = сейчас,failures = 0,error_kind = NULL; сбой -last_attempt = сейчас,failures + 1,error_kind;last_successне меняется. error_kind- короткая категория без деталей:timeout,connection,http_429,http_4xx,http_5xx,invalid_response(нечитаемый ответ),dns,no_global_addresses(имя разрешилось, но все адреса отфильтрованы),unknown. Полный текст ошибки остаётся в логе; наружу он не отдаётся (как и пути в находке 6 ревью).- Пустой, но корректный ответ RIPEstat считается успехом (число адресов видно в
/sources). - Строки состояния источников, которых уже нет в конфигурации, удаляются в очередном запуске сбора и при
purge.
2. /health
- В ответ добавляется блок
sources: по типам (asn,fqdn) число источников (total) и список только неисправных (failing):source,failures,last_success,error_kind. Компактно и без лишних деталей. - Источник считается неисправным при
failures >= source_failure_threshold(ключ вconfig.json, по умолчанию 3): один сбой RIPEstat не «краснит» систему. При наличии неисправных источниковstatus=degraded. - Существующие поля и поведение (
collector_alive,jobs,db_recreated,last_restore) не меняются.
3. GET /sources (чтение открыто, как /asns)
Полная картина по всем источникам: kind, source, addresses (сколько значений в базе), last_attempt, last_success, failures, error_kind. Позволяет увидеть источник, который «успешно» вернул ноль адресов или давно не обновлялся. Существующие /asns и /fqdns не меняются.
4. Логи
- Итог запуска одной строкой: «ASN collection finished: 6 sources, 5 ok, 1 failed, +12/-3 prefixes» (для FQDN так же).
- Сообщение «... data saved to ...» после каждой транзакции убирается (наблюдение 5 анализа); подробности по источникам остаются на уровне INFO.
Изменения
db.py: схема v3 и миграция,record_source_result,source_statuses, очистка состояния (sweep,purge).cidr_collector.py: классификация ошибок (error_kind), запись результата по каждому источнику в обоихrun_collection, итоговая строка лога, ключsource_failure_threshold.api_server.py: блокsourcesи статус в/health,GET /sources.README.md:/health,/sources, ключ конфигурации, лог, схема базы.- Тесты (2 новых, всего 30): сборщик (успех и сбой источников записываются, категории ошибок, сброс
failuresпри успехе, очистка удалённого источника); API (/healthokдо порога иdegradedпосле, ответ без текста ошибок,/sourcesс числом адресов).
Не входит
- Метрики Prometheus и
/metrics(исключены по решению пользователя). - Уведомления (webhook, Telegram) и алерты:
/healthи/sourcesпригодны для внешних проверок, сами уведомления - отдельная доработка. - Свежесть резервных копий как отдельный признак здоровья, команда CLI
status, ограничение частотыPOST /collect. - Проверка
docker healthcheckне меняется:degradedпо-прежнему HTTP 200, контейнер из-за внешнего сбоя перезапускать нечего.
Проверка
Тесты в контейнере. Вручную: миграция базы версии 2 (созданной кодом до изменения) с сохранением данных; локальный «RIPEstat» (как при проверке повторов) отвечает 503: после трёх запусков /health показывает degraded и источник в failing, после восстановления сервера ok; сравнение ответов существующих эндпоинтов до и после; Docker Compose (демон и API, ручной сбор).
Риски и откат
- Схема базы v3: таблица добавляется, существующие таблицы не меняются; откат кода оставляет лишнюю таблицу без последствий (старый код её не читает,
user_version3 у старого кода вызовет только пропуск миграции). - Порог 3 на редких расписаниях (сбор FQDN раз в сутки) означает три дня до
degraded; порог настраивается.