Files
ripe-cidr-collector/docs/plan-observability.md
T
ayurishchevandClaude Sonnet 5 cb935fef0d Add per-source status tracking, /health sources block and /sources
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>
2026-09-21 10:46:38 +03:00

7.4 KiB
Raw Blame History

План: наблюдаемость (сбои источников, здоровье, логи)

Источник: 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.

Изменения

  1. db.py: схема v3 и миграция, record_source_result, source_statuses, очистка состояния (sweep, purge).
  2. cidr_collector.py: классификация ошибок (error_kind), запись результата по каждому источнику в обоих run_collection, итоговая строка лога, ключ source_failure_threshold.
  3. api_server.py: блок sources и статус в /health, GET /sources.
  4. README.md: /health, /sources, ключ конфигурации, лог, схема базы.
  5. Тесты (2 новых, всего 30): сборщик (успех и сбой источников записываются, категории ошибок, сброс failures при успехе, очистка удалённого источника); API (/health ok до порога и 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_version 3 у старого кода вызовет только пропуск миграции).
  • Порог 3 на редких расписаниях (сбор FQDN раз в сутки) означает три дня до degraded; порог настраивается.