diff --git a/README.md b/README.md index 079ee04..1c772dc 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@
(К началу)
-## Интеграция с системами мониторинга +## Интеграция с системами мониторинга Prometheus и Grafana + +`futriiX` умеет отдавать метрики в формате **Prometheus text exposition**. Это значит, что вы можете: + +- Подключить **Prometheus** как time-series базу и настроить pull-скрейпинг `/metrics`. +- Подключить **Grafana** к Prometheus — и получить дашборды по состоянию кластера, нагрузке, репликации, HTTP-трафику. +- Дополнительно использовать **Grafana JSON API (Infinity) datasource** для запросов к REST API (`/api/cluster/status`, `/api/db/...`) и построения табличных панелей с «сырыми» данными. + +Метрики работают **одинаково на Linux и OpenIndiana (illumos)**: реализация использует только стандартную библиотеку Go (`net/http`, `sync/atomic`, `math`), без внешних зависимостей и без платформо-специфичных syscall'ов. + +### Включение + +В `config.toml`: + +```toml +[metrics] +# Включить экспорт метрик в формате Prometheus +enabled = true +# Интервал сбора метрик в секундах (по умолчанию 15) +collect_interval_sec = 15 +``` + +Если секция отсутствует — метрики отключены (`enabled = false`) и используются дефолты. Если `enabled = true`, но `collect_interval_sec <= 0` — валидатор вернёт ошибку на старте. + +### HTTP endpoints + +После запуска `futriiX` доступны: + +| Endpoint | Назначение | +|---|---| +| `GET /metrics` | Prometheus text exposition (`text/plain; version=0.0.4`). Endpoint **без аутентификации** — так принято в Prometheus-экосистеме, ограничивайте доступ на уровне сети/файрвола. | +| `GET /-/healthy` | Liveness-проба. Всегда `200 OK`, если процесс жив. | +| `GET /api/metrics` | JSON-снимок метрик (rate-limiter, store, cluster). Удобно для Grafana JSON API / Infinity datasource. | + +### Какие метрики отдаются + +**Process:** + +| Метрика | Тип | Описание | +|---|---|---| +| `futriis_up` | gauge | `1`, если процесс работает. | +| `futriis_uptime_seconds` | gauge | Время с момента старта процесса. | + +**Storage:** + +| Метрика | Тип | Labels | Описание | +|---|---|---|---| +| `futriis_storage_databases_total` | gauge | — | Количество баз данных. | +| `futriis_storage_documents_total` | gauge | — | Общее число документов во всех коллекциях. | +| `futriis_database_documents_total` | gauge | `database` | Документов в конкретной БД. | +| `futriis_database_size_bytes` | gauge | `database` | Размер БД в байтах. | + +**Cluster:** + +| Метрика | Тип | Labels | Описание | +|---|---|---|---| +| `futriis_cluster_nodes` | gauge | `status=total\|active\|failed` | Количество узлов по статусам. | +| `futriis_cluster_has_leader` | gauge | — | `1`, если лидер выбран, иначе `0`. | +| `futriis_cluster_health` | gauge | `health` | Метка здоровья (`healthy`/`degraded`/`critical`). | +| `futriis_cluster_raft_term` | gauge | — | Текущий терм Raft. | +| `futriis_node_last_seen_seconds` | gauge | `node_id`, `ip` | Unix-время последнего контакта с узлом (в секундах). | + +**HTTP (middleware на `/api/*`):** + +| Метрика | Тип | Labels | Описание | +|---|---|---|---| +| `futriis_http_requests_total` | counter | `method`, `path`, `status` | Число HTTP-запросов. | +| `futriis_http_request_duration_seconds` | histogram | `method`, `path` | Длительность HTTP-запросов (buckets: 1ms, 5ms, 10ms, 25ms, 50ms, 100ms, 250ms, 500ms, 1s, 2.5s, 5s). | + +**Репликация и backpressure (доступны при использовании соответствующих подсистем):** + +| Метрика | Тип | Описание | +|---|---|---| +| `futriis_replication_total` | counter | Всего операций репликации. | +| `futriis_replication_failed_total` | counter | Неудачных операций репликации. | +| `futriis_backpressure_level` | gauge | Уровень backpressure (0 — нет, 4 — critical). | +| `futriis_migration_tasks` | gauge | Задачи миграции по статусу. | + +### Подключение Prometheus + +Пример `prometheus.yml`: + +```yaml +global: + scrape_interval: 15s + evaluation_interval: 15s + +scrape_configs: + - job_name: futriis + metrics_path: /metrics + static_configs: + - targets: ['futriis-host:8080'] + labels: + cluster: futriis-prod +``` + +Запуск (Docker): + +```sh +docker run --rm -p 9090:9090 \ + -v "$PWD/prometheus.yml:/etc/prometheus/prometheus.yml:ro" \ + prom/prometheus +``` + +Проверка: + +```sh +curl -s http://futriis-host:8080/metrics | head -40 +curl -s http://localhost:9090/api/v1/targets | jq . +``` + +### Подключение Grafana + +1. Откройте Grafana (`http://grafana-host:3000`), войдите под администратором. +2. **Configuration → Data Sources → Add data source** → выберите **Prometheus**. +3. **URL** = `http://prometheus-host:9090`, **Scrape interval** = `15s`, нажмите **Save & Test**. +4. (Опционально) Добавьте второй datasource типа **Infinity** или **JSON API**: + - **Base URL** = `http://futriis-host:8080` + - **Allowed hosts** = `futriis-host` + - **Auth** = none (или включите Basic Auth, если у вас есть reverse-proxy перед futriiX). +5. **Create → Dashboard → Add visualization**: + - Панель «Cluster health» — Prometheus query: `futriis_cluster_nodes{status="active"}`. + - Панель «Documents total» — `futriis_storage_documents_total`. + - Панель «HTTP RPS» — `sum(rate(futriis_http_requests_total[1m])) by (method)`. + - Панель «HTTP p95 latency» — `histogram_quantile(0.95, sum(rate(futriis_http_request_duration_seconds_bucket[5m])) by (le))`. + - Таблица «Databases» — Infinity datasource → GET `/api/cluster/status`. + +### Полезные PromQL-запросы + +```promql +# Кол-во активных узлов +futriis_cluster_nodes{status="active"} + +# Есть ли лидер +futriis_cluster_has_leader + +# Скорость обработки запросов (RPS) +sum(rate(futriis_http_requests_total[1m])) + +# 95-й перцентиль длительности запросов +histogram_quantile(0.95, + sum(rate(futriis_http_request_duration_seconds_bucket[5m])) by (le)) + +# Отношение ошибок (5xx) к общему числу запросов +sum(rate(futriis_http_requests_total{status=~"5.."}[5m])) + / sum(rate(futriis_http_requests_total[5m])) + +# Алерт: нет лидера больше минуты +min_over_time(futriis_cluster_has_leader[1m]) == 0 +``` + +### Пример правил алертинга (Prometheus) + +```yaml +groups: + - name: futriis + rules: + - alert: FutriisDown + expr: futriis_up == 0 + for: 30s + labels: { severity: critical } + annotations: + summary: "futriiX instance is down" + - alert: FutriisNoLeader + expr: min_over_time(futriis_cluster_has_leader[1m]) == 0 + for: 1m + labels: { severity: critical } + annotations: + summary: "futriiX cluster has no elected leader" + - alert: FutriisHighHTTPErrorRate + expr: | + sum(rate(futriis_http_requests_total{status=~"5.."}[5m])) + / sum(rate(futriis_http_requests_total[5m])) > 0.05 + for: 5m + labels: { severity: warning } + annotations: + summary: "futriiX HTTP 5xx rate > 5%" + - alert: FutriisDegraded + expr: futriis_cluster_health{health="degraded"} == 1 + for: 2m + labels: { severity: warning } + annotations: + summary: "futriiX cluster is degraded" +``` + +### Безопасность + +- Endpoint `/metrics` **не требует аутентификации** (по спецификации Prometheus). Рекомендуется: + - не публиковать его в интернет; + - ограничивать доступ по IP/сети (firewall, security group); + - либо ставить reverse-proxy с Basic Auth и отключать встроенный endpoint. +- Endpoint `/api/*` защищён ACL-сессиями (`X-Session-ID` / `Authorization: Bearer ...`). +- Метрики не содержат пользовательских данных — только агрегаты и labels с именами БД/узлов/HTTP-путей. + +### Отключение + +В `config.toml`: + +```toml +[metrics] +enabled = false +``` + +При этом: +- HTTP-endpoint `/metrics` по-прежнему вернёт базовые process-метрики (`futriis_up`, `futriis_uptime_seconds`). +- Периодический сбор и публикация в реестр останавливаются. + +### Диагностика + +| Симптом | Причина | Решение | +|---|---|---| +| `/metrics` возвращает 404 | HTTP-сервер не запустился или не зарегистрировал маршрут | Проверить логи, проверить `cfg.API.Port`; `/metrics` регистрируется всегда. | +| Метрики есть, но только `futriis_up` / `futriis_uptime_seconds` | Коллектор не установлен (`SetMetricsCollector` не вызывался) или `metrics.enabled = false` | Включить `[metrics].enabled = true`; проверить, что `main.go` передаёт коллектор в HTTP-сервер. | +| Метрики не обновляются | Интервал слишком большой, либо коллектор остановлен | Проверить `collect_interval_sec`; посмотреть в логах `Prometheus metrics collector started`. | +| Grafana не видит Prometheus | Неверный URL / network policy | `curl http://prometheus-host:9090/-/healthy`; проверить firewall между Grafana и Prometheus. |