Tracing لـ Rust: دليل شامل مع أمثلة

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

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

ابدأ الدورة

ما هو Tracing ولماذا هو مطلوب في Rust؟

\n\n

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

\n\n

الهدف الرئيسي لـ Tracing هو إعطاء المطور صورة كاملة عما يحدث داخل البرنامج: أي الدوال يتم استدعاؤها، وكم من الوقت تستغرق في التنفيذ، وما هي الأخطاء التي تظهر وكيف ترتبط ببعضها البعض. إنها أداة لا غنى عنها لتصحيح الأخطاء، وتحليل الأداء، ومراقبة أنظمة الإنتاج.

\n\n

المكتبة جزء من نظام Tokio البيئي وتُستخدم بنشاط في مشاريع مثل actix-web و axum و hyper والعديد غيرها.

\n\n

تثبيت Tracing

\n\n

لإضافة Tracing إلى مشروعك في Rust، افتح ملف Cargo.toml وأضف التبعيات التالية:

\n\n
[dependencies]\ntracing = "0.1"\ntracing-subscriber = "0.3"  # لإخراج السجلات إلى وحدة التحكم\ntracing-appender = "0.2"    # لتسجيل السجلات في ملف (اختياري)
\n\n

بعد ذلك، قم بتنفيذ الأمر cargo build لتنزيل المكتبات وتجميعها.

\n\n

بداية سريعة: المثال الأول

\n\n

لنكتب برنامجًا بسيطًا يسجل رسالة باستخدام Tracing:

\n\n
use tracing::{info, Level};\nuse tracing_subscriber::FmtSubscriber;\n\nfn main() {\n    // تهيئة المشترك (subscriber) لإخراج السجلات إلى stdout\n    let subscriber = FmtSubscriber::builder()\n        .with_max_level(Level::INFO)\n        .finish();\n    tracing::subscriber::set_global_default(subscriber)\n        .expect("فشل في تعيين المشترك العام");\n\n    // تسجيل رسالة بسيطة\n    info!("تم تشغيل التطبيق!");\n\n    // استدعاء دالة مع التتبع\n    process_data("example.txt");\n}\n\nfn process_data(filename: &str) {\n    // إنشاء نطاق (span) لتتبع الدالة\n    let span = tracing::span!(Level::INFO, "process_data", filename = filename);\n    let _guard = span.enter(); // الدخول إلى النطاق\n\n    info!("بدء معالجة الملف");\n    // ... بعض العمل ...\n    std::thread::sleep(std::time::Duration::from_millis(100));\n    info!("اكتملت المعالجة");\n}
\n\n

عند التشغيل، سترى إخراجًا منظمًا مع طوابع زمنية ومستويات وأسماء النطاقات.

\n\n

الطرق والوظائف الأساسية لـ Tracing

\n\n

فيما يلي 10 وظائف ووحدات ماكرو رئيسية لمكتبة Tracing مع وصف تفصيلي وأمثلة.

\n\n

1. tracing::span! — إنشاء نطاق

\n

ما يفعله: ينشئ نطاقًا جديدًا - وحدة عمل منطقية يمكن أن تكون متداخلة. للنطاق اسم ومستوى ومجموعة من الحقول.

\n

المعلمات:

\n
    \n
  • Level — مستوى التسجيل (ERROR, WARN, INFO, DEBUG, TRACE)
  • \n
  • target (اختياري) — سلسلة تحدد الوحدة النمطية
  • \n
  • field = value — حقول عشوائية للسياق
  • \n
\n

مثال:

\n
use tracing::Level;\n\nfn handle_request(id: u64) {\n    let span = tracing::span!(Level::INFO, "handle_request", request_id = id);\n    let _guard = span.enter();\n    // الكود داخل النطاق\n    tracing::info!("جارٍ معالجة الطلب");\n}
\n\n

2. tracing::info! — التسجيل على مستوى INFO

\n

ما يفعله: يسجل حدثًا بمستوى INFO. الحدث هو رسالة فردية يمكن ربطها بالنطاق الحالي.

\n

المعلمات:

\n
    \n
  • سلسلة التنسيق (كما في format!)
  • \n
  • وسائط التنسيق
  • \n
  • الحقول عبر field = value

توصيات