مراقبة تطبيقات Rust: المقاييس والتنبيهات من الألف إلى الياء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مراقبة تطبيقات Rust: المقاييس والتنبيهات من الألف إلى الياء

\n\n

عندما يخرج تطبيق Rust الخاص بك إلى الإنتاج، يتوقف الكود عن كونه مجرد كود. يصبح خدمة يعتمد عليها المستخدمون والأعمال. بدون مراقبة، أنت تطير بشكل أعمى: يتم اكتشاف الأعطال من خلال الشكاوى، ويتم تقييم الأداء "بالتخمين". في هذه المقالة، سنشرح كيفية بناء نظام مراقبة كامل لـ Rust - من جمع المقاييس الأساسية إلى إعداد التنبيهات في Prometheus والتصور في Grafana.

\n\n

1. لماذا تعتبر المراقبة مهمة لمشاريع Rust

\n

تشتهر Rust بالأداء العالي وأمان الذاكرة، لكن هذا لا يلغي الحاجة إلى مراقبة التطبيق. المشاكل النموذجية في الإنتاج:

\n
    \n
  • تسرب الذاكرة (على سبيل المثال، عبر Arc أو المراجع الدائرية).
  • \n
  • الانسدادات في الكود غير المتزامن (deadlocks أو starvation في tokio).
  • \n
  • الانهيارات غير المتوقعة (حتى مع catch_unwind).
  • \n
  • تدهور الأداء بسبب الخوارزميات غير المثلى.
  • \n
\n

توفر المراقبة إجابات على الأسئلة: "ماذا يحدث الآن؟"، "لماذا حدث هذا؟" و"كيف نمنعه؟".

\n\n

2. جمع المقاييس: مكتبة metrics والتصدير إلى Prometheus

\n

المكدس القياسي لـ Rust هو crate metrics (أو prometheus). نحن نستخدم metrics لأنه يجرد عملية التصدير ويسمح بتغيير الخلفية بسهولة.

\n\n

2.1. التثبيت والإعداد الأساسي

\n

أضف التبعيات إلى Cargo.toml:

\n
[dependencies]\nmetrics = "0.21"\nmetrics-exporter-prometheus = "0.12"\ntokio = { version = "1", features = ["full"] }
\n\n

نقوم بإنشاء خادم HTTP بسيط لنقطة النهاية /metrics:

\n
use metrics_exporter_prometheus::PrometheusBuilder;\nuse std::net::SocketAddr;\nuse tokio::net::TcpListener;\n\n#[tokio::main]\nasync fn main() {\n    // تهيئة مصدر Prometheus\n    let (recorder, exporter) = PrometheusBuilder::new()\n        .build()\n        .expect("فشل إنشاء مصدر Prometheus");\n\n    metrics::set_boxed_recorder(Box::new(recorder))\n        .expect("فشل تعيين المسجل العام");\n\n    // تشغيل خادم المقاييس\n    let addr: SocketAddr = "0.0.0.0:9090".parse().unwrap();\n    let listener = TcpListener::bind(addr).await.unwrap();\n    println!("المقاييس متاحة على http://{}", addr);\n\n    loop {\n        let (mut stream, _) = listener.accept().await.unwrap();\n        let body = exporter.encode().unwrap();\n        let response = format!(\n            "HTTP/1.1 200 OK\\r\\nContent-Type: text/plain\\r\\nContent-Length: {}\\r\\n\\r\\n{}",\n            body.len(),\n            body\n        );\n        tokio::io::AsyncWriteExt::write_all(&mut stream, response.as_bytes())\n            .await\n            .unwrap();\n    }\n}
\n\n

2.2. تسجيل المقاييس المخصصة

\n

نضيف عداد الطلبات ومدرج تكراري لوقت الاستجابة:

\n
use metrics::{counter, histogram, increment_counter};\nuse std::time::Instant;\n\nasync fn handle_request() {\n    let start = Instant::now();\n\n    // منطق عملك\n    tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;\n\n    // تسجيل المقاييس\n    increment_counter!("http_requests_total", "method" => "GET");\n    histogram!("http_request_duration_seconds", start.elapsed().as_secs_f64(), "method" => "GET");\n}
\n

الآن على /metrics سترى:

\n
# HELP http_requests_total إجمالي طلبات HTTP\n# TYPE http_requests_total counter\nhttp_requests_total{method="GET"} 1\n# HELP http_request_duration_seconds مدة طلب HTTP\n# TYPE http_request_duration_seconds histogram\nhttp_request_duration_seconds_bucket{method="GET",le="0.005"} 0\nhttp_request_duration_seconds_bucket{method="GET",le="0.01"} 0\nhttp_request_duration_seconds_bucket{method="GET",le="0.025"} 0\n                

المدونات

توصيات الكتب