در بخش دوم اپلیکیشن Django را با روش GitOps مستقر کردیم. حالا اولین سیگنال از سیگنالهای Observability را اضافه میکنیم: متریکها. متریکها دادههای عددی و سریزمانی هستند؛ مانند تعداد درخواستها در ثانیه، نرخ خطا و تأخیر پاسخدهی.
مسیر داده در این بخش چهار حلقه دارد: اپلیکیشن متریکها را نمایان میکند، یک جمعکننده آنها را برمیدارد، یک پایگاه ذخیرهسازی نگهشان میدارد، و در نهایت Grafana آنها را رسم میکند:
- Django با کتابخانهی
django-prometheusمتریکها را روی مسیر/metricsنمایان میکند. - Grafana Alloy نقش جمعکننده (collector) را دارد و متریکها را از pod ها میخواند.
- Mimir پایگاه ذخیرهسازی متریکها و سازگار با Prometheus است.
- Grafana دادهها را از Mimir میخواند و در داشبورد نمایش میدهد.
همهی این اجزا نیز مانند اپلیکیشن، بهشکل مانیفست در همان مخزن قرار میگیرند و Argo CD آنها را روی cluster مستقر میکند.
نمایانکردن متریکها در Django
ابتدا کتابخانهی django-prometheus را به اپلیکیشن اضافه میکنیم. این کتابخانه با دو middleware، متریکهای درخواست و پاسخ را جمع میکند و یک مسیر /metrics در اختیار میگذارد. در فایل settings.py:
INSTALLED_APPS = [
"django_prometheus",
# ...
]
MIDDLEWARE = [
"django_prometheus.middleware.PrometheusBeforeMiddleware",
# ... other middleware ...
"django_prometheus.middleware.PrometheusAfterMiddleware",
]
و در فایل urls.py مسیر متریکها را اضافه میکنیم:
urlpatterns = [
path("", include("django_prometheus.urls")),
# ... other routes ...
]
پس از استقرار نسخهی جدید، خروجی /metrics شامل شمارندههایی مانند تعداد درخواستها و پاسخهاست. این خروجی خام را Alloy میخواند و به Mimir میفرستد؛ سپس میتوانیم همان داده را از Mimir بازخوانی کنیم:
/metrics؛ سپس همان متریک پس از عبور از Alloy، با یک پرسوجوی PromQL از Mimir بازخوانی میشود.جمعآوری با Grafana Alloy
Alloy جمعکنندهی واحدی است که در ادامهی مجموعه برای لاگ و ردیابی هم از آن استفاده میکنیم. پیکربندی آن روشن و خوانا است: ابتدا pod ها را کشف میکند، سپس فقط pod های اپلیکیشن را نگه میدارد، از آنها متریک میخواند و به Mimir میفرستد:
discovery.kubernetes "pods" {
role = "pod"
}
prometheus.scrape "guestbook" {
targets = discovery.relabel.guestbook.output
forward_to = [prometheus.remote_write.mimir.receiver]
metrics_path = "/metrics"
scrape_interval = "15s"
}
prometheus.remote_write "mimir" {
endpoint {
url = "http://mimir.observability.svc:8080/api/v1/push"
}
}
رابط کاربری Alloy این زنجیره را بهشکل یک نمودار نشان میدهد و سلامت هر جزء را مشخص میکند:
discovery.kubernetes) و انتخاب pod های هدف (discovery.relabel) تا خواندن متریکها (prometheus.scrape) و ارسال به Mimir (prometheus.remote_write). همه در وضعیت Healthy هستند.داشبورد بهشکل کد و روش RED
برای اینکه داشبورد قابل بازتولید و نسخهپذیر باشد، بهجای ساختن دستی، آن را بهشکل یک فایل JSON در Git نگه میداریم و از طریق provisioning به Grafana میدهیم. برای طراحی داشبورد از روش RED استفاده میکنیم که سه پرسش کلیدی دربارهی هر سرویس را پاسخ میدهد:
- Rate (نرخ): چند درخواست در ثانیه دریافت میشود؟
- Errors (خطاها): چه تعداد از پاسخها با خطا همراهاند؟
- Duration (تأخیر): پاسخدهی چهقدر طول میکشد؟
هر پنل با یک پرسوجوی PromQL روی متریکهای Django ساخته میشود؛ برای نمونه، نرخ درخواست و صدک ۹۵ تأخیر:
sum(rate(django_http_requests_total_by_method_total[5m]))
histogram_quantile(0.95,
sum(rate(django_http_requests_latency_seconds_by_view_method_bucket[5m])) by (le))
نتیجه یک داشبورد زنده است که با تولید ترافیک روی اپلیکیشن، دادهی واقعی را نشان میدهد:
جمعبندی و بخش بعد
در این بخش زنجیرهی کامل متریک را ساختیم: نمایانکردن متریک در Django، جمعآوری با Alloy، ذخیره در Mimir و نمایش در یک داشبورد RED که بهشکل کد نگهداری میشود. متریکها به ما میگویند «چهقدر» و «چه زمانی» مشکلی رخ داده است.
در بخش بعد سیگنال دوم را اضافه میکنیم: لاگها را با Loki جمعآوری میکنیم تا بفهمیم «چرا» یک مشکل رخ داده است.
بخشهای این مجموعه
- بخش ۱: پیشنیاز، یک Kubernetes ساده با k0s
- بخش ۲: استقرار اپلیکیشن Django با GitOps و Argo CD
- بخش ۳: متریکها با Mimir (همین بخش)
- بخش ۴: لاگها با Loki
- بخش ۵: ردیابی (Tracing) با Tempo
- بخش ۶: پروفایلینگ پیوسته با Pyroscope