مراقبة تطبيقات Rust: المقاييس والتنبيهات على المستوى المتقدم

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

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

ابدأ الدورة

مقدمة: لماذا تعتبر مراقبة تطبيقات Rust تحديًا وفرصة



تشتهر Rust بأدائها العالي وأمان الذاكرة. ومع ذلك، عندما يعمل تطبيقك على حافة إمكانيات الأجهزة (على سبيل المثال، خادم WebSocket عالي التحميل أو محلل بيانات)، غالبًا ما تكون المقاييس القياسية لوحدة المعالجة المركزية والذاكرة غير كافية. على المستوى المتقدم، تتطلب مراقبة تطبيقات Rust ليس فقط جمع البيانات، بل إنشاء نظام دقيق للتنبيهات يتنبأ بالعطل قبل حدوثه.



في هذه المقالة، سنناقش كيفية بناء نظام مراقبة جاهز للإنتاج لتطبيقات Rust: من المقاييس المخصصة باستخدام prometheus crate إلى إعداد التنبيهات عبر Alertmanager و Grafana.



1. المقاييس المتقدمة: ليست مجرد طلبات HTTP



المراقبة الأساسية (عدد الطلبات، زمن الاستجابة) هي الحد الأدنى. على المستوى المتقدم، نجمع مقاييس تعكس الحالة الداخلية للتطبيق: حجم قوائم الانتظار، عدد المهام النشطة في Tokio، حالة تجمع الاتصالات.



1.1. مقاييس مخصصة من نوع Histogram و Gauge



نستخدم crate prometheus. لننظر إلى مثال لجمع مقاييس لتجمع اتصالات قاعدة البيانات:



use prometheus::{HistogramOpts, HistogramVec, Gauge, register_histogram_vec, register_gauge};use lazy_static::lazy_static;

lazy_static! { static ref DB_CONNECTION_POOL: Gauge = register_gauge!( "db_connection_pool_size", "العدد الحالي للاتصالات النشطة في التجمع" ).unwrap();

static ref DB_QUERY_DURATION: HistogramVec = register_histogram_vec!( HistogramOpts::new("db_query_duration_seconds", "وقت تنفيذ الاستعلام لقاعدة البيانات"), &["query_type", "status"] ).unwrap();}

// الاستخدام في الكودfn execute_query(query_type: &str) -> Result<(), String> { DB_CONNECTION_POOL.inc(); let start = std::time::Instant::now(); // ... تنفيذ الاستعلام ... let duration = start.elapsed().as_secs_f64(); DB_QUERY_DURATION.with_label_values(&[query_type, "success"]).observe(duration); DB_CONNECTION_POOL.dec(); Ok(())}


هام: استخدم HistogramVec لتصنيف الاستعلامات حسب النوع (SELECT, INSERT) والحالة (success, error). سيسمح لك هذا ببناء خرائط حرارية في Grafana.



1.2. مقاييس من داخل Tokio runtime



للتطبيقات غير المتزامنة، من الضروري معرفة مدى تحميل المجدول. نستخدم tokio-metrics:



use tokio_metrics::RuntimeMetrics;use std::sync::Arc;

async fn monitor_runtime(metrics: Arc<RuntimeMetrics>) { loop { tokio::time::sleep(std::time::Duration::from_secs(5)).await; let num_alive_tasks = metrics.num_alive_tasks(); let blocking_threads = metrics.num_blocking_threads(); // نرسل هذه القيم إلى Prometheus عبر Gauge println!("المهام النشطة: {}, الخيوط المحظورة: {}", num_alive_tasks, blocking_threads); }}


تساعد هذه المقاييس في اكتشاف تسرب المهام (عندما يرتفع num_alive_tasks باستمرار) أو الاستخدام المفرط لـ block_in_place.



2. بنية جمع المقاييس: Push مقابل Pull



في نظام Rust البيئي، يُستخدم نموذج Pull بشكل أكثر شيوعًا (Prometheus scraper)، ولكن للعمليات قصيرة العمر (أدوات CLI، المحللات) يكون نهج Push مناسبًا عبر Pushgateway.



2.1. نموذج Pull: نقطة نهاية HTTP



الطريقة القياسية هي تشغيل خادم HTTP منفصل على المنفذ 9090 (أو غيره) داخل تطبيقك:



use warp::Filter;use prometheus::{Encoder, TextEncoder};

async fn metrics_handler() -> Result<impl warp::Reply, warp::Rejection> { let metric_families = prometheus::gather(); let mut buffer = Vec::new(); let encoder = TextEncoder::new(); encoder.encode(&metric_families, &mut buffer).unwrap(); Ok(warp::reply::with_header(bu

المدونات

توصيات الكتب