مراقبة تطبيقات Rust: مكتبة tracing وجمع المقاييس
المراقبة عنصر أساسي في أنظمة الإنتاج. بالنسبة لتطبيقات Rust، المعروفة بأدائها وموثوقيتها، من المهم وجود أداة خفيفة وفعالة لجمع التليمترية. أصبحت مكتبة tracing المعيار الفعلي لقابلية المراقبة في نظام Rust البيئي. توفر تسجيلاً منظمًا، و spans (نطاقات) لتتبع الطلبات، وتكاملًا مع أنظمة جمع المقاييس.
ما هي tracing؟
tracing هي إطار عمل لأدوات برامج Rust. على عكس التسجيل التقليدي، تعمل بناءً على الأحداث (events) والنطاقات (spans). تمثل النطاقات فترات زمنية لتنفيذ الكود (مثل معالجة طلب HTTP)، بينما تمثل الأحداث نقاطًا داخل النطاقات (مثل "استجابت قاعدة البيانات خلال 10 مللي ثانية").
الإمكانيات الرئيسية:
- تسجيل منظم — يحتوي كل حدث على حقول (مفتاح-قيمة)، وليس مجرد سلسلة نصية.
- تسلسل هرمي للنطاقات — يمكن تداخل النطاقات داخل بعضها البعض، لتتبع مسار التنفيذ الكامل.
- دعم غير متزامن — يعمل بشكل ممتاز مع tokio و async/await.
- المشترك (Subscriber) — يمكن توصيل واجهات خلفية مختلفة: stdout، OpenTelemetry، Prometheus، ملفات.
التثبيت والاستخدام الأساسي
أضف إلى Cargo.toml:
[dependencies]tracing = "0.1"tracing-subscriber = "0.3"مثال بسيط للتسجيل المنظم:
use tracing::{info, warn, error};use tracing_subscriber;
fn main() { // تهيئة المشترك للإخراج إلى stdout tracing_subscriber::fmt::init();
let user_id = 42; let request_duration_ms = 150;
info!(user_id, duration = request_duration_ms, "تمت معالجة الطلب");
// تسجيل بمستوى warn warn!(user_id, "وقت الاستجابة تجاوز الحد");
// تسجيل خطأ error!("فشل الاتصال بقاعدة البيانات");}سيحتوي الإخراج على حقول بتنسيق يشبه JSON، مما يسهل التحليل في أنظمة المراقبة.
النطاقات والتتبع
تسمح النطاقات بقياس وقت تنفيذ العمليات وربط الأحداث في سلسلة:
use tracing::{span, info, Level};use tracing_subscriber;
fn process_request(user_id: u32) { // إنشاء نطاق مع سياق let span = span!(Level::INFO, "process_request", user_id); let _guard = span.enter(); // تفعيل النطاق
info!("بدء المعالجة"); std::thread::sleep(std::time::Duration::from_millis(50)); info!("اكتملت المعالجة");}
fn main() { tracing_subscriber::fmt::init(); process_request(100);}سيظهر في الإخراج سياق متداخل، يوضح أن الأحداث تنتمي إلى النطاق process_request.
جمع المقاييس باستخدام tracing و Prometheus
لمراقبة الإنتاج، غالبًا ما يكون تصدير المقاييس إلى Prometheus مطلوبًا. استخدم crate tracing-appender للكتابة إلى ملف أو tracing-opentelemetry للتكامل مع OpenTelemetry. ومع ذلك، فإن الطريقة الأكثر مباشرة هي استخدام مكتبة metrics مع tracing.
مثال على التكامل مع metrics-exporter-prometheus:
[dependencies]metrics = "0.21"metrics-exporter-prometheus = "0.12"tracing = "0.1"tokio = { version = "1", features = ["full"] }كود جمع المقاييس:
use metrics::{counter, gauge, histogram};use metrics_exporter_prometheus::PrometheusBuilder;use std::net::SocketAddr;
#[tokio::main]async fn main() { // تشغيل خادم HTTP لـ Prometheus let addr: SocketAddr = "0.0.0.0:9090".parse().unwrap(); let builder = PrometheusBuilder::new(); builder .wit