Как мониторить callbacks и wallet events в crypto API, чтобы проблемы ловить раньше клиента

В crypto API почти никогда не бывает одной точки правды.

Есть входящие callbacks от провайдеров, внутренние очереди, wallet daemons, индексаторы блокчейна, фоновые ретраи, reconciliation jobs и пользовательский API поверх этого. На демо всё выглядит линейно: транзакция пришла, статус обновился, клиент получил уведомление. В production цепочка ломается не так драматично, как в презентациях, но куда неприятнее: callback доехал с задержкой, wallet node подвисла, очередь переиграла старое сообщение, а support узнаёт о проблеме первым — из жалобы клиента.

Поэтому для Sassoft-подобных систем monitoring — это не «поставить график CPU и пару 500-ок». Нужен контроль именно над платёжным потоком: что вошло, что обработалось, что застряло, что было доставлено повторно и где данные начали расходиться.

Что именно нужно мониторить

Если смотреть практично, в crypto payments есть минимум пять критичных контуров:

  1. Ingress событий — callbacks, webhooks, polling-результаты, on-chain detections
  2. Очереди и workers — обработка статусов, crediting, payout pipeline, retries
  3. Wallet layer — RPC к нодам, баланс, высота блоков, задержка синка, ошибки broadcast
  4. State transitions — как invoice, deposit, withdrawal и payout меняют состояние
  5. Delivery наружу — уведомления клиентам, callbacks во внешние системы, API latency

Если хотя бы один из этих контуров не наблюдаем, команда очень быстро начинает работать «по симптомам», а не по сигналам.

Главный принцип: мониторить не компоненты, а путь денег

Классическая ошибка — видеть метрики сервисов, но не видеть бизнес-процесс.

Например:

  • API отвечает 200 OK
  • очередь жива
  • PostgreSQL не красная
  • CPU нормальный

И при этом callback от провайдера уже 18 минут не приводит к смене статуса invoice, а клиент не получает подтверждение.

С технической точки зрения всё как будто зелёное. С точки зрения бизнеса — инцидент уже начался.

Поэтому основной объект мониторинга в crypto backend — не только сервис, а pipeline движения события:

event received -> persisted -> deduplicated -> processed -> state changed -> outward notification delivered

Для каждого шага нужен измеримый сигнал.

Минимальный набор метрик, который реально полезен

Ниже — тот baseline, с которого обычно стоит начинать.

1. Callback throughput и error rate

Нужно видеть:

  • сколько callbacks прилетает по каждому провайдеру / типу события
  • сколько из них завершается успехом
  • сколько уходит в 4xx / 5xx
  • сколько приходит повторно

Практически полезные метрики:

  • callbacks_received_total{provider,event_type}
  • callbacks_processed_total{provider,event_type,status="ok|error|duplicate"}
  • callback_processing_duration_seconds
  • callback_duplicates_total{provider}

Если duplicate rate неожиданно вырос, это часто означает одно из трёх:

  • провайдер начал агрессивно ретраить
  • ваш endpoint отвечает слишком медленно
  • downstream-обработка не подтверждает успех вовремя

2. Event lag

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

Например:

  • когда провайдер создал событие
  • когда вы его получили
  • когда записали в БД
  • когда worker сменил статус
  • когда клиент получил уведомление

Это позволяет строить:

  • provider_to_ingest_lag_seconds
  • ingest_to_process_lag_seconds
  • process_to_notify_lag_seconds
  • end_to_end_event_lag_seconds

Именно лаг очень часто показывает деградацию раньше, чем error rate. Система может ещё «работать», но уже с опозданием в 7–10 минут, и это уже operational problem.

3. Queue depth и oldest message age

Если у вас есть workers, надо смотреть не только длину очереди, но и возраст самого старого сообщения.

Почему это важно:

  • длина очереди может быть умеренной, но одно сообщение уже висит 25 минут
  • резкий рост oldest_message_age почти всегда означает реальный затык
  • для payout и balance updates это критичнее, чем средняя длина очереди

Нужные сигналы:

  • queue_messages_visible
  • queue_messages_inflight
  • queue_oldest_message_age_seconds
  • worker_jobs_processed_total
  • worker_job_failures_total{job_type}

4. Wallet health

Если crypto API опирается на собственные wallet daemons или RPC провайдеров, нужны отдельные метрики на этот слой.

Минимум:

  • RPC latency
  • RPC error rate
  • current block height
  • block lag относительно reference source
  • mempool/broadcast failures
  • hot wallet balance
  • число неподтверждённых и зависших withdrawal attempts

Практические примеры:

  • wallet_rpc_requests_total{chain,method,status}
  • wallet_rpc_duration_seconds{chain,method}
  • wallet_block_height{chain,node}
  • wallet_block_lag{chain,node}
  • wallet_broadcast_failures_total{chain}
  • wallet_available_balance{asset,wallet_type="hot"}

Если block lag растёт, а callbacks и API пока ещё зелёные, это уже ранний индикатор, что через некоторое время начнутся жалобы на депозиты и confirmations.

5. State machine anomalies

Сильный production monitoring в платёжной системе должен ловить не только падения, но и невозможные или подозрительные переходы состояний.

Например:

  • paid -> pending
  • confirmed -> new
  • повторное crediting одного и того же deposit
  • payout в completed без успешного broadcast
  • invoice слишком долго в processing

Это не просто логические ошибки — это часто следствие гонок, duplicate events или ручных вмешательств.

Полезно считать:

  • state_transition_total{entity,from,to}
  • invalid_state_transition_total{entity,from,to}
  • stuck_entities_total{entity,state}

Какими должны быть алерты

Плохой алерт — это «что-то пошло не так». Хороший алерт — это короткая гипотеза о том, где именно началась деградация.

Для crypto/payments обычно работают такие правила.

Callback pipeline

Триггерить, если:

  • callback 5xx rate > 2% за 5–10 минут
  • callback duplicate rate резко вырос относительно baseline
  • ingest_to_process_lag p95 превысил допустимый порог
  • конкретный провайдер перестал присылать события, хотя обычно трафик есть

Wallet layer

Триггерить, если:

  • block lag превышает порог по сети
  • RPC error rate растёт сериями, а не единично
  • broadcast pending слишком долго не меняется
  • hot wallet balance опускается ниже операционного минимума

Queue/workers

Триггерить, если:

  • oldest message age > SLO
  • один тип job массово уходит в retry
  • consumer throughput упал при стабильном входящем потоке

Data integrity

Триггерить, если:

  • число invalid transitions > 0
  • duplicate credit attempt > 0
  • reconciliation mismatch выше baseline

В этой зоне лучше иметь один жёсткий alert с низкой толерантностью, потому что такие события редко бывают «шумом».

Нормальная SLO-модель для callbacks и событий

Если нужен практичный старт, можно ввести простую модель:

  • 99% callbacks должны быть приняты и записаны меньше чем за 2 секунды
  • 95% inbound payment events должны приводить к смене внутреннего статуса меньше чем за 30 секунд
  • 99% client notifications должны уходить меньше чем за 60 секунд после внутренней обработки
  • 0 tolerated duplicate credits

Важно, что SLO надо задавать по этапам, а не только по HTTP endpoint. Иначе вы формально выполните SLO по приёму запроса, но провалите реальную пользовательскую задачу.

Логи, без которых расследование становится мучением

Метрики показывают, что болит. Логи нужны, чтобы понять почему.

Для каждого события полезно тащить единый набор полей:

  • provider
  • event_type
  • external_event_id
  • invoice_id / payment_id / withdrawal_id
  • txid
  • idempotency_key
  • attempt
  • processing_result
  • dedup_hit=true|false
  • trace_id

Если этих полей нет, каждое расследование превращается в ручной grep по несвязанным строкам.

Дашборд, который действительно нужен on-call инженеру

Один рабочий dashboard лучше десяти красивых.

В хорошем operational dashboard для Sassoft-подобного API обычно есть:

  1. входящий поток callbacks / events по провайдерам
  2. error rate и duplicate rate
  3. p50 / p95 / p99 lag по этапам pipeline
  4. queue depth + oldest message age
  5. wallet RPC latency / errors / block lag
  6. stuck invoices, stuck payouts, stuck withdrawals
  7. последние invalid transitions и reconciliation mismatches

Главная идея: on-call должен за 1–2 минуты понять, проблема:

  • во внешнем провайдере
  • в очередях
  • в wallet layer
  • в бизнес-логике переходов
  • или в доставке уведомлений наружу

Что автоматизировать помимо алертов

Monitoring в одиночку не закрывает операционный цикл. Хорошая система ещё и автоматически делает базовые защитные действия.

Например:

  • переводит noisy provider в режим rate-limited retries
  • ставит зависшие payout jobs в quarantine queue
  • запускает reconciliation для сущностей с долгим processing
  • создаёт отдельный high-priority alert, если есть риск двойного crediting
  • периодически сверяет block height и health нескольких RPC endpoints

То есть часть проблем должна не только обнаруживаться, но и автоматически локализоваться.

Где команды чаще всего недомониторивают

На практике чаще всего проваливают не CPU, не память и даже не uptime.

Обычно упускают именно это:

  • нет метрики duplicate delivery
  • нет age-based alert на очереди
  • нет контроля impossible transitions
  • нет block lag monitoring по конкретным chains
  • нет end-to-end lag между ingest и клиентским уведомлением
  • нет разделения на provider issue vs internal processing issue

Из-за этого инцидент виден слишком поздно: когда support уже получил пачку обращений, а finance начинает сомневаться в корректности статусов.

Практический блок: где у бизнеса реально болит и что имеет смысл внедрить

Если перевести тему мониторинга с инженерного языка на язык бизнеса, проблема обычно выглядит так:

  1. деньги и статусы проходят через несколько систем, но у команды нет одной операционной картины
  2. support узнаёт о проблеме раньше backend-команды
  3. finance и operations не уверены, где именно сломалась цепочка — у провайдера, в очереди, в wallet layer или в вашей логике
  4. любой незамеченный лаг превращается в ручные разборы, эскалации и риск неверного зачисления или выплаты

Практически сильное решение обычно состоит из трёх слоёв:

  1. наблюдаемость money pipeline — end-to-end lag, duplicate delivery, queue age, block lag, state anomalies
  2. операционный control layer — quarantine для stuck jobs, escalation rules, runbooks и автоматический запуск reconciliation
  3. implementation layer — dashboard, alert routing, event correlation, tracing и policy-aware monitoring вокруг wallet/exchange workflow

Как сервис или implementation layer здесь обычно имеет смысл делать не «ещё один Grafana dashboard», а прикладной operational контур:

  • unified dashboard для callbacks, deposits, withdrawals и wallet health
  • alerting и escalation rules под реальные бизнес-SLO, а не только под CPU и 500-ки
  • correlation между provider events, internal queue processing и внешними клиентскими уведомлениями
  • auto-remediation hooks: quarantine, retry, reconciliation trigger, maintenance switch
  • журнал инцидентных и подозрительных state transitions для операторов и finance

Именно это превращает monitoring из пассивной картинки в реальный safety layer для money workflows.

Практический стартовый чеклист

Если система уже работает, я бы шёл в таком порядке:

  1. добавить end-to-end event lag метрики
  2. вынести duplicate callbacks и duplicate processing в отдельные counters
  3. повесить alert на queue oldest message age
  4. отдельно мониторить wallet block lag и RPC failures
  5. добавить контроль invalid state transitions
  6. собрать один on-call dashboard вокруг payment pipeline, а не вокруг отдельных контейнеров

Это даёт гораздо более ранний сигнал, чем очередной универсальный dashboard из категории «всё вроде зелёное».

Вывод

В crypto API клиенты редко жалуются на то, что у вас выросла латентность RPC или увеличилась глубина очереди. Они жалуются на пропавший callback, зависший payout, неподтверждённый депозит или странный статус invoice.

Поэтому сильный monitoring в этой области должен смотреть не только на инфраструктуру, а на путь события от входа до финального эффекта.

Когда видно duplicate rate, pipeline lag, возраст очереди, здоровье wallet layer и аномалии state machine, команда начинает ловить проблемы до того, как их заметит клиент. А это и есть тот уровень наблюдаемости, который отличает просто работающий backend от production-grade платёжной платформы.