تطبيق C++ الخاص بك هو صندوق أسود؟ حان الوقت لإصلاح ذلك!
\n\nتخيل الموقف: لقد قمت بتشغيل خدمة C++ عالية التحميل، كل شيء يعمل بشكل رائع. يمر أسبوع، ثم آخر - وفجأة يشتكي المستخدمون من البطء. تذهب إلى الكود، وتضع std::cout في الأماكن الحرجة، وتعيد الترجمة، وتعيد التشغيل... هل هذا مألوف؟ إذا كان الأمر كذلك، فهذه المقالة لك.
في عالم الإنتاج C++، المراقبة والتسجيل ليسا رفاهية، بل ضرورة. بدونها، أنت أعمى مثل الخلد في غرفة مظلمة. لكن الخبر السار هو أن لغة C++ الحديثة (خاصة بدءًا من C++17) توفر جميع الأدوات لإنشاء نظام شفاف وقابل للمراقبة.
\n\nفي هذه المقالة، سنشرح كيفية تحويل تطبيقك من "صندوق أسود" إلى نظام شفاف تمامًا باستخدام مكتبات وتقنيات حقيقية. ستتعلم كيفية التسجيل بحيث تكون السجلات مفيدة، وليس مجرد ضوضاء، وكيفية إعداد مراقبة تساعد حقًا أثناء النشر.
\n\nلماذا std::cout مجرد ألم؟
\n\nيكتب العديد من مطوري C++ المبتدئين بهذه الطريقة:
\n\nstd::cout << "خطأ: الملف غير موجود" << std::endl;\n\nللوهلة الأولى - يبدو طبيعيًا. لكن دعنا نفكر في المشاكل:
\n\n- \n
- لا توجد مستويات أهمية. لا يمكنك التمييز بين رسالة التصحيح والخطأ الحرج. \n
- لا توجد طوابع زمنية. متى حدث هذا؟ أمس؟ منذ ثانية؟ \n
- لا يوجد سياق. أي مؤشر ترابط؟ أي طلب؟ أي بيانات؟ \n
- إخراج حظر.
std::endlيمسح المخزن المؤقت، مما يقتل الأداء في الأنظمة عالية التحميل. \n - لا يوجد تدوير. سينمو ملف السجل إلى أجل غير مسمى حتى يملأ القرص بأكمله. \n
باختصار، std::cout مناسب فقط للمشاريع الصغيرة. للإنتاج الجاد C++، تحتاج إلى نهج جاد لـ تسجيل تطبيقات C++.
Spdlog: صديقك الجديد المفضل
\n\nمكتبة spdlog هي المعيار الذهبي للتسجيل في لغة C++ الحديثة. إنها سريعة (واحدة من الأسرع)، وheader-only (لا حاجة للبناء)، ومرنة بشكل لا يصدق. دعنا نرى كيفية إعدادها بشكل صحيح.
\n\nالتثبيت والإعداد الأساسي
\n\nيمكن تضمين Spdlog عبر CMake FetchContent أو ببساطة نسخ ملفات الرأس. إليك الإعداد الأدنى للإنتاج:
\n\n#include <spdlog/spdlog.h>\n#include <spdlog/sinks/rotating_file_sink.h>\n#include <spdlog/sinks/stdout_color_sinks.h>\n#include <memory>\n\nvoid setup_logging() {\n // إنشاء مسجل وحدة التحكم مع إخراج ملون\n auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();\n \n // إنشاء مسجل ملف مع تدوير: 5 ملفات بحجم 10 ميجابايت لكل منها\n auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(\n "logs/myapp.log", // مسار الملف\n 10 * 1024 * 1024, // الحد الأقصى لحجم الملف: 10 ميجابايت\n 5 // عدد الملفات للتدوير\n );\n\n // الدمج في مسجل متعدد الخيوط\n auto logger = std::make_shared<spdlog::logger>(\n "main_logger",\n spdlog::sinks_init_list{console_sink, file_sink}\n );\n\n // تعيين التنسيق: [الوقت] [المستوى] [اسم_المسجل] الرسالة\n logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%n] %v");\n \n // تعيين مستوى التسجيل العام (يمكن تغييره أثناء التشغيل)\n logger->set_level(spdlog::level::info);\n \n // التسجيل كمسجل عام\n spdlog::set_default_logger(logger);\n}\n\nint main() {\n setup_logging();\n \n spdlog::info("تم تشغيل التطبيق. الإصدار: {}", APP_VERSION);\n spdlog::warn("لم يتم العثور على التكوين، نستخدم القيم الافتراضية");\n \n try {\n // بعض الكود\n throw std::runtime_error("خطأ في الاتصال بقاعدة البيانات");\n } catch (const std