المراقبة — Prometheus + Grafana لقابلية الملاحظة الكاملة للمكدس
المراقبة مثل لوحة أجهزة السيارة — عداد السرعة (QPS)، درجة حرارة الزيت (زمن الاستجابة)، ومصباح فحص المحرك (معدل الخطأ) تبقيك على اطلاع دائم بصحة السيارة (النظام). بدون لوحة أجهزة، لن تعرف أن هناك مشكلة حتى يبدأ الدخان يتصاعد من المحرك.
1. ما ستتعلمه
- كشف مقاييس Prometheus: تكامل
prometheus-fastapi-instrumentator - مقاييس أعمال مخصصة: معدل تحديث الأسعار، نسبة مئوية لزمن استجابة API، عدد المستخدمين النشطين
- تصميم لوحة Grafana: حجم الطلبات/زمن الاستجابة/معدل الخطأ (طريقة RED) + مقاييس الأعمال
- قواعد التنبيه: زمن الاستجابة P99 يتجاوز الحد، ارتفاع معدل الخطأ، انخفاض معدل إصابة ذاكرة التخزين المؤقت Redis
- سيناريو Alice: لوحة مراقبة Charlie لـ PriceTracker
2. القصة الحقيقية لـ Alice
(1) نقطة الألم: لا تدرك وجود المشكلة إلا بعد حدوثها
في الساعة 3 صباحًا، نُفد تجمع اتصالات قاعدة بيانات PriceTracker، وبدأت API تُرجع أخطاء 500. لم تعرف Alice إلا في الساعة 8 صباحًا، عندما بدأ المستخدمون يشكون. بدون مراقبة في الوقت الفعلي، لم يستطع Charlie سوى مراجعة السجلات بعد وقوع الحادث واكتشف أن تجمع الاتصالات كان يُطلق تنبيهات منذ الساعة 5 صباحًا — لو كانت المراقبة موجودة، كان يمكن كشف المشكلة وحلها في غضون خمس دقائق.
(2) حل باستخدام Prometheus و Grafana
يجمع Prometheus المقاييس (عدد الطلبات، زمن الاستجابة، معدل الخطأ) كل ثانية؛ يُصورها Grafana في الوقت الفعلي؛ ويرسل AlertManager تنبيهات تلقائيًا عندما تنحرف المقاييس عن النطاقات الطبيعية — مما ينقل العملية من "معرفة المشاكل فقط بعد شكاوى المستخدمين" إلى "إشعارات تلقائية خلال 5 دقائق".
(3) العائد
ارتفاعات زمن الاستجابة P99 تُطلق تنبيهًا خلال دقيقة واحدة؛ تُرسل إشعارات تلقائية قبل نفاد تجمع اتصالات قاعدة البيانات؛ انخفض وقت كشف المشاكل من "ساعات" إلى "دقائق"، لذا لم يعد Charlie مضطرًا للمراقبة المستمرة على الشاشة لمدة 24 ساعة متواصلة.
3. كشف مقاييس Prometheus
(1) بنية المراقبة
flowchart LR
App[تطبيق FastAPI] -->|/metrics| Prom[Prometheus]
Prom -->|استعلام| Grafana[لوحة Grafana]
Prom -->|تنبيه| AlertMgr[AlertManager]
AlertMgr -->|إشعار| Slack[Slack / بريد إلكتروني]
Grafana -->|تصور| Charlie[Charlie DevOps]
(1) ▶مثال: تكامل prometheus-fastapi-instrumentator
# تثبيت: uv add prometheus-fastapi-instrumentator
from fastapi import FastAPI
from prometheus_fastapi_instrumentator import Instrumentator
app = FastAPI()
# إضافة مقاييس افتراضية: عدد الطلبات، المدة، الحجم، الاستثناءات
Instrumentator().instrument(app).expose(app)
# الآن نقطة النهاية /metrics تكشف مقاييس Prometheus
# بما في ذلك: http_requests_total, http_request_duration_seconds, إلخ
الناتج:
# التنفيذ ناجح
(2) ▶مثال: مقاييس مخصصة
from prometheus_client import Counter, Histogram, Gauge
from fastapi import FastAPI
app = FastAPI()
# مقاييس أعمال مخصصة
PRICE_UPDATES = Counter(
"pricetracker_price_updates_total",
"العدد الإجمالي لتحديثات الأسعار",
["category", "currency"],
)
REQUEST_LATENCY = Histogram(
"pricetracker_request_latency_seconds",
"زمن استجابة الطلب بالثواني",
buckets=[0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0],
)
ACTIVE_USERS = Gauge(
"pricetracker_active_users",
"عدد المستخدمين النشطين في آخر 5 دقائق",
)
CACHE_HIT_RATE = Gauge(
"pricetracker_cache_hit_rate",
"نسبة إصابة ذاكرة التخزين المؤقت Redis بالنسبة المئوية",
)
@app.post("/api/v1/prices")
async def create_price(price: PriceCreate):
result = await service.create_price(price)
# تسجيل المقياس المخصص
PRICE_UPDATES.labels(category="electronics", currency="USD").inc()
return result
الناتج:
# تم تعريف الدالة بنجاح
(2) المقاييس الرئيسية لطريقة RED
| المقياس | النوع | الوصف | PromQL |
|---|---|---|---|
| Rate | Counter | معدل الطلبات (QPS) | rate(http_requests_total[5m]) |
| Errors | Counter | معدل الخطأ | rate(http_requests_total{status=~"5.."}[5m]) |
| Duration | Histogram | توزيع زمن الاستجابة | histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) |
4. تصميم لوحة Grafana
(1) تخطيط لوحة المعلومات
graph TD
Title[لوحة مراقبة PriceTracker]
Title --> Row1[الصف 1: نظرة عامة]
Row1 --> QPS[QPS - المعدل]
Row1 --> P50[P50 زمن الاستجابة]
Row1 --> P99[P99 زمن الاستجابة]
Row1 --> ErrRate[معدل الخطأ]
Title --> Row2[الصف 2: الأعمال]
Row2 --> PriceUpd[تحديثات الأسعار/دقيقة]
Row2 --> ActiveUsers[المستخدمون النشطون]
Row2 --> CacheHit[معدل إصابة التخزين المؤقت]
Title --> Row3[الصف 3: البنية التحتية]
Row3 --> DBConns[اتصالات قاعدة البيانات]
Row3 --> RedisConns[اتصالات Redis]
Row3 --> CeleryQ[حجم طابور Celery]
(1) ▶مثال: إعداد JSON للوحة Grafana (مقتطف)
{
"dashboard": {
"title": "PriceTracker Monitoring",
"panels": [
{
"title": "Request Rate (QPS)",
"type": "timeseries",
"targets": [
{
"expr": "sum(rate(http_requests_total[5m]))",
"legendFormat": "Total QPS"
}
]
},
{
"title": "P99 Latency",
"type": "stat",
"targets": [
{
"expr": "histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))",
"legendFormat": "P99"
}
],
"thresholds": {
"steps": [
{ "value": 0, "color": "green" },
{ "value": 0.1, "color": "yellow" },
{ "value": 0.5, "color": "red" }
]
}
},
{
"title": "Cache Hit Rate",
"type": "gauge",
"targets": [
{
"expr": "pricetracker_cache_hit_rate",
"legendFormat": "Hit Rate %"
}
]
}
]
}
}
الناتج:
{
"dashboard": {
"title": "PriceTracker Monitoring",
"panels": [
{
"title": "Request Rate (QPS)",
"type": "timeseries",
"targets": [
{
"expr": "sum(rate(http_requests_total[5m]))",
"legendFormat": "Total QPS"
}
]
},
{
"title": "P99 Latency",
"type": "stat",
"targets": [
{
"expr": "histogram_quantile(0.99, sum(rate(http_request_duration_seconds_buck
5. قواعد التنبيه
(1) ▶مثال: قواعد تنبيه Prometheus
# prometheus/alert_rules.yml
groups:
- name: pricetracker_alerts
rules:
- alert: HighP99Latency
expr: histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) > 0.5
for: 2m
labels:
severity: warning
annotations:
summary: "زمن الاستجابة P99 يتجاوز 500 مللي ثانية"
description: "زمن الاستجابة P99 هو {{ $value }}s، الحد هو 0.5s"
- alert: HighErrorRate
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05
for: 1m
labels:
severity: critical
annotations:
summary: "معدل الخطأ يتجاوز 5%"
description: "معدل الخطأ هو {{ $value | humanizePercentage }}"
- alert: LowCacheHitRate
expr: pricetracker_cache_hit_rate < 60
for: 5m
labels:
severity: warning
annotations:
summary: "معدل إصابة التخزين المؤقت أقل من 60%"
description: "معدل الإصابة الحالي هو {{ $value }}%"
- alert: DatabaseConnectionPoolExhausted
expr: pricetracker_db_connections_in_use / pricetracker_db_connections_max > 0.9
for: 3m
labels:
severity: critical
annotations:
summary: "تجمع اتصالات قاعدة البيانات مستخدم بنسبة تتجاوز 90%"
الناتج:
تم تحميل إعداد المراقبة
أهداف Prometheus: 3 نشطة
لوحة Grafana: جاهزة
(2) ▶مثال: إضافة مكدس مراقبة إلى Docker Compose
# أضف إلى docker-compose.yml
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./docker/prometheus.yml:/etc/prometheus/prometheus.yml
- ./docker/alert_rules.yml:/etc/prometheus/alert_rules.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--alert.rule-files=/etc/prometheus/alert_rules.yml'
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
alertmanager:
image: prom/alertmanager:latest
ports:
- "9093:9093"
volumes:
- ./docker/alertmanager.yml:/etc/alertmanager/alertmanager.yml
الناتج:
CONTAINER ID IMAGE STATUS PORTS
abc123 nginx:latest Up 2 hours 0.0.0.0:80->80/tcp
(3) ▶مثال: إعداد prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: "pricetracker-api"
metrics_path: "/metrics"
static_configs:
- targets: ["api:8000"]
rule_files:
- "alert_rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
الناتج:
تم تفعيل الإعداد.
❓أسئلة شائعة
user_id).📖ملخص
prometheus-fastapi-instrumentatorسطر واحد من الكود يكشف مقاييس HTTP الافتراضية- خصص ثلاثة أنواع من مقاييس الأعمال: Counter (العد)، Histogram (توزيع زمن الاستجابة)، Gauge (القيمة الحالية)
- لوحة Grafana منظمة بطريقة RED: Rate (QPS)، Errors (معدل الخطأ)، Duration (زمن الاستجابة)
- إعداد قواعد تنبيه AlertManager: P99 > 500 مللي ثانية، معدل الخطأ > 5%، معدل إصابة التخزين المؤقت < 60%
- نشر مكدس مراقبة كامل بنقرة واحدة مع Docker Compose: Prometheus + Grafana + AlertManager
📝تمارين
- تمرين أساسي (الصعوبة: ⭐): أضف
prometheus-fastapi-instrumentatorإلى FastAPI وتحقق من أن نقطة النهاية/metricsتُرجع مقاييس HTTP الافتراضية (مثل http_requests_total). تلميح:Instrumentator().instrument(app).expose(app) - تمرين متقدم (الصعوبة ⭐⭐): أضف ثلاثة مقاييس مخصصة — PRICE_UPDATES (Counter حسب الفئة)، REQUEST_LATENCY (Histogram بنسب مئوية)، CACHE_HIT_RATE (Gauge) — وسجّل قيم المقاييس في نقطة النهاية. تلميح:
Counter(..., ["category"])+.labels(category="electronics").inc() - تحدٍ (الصعوبة: ⭐⭐⭐): أضف Prometheus و Grafana و AlertManager إلى Docker Compose؛ إعداد
prometheus.ymlلجمع مقاييس FastAPI؛ اكتب قاعدتي تنبيه — واحدة لـ P99 > 500 مللي ثانية وأخرى لمعدل الخطأ > 5%؛ واستورد لوحة المعلومات إلى Grafana لعرض المقاييس في الوقت الفعلي. تلميح:docker/prometheus.yml+alert_rules.yml+ إعداد مصدر بيانات Grafana
---|



