feat(obs): наблюдаемость Prometheus + Grafana под профилем observability
Раньше видимости в прод не было — только email-монитор (костыль). Добавлено без нагрузки по умолчанию (профиль не поднимается, пока не попросят): - API: /metrics через prometheus-fastapi-instrumentator (кол-во/латентность запросов по хендлерам); - Prometheus (infra/prometheus/prometheus.yml) скрейпит API и Flower — из Flower приходят метрики Celery (задачи, время, воркеры) вообще без доп. кода; - Grafana с автопровижном источника Prometheus (infra/grafana/provisioning), пароль через GRAFANA_ADMIN_PASSWORD; - docker-compose.prod.yml: сервисы prometheus/grafana под profiles:[observability] + volumes; .env.example и README пополнены. Запуск: docker compose --profile observability up -d prometheus grafana. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -39,3 +39,11 @@ SMTP_TLS_VERIFY=true
|
||||
# App
|
||||
APP_URL=https://academic.jze9.ru
|
||||
ENVIRONMENT=development
|
||||
|
||||
# Векторный бэкенд (опционально): faiss (по умолчанию) или qdrant. См. README.
|
||||
VECTOR_BACKEND=faiss
|
||||
QDRANT_URL=http://qdrant:6333
|
||||
QDRANT_COLLECTION=documents
|
||||
|
||||
# Наблюдаемость (профиль observability, опционально)
|
||||
GRAFANA_ADMIN_PASSWORD=admin
|
||||
|
||||
14
README.md
14
README.md
@@ -184,6 +184,20 @@ docker compose -f docker-compose.prod.yml exec worker-gpu python -m app.migrate_
|
||||
docker compose -f docker-compose.prod.yml up -d worker-gpu
|
||||
```
|
||||
|
||||
## Наблюдаемость (Prometheus + Grafana)
|
||||
|
||||
Опционально (профиль `observability`, по умолчанию не поднимается):
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.prod.yml --profile observability up -d prometheus grafana
|
||||
```
|
||||
|
||||
- API отдаёт HTTP-метрики на `/metrics` (кол-во и латентность запросов по хендлерам).
|
||||
- Prometheus (`infra/prometheus/prometheus.yml`) скрейпит API и **Flower** — из
|
||||
Flower приходят метрики Celery (задачи, время выполнения, воркеры) без доп. кода.
|
||||
- Grafana с автоподключённым источником Prometheus (`infra/grafana/provisioning/`);
|
||||
пароль admin — через `GRAFANA_ADMIN_PASSWORD` в `.env` (по умолчанию `admin`).
|
||||
|
||||
## Тестирование и качество кода
|
||||
|
||||
Перед деплоем CI (`.gitea/workflows/deploy.yml`, job `test`) прогоняет два гейта,
|
||||
|
||||
@@ -14,6 +14,8 @@ volumes:
|
||||
es_prod_data:
|
||||
faiss_index_prod:
|
||||
qdrant_prod_data:
|
||||
prometheus_data:
|
||||
grafana_data:
|
||||
|
||||
x-app-env: &app-env
|
||||
env_file: .env
|
||||
@@ -65,6 +67,36 @@ services:
|
||||
- antiplagiator
|
||||
restart: unless-stopped
|
||||
|
||||
# ─── Наблюдаемость (опционально; профиль observability) ────────────────────
|
||||
# docker compose -f docker-compose.prod.yml --profile observability up -d prometheus grafana
|
||||
# Prometheus скрейпит api:/metrics и flower:/metrics (метрики Celery).
|
||||
prometheus:
|
||||
image: prom/prometheus:v2.54.1
|
||||
container_name: antiplagiator-prometheus
|
||||
profiles: ["observability"]
|
||||
volumes:
|
||||
- ./infra/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||
- prometheus_data:/prometheus
|
||||
networks:
|
||||
- antiplagiator
|
||||
restart: unless-stopped
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:11.2.0
|
||||
container_name: antiplagiator-grafana
|
||||
profiles: ["observability"]
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-admin}
|
||||
- GF_USERS_ALLOW_SIGN_UP=false
|
||||
volumes:
|
||||
- ./infra/grafana/provisioning:/etc/grafana/provisioning:ro
|
||||
- grafana_data:/var/lib/grafana
|
||||
networks:
|
||||
- antiplagiator
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- prometheus
|
||||
|
||||
# ─── Приложение ────────────────────────────────────────────────────────────
|
||||
# RabbitMQ вынесен на отдельный сервер 192.168.20.82 (см. RABBITMQ_URL в .env)
|
||||
api:
|
||||
|
||||
10
infra/grafana/provisioning/datasources/prometheus.yml
Normal file
10
infra/grafana/provisioning/datasources/prometheus.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
# Автопровижн источника данных Grafana → Prometheus (профиль observability).
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Prometheus
|
||||
type: prometheus
|
||||
access: proxy
|
||||
url: http://prometheus:9090
|
||||
isDefault: true
|
||||
editable: false
|
||||
20
infra/prometheus/prometheus.yml
Normal file
20
infra/prometheus/prometheus.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
# Prometheus scrape-конфиг (профиль observability в docker-compose.prod.yml).
|
||||
# Скрейпит HTTP-метрики API и Celery-метрики из Flower (Flower 2.0 отдаёт их сам).
|
||||
global:
|
||||
scrape_interval: 30s
|
||||
evaluation_interval: 30s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: prometheus
|
||||
static_configs:
|
||||
- targets: ["localhost:9090"]
|
||||
|
||||
- job_name: api
|
||||
metrics_path: /metrics
|
||||
static_configs:
|
||||
- targets: ["api:8000"]
|
||||
|
||||
- job_name: flower # метрики Celery: задачи, время выполнения, воркеры
|
||||
metrics_path: /metrics
|
||||
static_configs:
|
||||
- targets: ["flower:5555"]
|
||||
@@ -7,6 +7,7 @@ from contextlib import asynccontextmanager
|
||||
from fastapi import Depends, FastAPI, WebSocket, WebSocketDisconnect
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
from prometheus_fastapi_instrumentator import Instrumentator
|
||||
|
||||
from app.api import admin, auth, documents, reports, search, tasks
|
||||
from app.config import settings
|
||||
@@ -80,6 +81,11 @@ app.include_router(documents.router, prefix="/api")
|
||||
app.include_router(reports.router, prefix="/api")
|
||||
app.include_router(admin.router, prefix="/api")
|
||||
|
||||
# ─── Метрики Prometheus ───────────────────────────────────────────────────────
|
||||
# HTTP-метрики (кол-во/латентность запросов по хендлерам) на /metrics.
|
||||
# Prometheus скрейпит их (см. infra/prometheus/prometheus.yml, профиль observability).
|
||||
Instrumentator().instrument(app).expose(app, endpoint="/metrics", include_in_schema=False)
|
||||
|
||||
|
||||
# ─── WebSocket ────────────────────────────────────────────────────────────────
|
||||
@app.websocket("/ws/tasks/{public_id}")
|
||||
|
||||
@@ -16,3 +16,4 @@ minio==7.2.7
|
||||
httpx==0.27.0
|
||||
aiofiles==23.2.1
|
||||
websockets==12.0
|
||||
prometheus-fastapi-instrumentator==7.0.0 # /metrics для Prometheus (профиль observability)
|
||||
|
||||
Reference in New Issue
Block a user