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

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

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

ابدأ الدورة

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



يُعد تسجيل الدخول أحد العناصر الأساسية لأي تطبيق إنتاج. فهو يساعد في تشخيص الأخطاء، وتتبع سلوك النظام، وجمع المقاييس. في نظام Rust البيئي، توجد عدة حلول ناضجة لذلك. في هذه المقالة، سنستعرض أفضل ممارسات تسجيل الدخول مع أمثلة كود واقعية.



1. الأساسيات: crate log والهندسة الواجهية



في Rust، المعيار الفعلي هو crate log. فهو يوفر واجهة مجردة غير مرتبطة بتنفيذ محدد. هذا يعني أنك تكتب السجلات عبر وحدات الماكرو log، بينما يتم تحديد أي backend سيعالجها (الإخراج إلى وحدة التحكم، إلى ملف، الإرسال إلى ELK) في مرحلة ربط crate آخر.



ربط تسجيل الدخول الأساسي



// Cargo.toml[dependencies]log = "0.4"env_logger = "0.11"


// main.rsuse log::{info, warn, error, debug};

fn main() { // تهيئة env_logger (يقرأ متغير RUST_LOG) env_logger::init();

info!("تم تشغيل التطبيق"); warn!("يتم استخدام التكوين الافتراضي"); error!("خطأ حرج: {}", "الملف غير موجود");}


قم بتشغيل التطبيق مع متغير البيئة:

RUST_LOG=info cargo run


سترى على الشاشة:

[2025-01-15T10:30:00Z INFO  my_app] تم تشغيل التطبيق[2025-01-15T10:30:00Z WARN  my_app] يتم استخدام التكوين الافتراضي[2025-01-15T10:30:00Z ERROR my_app] خطأ حرج: الملف غير موجود


2. ضبط مرن لمستويات تسجيل الدخول



يسمح المتغير RUST_LOG بتصفية الرسائل بمرونة حسب الوحدات والمستويات. هذا أمر بالغ الأهمية للمشاريع الكبيرة، حيث يمكن للضوضاء الناتجة عن سجلات التصحيح أن تخفي الأحداث الهامة.



أمثلة على التصفية



# الأخطاء والتحذيرات فقط من التطبيق بأكملهRUST_LOG=warn

# التصحيح فقط في وحدة database، والباقي infoRUST_LOG=info,my_crate::database=debug

# جميع المستويات، بما في ذلك traceRUST_LOG=trace


عملياً، استخدم هذا الأسلوب:

use std::env;

fn setup_logging() { if env::var("RUST_LOG").is_err() { // القيمة الافتراضية للتطوير env::set_var("RUST_LOG", "info,my_crate=debug"); } env_logger::init();}


3. تسجيل الدخول المنظم باستخدام tracing



للأنظمة المعقدة (الخدمات المصغرة، التطبيقات غير المتزامنة)، من الأفضل استخدام crate tracing. فهو يدعم النطاقات (spans) والحقول المنظمة، مما يسمح بربط السجلات في سلاسل الطلبات.



مقارنة بين log و tracing



  • log — بسيط، خفيف، مناسب للمشاريع الصغيرة.
  • tracing — قوي، يدعم النطاقات، الأحداث، الحقول المنظمة؛ مثالي للكود غير المتزامن والأنظمة ذات التجهيز بالتتبع.


مثال مع tracing و tracing-subscriber



// Cargo.toml[dependencies]tracing = "0.1"tracing-subscriber = "0.3"


use tracing::{info, error, span, Level};use tracing_subscriber::FmtSubscriber;

#[tokio::main]async fn main() { // إعداد subscriber للإخراج إلى stdout let subscriber = FmtSubscriber::builder() .with_max_level(Level::TRACE) .finish(); tracing::subscriber::set_global_default(subscriber) .expect("فشل في تعيين subscriber");

// إنشاء نطاق لطلب HTTP let request_span = span!(Level::INFO, "http_request", method = "GET", path = "/api/users"); let _guard = request_span.enter();

info!("بدأت معالجة الطلب");

// نطاق متداخل للعمل مع قاعدة البيانات let db_span = span!(Level::DEBUG, "db_query", query = "SELECT * FROM users"); let _db_gu

المدونات

توصيات الكتب