Files
ERP/bot/docs/DEPLOY-AND-MONITORING.md
T
whqreza 887a3af84f refactor(monitoring): move grafana into the main compose stack
Owner request: one 'docker compose up -d' should bring the whole system up —
no separate monitoring project to start for the dashboards.

- docker-compose.yml: grafana service (procurement-grafana, loopback :3001,
  default+shared networks, obs datasource env) + grafana_data volume;
  provisioning and dashboard JSONs stay in ./monitoring/grafana/ (no file
  moves, provisioning unchanged)
- docker-compose.prod.yml: GRAFANA_ADMIN_PASSWORD forced via the existing
  ${VAR:?} pattern (local keeps a lenient default, prod refuses defaults)
- monitoring/docker-compose.monitoring.yml: grafana service + volume removed
  (no name/port conflict); glitchtip/prometheus/loki stay server-side as before
- docs updated: grafana restarts on app deploys are harmless (settings live
  in the volume); SSH-tunnel posture unchanged

Verified locally: both compose files validate; 'docker compose up -d' starts
all 10 services incl. procurement-grafana; BotPostgres datasource health OK;
all 3 dashboards provisioned in the fresh volume; monitoring compose no
longer contains grafana; old monitoring-grafana container removed; port
still loopback-only.
2026-10-27 01:43:31 +03:30

106 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# استقرار و پایش — فاز ۷ (Jev + Observability)
وضعیت به‌روزشده: 2026-10-12 · برنچ: `prod-v7` · **هیچ پوشی انجام نمی‌شود تا مالک دستور بدهد.**
## الف) وضعیت فعلی
- بات همین حالا **روی استک لوکال** اجرا می‌شود (long-polling بله؛ بدون پورت ورودی) و
`JEV_ENABLED` + `OBS_ENABLED` روی آن فعال است.
- استقرار بات روی سرور یک **تصمیم جدا** است (نه بخشی از مرج تیم). تا آن تصمیم، بات لوکال می‌ماند.
- ⚠️ **قانون یک‌پولره:** Bale فقط اجازه‌ی یک مصرف‌کننده‌ی `getUpdates` می‌دهد. اگر باتِ سرور و
باتِ لوکال هم‌زمان روشن باشند، پیام‌ها بین آن‌ها گم/تکراری می‌شوند. **قبل از روشن‌کردن بات سرور،
بات لوکال باید خاموش شود.**
## ب) پیش‌نیازهای سرور (وقتی تصمیم گرفته شد)
کلیدها و تنظیم‌های بات (در گیت نیستند — از طریق Coolify env یا فایل `bot/.env` روی سرور):
| متغیر | مقدار |
|---|---|
| `PROCUREMENT_BOT_BOT_TOKEN` | توکن بله (rotated — بخش امنیتی پایین را ببین) |
| `PROCUREMENT_BOT_AI_API_KEY` | کلید DeepSeek |
| `PROCUREMENT_BOT_TYPESAFE_API_KEY` | کلید Jev |
| `PROCUREMENT_BOT_API_BASE_URL` | `http://api:8000/api/v1` |
| `PROCUREMENT_BOT_DATABASE_URL` | `postgresql+asyncpg://postgres:***@postgres:5432/procurement` |
| `PROCUREMENT_BOT_JEV_CONF_EXACT` / `_FLOOR` | اختیاری — پیش‌فرض کالیبره: `0.85` / `0.65` |
| `PROCUREMENT_BOT_OBS_PROMPT_VERSION` | `nlu-v2-entity-mentions` (برای prompt_hash) |
ولوم‌ها: `bot/app` (کد)، `bot/tools` (ابزارها/pایش)، `bot/data` (**صدای خام — آرشیو، نه حذف**)،
`bot/.env:ro`.
نکته: **mount جدید فقط با recreate اعمال می‌شود، نه restart** → `docker compose up -d --force-recreate bot`.
بلوک آماده‌ی سرویس بات برای کامپوز دیپلوی Coolify (فقط «در صورت» تصمیم — عمداً به فایل کامپوز
اضافه نشده چون سرویس‌شدن خودکار = خطر دو‌پولری و تغییر رفتار سرور):
```yaml
bot:
image: v15-bot:latest
build: { context: ./bot, dockerfile: Dockerfile }
restart: unless-stopped
mem_limit: 512m
volumes:
- ./bot/data:/srv/bot/data
- ./bot/tools:/srv/bot/tools
environment:
PROCUREMENT_BOT_BOT_TOKEN: ${BALE_BOT_TOKEN}
PROCUREMENT_BOT_AI_API_KEY: ${AI_API_KEY}
PROCUREMENT_BOT_TYPESAFE_API_KEY: ${TYPESAFE_API_KEY}
PROCUREMENT_BOT_API_BASE_URL: http://api:8000/api/v1
PROCUREMENT_BOT_DATABASE_URL: postgresql+asyncpg://postgres:${POSTGRES_PASSWORD}@postgres:5432/procurement
```
## ج) ترتیب استقرار (فقط وقتی مالک گفت «پوش کن»)
1. مهندس ارشد `prod-v7` را با بقیه مرج و CI/Coolify دیپلوی ERP را انجام می‌دهد.
2. تصمیم بات سرور (بالا) → در صورت تأیید: خاموش‌کردن بات لوکال → روشن‌کردن بات سرور.
3. **Smoke test (چک‌لیست پلن §۷ بند ۱۲):** ۱۰ پیام نمونه شامل «منشیانه/دفتر/مصطفوی» + یک ویس؛
بررسی: اتصال دقیق‌ها، پیام ابهام با دکمه‌های کاندیدا، ساخت جدید، پیش‌نویس، ثبت نهایی.
4. راستی‌آزمایی پایش: `docker compose exec bot python tools/monitor.py --days 1`
→ قیف باید پر شود و رخدادهای همان پیام‌ها در `bot_trace_events` باشد.
5. چک سهمیه: `usage` در `jev.result` (توکن ورودی/خروجی) + latency p95.
6. **داشبوردها (به‌روز ۲۰۲۶-۱۰-۲۵، v2.1):** `PROCUREMENT_BOT_OBS_READER_PASSWORD` را در `.env` ست کنید و
یک بار بات را restart کنید تا نقش فقط‌خواندنی `obs_reader` ساخته شود. **گرفانا حالا جزو استک اصلی است**
(تصمیم ۲۰۲۶-۱۰-۲۵: یک `docker compose up -d` همه‌چیز از جمله گرفانا را بالا می‌آورد؛ در پروداکشن
overlay، رمز `GRAFANA_ADMIN_PASSWORD` الزامی است). دیتاسورس `BotPostgres` و داشبوردهای
«بات — Observability خط لوله» و «بات — اکسپلورر پیام‌ها» خودکار provision می‌شوند
(جزئیات در `monitoring/README.md`). صفحه‌ی فارسی داخل ERP روی `/bot-monitor` (فقط ادمین) چهار تب دارد: نمای کلی،
**مدل‌ها** (رکورد و روند زمانی هر مدل: Jev، DeepSeek-NLU، داور، فالبک، هر STT، بهبود صدا)،
**بخش‌ها** (مراحل به تفکیک بخش خط‌لوله) و **پیام‌ها** (پرونده‌ی هر پیام با پخش/دانلود ویس و
ترنسکریپت همه‌ی موتورها کنار هم).
**رسانه (v2.1):** فایل‌های بات دو-نویسی می‌شوند — دیسک (آرشیو) + باکت MinIO `bot-media`
(env: `BOT_MINIO_ENDPOINT/BOT_MINIO_BUCKET`؛ خالی = خاموش). سرو پخش/دانلود از MinIO با
fallback به دیسک از `/api/v1/bot-metrics/media` با لینک امضاشده‌ی کوتاه‌مدت انجام می‌شود؛
سرویس api ولوم فقط‌خواندنی `./bot/data` دارد (ولیم جدید = `up -d --build api` برای recreate).
برای دیدن همه‌ی پنل‌ها روی نصب تازه: `docker compose exec bot python tools/seed_observability_demo.py --days 7`
(داده‌ها با `source='demo'` از آمار ترافیک واقعی جدا می‌مانند و در MinIO هم آینه می‌شوند).
## د) Rollback (بدون دیپلوی — فقط env + restart)
| سوئیچ | اثر |
|---|---|
| `JEV_ENABLED=false` | غیرفعال‌شدن Jev — mentionها مستقیم به فالبک DeepSeek می‌روند |
| `OBS_ENABLED=false` | خاموش‌شدن ثبت (داده‌های قبلی دست‌نخورده می‌مانند) |
حذف کامل داشبوردها (در صورت نیاز): دو JSON در `monitoring/grafana/dashboards/` + دیتاسورس در
`datasources.yml` + `backend/app/routers/bot_metrics.py` + `frontend/src/pages/BotMonitor/` + `DROP ROLE obs_reader`.
هیچ داده‌ای حذف نمی‌شود.
## ه) پایش هفتگی
```bash
docker compose exec bot python tools/monitor.py --days 7 # DIGEST
docker compose exec bot python tools/monitor.py --days 7 --check # exit 1 اگر هشدار
```
- خروجی: کنسول + فایل `bot/data/reports/monitoring_<ts>.md`
- آمار **فقط روی ترافیک واقعی** است (calibration/test حذف می‌شوند؛ `--include-calibration` برای دیدن همه).
- هشدارها (پلن §۴.۵): حجم Observability > ۵GB یا رخداد ماهانه > ۱۰۰هزار → **جلسه‌ی «آرشیو، نه حذف»**؛
انحراف نسخه‌ی مدل از پین `jev-1.13.0`؛ نسبت خطای Jev > ۲۰٪.
- پروکسی کیفیت: انتخاب کاربر در ابهام‌ها (گزینه اول مدل / گزینه دیگر / «هیچ‌کدام») — این عددِ A/B واقعی است.
## و) یادآوری امنیتی (از قبل علامت‌خورده — تصمیم مالک)
`docker-compose.yml` (نسخه لوکال) هنوز توکن بله و کلید DeepSeek را به‌صورت پیش‌فرض
(`:-...`) داخل خود دارد. قبل از هر پوش/جابه‌جایی سرور، چرخش کلیدها توصیه می‌شود.