تسجيل الدخول في تطبيقات Rust: أفضل ممارسات الإعداد

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

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

ابدأ الدورة

مقدمة: لماذا يعتبر التسجيل (Logging) أمرًا حيويًا لتطبيقات Rust

التسجيل (Logging) ليس مجرد تسجيل للأحداث في ملف. في بيئة الإنتاج (production)، تتيح السجلات عالية الجودة تشخيص الأخطاء بسرعة، وتتبع الأداء، وتحليل سلوك النظام. Rust، كونه لغة برمجة أنظمة، يقدم أدوات مرنة وعالية الأداء لهذه المهمة. في هذه المقالة، سنشرح أفضل ممارسات التسجيل في Rust: من اختيار الكريت (crate) إلى إعداد السجلات المنظمة (structured logs) وتدوير الملفات (rotation).



1. الأساسيات: كريتات log و env_logger

يقدم نظام Rust البيئي نهجًا معياريًا. يوفر كريت log طبقة تجريد (واجهة)، بينما يتم توصيل تطبيق محدد (الخلفية) بواسطة كريت منفصل، مثل env_logger أو pretty_env_logger.



التثبيت والإعداد

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

[dependencies]log = "0.4"env_logger = "0.10"


مثال أساسي

use log::{info, warn, error};

fn main() { env_logger::init();

info!("تم تشغيل التطبيق"); let user_id = 42; warn!("المستخدم {} غير موجود في ذاكرة التخزين المؤقت", user_id); error!("خطأ في الاتصال بقاعدة البيانات: {:?}", "timeout");}


هام: افتراضيًا، لا يتم عرض السجلات حتى تقوم بتعيين متغير البيئة RUST_LOG. قم بتشغيل البرنامج كالتالي:

RUST_LOG=info cargo run


مستويات التسجيل

يدعم كريت log خمسة مستويات قياسية (من الأعلى أولوية إلى الأقل):

  • error — أخطاء حرجة تتطلب تدخلاً فوريًا.
  • warn — تحذيرات بشأن مشاكل محتملة.
  • info — معلومات عامة حول سير التنفيذ.
  • debug — معلومات تصحيح أخطاء للمطورين.
  • trace — أحداث مفصلة للغاية (تُستخدم غالبًا في الحلقات).

التصفية حسب الوحدات (modules): RUST_LOG=my_crate=debug,other_crate=info.



2. التسجيل المتقدم: كريت tracing

للتطبيقات المعقدة (خوادم الويب، الخدمات المصغرة)، يُوصى باستخدام كريت tracing. يوفر مفهوم span (فترات زمنية) وتسجيلًا منظمًا مع سياق (context).



تثبيت tracing

[dependencies]tracing = "0.1"tracing-subscriber = "0.3"


مثال مع span

use tracing::{info, instrument, span, Level};use tracing_subscriber;

fn main() { tracing_subscriber::fmt::init();

let parent_span = span!(Level::INFO, "معالجة_الطلب", request_id = 123); let _guard = parent_span.enter(); process_data();}

#[instrument]fn process_data() { info!("بدأت معالجة البيانات"); std::thread::sleep(std::time::Duration::from_millis(50)); info!("اكتملت معالجة البيانات");}

الخاصية #[instrument] تنشئ تلقائيًا span للدالة وتسجل وقت التنفيذ. سيحتوي المخرَج على طوابع زمنية متداخلة، وهو أمر لا غنى عنه لتحليل الأداء (profiling).



3. السجلات المنظمة (JSON) وتدوير الملفات (Rotation)

في بيئة الإنتاج، غالبًا ما يتم جمع السجلات مركزيًا (ELK, Loki, Grafana). لهذا، من المناسب إخراج السجلات بتنسيق JSON.



الإخراج بتنسيق JSON باستخدام tracing-subscriber

use tracing_subscriber::fmt::format::Json;use tracing_subscriber::prelude::*;

fn main() { let format = Json::new() .with_timer(tracing_subscriber::fmt::time::UtcTime::rfc3339()) .with_target(true) .with_level(true);

tracing_subscriber::fmt() .event_format(format) .init();

tracing::info!("تم تشغيل الخادم على المنفذ 8080");}

الآن ستبدو السجلات كالتالي:

المدونات

توصيات الكتب