This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
| Файлы | MinIO (S3-совместимое хранилище) |
|
||||
| Фронтенд | Vue 3 + Vite + Tailwind |
|
||||
| Межсервисно | gRPC + Protobuf (mTLS — за флагом `DEAL_MTLS_*`, §10/§13.8) |
|
||||
| Наблюдаемость | Serilog (JSON: консоль + rolling-файл) → Promtail → Loki → Grafana; метрики OTel → Prometheus → Grafana |
|
||||
| Наблюдаемость | Serilog (JSON: консоль + rolling-файл) → Promtail → Loki → Grafana; метрики OTel → Prometheus; трейсы OTel → Collector → Tempo; ресурсы cAdvisor/node-exporter → Prometheus; единый UI — Grafana |
|
||||
| Прокси/edge | Caddy (TLS, security-заголовки); Cloudflare/k8s — вне этапа (§10/§11) |
|
||||
| Контейнеры | Docker / docker compose (VPS); k8s — позже |
|
||||
| Бэкапы | Ежедневные: pg_dump + MinIO + сессии |
|
||||
@@ -236,7 +236,9 @@ settings(Key varchar(200) PK, ValueJson text, UpdatedAt timestamptz) --
|
||||
(нужен `DEAL_GRAFANA_ADMIN_PASSWORD` в `.env.prod`; порты Grafana/Prometheus — только loopback). Остановка —
|
||||
`docker compose -f deploy/compose.prod.yml --profile observability down`.
|
||||
- **Провижининг Grafana — как код** (`deploy/observability/grafana/provisioning`, монтируется в
|
||||
контейнер): `datasources/datasources.yml` — датасорс Loki (uid `loki`, URL `http://loki:3100`);
|
||||
контейнер): `datasources/datasources.yml` — датасорсы Loki (uid `loki`, default), Prometheus
|
||||
(uid `prometheus`) и Tempo (uid `tempo`); у Loki — `derivedFields` TraceID → Tempo (клик по traceId
|
||||
в логе открывает трейс), у Tempo — `tracesToLogsV2` → Loki и `serviceMap`/`nodeGraph` по метрикам;
|
||||
`dashboards/dashboards.yml` — папка `Дейл` из `/var/lib/grafana/dashboards`. Дашборды — файлы
|
||||
`deploy/observability/grafana/dashboards/*.json`: правки только в репозитории, UI-изменения не
|
||||
сохраняются (`allowUiUpdates: false`).
|
||||
@@ -251,7 +253,10 @@ settings(Key varchar(200) PK, ValueJson text, UpdatedAt timestamptz) --
|
||||
access-лога core) и активация инвайтов (`/api/join`);
|
||||
- `Deal-Errors` — HTTP 5xx, необработанные исключения (`@x`), Error/Fatal, ошибки gRPC и общая лента;
|
||||
- `Deal-Rps` — нагрузка HTTP+gRPC (RPS), top-путей/методов и p50/p95 длительности запроса;
|
||||
- `Deal-Logs` — обзор логов с фильтрами по сервису и уровню, активность по тенантам (AI/ML/Telegram).
|
||||
- `Deal-Logs` — обзор логов с фильтрами по сервису и уровню, активность по тенантам (AI/ML/Telegram);
|
||||
- `Deal-Traces` — поиск трейсов (Tempo, TraceQL), спаны по сервисам, переход к логам по traceId;
|
||||
- `Deal-Resources` — потребление ресурсов контейнерами (cAdvisor) и хостом (node-exporter): CPU/RAM,
|
||||
свободное место на дисках.
|
||||
**Актор в логах:** с BL-LOG-ACTOR access-лог включает `actor` (login пользователя/оператора) и
|
||||
`tenant`; полная лента действий с деталями — `public.audit_log` (append-only) через
|
||||
`GET /api/operator/audit` / экран «Аудит» оператор-консоли.
|
||||
@@ -295,9 +300,36 @@ settings(Key varchar(200) PK, ValueJson text, UpdatedAt timestamptz) --
|
||||
`deal_ml_outbox_depth`), пропажа метрик ядра (`absent(deal_sessions_active)`). Замечание: правила
|
||||
бюджета токенов нет — метрика бюджета в Prometheus отсутствует (см. §6/§10), поэтому алерт не вводится.
|
||||
- Как поднять/проверить: `docker compose --env-file deploy/.env.prod -f deploy/compose.prod.yml
|
||||
--profile observability up -d` → Prometheus `/targets` (все 4 UP) → Grafana → папка «Дейл» →
|
||||
`Deal-Metrics-Overview`. Быстрая проверка экспортёра без Grafana: `curl http://<процесс>:9464/metrics`
|
||||
изнутри сети.
|
||||
--profile observability up -d` → Prometheus `/targets` (все UP) → Grafana → папка «Дейл» →
|
||||
`Deal-Metrics-Overview`/`Deal-Resources`/`Deal-Traces`. Быстрая проверка экспортёра без Grafana:
|
||||
`curl http://<процесс>:9464/metrics` изнутри сети.
|
||||
|
||||
### Трейсы (OpenTelemetry Collector + Tempo)
|
||||
|
||||
- **Экспорт из 5 процессов**: OpenTelemetry SDK → OTLP → **OpenTelemetry Collector** (`otel-collector:
|
||||
4317`) → **Tempo** (`tempo:4317`, хранилище трейсов, retention 7 суток). Настройка — общая в
|
||||
`Deal.Grpc.Hosting` (`DealTracingHosting`) для telegram/ai/ml/storage и `Deal.Api/Observability/
|
||||
DealTracingHosting.cs` для ядра. Инструментируется входящий HTTP/gRPC (AspNetCore), исходящие
|
||||
HTTP-клиенты и gRPC-клиенты (GrpcNetClient) — трейсы сквозные от входа до БД/внешних сервисов.
|
||||
- **Включение — через env** `OTEL_EXPORTER_OTLP_ENDPOINT` (адрес коллектора, напр.
|
||||
`http://otel-collector:4317`); без него трейсинг выключен (коллектор не задан — dev без профиля
|
||||
`observability`). Имя сервиса в трейсах — `OTEL_SERVICE_NAME` (дефолт по процессу: `core`,
|
||||
`telegram-service`, `ai-service`, `ml-service`, `storage-service`).
|
||||
- **Корреляция с логами**: Serilog обогащается `TraceId`/`SpanId` из `Activity.Current`
|
||||
(`TraceContextEnricher`) — в Loki-логе есть `TraceId`, а датасорс Loki `derivedFields` даёт переход
|
||||
из лога в трейс Tempo (и обратно — `tracesToLogsV2`).
|
||||
- Сервисы профиля: `otel-collector` (`otel/opentelemetry-collector-contrib:0.160.0`, конфиг
|
||||
`deploy/observability/otel-collector.yml`) и `tempo` (`grafana/tempo:2.8.1`, конфиг
|
||||
`deploy/observability/tempo.yml`, volume `deal_tempo_data`). Наружу порты не публикуются (dev — для отладки).
|
||||
|
||||
### Ресурсы (cAdvisor + node-exporter)
|
||||
|
||||
- **cAdvisor** (`gcr.io/cadvisor/cadvisor:v0.52.1`) — потребление ресурсов **контейнерами**
|
||||
(CPU/RAM/сеть/диск); **node-exporter** (`prom/node-exporter:v1.9.1`) — ресурсы **хоста** (CPU/RAM/
|
||||
диски/сеть). Оба scrape'ит Prometheus (jobs `cadvisor`, `node-exporter` в `prometheus.yml`).
|
||||
- Дашборд `Deal-Resources` (uid `deal-resources`): CPU/RAM контейнеров, CPU/RAM хоста, свободное место
|
||||
на дисках. Алерты группы `deal-resources` (`prometheus-rules.yml`): высокая загрузка CPU/памяти
|
||||
хоста, мало места на диске, приближение контейнера к лимиту CPU/памяти.
|
||||
|
||||
---
|
||||
|
||||
@@ -333,7 +365,8 @@ settings(Key varchar(200) PK, ValueJson text, UpdatedAt timestamptz) --
|
||||
- `core` (:5080 http + :5082 gRPC-ингресс), `telegram/ai/ml-service` (mTLS-env, Ruling 6),
|
||||
`postgres`/`minio` **без host-портов**; healthcheck'и — `grpc_health_probe` (при mTLS — TLS-проба с
|
||||
PEM `deal-client.crt/.key`)/`pg_isready`.
|
||||
- Профиль `observability`: `loki`/`promtail`/`grafana` + `prometheus` (метрики — этап 12, пакет A; см. §7).
|
||||
- Профиль `observability`: `otel-collector`/`tempo` (трейсы), `loki`/`promtail` (логи),
|
||||
`prometheus`/`cadvisor`/`node-exporter` (метрики и ресурсы), `grafana` (UI); см. §7.
|
||||
Секреты — только из `.env.prod`
|
||||
(шаблон `deploy/.env.prod.example`, без дефолтных паролей; отсутствие → fail-fast `:?`).
|
||||
Rate limiting включён (`RateLimit__Enabled: true`), CORS — явный `Security__AllowedOrigins`
|
||||
@@ -1152,11 +1185,12 @@ docker compose -f deploy/compose.dev.yml down # погасить ст
|
||||
(RpcCallLoggingInterceptor; gRPC-health не логируется). **Метрики** — OTel → Prometheus: `/metrics`
|
||||
(HTTP/1.1 :9464) + прикладные `deal.*` (токены/вызовы AI/ML, аудит, глубины очередей, сессии) — см. §7.
|
||||
PROD-стек: docker-логи → Promtail → Loki (retention 7 сут.) → Grafana (`127.0.0.1:3001`, SSH-туннель),
|
||||
метрики → Prometheus (`127.0.0.1:9090`) → Grafana; профиль `observability` compose.prod.
|
||||
метрики → Prometheus (`127.0.0.1:9090`) → Grafana, трейсы OTel → otel-collector → Tempo, ресурсы
|
||||
cAdvisor/node-exporter → Prometheus; профиль `observability` compose.prod.
|
||||
- **compose.prod** (Ruling 9): `deploy/compose.prod.yml` — postgres/minio (без host-портов), core + telegram/ai/ml
|
||||
(mTLS env; healthcheck — `grpc_health_probe`, при mTLS — TLS-проба с PEM), `caddy` (80/443: статика
|
||||
`src/frontend/dist` + `reverse_proxy /api → core:5080`, security-заголовки; домен/TLS/Cloudflare — шапка
|
||||
`deploy/caddy/Caddyfile`), профиль `observability` (loki/promtail/grafana/prometheus). Секреты — только из `.env.prod`
|
||||
`deploy/caddy/Caddyfile`), профиль `observability` (otel-collector/tempo/loki/promtail/prometheus/cadvisor/node-exporter/grafana). Секреты — только из `.env.prod`
|
||||
(шаблон `deploy/.env.prod.example`, без дефолтных паролей, fail-fast `:?`). Запуск:
|
||||
`docker compose --env-file deploy/.env.prod -f deploy/compose.prod.yml up -d --build` (+ `--profile observability`);
|
||||
авто-проверка — `... config` rc=0.
|
||||
@@ -1305,7 +1339,8 @@ docker compose -f deploy/compose.dev.yml start core telegram-service ml-service
|
||||
(`container_created`, `container_updated`, `container_deleted`), `settings_updated`, `channel_enabled`,
|
||||
`telegram_linked` (таблица — в контракте; `channel_created` зарезервирован, но не эмитится).
|
||||
- **Наблюдаемость** (Grafana provisioning + promtail-лейблы, дашборды `Deal-Auth/Errors/Rps/Logs`; с этапа 12 —
|
||||
метрики OTel → Prometheus и дашборд `Deal-Metrics-Overview`, см. §7).
|
||||
метрики OTel → Prometheus и дашборд `Deal-Metrics-Overview`; трейсы OTel → Collector → Tempo (`Deal-Traces`)
|
||||
и ресурсы cAdvisor/node-exporter (`Deal-Resources`), см. §7).
|
||||
- **Как открыть (dev):** `docker compose -f deploy/compose.dev.yml up -d --build` (или core на `:5080`
|
||||
с Postgres `:5433`, AI в Local-режиме) → фронт `cd src/frontend && npm run dev` (`:5173`, прокси `/api`)
|
||||
→ **оператор:** `http://localhost:5173/#/operator`, вход `operator`/`operator` (dev-дефолт; в Production —
|
||||
|
||||
Reference in New Issue
Block a user