Моніторинг Solana-застосунку в production відрізняється від локального дебагу тим, що ви не контролюєте ноду, не бачите внутрішніх логів валідатора і залежите від зовнішніх RPC-провайдерів. Тому інфраструктура спостереження має будуватися навколо трьох незалежних площин: метрики вашого бекенду, телеметрія від RPC-провайдера та стан вашого індексатора. Нижче — покрокова схема, яку можна адаптувати під конкретний стек.
Метрики для моніторингу: успішність транзакцій, затримки
Перш ніж будувати дашборди, визначте, які саме сигнали свідчать про здоров'я вашого застосунку. Для Solana-програм це дві ключові групи метрик: успішність транзакцій (transaction success rate) та затримки (latency) на кожному етапі обробки.
Успішність транзакцій. Не обмежуйтеся одним лічильником «успіх/невдача». Розрізняйте причини відмов за кодами помилок, які повертає RPC:
- Pre-flight failure — транзакція не пройшла симуляцію (недостатній баланс, невірна структура інструкції, слот вже минув). Це означає помилку в бізнес-логіці вашого клієнта, а не проблему мережі.
- TransactionError — транзакція пройшла симуляцію, але впала під час виконання (наприклад, помилка в Anchor-програмі, невірний PDA, порушення умов). Відстежуйте конкретні error code з логів програми.
- BlockhashNotFound — транзакція не потрапила в блок протягом часу життя blockhash. Це сигнал про перевантаження мережі або проблеми з підключенням до RPC.
- Timeout — ваш бекенд не отримав відповідь від RPC за встановлений ліміт. Це проблема інфраструктури, а не програми.
Затримки. Вимірюйте три окремі інтервали:
- Pre-flight latency — час від відправки запиту
simulateTransactionдо отримання результату. Нормальний діапазон залежить від складності транзакції, але різкий ріст свідчить про проблеми з RPC або перевантаження кластера. - Confirmation latency — час від відправки
sendTransactionдо отримання підтвердження (commitment levelconfirmed). Зазвичай це 400–800 мс за нормальних умов. - Finalization latency — час до досягнення
finalizedстатусу. Теоретично це може тривати до кількох секунд, але якщо стабільно перевищує 2–3 секунди — кластер деградує.
Передумови: ваш бекенд має експортувати метрики у форматі Prometheus. Якщо ви використовуєте Node.js — підійде бібліотека prom-client, для Rust — metrics з експортером у Prometheus.
Очікуваний результат: після налаштування ви бачите окремі таймсерії для кожного типу помилки та кожного етапу затримки, а не один агрегований «середній час транзакції».
Налаштування Grafana дашборду
Створіть окремий дашборд з трьома рядами панелей.
Перший ряд — throughput та успішність:
- Панель «Транзакції за хвилину» (TPM): загальна кількість відправлених транзакцій, розділена за статусом (success / pre-flight fail / runtime error / timeout).
- Панель «Success rate %»: відношення успішних транзакцій до загальної кількості за останні 5 хвилин. Не використовуйте середнє за годину — це замаскує різкі спади.
Другий ряд — затримки:
- Три панелі з графіками p50, p95 та p99 для кожного етапу (pre-flight, confirmation, finalization). Percentile p99 важливіший за середнє, оскільки саме він відображає досвід найгірших користувачів.
- Панель «Blockhash age at send» — час між отриманням blockhash і моментом відправки транзакції. Якщо цей показник стабільно росте, ваш бекенд не встигає збирати транзакції в блок.
Третій ряд — контекст мережі:
- Панель «Current slot» з відображенням слота, який повертає ваш RPC. Додайте другий рядок зі слотом з публічного ендпоінту (наприклад,
api.mainnet-beta.solana.com) для порівняння. Різниця понад 10 слотів означає, що ваш RPC відстає. - Панель «Slot skip rate» — частота пропусків слотів, якщо ваш провайдер надає цю метрику.
Ризик: якщо ви використовуєте один Prometheus-сервер для кількох проєктів, високий кардиналітет метрик (унікальні комбінації error code × endpoint × program_id) може перевантажити пам'ять. Обмежте кількість міток: залиште error_type, rpc_endpoint та commitment, але не додавайте tx_signature або account_key як мітки — ці дані належать у логи.
Алерти на критичні події
Налаштуйте алерти за такими правилами, перевірені на практиці:
| Алерт | Умова | Серйозність | Рекомендована дія |
|---|---|---|---|
| Success rate drop | Success rate < 95% за 5 хвилин | Critical | Перевірити типи помилок на дашборді, визначити, чи це проблема програми чи мережі |
| Confirmation latency spike | p95 confirmation > 3 с за 5 хвилин | Warning | Перевірити стан кластера та слот-лаг вашого RPC |
| RPC timeout rate | Timeouts > 5% від усіх запитів за 3 хвилини | Critical | Перемкнути трафік на резервний RPC-ендпоінт |
| Slot lag | Різниця слотів між вашим RPC і референсним > 20 | Warning | Зв'язатися з провайдером, тимчасово перемкнути на інший ендпоінт |
| Pre-flight failure spike | Pre-flight fails > 30% за 3 хвилини | Warning | Перевірити, чи не змінилася версія програми на мережі, чи не оновилися акаунти |
Важливо: не налаштовуйте алерт на абсолютне значення TPM — воно природно коливається залежно від часу доби та активності користувачів. Алертуйте на відносні зміни (відсоток помилок, percentile затримок), а не на абсолютні числа.
Збір логів з RPC-провайдерів
Ви не маєте прямого доступу до логів валідатора, але більшість комерційних RPC-провайдерів надають власні панелі з метриками їхньої інфраструктури. Проте цього недостатньо — вам потрібні логи саме ваших запитів і відповідей на стороні вашого бекенду.
Що логувати на стороні бекенду:
- Кожен вихідний RPC-запит: метод (
sendTransaction,getAccountInfo,simulateTransaction), розмір payload, timestamp. - Кожну відповідь: HTTP-статус, тіло відповіді (обрізане для
getAccountInfo, повне для помилок), час відповіді. - Контекст транзакції: signature (після відправки), blockhash, використаний commitment level, ідентифікатор RPC-ендпоінту.
Що не логувати: повне тіло транзакції в base64 для кожного успішного запиту — це створить величезний обсяг даних без практичної цінності. Зберігайте повне тіло лише для транзакцій, що впали, і обмежте ретенцію такими даними до 24–48 годин.
Практична схема збору:
- Оберніть кожен RPC-виклик у middleware, який фіксує стартовий timestamp, метод та ідентифікатор ендпоінту.
- Після отримання відповіді запишіть статус, час виконання та (у разі помилки) повне тіло відповіді.
- Для транзакцій додайте окремий крок: після відправки запишіть signature, а після отримання підтвердження — фінальний статус і повний час циклу.
- Виводьте логи у структурованому форматі (JSON) до stdout, щоб їх міг забирати ваш log-агрегатор (Fluentd, Vector, Logstash).
Ризик: при високому TPM (тисячі транзакцій за хвилину) обсяг логів може перевищити пропускну здатність log-агрегатора. Мітрікуйте самі логи: рахуйте кількість рядків на секунду, що надсилає кожен інстанс бекенду, і налаштуйте алерт на різке зростання.
Перевірка: після розгортання відправте тестову транзакцію, що навмисно впаде (наприклад, з невірним PDA), і переконайтеся, що в вашому log-агрегаторі з'явився запис із повним тілом помилки та контекстом.
Відкат: якщо логування перевантажує бекенд, додайте прапорець конфігурації для зниження рівня деталізації (наприклад, логувати лише помилки та p99 затримки) без перерозгортання.
Моніторинг стану індексатора
Якщо ваш застосунок використовує індексатор (Yellowstone Geyser, Helius WebSocket, власний gRPC-підписник з PostgreSQL), його стан критичний — без актуальних даних ваш бекенд приймає рішення на основі застарілої інформації.
Ключові метрики індексатора:
- Slot lag індексатора — різниця між останнім обробленим слотом і поточним слотом кластера. Це найважливіша метрика. Нульовий лаг означає синхронізацію в реальному часі; лаг у 100+ слотів означає, що ваш застосунок працює з даними, які відстають на 400+ мілісекунд.
- Blocks processed per second — швидкість обробки блоків. Якщо цей показник падає нижче 0.6–0.7 (приблизно 2 блоки на 3 секунди), індексатор не встигає за кластером.
- Account update queue depth — розмір черги оновлень акаунтів, які ще не записані в базу даних. Ріст цієї черги свідчить про вузьке місце на етапі запису (зазвичай — база даних).
- Database connection pool utilization — якщо ви використовуєте PostgreSQL, відстежуйте кількість активних з'єднань відносно ліміту пулу. 100% використання означає, що нові запити на запис будуть блокуватися.
- gRPC/WebSocket reconnect count — кількість перепідключень до джерела даних за останню годину. Часті реконекти свідчать про нестабільність мережевого з'єднання або проблеми на боці провайдера.
Специфіка Yellowstone Geyser: якщо ви використовуєте плагін Geyser для підписки на оновлення, відстежуйте метрики самого плагіна (якщо вони доступні через вашого провайдера) — кількість оброблених слотів, розмір внутрішньої черги повідомлень, кількість відкинутих оновлень через переповнення буфера.
Перевірка цілісності даних: періодично (наприклад, кожну хвилину) виконуйте прямий RPC-запит getAccountInfo для кількох ключових акаунтів і порівнюйте результати з даними в вашій індексованій базі. Розбіжність у lamports або data — критичний сигнал, що індексатор пропустив оновлення або записав його некоректно.
Очікуваний результат: ви бачите окремий дашборд індексатора з графіком slot lag (має бути близьким до нуля), throughput обробки блоків та станом черг і пулів з'єднань.
Ризик: індексатор може «тихо» відставати без видимих помилок — усі запити успішні, але дані застарілі. Тому алерт на slot lag є обов'язковим, навіть якщо інші метрики виглядають нормально.
План реагування на деградацію
Коли алерт спрацював, команда має діяти за заздалегідь підготованим планом, а не імпровізувати. Нижче — структура runbook, яку треба адаптувати під ваш стек.
Крок 1. Ізоляція проблеми (перші 2–3 хвилини).
- Відкрийте дашборд метрик і визначте площину: це проблема нашої програми (зростання pre-flight fails), проблема RPC (зростання timeout, slot lag) чи проблема індексатора (зростання slot lag індексатора при нормальному RPC)?
- Перевірте статус кластера на
explorer.solana.comабо через публічний RPC — чи не має глобальної деградації.
Крок 2. Перемикання RPC (якщо проблема в провайдері).
- Якщо ваш бекенд підтримує кілька RPC-ендпоінтів, перемкніть трафік на резервний. Це має бути автоматизоване через circuit breaker: при досягненні порогу timeout або error rate нові запити йдуть на наступний ендпоінт у списку.
- Якщо автоматичного перемикання немає, змініть ендпоінт у конфігурації та перезапустіть бекенд (або використовуйте hot-reload конфігурації, якщо він підтримується).
- Зафіксуйте час перемикання — це важливо для постмортему.
Крок 3. Деградація функціональності (якщо проблема глобальна).
- Якщо весь кластер перевантажений, перемикання RPC не допоможе. У цьому випадку переведіть застосунок у режим пониженої функціональності: призупиніть некритичні операції (наприклад, періодичне оновлення кешу, фонові агрегації), залишивши лише критичний шлях користувача.
- Якщо ваш застосунок дозволяє, збільште timeout для confirmation і тимчасово перейдіть з
confirmedнаprocessedcommitment для зменшення навантаження на RPC.
Крок 4. Робота з індексатором (якщо він відстає).
- Якщо slot lag індексатора зростає, перевірте метрики бази даних та черг. Якщо проблема у базі — збільште пул з'єднань або тимчасово призупиніть некритичні читання.
- Якщо лаг перевищує 500 слотів і не зменшується, розгляньте перезапуск індексатора з останнього збереженого слота. Це призведе до пропуску оновлень за час лагу, але поверне систему в синхронний стан.
- Після відновлення запустіть процедуру перевірки цілісності (порівняння з прямими RPC-запитами) для ключових акаунтів.
Крок 5. Комунікація та постмортем.
- Якщо деградація тривала понад 15 хвилин і вплинула на користувачів, поінформуйте їх через наявні канали.
- Після відновлення проведіть постмортем: зафіксуйте хронологію, кореневу причину, час реагування на кожен етап та конкретні дії для запобігання повторенню.
Відкат: якщо після перемикання RPC або зміни конфігурації ситуація погіршилася, поверніть попередню конфігурацію з репозиторію (використовуйте версіоновані конфігураційні файли, а не ручні зміни на сервері). Якщо проблема в оновленні програми на мережі — перевірте, чи не було нещодавнього розгортання, і за потреби відкотіть програму до попередньої версії (за умови, що вона залишається на мережі як окремий executable).
Межі застосування: цей план охоплює моніторинг та реагування на рівні застосунку та його інфраструктури (бекенд, індексатор, RPC-клієнт). Він не стосується експлуатації валідатора — для цього існує окремий інструментарій та процедури.