Опирается на правила: R-OBS-SLO-1R-OBS-SLO-4 и R-OBS-SLO-X1R-OBS-SLO-X3 из Observability Style Guide → раздел 7. SLO и алерты.

Важно знать

  • Каждый critical-endpoint имеет SLO (например, 99.9% successful + p95 < 500ms на rolling 30-day window).
  • Multi-window multi-burn-rate alerts по Google SRE Workbook: fast burn (1h, rate > 14.4) и slow burn (6h, rate > 6).
  • Error budget: 99.9% target = 43 минуты downtime/month как бюджет. 100% — нечем оперировать.
  • Алерт на исчерпание бюджета (< 10%) → команда переключается с features на reliability.
  • Алерты отдельные от SLO: infra (JVM heap, HikariCP saturation), domain (бизнес-фейлы), Resilience (CB open), Kafka lag, cache hit rate.
  • Alert на каждый ERROR → fatigue → команда игнорирует. Фильтр: повторяющиеся группируются, единичные не алертят.
  • Каждый alert имеет runbook. PagerDuty в 3 ночи без инструкции — эскалация без действия.

SLO (Service Level Objective) — это обещание уровню обслуживания, который сервис даёт пользователям. Не «всё всегда работает», а «99.9% запросов успешны в течение 30-day window». Разница принципиальная: появляется error budget, появляется возможность приоритизации reliability vs features.

SLO для critical endpoints

R-OBS-SLO-1: для каждого critical-endpoint — две метрики.

EndpointAvailability SLOLatency SLO
POST /orders99.9% non-5xxp95 < 500ms
POST /payments99.95% non-5xxp95 < 1s
GET /orders/{id}99.95% non-5xxp95 < 200ms
GET /search?q=99.5% non-5xxp95 < 800ms

Бизнес выбирает target вместе с product owner: «сколько вы готовы платить за дополнительную девятку?». 99.99% (52 мин/год) на порядок дороже 99.9% (8.7 ч/год) — другая архитектура, другая инфра.

Расчёт SLI (Service Level Indicator) в Prometheus:

# Availability SLI
sum(rate(http_server_requests_seconds_count{uri="/orders",method="POST",status!~"5.."}[30d]))
  /
sum(rate(http_server_requests_seconds_count{uri="/orders",method="POST"}[30d]))

# Latency SLI
histogram_quantile(0.95,
  sum by (le) (rate(http_server_requests_seconds_bucket{uri="/orders",method="POST"}[30d]))
)

Multi-window multi-burn-rate

R-OBS-SLO-2: классический подход SRE Workbook chapter 5.

Идея: SLO 99.9% даёт error budget 0.1% за 30 дней. Если за 1 час расходуется 5% бюджета — это быстрое сжигание, при таком темпе бюджет кончится за 20 часов. Это алерт.

Формула burn rate:

burn_rate = (error_rate_in_window) / (1 - SLO_target)

Для SLO 99.9% и window 1h:

  • burn rate > 14.4 → 5% бюджета сгорает за 1 час
  • burn rate > 6 (window 6h) → 5% бюджета сгорает за 6 часов
  • burn rate > 1 (window 24h) → нормальная скорость
- alert: OrdersSloFastBurn
  expr: |
    (
      sum(rate(http_server_requests_seconds_count{uri="/orders",method="POST",status=~"5.."}[1h]))
      /
      sum(rate(http_server_requests_seconds_count{uri="/orders",method="POST"}[1h]))
    ) > (14.4 * (1 - 0.999))
  for: 2m
  annotations:
    runbook: https://runbooks.internal/orders-slo-fast-burn

- alert: OrdersSloSlowBurn
  expr: |
    (
      sum(rate(http_server_requests_seconds_count{uri="/orders",method="POST",status=~"5.."}[6h]))
      /
      sum(rate(http_server_requests_seconds_count{uri="/orders",method="POST"}[6h]))
    ) > (6 * (1 - 0.999))
  for: 15m
  annotations:
    runbook: https://runbooks.internal/orders-slo-slow-burn

Fast burn будит ops немедленно — потенциальный outage. Slow burn создаёт ticket — деградация, не критичная, но требует разбора.

Error budget exhaustion

R-OBS-SLO-3: отдельный алерт на остаток бюджета.

# Сколько бюджета осталось (0 = весь израсходован, 1 = весь свободен)
1 - (
  (1 - <availability_sli_30d>) / (1 - <slo_target>)
)

Алерт если < 10%:

- alert: OrdersErrorBudgetExhausted
  expr: <budget_remaining_expression> < 0.1
  for: 1h
  annotations:
    summary: "Только 10% error budget осталось"
    description: |
      Команда переключается с features на reliability.
      Релизы рискованных изменений приостановлены до восстановления бюджета.

Это не «срочно чинить ночью», а сигнал бизнесу: следующий месяц команда фокусируется на устойчивости.

Алерты отдельные от SLO

R-OBS-SLO-4: SLO — про user-facing успешность. Есть отдельные категории алертов.

КатегорияМетрикаДействие
Infrastructurejvm_memory_used / max > 0.85, hikaricp_connections_pending > 0SRE: scale, tune
Domainorder_failed_total rate > 100/minProduct: что-то изменилось в данных
Resilienceresilience4j_circuitbreaker_state{state="open"}внешний сервис недоступен
Cachecache_hits / (hits+misses) < 0.7tune TTL / size
Kafka consumer lagkafka_consumer_lag_max > 10000scale consumers

Эти алерты не обязательно нарушают SLO — но дают раннее предупреждение. Resilience CB open → запросы уходят на fallback → SLO ещё в норме, но проблема назревает.

Что запрещено

Alert на каждый ERROR

R-OBS-SLO-X1: главная причина alert fatigue.

Сценарий: каждый log.error(...) → алерт. Один client пытается за минуту 1000 раз с невалидным payload → 1000 ERROR → 1000 алертов → команда мьютит канал → пропускает реальный инцидент.

Группировка / фильтрация на уровне alerting:

  • ERROR одного класса (ValidationException) повторяющийся 100 раз/мин → один алерт с count.
  • Единичные ValidationException — не алерт (это нормальный flow для bad input).
  • ServiceUnavailableException повторяющийся → один алерт с указанием external system.
- alert: HighErrorRate
  expr: sum by (exception) (rate(app_errors_total[5m])) > 1
  for: 5m
  annotations:
    runbook: https://runbooks.internal/high-error-rate

SLO без error budget

R-OBS-SLO-X2: 100% target — это обещание не ошибаться никогда, что невозможно.

  • Каждая ошибка → нарушение → срочно чинить.
  • Команда боится релизов («любая регрессия = инцидент»).
  • Не остаётся ресурса на reliability-work.

99.9% даёт 43 минуты downtime/month как «легально потраченный» бюджет — раз в неделю можно потерпеть короткую деградацию ради рискованного релиза.

99.99% (52 мин/год) — намного дороже: multi-region active-active, immediate failover, отдельная инфра. Бизнес выбирает осознанно.

Алерты без runbook'ов

R-OBS-SLO-X3: PagerDuty в 3 ночи будит дежурного. Алерт: «p95 latency на /orders > 1s».

Без runbook:

  • Дежурный открывает Grafana.
  • Не знает, кому звонить.
  • Не знает, что трогать.
  • Эскалирует тимлиду → тимлиду эскалация в 3 ночи без контекста.

С runbook (https://runbooks.internal/orders-latency-high):

  1. Проверить hikaricp_connections_pending — если > 0, scale up DB или приложение.
  2. Проверить external_calls_duration_seconds{system="payment-provider"} — если > 2s, есть инцидент у payment, ack and wait.
  3. Если ни 1 ни 2 — escalate to #order-service-oncall.

Runbook — обязательная часть каждого алерта.

Что запрещено — таблица

АнтипаттернПравилоЧто взамен
Alert на каждый ERROR в логахR-OBS-SLO-X1group by exception, rate threshold
SLO 100% targetR-OBS-SLO-X299.9% (43m/mo) или 99.95% / 99.99%
Алерт без runbook URLR-OBS-SLO-X3annotations.runbook ссылка обязательна
Один универсальный алерт «что-то сломалось»R-OBS-SLO-4категории: infra / domain / resilience / SLO burn
Burn rate window 30d без short windowR-OBS-SLO-2multi-window: 1h fast + 6h slow
Латентность SLO без percentileR-OBS-SLO-1p95 или p99, не avg
Alert на metric «когда-то превысила» (без for:)R-OBS-SLO-2for: 2m (fast) / for: 15m (slow)

Куда дальше