Four Golden Signals
Це концепція з книги “Site Reliability Engineering” (Google SRE Book).
Основна ідея: замість того щоб моніторити все підряд (сотні метрик), фокусуйся лише на тому, що безпосередньо відображає досвід користувача.
1. Latency — час відповіді
Час обробки запиту від отримання до відповіді.
Важливо розділяти успішні запити від помилкових — помилка за 1ms не означає що система швидка.
Треба трекати перцентилі, а не середнє — середнє приховує аномалії:
| Перцентиль | Що показує |
|---|---|
| p50 | Медіана — “типовий” користувач |
| p95 | 95% запитів вкладаються в цей час |
| p99 | Найгірший досвід 1% користувачів |
Точний (наївний) спосіб — O(n log n)
N = 1000 запитів
1. Сортуємо масив значень → O(n log n)
2. p95 → позиція ceil(0.95 * 1000) = 950-те значення у сортованому масиві
3. p99 → позиція ceil(0.99 * 1000) = 990-те значення
2. Traffic — навантаження на систему
Міра того, скільки “роботи” зараз виконує система.
| Компонент | Метрика |
|---|---|
| HTTP API | RPS (requests per second) |
| Proxy (Squid/HAProxy) | Connections/s, bandwidth MB/s |
| База даних | Transactions/s, queries/s |
Без Traffic інші метрики втрачають сенс — ти не знаєш чому щось змінилось.
Приклади кореляції:
- Errors зросли з 10 до 100? — Якщо трафік теж зріс в 10 разів, це нормально. Якщо трафік той самий — alarm.
- Latency збільшилась? — Може просто прийшов spike навантаження.
3. Errors — частота помилок
Частота запитів, що завершились помилкою:
- Явні: HTTP 5xx, таймаути
- Неявні: відповідь 200, але з некоректним вмістом
4. Saturation — насиченість ресурсів
Наскільки ресурс вичерпаний — не просто “скільки використовується”, а скільки ще залишилось.
Ключова відмінність від utilization:
Utilization 80% CPU → є запас, система справляється
Saturation → є черга задач, що чекають на CPU → система вже деградує
Saturation — це випереджувальний сигнал. Система ще не падає, але вже “захлинається”.
Що моніторити
| Ресурс | Метрика насиченості |
|---|---|
| CPU | Load average / run queue length |
| RAM | Swap usage, OOM events |
| Disk | I/O queue depth, await time |
| Network | Interface errors, drops, TX queue |
| HAProxy | Connections queue (qcur) |
| Squid | File descriptors usage |
# HAProxy — черга з'єднань (якщо > 0 — вже saturation)
haproxy_backend_current_queue
# Linux — disk I/O saturation
node_disk_io_time_weighted_seconds_total # "pressure"
Навіщо: Це єдиний сигнал, який дає попередження до того, як система впаде. Latency і Errors — це вже наслідок. Saturation — це причина, яку ти бачиш раніше.
Як вони пов’язані між собою
Traffic зростає
↓
Saturation починає рости (ресурси заповнюються)
↓
Latency починає рости (черги, wait time)
↓
Errors починають рости (таймаути, відмови)
↓
Користувач відчуває деградацію
Ідеальний алерт — спрацював на Saturation, ти виправив до того, як дійшло до Errors.
Error Budget — скільки можна “ламати” систему
Чотири золотих сигнали кажуть що міряти. Error budget каже скільки поганого допустимо, перш ніж це стане проблемою — і це той інструмент, який перетворює “errors зросли” на конкретне управлінське рішення (деплоїти далі чи зупинятись).
SLI / SLO / SLA — три різні речі
| Термін | Що це | Приклад |
|---|---|---|
| SLI (Indicator) | Метрика, яку реально вимірюєш | “% запитів з latency < 300ms” |
| SLO (Objective) | Внутрішня ціль для SLI на період | “99.9% успішних запитів за rolling 30 днів” |
| SLA (Agreement) | Контрактне зобов’язання перед клієнтом | “99.5% uptime, інакше — компенсація” |
SLA зазвичай слабший за SLO — щоб був буфер на помилку і не платити штрафи за кожен внутрішній інцидент.
Error budget — формула
Error budget = 1 - SLO
Приклад на твоєму масштабі (фліт проксі-серверів):
SLO = 99.9% успішних запитів за 30 днів
Трафік: ~50,000,000 запитів/місяць
Error budget = 50,000,000 * (1 - 0.999) = 50,000,000 * 0.001 = 50,000 запитів
Це означає: тобі "дозволено" мати до 50,000 невдалих запитів за місяць,
перш ніж SLO буде порушено.
Burn rate — швидкість “спалювання” бюджету
burn_rate = (фактичний error rate) / (допустимий error rate, тобто 1 - SLO)
Продовження прикладу: ми на 10-й день із 30. При рівномірному (1x) спалюванні бюджету мало б бути використано 10/30 = 33% бюджету = 16,667 невдалих запитів. Фактично вже маємо 40,000.
burn_rate = 40,000 / 16,667 ≈ 2.4x
Висновок: ми спалюємо бюджет у 2.4 рази швидше за "стійкий" темп.
Якщо так продовжиться — бюджет на місяць скінчиться значно раніше дня 30.
burn_rate = 1x → бюджету акурат вистачить до кінця періоду. burn_rate = 10x → весь місячний бюджет згорить за ~3 дні.
Multi-window, multi-burn-rate алертинг
Класична проблема: алерт лише на “% помилок > X” або весь час шумить на коротких сплесках, або реагує занадто пізно на повільне виснаження бюджету. Рішення — кілька алертів з різними вікнами й порогами burn rate:
| Рівень | Burn rate | Вікно спостереження | За скільки згорить весь бюджет | Дія |
|---|---|---|---|---|
| 🔴 Критичний | 14.4x | 1h (підтвердження 5m) | ~2 дні | Page on-call негайно |
| 🟡 Помірний | 6x | 6h (підтвердження 30m) | ~5 днів | Ticket, розслідувати протягом дня |
| 🔵 Інфо | 1x | 3 дні (підтвердження 6h) | ~30 днів (весь бюджет) | Завести задачу, не терміново |
Навіщо так складно: короткий burn-rate алерт ловить швидкі інциденти (типу OOM), а довгий — повільну деградацію, яку не побачиш на 5-хвилинному вікні (наприклад, повільний memory leak, що накопичується тижнями).
Чому це корисно операційно
Error budget перетворює суб’єктивну дискусію “можна деплоїти чи ні” на число:
- Бюджет ще є → команда може ризикувати: нові фічі, експериментальні rollout’и, ризиковані миграції (типу твого переходу на native HAProxy exporter).
- Бюджет вичерпано → release freeze, фокус тільки на стабільність, поки бюджет не “відновиться” в наступному вікні.