Моніторинг парсерів: heartbeat-метрики та алерти для крипто-проектів

Парсер упав уночі, а ви дізналися про це лише вранці — втрачені дані та втрачена вигода. Ми налаштовуємо моніторинг та алерти на збої грабінгу, щоб ви завжди були в курсі. Наша команда реалізує систему сповіщень під ключ — від heartbeat-метрик до повідомлень у Telegram, з подальшою підтримкою.

Моніторинг парсерів: heartbeat-метрики та алерти для крипто-проектів

Блокчейн інфраструктураПростийвід 1 дня до 3 днів
Часті запитання

Парсер впав о 3 ночі, дані перестали оновлюватися — і ніхто не дізнався до ранку. Для крипто-проекту кожна година простою парсера цінових даних з Binance або CoinGecko — це втрачені угоди, застарілі ордери і slippage в DeFi-протоколах. Середня вартість такого даунтайму може перевищувати $500 на годину. Для проекту з ліквідним пулом на $10 млн кожна година простою — $500–$1000 збитків. Навіть одна непомічена помилка здатна обернутися тисячами доларів втраченої ліквідності. Моніторинг грабінгу ми не зводимо до встановлення Prometheus і забування. Це продумана система сигналів: що саме зламалося, наскільки критично, кому повідомити і в якій формі. За 5 років роботи ми налаштували моніторинг для 30+ парсерів у крипто- та фінтех-проектах. Нижче — конкретна архітектура, яку ми використовуємо в продакшені.

Чому стандартний моніторинг не рятує?

Типова помилка — моніторити тільки доступність HTTP-ендпоінта. Парсер може висіти в нескінченному циклі, отримувати порожні відповіді або падати з rate limit, але ендпоінт буде відповідати 200. Потрібна heartbeat-метрика від кожного запуску та детекція трьох класів проблем. Два з трьох збоїв — часткові, і їх не бачить моніторинг доступності. 75% хибних алертів можна відсікти налаштуванням порогів.

Клас збою Приклад Виявлення Критичність
Повний Парсер не запустився Немає heartbeat > порогу Critical
Частковий Дані неповні records_fetched < minExpected Warning
Деградація Повільна робота Duration > maxDurationMs Warning

Як відрізнити частковий збій від повного?

Повний збій — парсер не запустився або впав (перевірка за timestamp останнього успішного запуску). Частковий — парсер працює, але дані неповні (кількість записів нижче порогу) або є помилки. Частковий збій небезпечніший, оскільки проходить непоміченим без метрик кількості записів. Heartbeat-моніторинг у 3 рази надійніший за просту перевірку статусу, оскільки фіксує якість даних, а не тільки факт запуску.

Heartbeat метрика: основа моніторингу

Кожен запуск парсера повинен фіксувати результат. Приклад на TypeScript:

class ScraperMonitor {
  constructor(private db: Database, private alerter: AlertService) {}

  async recordRun(scraperId: string, result: ScraperResult): Promise<void> {
    await this.db('scraper_runs').insert({
      scraper_id: scraperId,
      started_at: result.startedAt,
      finished_at: result.finishedAt,
      duration_ms: result.finishedAt.getTime() - result.startedAt.getTime(),
      records_fetched: result.recordsFetched,
      records_saved: result.recordsSaved,
      errors_count: result.errors.length,
      status: result.errors.length === 0 ? 'success' : 'partial_failure',
      error_details: result.errors.length > 0 ? JSON.stringify(result.errors) : null,
    })
    await this.checkThresholds(scraperId, result)
  }

  private async checkThresholds(scraperId: string, result: ScraperResult): Promise<void> {
    const config = await this.getScraperConfig(scraperId)
    if (result.recordsFetched < config.minExpectedRecords) {
      await this.alerter.send({
        severity: 'warning',
        title: `Low record count: ${scraperId}`,
        message: `Expected ≥${config.minExpectedRecords}, got ${result.recordsFetched}`,
      })
    }
    if (result.finishedAt.getTime() - result.startedAt.getTime() > config.maxDurationMs) {
      await this.alerter.send({
        severity: 'warning',
        title: `Slow scraper: ${scraperId}`,
        message: `Took ${result.finishedAt.getTime() - result.startedAt.getTime()}ms, threshold ${config.maxDurationMs}ms`,
      })
    }
  }
}

Heartbeat-метрики — стандарт моніторингу розподілених систем. Документація Prometheus.

Детекція staleness: дані застаріли

Основна перевірка — коли востаннє успішно оновлювалися дані. SQL-запит для виявлення парсерів, що зависли більш ніж на 1.5 очікуваних інтервали:

SELECT sc.id, sc.name, sc.expected_interval_minutes, MAX(sr.finished_at) AS last_success, EXTRACT(EPOCH FROM (NOW() - MAX(sr.finished_at))) / 60 AS minutes_since_last
FROM scraper_configs sc
LEFT JOIN scraper_runs sr ON sr.scraper_id = sc.id AND sr.status = 'success'
GROUP BY sc.id, sc.name, sc.expected_interval_minutes
HAVING EXTRACT(EPOCH FROM (NOW() - MAX(sr.finished_at))) / 60 > sc.expected_interval_minutes * 1.5
ORDER BY minutes_since_last DESC;

Цей запит ми запускаємо кожні 5 хвилин через окремий watchdog-процес. Важливо: watchdog має бути незалежним — якщо парсер впаде, watchdog продовжить моніторинг.

Чому watchdog має бути незалежним?

Watchdog — це зовнішній процес (наприклад, cron-задача на окремому сервері), який перевіряє staleness. Якщо парсер завис, watchdog побачить, що last_success_timestamp не оновлюється, і відправить алерт. Якщо watchdog запускати всередині парсера, при падінні парсера watchdog теж впаде — і алерт не прийде. Це класична проблема single point of failure. За досвідом, 30% інцидентів пов'язані саме з тим, що моніторинг не пережив падіння основного сервісу.

Алертинг: канали та пріоритети

Канали оповіщення вибираємо за severity:

class AlertService {
  async send(alert: Alert): Promise<void> {
    const handlers = this.getHandlersForSeverity(alert.severity)
    await Promise.all(handlers.map(h => h.send(alert)))
  }

  private getHandlersForSeverity(severity: string) {
    switch (severity) {
      case 'critical':
        return [this.telegram, this.pagerDuty] // будить людей
      case 'warning':
        return [this.telegram] // в робочий час
      case 'info':
        return [this.slackChannel] // для логів
    }
  }
}

class TelegramAlerter {
  async send(alert: Alert): Promise<void> {
    const emoji = alert.severity === 'critical' ? '🔴' : '🟡'
    const text = `${emoji} *${alert.title}*\n\n${alert.message}\n\n_${new Date().toISOString()}_`
    await fetch(`https://api.telegram.org/bot${this.token}/sendMessage`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        chat_id: this.chatId,
        text,
        parse_mode: 'Markdown',
      }),
    })
  }
}

Grafana дашборд для візуального моніторингу

Ключові панелі на дашборді:

  • Success rate по скраперах — відсоток успішних запусків за останні 24h. Якщо падає нижче 95% — попередження.
  • Records per run — часовий ряд кількості зібраних записів. Аномальний провал добре видно на графіку.
  • Duration heatmap — розподіл часу виконання. Повільні outlier-и сигналізують про проблеми з джерелом.

Prometheus-метрики з парсера:

---
# Приклад Prometheus метрик зі скрапера
scraper_run_duration_seconds{scraper="coingecko"} 1.245
scraper_records_fetched_total{scraper="coingecko"} 4521
scraper_errors_total{scraper="coingecko", error_type="rate_limit"} 3
scraper_last_success_timestamp{scraper="coingecko"} 1704067200
---

Alerting-правила для Prometheus / Grafana:

groups: - name: scraper_alerts rules: - alert: ScraperDown expr: time() - scraper_last_success_timestamp > 600 # 10 хвилин for: 2m labels: severity: critical annotations: summary: "Scraper {{ $labels.scraper }} has not run successfully for 10+ minutes" - alert: ScraperLowRecords expr: scraper_records_fetched_total < 100 for: 5m labels: severity: warning annotations: summary: "Scraper {{ $labels.scraper }} fetching unusually few records" 

Як ми налаштовуємо моніторинг: процес роботи

  1. Аудит поточних парсерів: виявляємо точки інтеграції метрик, визначаємо очікувані інтервали та пороги.
  2. Інтеграція heartbeat-метрик: додаємо в код парсера виклики recordRun з потрібними параметрами.
  3. Розгортання стеку моніторингу: налаштовуємо Prometheus exporter, конфігуруємо збір метрик.
  4. Створення дашборду в Grafana: візуалізація ключових метрик, налаштування оповіщень.
  5. Налаштування алертів: інтеграція з Telegram, PagerDuty, визначення severity.
  6. Документація та навчання: передаємо шаблони та навчаємо команду реагувати на алерти.

Додаткові метрики для крипто-парсерів

Для проектів, що працюють з DeFi-даними, окрім базових метрик варто додати:

Метрика Опис Чому важлива
oracle_price_spread Відхилення ціни від Chainlink оракула Виявляє застарілі дані
cross_chain_lag Затримка між L1 та L2 rollup Критично для bridge-парсерів
slippage_impact Втрати від просковзування при угодах Відстежує якість даних

Що входить у налаштування моніторингу під ключ

Ми надаємо:

  • Інтеграція heartbeat-метрик в код парсерів (TypeScript/Python/Rust)
  • Watchdog-процес з SQL-запитами staleness
  • Prometheus exporter + custom метрики
  • Grafana дашборд (Success rate, Records per run, Duration heatmap)
  • Telegram-бота для алертів (критичні — з PagerDuty)
  • Письмову документацію та доступ до репозиторію з шаблонами
  • Навчання команди роботі з дашбордом та реагуванню на алерти
  • Гарантію SLA 99.9% uptime системи моніторингу

Зв'яжіться з нами для консультації — підберемо оптимальну конфігурацію під ваш парсер. Базовий моніторинг ставимо за 1 день, повний — за 2–3 дні, залежно від кількості парсерів та кастомних порогів. Середня економія від запобіганого даунтайму окупає налаштування моніторингу за 2 дні. Замовте налаштування моніторингу з гарантією SLA 99.9% — отримайте детальний розрахунок для вашого проекту, напишіть нам.

Напрямки блокчейн-розробки

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1543
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1395
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1374
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142