مقاييس Prometheus في Rust: مراقبة الأداء وتحمل الأعطال
في تطوير تطبيقات الواجهة الخلفية الحديثة بلغة Rust، أصبحت المراقبة جزءًا لا يتجزأ من البنية التحتية للإنتاج. Prometheus هو المعيار الفعلي لجمع وتخزين المقاييس، ويتيح تكامله مع Rust تتبع الأداء، واستخدام المعالج، وعدد الطلبات، والأخطاء، وغير ذلك الكثير. في هذا المقال، سنستعرض المكتبتين الرئيسيتين: prometheus (العميل الرسمي) و metrics + metrics-exporter-prometheus (النهج الأكثر تجريدًا).
لماذا تحتاج المقاييس في Rust؟
تتيح لك المقاييس:
- مراقبة حالة الخدمة في الوقت الفعلي
- اكتشاف الاختناقات (زمن الاستجابة، الأخطاء)
- بناء لوحات معلومات في Grafana
- إعداد التنبيهات (مثل انخفاض QPS أو زيادة الأخطاء)
تثبيت وإعداد مكتبة prometheus
أضف إلى ملف Cargo.toml:
[dependencies]
prometheus = { version = "0.13", features = ["process"] }
actix-web = "4" # لمثال خادم الويب
tokio = { version = "1", features = ["full"] }
توفر مكتبة prometheus ثلاثة أنواع رئيسية من المقاييس: Counter، Gauge، Histogram.
مثال: إنشاء وتسجيل المقاييس
use prometheus::{Counter, Gauge, Histogram, HistogramOpts, Opts, Registry};
fn main() {
// إنشاء سجل المقاييس
let registry = Registry::new();
// Counter — عداد الطلبات
let request_counter = Counter::with_opts(
Opts::new("http_requests_total", "إجمالي طلبات HTTP")
.const_label("service", "my_app")
).unwrap();
registry.register(Box::new(request_counter.clone())).unwrap();
// Gauge — عدد الاتصالات النشطة الحالية
let active_connections = Gauge::with_opts(
Opts::new("active_connections", "عدد الاتصالات النشطة")
).unwrap();
registry.register(Box::new(active_connections.clone())).unwrap();
// Histogram — توزيع زمن الاستجابة
let request_duration = Histogram::with_opts(
HistogramOpts::new("http_request_duration_seconds", "مدة الطلب بالثواني")
.buckets(vec![0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0])
).unwrap();
registry.register(Box::new(request_duration.clone())).unwrap();
// محاكاة الاستخدام
request_counter.inc();
active_connections.set(42.0);
request_duration.observe(0.123);
}
تصدير المقاييس عبر HTTP (actix-web)
لكي يتمكن Prometheus من جمع المقاييس، يجب عرضها بتنسيق /metrics:
use actix_web::{web, App, HttpServer, HttpResponse, Responder};
use prometheus::{Encoder, TextEncoder, Registry};
use std::sync::Arc;
async fn metrics_handler(registry: web::Data<Arc<Registry>>) -> impl Responder {
let encoder = TextEncoder::new();
let mut buffer = Vec::new();
encoder.encode(®istry.gather(), &mut buffer).unwrap();
HttpResponse::Ok()
.content_type("text/plain; charset=utf-8")
.body(buffer)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let registry = Arc::new(Registry::new());
// ... تسجيل المقاييس كما في المثال السابق ...
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(registry.clone()))
.route("/metrics", web::get().to(metrics_handler))
})
.bind("127.0.0.1:9090")?
.run()
.await
}
مكتبة metrics — نهج عالي المستوى
البديل هو كريت metrics مع المُصدّر metrics-exporter-prometheus. يوفر هذا النهج وحدات ماكرو لإنشاء المقاييس بسرعة:
[dependencies]
metrics = "0.21"
metrics-exporter-prometheus = "0.12"
use metrics::{counter, gauge, histogram};
use metrics_exporter