中文文档
BqLog هو نظام تسجيل خفيف الوزن وعالي الأداء يُستخدم في مشاريع مثل "Honor of Kings"، وقد تم نشره بنجاح ويعمل بسلاسة.
ويندوز 64 بت
ماك
لينكس
دائرة الرقابة الداخلية
أندرويد (X86_64،arm64-v8a،armeabi-v7a)
يونكس (اجتياز الاختبار على FreeBSD)
سي ++
جافا
كوتلين
ج#
بالمقارنة مع مكتبات التسجيل مفتوحة المصدر الموجودة، يقدم BqLog مزايا أداء كبيرة (راجع المعيار). إنه ليس مناسبًا للخوادم والعملاء فحسب، بل إنه متوافق أيضًا بشكل كبير مع الأجهزة المحمولة.
مع انخفاض استهلاك الذاكرة، في الحالة المعيارية المكونة من 10 سلاسل رسائل و20,000,000 إدخال سجل، يستهلك BqLog نفسه أقل من 1 ميغابايت من الذاكرة.
يوفر تنسيق سجل في الوقت الحقيقي عالي الأداء وعالي الضغط
يمكن استخدامه بشكل طبيعي في محركات الألعاب ( Unity
، Unreal
)، مع دعم الأنواع الشائعة المقدمة لـ Unreal.
يدعم أحرف وسلاسل UTF-8
و UTF-16
و UTF-32
، بالإضافة إلى أنواع المعلمات الشائعة مثل bool وfloat وdouble وأطوال وأنواع مختلفة من الأعداد الصحيحة
يدعم format specifications
C++20
يدعم التسجيل غير المتزامن مراجعة الأعطال لتجنب فقدان البيانات (مستوحى من XLog)
حجم صغير للغاية، حيث يبلغ حجم المكتبة الديناميكية حوالي 200 كيلو بايت فقط بعد تجميع Android
لا يقوم بإنشاء تخصيصات كومة إضافية في Java وC#، مما يتجنب إنشاء كائن جديد بشكل مستمر أثناء وقت التشغيل
يعتمد فقط على مكتبة لغة C القياسية وواجهات برمجة تطبيقات النظام الأساسي، ويمكن تجميعه في وضع Android ANDROID_STL = none
يدعم C++11
ومعايير التجميع الأحدث، ويمكن تجميعه وفقًا لمتطلبات -Wall -Wextra -pedantic -Werror الصارمة
تعتمد وحدة التجميع على CMake
وتوفر نصوص تجميعية لمنصات مختلفة، مما يجعلها سهلة الاستخدام
يدعم أنواع المعلمات المخصصة
ودية للغاية لاقتراحات التعليمات البرمجية
لماذا يعتبر BqLog سريعًا جدًا - تنسيق سجل مضغوط عالي الأداء في الوقت الفعلي
لماذا يعتبر BqLog سريعًا جدًا - المخزن المؤقت الدائري عالي التزامن
دمج BqLog في مشروعك
عرض توضيحي بسيط
نظرة عامة على الهندسة المعمارية
تعليمات استخدام واجهة برمجة التطبيقات للعملية الرئيسية
1-إنشاء كائن السجل
2-استرجاع كائن السجل
3-تسجيل الرسائل
4-واجهات برمجة التطبيقات الأخرى
التسجيل المتزامن وغير المتزامن
1. سلامة خيط التسجيل غير المتزامن
مقدمة للملحقين
1. تطبيق وحدة التحكم
2.TextFileAppender
3. تطبيق CompressedFileAppender (موصى به للغاية)
4. RawFileAppender
تعليمات التكوين
1. المثال الكامل
2. شرح مفصل
فك التشفير دون اتصال لمُلحقي التنسيق الثنائي
تعليمات البناء
1. بناء المكتبة
2. إنشاء العرض التجريبي وتشغيله
3. تعليمات تشغيل الاختبار الآلي
4. تعليمات تشغيل المعيار
موضوعات الاستخدام المتقدمة
1. لا يوجد تخصيص كومة
2. تسجيل الكائنات مع دعم الفئة
3. حماية البيانات عند الخروج غير الطبيعي للبرنامج
4. حول NDK وANDROID_STL = لا شيء
5. أنواع المعلمات المخصصة
6. استخدام BqLog في Unreal Engine
المعيار
1. وصف المعيار
2. رمز BqLog C++ المعياري
3. كود BqLog Java المعياري
4. رمز Log4j المعياري
5. النتائج المعيارية
يمكن دمج BqLog في مشروعك بأشكال مختلفة. بالنسبة لـ C++، فهو يدعم المكتبات الديناميكية والمكتبات الثابتة والملفات المصدر. بالنسبة لـ Java وC#، فهو يدعم المكتبات الديناميكية ذات التعليمات البرمجية المصدرية المجمعة. فيما يلي طرق تضمين BqLog:
يتضمن مستودع التعليمات البرمجية ملفات مكتبة ديناميكية مجمعة مسبقًا موجودة في /dist/dynamic_lib/. لدمج BqLog في مشروعك باستخدام ملفات المكتبة، عليك القيام بما يلي:
حدد ملف المكتبة الديناميكي المتوافق مع نظامك الأساسي وأضفه إلى نظام بناء مشروعك.
انسخ الدليل /dist/dynamic_lib/include إلى مشروعك وأضفه إلى قائمة أدلة التضمين. (إذا كنت تستخدم مكتبة .framework الخاصة بـ XCode، فيمكنك تخطي هذه الخطوة لأن ملف .framework يتضمن بالفعل ملفات الرأس).
يتضمن مستودع التعليمات البرمجية ملفات مكتبة ثابتة مجمعة مسبقًا موجودة في /dist/static_lib/. لدمج BqLog في مشروعك باستخدام ملفات المكتبة، عليك القيام بما يلي:
حدد ملف المكتبة الثابتة المتوافق مع نظامك الأساسي وأضفه إلى نظام بناء مشروعك.
انسخ الدليل /dist/static_lib/include إلى مشروعك وأضفه إلى قائمة أدلة التضمين. (إذا كنت تستخدم مكتبة .framework الخاصة بـ XCode، فيمكنك تخطي هذه الخطوة لأن ملف .framework يتضمن بالفعل ملفات الرأس).
يدعم BqLog أيضًا التضمين المباشر للكود المصدري في مشروعك لتجميعه. لدمج BqLog باستخدام التعليمات البرمجية المصدر، اتبع الخطوات التالية:
انسخ الدليل /src إلى مشروعك كمرجع للكود المصدري.
انسخ الدليل /include إلى مشروعك وأضفه إلى قائمة أدلة التضمين.
في حالة ترجمة إصدار Windows في Visual Studio، قم بإضافة /Zc:__cplusplus إلى خيارات الترجمة لضمان تحديد الدعم القياسي الحالي لبرنامج التحويل البرمجي C++ بشكل صحيح.
إذا كنت تستخدم الكود المصدري في NDK الخاص بنظام Android، فيرجى الرجوع إلى 4. حول NDK وANDROID_STL = لا شيء للاعتبارات المهمة.
في C#، يمكن استخدام BqLog عبر مكتبة ديناميكية أصلية وC# Wrapper، يدعم محركات Mono وMicrosoft CLR وUnity. Unity متوافق مع الوضعين Mono وIL2CPP. لاستخدام BqLog في C#، اتبع الخطوات التالية:
حدد ملف المكتبة الديناميكية المتوافق مع نظامك الأساسي من /dist/dynamic_lib/ وأضفه إلى مشروعك (بالنسبة إلى Unity، راجع استيراد Unity وتكوين المكونات الإضافية).
انسخ ملفات التعليمات البرمجية المصدر من /wrapper/csharp/src إلى مشروعك.
في Java، يمكن استخدام BqLog عبر مكتبة ديناميكية أصلية وJava Wrapper، مما يدعم بيئات JVM الشائعة وAndroid. لدمج BqLog في JVM، اتبع الخطوات التالية:
حدد ملف المكتبة الديناميكي المتوافق مع نظامك الأساسي من /dist/dynamic_lib/ وأضفه إلى مشروعك.
انسخ ملفات التعليمات البرمجية المصدر من /wrapper/Java/src إلى مشروعك.
(اختياري) انسخ الدليل /dist/dynamic_lib/include إلى مشروعك وأضفه إلى قائمة دليل التضمين إذا كنت تنوي استدعاء BqLog من NDK.
سيُخرج الكود التالي أكثر من 1000 سجل إلى وحدة التحكم الخاصة بك (أو ADB Logcat إذا كان يعمل بنظام Android)
#إذا تم تعريفها (WIN32) #تتضمن#endif#include #include int main() { #if Defined(WIN32) // قم بتبديل سطر أوامر Windows إلى UTF-8 لأن BqLog يُخرج كل النص النهائي بترميز UTF-8 لتجنب مشكلات العرض SetConsoleOutputCP(CP_UTF8); SetConsoleCP(CP_UTF8); #endif // هذه السلسلة هي تكوين السجل. هنا يقوم بتكوين مُسجل باستخدام مُلحق واحد (هدف الإخراج) يُسمى appender_0، والذي يُخرج إلى وحدة التحكم. std::string config = R"( # هدف إخراج هذا المُلحق هو وحدة التحكم appenders_config.appender_0.type=console # يستخدم هذا المُلحق التوقيت المحلي للطوابع الزمنية appenders_config.appender_0.time_zone=default local time # يُخرج هذا المُلحق سجلات من هذه المستويات الستة (لا توجد مسافات بينهما) appenders_config.appender_0.levels=[verbose,debug,info,warning,error,fatal] )"; bq::log log = bq::log::create_log("my_first_log", config); // قم بإنشاء كائن سجل باستخدام التكوين for(int i = 0; i < 1024; ++i) { log.info ("هذا سجل اختبار معلومات، سلسلة التنسيق هي UTF-8، المعلمة int: {}، المعلمة المنطقية :{}، السلسلة المعلمة 8: {}، السلسلة المعلمة 16: {}، السلسلة المعلمة 32: {} ، تعويم المعلمة: {}"، i، true، "utf8-string"، u"utf16-string"، U"utf32-string"، 4.3464f)؛ } log.error(U"هذا سجل اختبار خطأ، سلسلة التنسيق هي UTF-32"); bq::log::force_flush_all_logs(); // BqLog الافتراضي هو الإخراج غير المتزامن. للتأكد من أن السجلات مرئية قبل الخروج من البرنامج، قم بفرض التدفق لمزامنة الإخراج مرة واحدة. العودة 0؛ }
باستخدام System.Text؛ باستخدام النظام؛ الطبقة العامة demo_main { public static void Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; Console.InputEncoding = Encoding.UTF8; string config = @" # هدف الإخراج لهذا المُلحق هو وحدة التحكم appenders_config.appender_0.type=console # يستخدم هذا المُلحق التوقيت المحلي للطوابع الزمنية ppenders_config.appender_0.time_zone=التوقيت المحلي الافتراضي # يُخرج هذا المُلحق سجلات هذه المستويات الستة (بدون مسافات في بين) appenders_config.appender_0.levels=[verbose,debug,info,warning,error,fatal] "; bq.log log = bq.log.create_log("my_first_log"، config); // قم بإنشاء كائن سجل باستخدام التكوين for (int i = 0; i < 1024; ++i) { log.info("هذا سجل اختبار معلومات، سلسلة التنسيق هي UTF-16، المعلمة int:{}، المعلمة المنطقية:{}، السلسلة المعلمة:{}، المعلمة العائمة:{}"، i، صحيح، " نص السلسلة"، 4.3464f)؛ } bq.log.force_flush_all_logs(); Console.ReadKey(); }}
public class demo_main { public static void main(String[] args) { // TODO Auto-generated way stub String config = """ # هدف إخراج هذا المُلحق هو وحدة التحكم appenders_config.appender_0.type=console # يستخدم هذا المُلحق التوقيت المحلي للطوابع الزمنية appenders_config.appender_0.time_zone=default local time # يُخرج هذا المُلحق سجلات هذه المستويات الستة (بدون مسافات بينها) appenders_config.appender_0.levels=[verbose,debug,info,warning,error,fatal] """; bq.log log = bq.log.create_log("my_first_log"، config); // قم بإنشاء كائن سجل باستخدام التكوين for (int i = 0; i < 1024; ++i) { log.info("هذا سجل اختبار معلومات، سلسلة التنسيق هي UTF-16، المعلمة int:{}، المعلمة المنطقية:{}، السلسلة المعلمة:{}، المعلمة العائمة:{}"، i، صحيح، "نص السلسلة"، 4.3464f)؛ } bq.log.force_flush_all_logs(); } }
يوضح الرسم البياني أعلاه بوضوح البنية الأساسية لـ BqLog. على الجانب الأيمن من الرسم التخطيطي يوجد التنفيذ الداخلي لمكتبة BqLog، بينما على الجانب الأيسر يوجد البرنامج والكود الخاص بك. يمكن لبرنامجك استدعاء BqLog باستخدام الأغلفة المتوفرة (واجهات برمجة التطبيقات الموجهة للكائنات للغات مختلفة). في الرسم التخطيطي، يتم إنشاء سجلين: أحدهما يسمى "السجل أ" والآخر يسمى "السجل ب". يتم إرفاق كل سجل بملحق واحد أو أكثر. يمكن فهم المُلحق على أنه هدف الإخراج لمحتوى السجل. يمكن أن يكون هذا وحدة التحكم (سجلات ADB Logcat لنظام Android)، أو ملفات نصية، أو حتى تنسيقات متخصصة مثل ملفات السجل المضغوطة أو ملفات تنسيق السجل الثنائي العادي.
ضمن نفس العملية، يمكن لمغلفات اللغات المختلفة الوصول إلى نفس كائن السجل. على سبيل المثال، إذا تم إنشاء كائن سجل باسم Log A في Java، فيمكن أيضًا الوصول إليه واستخدامه من جانب C++ بالاسم Log A.
في الحالات القصوى، مثل لعبة تم تطويرها بواسطة Unity وتعمل على نظام Android، قد تقوم بإدراج لغات Java وKotlin وC# وC++ داخل نفس التطبيق. يمكنهم جميعًا مشاركة نفس كائن السجل. يمكنك إنشاء السجل على جانب Java باستخدام create_log، ثم الوصول إليه بلغات أخرى باستخدام get_log_by_name.
ملاحظة: تم الإعلان عن واجهات برمجة التطبيقات التالية في فئة bq::log (أو bq.log). لتوفير المساحة، يتم إدراج واجهات برمجة تطبيقات C++ فقط. واجهات برمجة التطبيقات في Java وC# متطابقة ولن يتم تكرارها هنا.
في C++، bq::string
هو نوع سلسلة UTF-8 في مكتبة BqLog. يمكنك أيضًا تمرير سلاسل على النمط C مثل char أو std::string
أو std::string_view
، والتي سيتم تحويلها تلقائيًا وضمنيًا.
يمكن إنشاء كائن سجل باستخدام الوظيفة الثابتة create_log. وإعلانها هو كما يلي:
//C++ API ////// إنشاء كائن سجل /// /// إذا كان اسم السجل عبارة عن سلسلة فارغة، فسيقوم bqLog تلقائيًا بتعيين كائن لك اسم السجل الفريد. إذا كان اسم السجل موجودًا بالفعل، فسيعيد كائن السجل الموجود مسبقًا ويستبدل التكوين السابق بالتكوين الجديد. /// سلسلة تكوين السجل ///كائن سجل، إذا فشل الإنشاء، فإن طريقة is_valid() الخاصة به ستعيد خطأ static log create_log(const bq::string& log_name, const bq::string& config_content);
يقوم الكود بإنشاء كائن سجل عن طريق تمرير اسم كائن السجل وسلسلة التكوين. يمكن الرجوع إلى تكوين السجل في تعليمات التكوين. فيما يلي بعض النقاط الرئيسية التي يجب ملاحظتها:
بغض النظر عما إذا كان C# أو Java، فإن كائن السجل الذي تم إرجاعه لن يكون فارغًا أبدًا. ومع ذلك، بسبب أخطاء التكوين أو لأسباب أخرى، قد يتم إنشاء كائن سجل غير صالح. ولذلك، يجب عليك استخدام الدالة is_valid() للتحقق من الكائن الذي تم إرجاعه. قد يؤدي تنفيذ العمليات على كائن غير صالح إلى تعطل البرنامج.
إذا تم تمرير سلسلة فارغة كاسم سجل، فسيقوم bqLog تلقائيًا بإنشاء اسم سجل فريد، مثل "AutoBqLog_1."
لن يؤدي استدعاء create_log على كائن سجل موجود بالفعل بنفس الاسم إلى إنشاء كائن سجل جديد ولكنه سيستبدل التكوين السابق بالتكوين الجديد. ومع ذلك، لا يمكن تعديل بعض المعلمات في هذه العملية؛ راجع تعليمات التكوين للحصول على التفاصيل.
باستثناء عند الاستخدام في NDK (راجع 4. حول NDK وANDROID_STL = لا شيء)، يمكنك تهيئة كائن السجل مباشرة في المتغيرات العامة أو الثابتة باستخدام واجهة برمجة التطبيقات هذه في مواقف أخرى.
إذا تم بالفعل إنشاء كائن سجل في مكان آخر، فيمكنك الحصول على كائن السجل الذي تم إنشاؤه مباشرةً باستخدام وظيفة get_log_by_name.
//C++ API ////// احصل على كائن السجل باسمه /// /// اسم كائن السجل الذي تريد البحث عنه ///كائن سجل، إذا لم يتم العثور على كائن السجل باسم محدد، فستعيد طريقة is_valid() الخاصة به خطأ static log get_log_by_name(const bq::string& log_name);
يمكنك أيضًا استخدام هذه الوظيفة لتهيئة كائن السجل في المتغيرات العامة أو الوظائف الثابتة. ومع ذلك، لاحظ أنه يجب عليك التأكد من وجود كائن السجل بالاسم المحدد بالفعل. بخلاف ذلك، سيكون كائن السجل الذي تم إرجاعه غير قابل للاستخدام، وسيُرجع أسلوب is_valid() الخاص به خطأ.
/// وظائف السجل الأساسية، هناك 6 مستويات سجل: /// مطول، تصحيح، معلومات، تحذير، خطأ، قالب فادحbq::enable_if_t ::value, bool> Verbose(const STR& log_content) const; القالب<اسم النوع STR، اسم النوع...الوسائط> bq::enable_if_t ::value, bool> Verbose(const STR& log_format_content, const Args&... args) const; القالب<اسم النوع STR> bq::enable_if_t ::value, bool> debug(const STR& log_content) const; القالب<اسم النوع STR، اسم النوع...الوسائط> bq::enable_if_t ::value, bool> debug(const STR& log_format_content, const Args&... args) const; القالب<اسم النوع STR> bq::enable_if_t ::value, bool> info(const STR& log_content) const; القالب<اسم النوع STR، اسم النوع...الوسائط> bq::enable_if_t ::value, bool> info(const STR& log_format_content, const Args&... args) const; القالب<اسم النوع STR> bq::enable_if_t ::value, bool> تحذير(const STR& log_content) const; القالب<اسم النوع STR، اسم النوع...الوسائط> bq::enable_if_t ::value, bool> تحذير(const STR& log_format_content, const Args&... args) const; القالب<اسم النوع STR> bq::enable_if_t ::value, bool> error(const STR& log_content) const; القالب<اسم النوع STR، اسم النوع...الوسائط> bq::enable_if_t ::value, bool> error(const STR& log_format_content, const Args&... args) const; القالب<اسم النوع STR> bq::enable_if_t ::value, bool> Fatal(const STR& log_content) const; القالب<اسم النوع STR، اسم النوع...الوسائط> bq::enable_if_t ::value, bool> Fatal(const STR& log_format_content, const Args&... args) const;
عند تسجيل الرسائل، انتبه إلى ثلاث نقاط رئيسية:
كما ترون، تنقسم سجلاتنا إلى ستة مستويات: مطول، وتصحيح الأخطاء، والمعلومات، والتحذير، والخطأ، والفادح، بما يتوافق مع Android. وتزداد أهميتها بالتتابع. عند إخراجها إلى وحدة التحكم، ستظهر بألوان مختلفة.
تشبه المعلمة STR المعلمة الأولى لـ printf ويمكن أن تكون أنواعًا مختلفة من السلاسل الشائعة، بما في ذلك:
Java.lang.String
سلسلة C #
ترميزات مختلفة لسلاسل نمط C++ و std::string
( char*
, char16_t*
, char32_t*
, wchar_t*
, std::string
, std::u8string
, std::u16string
, std::u32string
, std::wstring
، std::string_view
، std::u16string_view
، std::u32string_view
، std::wstring_view
وحتى أنواع السلاسل المخصصة، والتي يمكنك الرجوع إليها في أنواع المعلمات المخصصة )
يمكنك إضافة معلمات مختلفة بعد معلمة STR. سيتم تنسيق هذه المعلمات في الأماكن المحددة في STR، باتباع القواعد المشابهة لتنسيق std::format الخاص بـ C++20 (باستثناء عدم وجود دعم للوسائط الموضعية وتنسيق التاريخ والوقت). على سبيل المثال، يمثل استخدام {} واحدًا تنسيقًا افتراضيًا للمعلمة، ويحدد {:.2f} دقة تنسيق رقم الفاصلة العائمة. حاول استخدام المعلمات المنسقة لإخراج السجلات بدلاً من سلسلة السلاسل يدويًا. يعد هذا الأسلوب مثاليًا للأداء وتخزين التنسيق المضغوط.
تتضمن أنواع المعلمات المدعومة حاليًا ما يلي:
مؤشرات فارغة (الإخراج فارغًا)
المؤشرات (الإخراج كعنوان سداسي عشري يبدأ بـ 0x)
منطقي
أحرف أحادية البايت (char)
أحرف مزدوجة البايت (char16_t، wchar_t، C#'s char، Java's char)
أحرف ذات أربعة بايت (char32_t أو wchar_t)
أعداد صحيحة 8 بت
أعداد صحيحة غير موقعة ذات 8 بت
أعداد صحيحة 16 بت
أعداد صحيحة غير موقعة ذات 16 بت
أعداد صحيحة 32 بت
أعداد صحيحة غير موقعة 32 بت
أعداد صحيحة 64 بت
أعداد صحيحة غير موقعة 64 بت
أرقام الفاصلة العائمة 32 بت
أرقام الفاصلة العائمة 64 بت
أنواع POD أخرى غير معروفة في C++ (تقتصر على الأحجام 1 أو 2 أو 4 أو 8 بايت، ويتم التعامل معها على أنها int8 وint16 وint32 وint64 على التوالي)
السلاسل، بما في ذلك جميع أنواع السلاسل المذكورة في معلمة STR
أي فئة أو كائن في C# وJava (إخراج سلسلة ToString() الخاصة بهم)
أنواع المعلمات المخصصة، كما هو مفصل في أنواع المعلمات المخصصة
هناك واجهات برمجة تطبيقات إضافية شائعة الاستخدام يمكنها إنجاز مهام محددة. للحصول على أوصاف تفصيلية لواجهة برمجة التطبيقات، راجع bq_log/bq_log.h، بالإضافة إلى فئة bq.log في Java وC#. فيما يلي بعض واجهات برمجة التطبيقات الرئيسية التي يجب تسليط الضوء عليها:
////// قم بإلغاء تهيئة BqLog، يرجى استدعاء هذه الوظيفة قبل وجود البرنامج. /// static void uninit();
يوصى بتنفيذ uninit()
قبل الخروج من البرنامج أو إلغاء تثبيت المكتبة الديناميكية ذاتية التنفيذ التي تستخدم BqLog، وإلا فقد يتعطل البرنامج عند الخروج في ظل ظروف محددة معينة.
////// إذا كان bqLog غير متزامن، فقد يؤدي تعطل البرنامج إلى عدم استمرار حفظ السجلات الموجودة في المخزن المؤقت على القرص. /// إذا تم تمكين هذه الميزة، فسيحاول bqLog إجراء مسح قسري للسجلات الموجودة في المخزن المؤقت في حالة حدوث عطل. ومع ذلك، /// هذه الوظيفة لا تضمن النجاح، وتدعم فقط أنظمة POSIX. /// static void Enable_auto_crash_handle();
للحصول على مقدمة تفصيلية، راجع حماية البيانات عند الخروج غير الطبيعي للبرنامج
////// قم بمسح المخزن المؤقت لجميع كائنات السجل بشكل متزامن /// للتأكد من معالجة جميع البيانات الموجودة في المخزن المؤقت بعد المكالمة. /// static void force_flush_all_logs(); ////// قم بمسح المخزن المؤقت لكائن السجل هذا بشكل متزامن /// للتأكد من معالجة جميع البيانات الموجودة في المخزن المؤقت بعد المكالمة. /// void force_flush();
نظرًا لأن bqLog يستخدم التسجيل غير المتزامن بشكل افتراضي، فهناك أوقات قد ترغب فيها في مزامنة جميع السجلات وإخراجها على الفور. في مثل هذه الحالات، تحتاج إلى استدعاء force_flush() بالقوة.
////// سجل رد اتصال سيتم استدعاؤه عند إخراج رسالة سجل وحدة التحكم. /// يمكن استخدام هذا لنظام خارجي لمراقبة إخراج سجل وحدة التحكم. /// /// static void Register_console_callback(bq::type_func_ptr_console_callback callback); ////// إلغاء تسجيل رد اتصال وحدة التحكم. /// /// static void unregister_console_callback(bq::type_func_ptr_console_callback callback);
ينتقل إخراج ConsoleAppender إلى وحدة التحكم أو سجلات ADB Logcat على Android، لكن هذا قد لا يغطي جميع المواقف. على سبيل المثال، في محركات الألعاب المخصصة أو بيئة التطوير المتكاملة المخصصة، يتم توفير آلية لاستدعاء وظيفة رد اتصال لكل مخرجات سجل وحدة التحكم. يتيح لك ذلك إعادة معالجة وإخراج سجل وحدة التحكم في أي مكان في برنامجك.
تنبيه إضافي: لا تقم بإخراج أي سجلات BQ متزامنة ضمن رد اتصال وحدة التحكم حيث قد يؤدي ذلك بسهولة إلى حالة توقف تام.
////// تمكين أو تعطيل المخزن المؤقت لمُلحق وحدة التحكم. /// نظرًا لأن غلافنا قد يعمل في كل من الأجهزة الافتراضية C# وJava، ولا نريد استدعاء عمليات الاسترجاعات مباشرة من سلسلة رسائل أصلية، /// يمكننا تمكين هذا الخيار. بهذه الطريقة، سيتم حفظ جميع مخرجات وحدة التحكم في المخزن المؤقت حتى نحضرها. /// /// ///static void set_console_buffer_enable(bool Enable); /// /// جلب وإزالة إدخال السجل من المخزن المؤقت لمُلحق وحدة التحكم بطريقة آمنة لمؤشر الترابط. /// إذا لم يكن المخزن المؤقت لمُلحق وحدة التحكم فارغًا، فسيتم استدعاء وظيفة on_console_callback لإدخال السجل هذا. /// يرجى التأكد من عدم إخراج سجلات BQ المتزامنة داخل وظيفة رد الاتصال. /// /// وظيفة رد الاتصال التي سيتم استدعاؤها لإدخال السجل الذي تم جلبه إذا لم يكن المخزن المؤقت لمُلحق وحدة التحكم فارغًا ///صحيح إذا كان المخزن المؤقت لمُلحق وحدة التحكم ليس فارغًا ويتم جلب إدخال السجل؛ وإلا فسيتم إرجاع خطأ. static bool fetch_and_remove_console_buffer(bq::type_func_ptr_console_callback on_console_callback);
بالإضافة إلى اعتراض إخراج وحدة التحكم من خلال رد اتصال وحدة التحكم، يمكنك جلب مخرجات سجل وحدة التحكم بشكل فعال. في بعض الأحيان، قد لا نرغب في أن يأتي إخراج سجل وحدة التحكم من خلال رد اتصال لأنك لا تعرف من أي مؤشر ترابط سيأتي رد الاتصال (على سبيل المثال، في بعض الأجهزة الافتراضية C#، أو JVMs، قد يقوم VM بتنفيذ عملية جمع البيانات المهملة عندما تكون وحدة التحكم يتم استدعاء رد الاتصال، مما قد يؤدي إلى حدوث توقف أو تعطل).
تتضمن الطريقة المستخدمة هنا تمكين المخزن المؤقت لوحدة التحكم من خلال set_console_buffer_enable
. يؤدي هذا إلى تخزين كل مخرجات سجل وحدة التحكم في الذاكرة حتى نقوم باستدعاء fetch_and_remove_console_buffer
لاستردادها. لذلك، إذا اخترت استخدام هذه الطريقة، فتذكر جلب السجلات ومسحها على الفور لتجنب عدم تحرير الذاكرة.
تنبيه إضافي: لا تقم بإخراج أي سجلات BQ متزامنة ضمن رد اتصال وحدة التحكم حيث قد يؤدي ذلك بسهولة إلى حالة توقف تام.
تنبيه إضافي: إذا كنت تستخدم هذا الرمز في بيئة IL2CPP، فيرجى التأكد من وضع علامة on_console_callback على أنها غير آمنة ومزينة بالسمة [MonoPInvocCallback(typeof(type_console_callback))] .
////// قم بتعديل تكوين السجل، ولكن لا يمكن تعديل بعض الحقول، مثل buffer_size. /// /// ///boolset_config(const bq::string& config_content);
في بعض الأحيان قد ترغب في تعديل تكوين السجل داخل برنامجك. بالإضافة إلى إعادة إنشاء كائن السجل للكتابة فوق التكوين (انظر إنشاء كائن سجل)، يمكنك أيضًا استخدام واجهة إعادة التعيين. ومع ذلك، لاحظ أنه لا يمكن تعديل كافة عناصر التكوين بهذه الطريقة. للحصول على التفاصيل، راجع تعليمات التكوين
////// تعطيل مُلحق معين أو تمكينه مؤقتًا. /// /// /// void set_appenders_enable(const bq::string& appender_name, bool Enable) ;
بشكل افتراضي، تكون المُلحقات في التكوين نشطة، ولكن يتم توفير آلية هنا لتعطيلها مؤقتًا وإعادة تمكينها.
////// يعمل فقط عند تكوين اللقطة. /// سوف يقوم بفك تشفير المخزن المؤقت لللقطة إلى نص. /// /// ما إذا كان الطابع الزمني لكل سجل هو توقيت جرينتش أو التوقيت المحلي ///المخزن المؤقت لللقطة التي تم فك تشفيرها bq::string take_snapshot(bool use_gmt_time) const;
في بعض الأحيان، تتطلب بعض الميزات الخاصة إخراج الجزء الأخير من السجلات، وهو ما يمكن القيام به باستخدام ميزة اللقطة. لتمكين هذه الميزة، تحتاج أولاً إلى تنشيط اللقطة في تكوين السجل وتعيين الحد الأقصى لحجم المخزن المؤقت بالبايت. بالإضافة إلى ذلك، تحتاج إلى تحديد مستويات السجل والفئات التي سيتم تصفيتها لللقطة (اختياري). للحصول على التكوين التفصيلي، يرجى الرجوع إلى تكوين اللقطة. عند الحاجة إلى لقطة، سيؤدي استدعاء take_snapshot() إلى إرجاع السلسلة المنسقة التي تحتوي على أحدث إدخالات السجل المخزنة في المخزن المؤقت لللقطة. في C++، النوع هو bq::string
، والذي يمكن تحويله ضمنيًا إلى std::string
.
namespace bq{ namespace Tools { // هذه فئة مساعدة لفك تشفير تنسيقات السجل الثنائي. // لاستخدامه، قم أولاً بإنشاء كائن log_decoder، // ثم قم باستدعاء وظيفة فك التشفير الخاصة به لفك التشفير. // بعد كل مكالمة ناجحة، // يمكنك استخدام get_last_decoded_log_entry() لاسترداد النتيجة التي تم فك تشفيرها. // تقوم كل مكالمة بفك تشفير إدخال سجل واحد. بنية log_decoder { خاص: bq::string decode_text_; bq::appender_decode_result result_ = bq::appender_decode_result::success; uint32_t Handle_ = 0; public: ////// قم بإنشاء كائن log_decoder، حيث يتوافق كل كائن log_decoder مع ملف سجل ثنائي. /// /// يمكن أن يكون مسار ملف السجل الثنائي مسارًا نسبيًا أو مسارًا مطلقًا log_decoder(const bq::string& log_file_path); ~log_decoder(); ////// فك تشفير إدخال السجل. سيؤدي كل استدعاء لهذه الوظيفة إلى فك تشفير إدخال سجل واحد فقط /// ///نتيجة فك التشفير، appender_decode_result::eof يعني أنه تم فك تشفير ملف السجل بالكامل bq::appender_decode_result decode(); ////// احصل على آخر نتيجة لفك التشفير /// ///bq::appender_decode_result get_last_decode_result() const; /// /// احصل على آخر محتوى إدخال سجل فك التشفير /// ///const bq::string& get_last_decoded_log_entry() const; }; } }
هذه فئة أدوات مساعدة يمكنها فك تشفير إخراج ملفات السجل بواسطة المُلحقات من النوع الثنائي في وقت التشغيل، مثل CompressedFileAppender وRawFileAppender.
لاستخدامه، قم أولاً بإنشاء كائن log_decoder. بعد ذلك، في كل مرة تقوم فيها باستدعاء الدالة decode()، تقوم بفك تشفير إدخال سجل واحد بالتسلسل. إذا كانت النتيجة التي تم إرجاعها هي bq::appender_decode_result::success، فيمكنك الاتصال بـ get_last_decoded_log_entry() للحصول على محتوى النص المنسق لآخر إدخال سجل تم فك تشفيره. إذا كانت النتيجة bq::appender_decode_result::eof، فهذا يعني أن جميع السجلات قد تمت قراءتها بالكامل.
يسمح لك BqLog بتكوين ما إذا كان كائن السجل متزامنًا أو غير متزامن من خلال إعداد thread_mode. الاختلافات الرئيسية بين هذين الوضعين هي كما يلي:
التسجيل المتزامن | التسجيل غير المتزامن | |
---|---|---|
سلوك | بعد استدعاء وظيفة التسجيل، تتم كتابة السجل على الفور إلى المُلحق المقابل. | بعد استدعاء وظيفة التسجيل، لا تتم كتابة السجل على الفور؛ بدلاً من ذلك، يتم تسليمه إلى مؤشر ترابط عامل للمعالجة الدورية. |
أداء | منخفض، نظرًا لأن الخيط الذي يكتب السجل يحتاج إلى الحظر والانتظار حتى تتم كتابة السجل إلى المُلحق المقابل قبل العودة من وظيفة التسجيل. | عالي، حيث أن الخيط الذي يكتب السجل لا يحتاج إلى انتظار الإخراج الفعلي ويمكنه العودة فورًا بعد التسجيل. |
سلامة الموضوع | عالية، ولكنها تتطلب عدم تعديل معلمات السجل أثناء تنفيذ وظيفة التسجيل. | عالية، ولكنها تتطلب عدم تعديل معلمات السجل أثناء تنفيذ وظيفة التسجيل. |
من المفاهيم الخاطئة الشائعة حول التسجيل غير المتزامن أنه أقل أمانًا لمؤشر الترابط، حيث يشعر المستخدمون بالقلق من إمكانية استعادة المعلمات بحلول الوقت الذي يقوم فيه مؤشر ترابط العامل بمعالجة السجل. على سبيل المثال:
{ const char str_array[5] = {'T', 'E', 'S', 'T', ' �'}; const char* str_ptr = str_array; log_obj.info ("هذه معلمة اختبار: {}، {}"، str_array، str_ptr)؛ }
في المثال أعلاه، تم تخزين str_array
على المكدس، وبمجرد الخروج من النطاق، لم تعد ذاكرته صالحة. قد يشعر المستخدمون بالقلق من أنه في حالة استخدام التسجيل غير المتزامن، بحلول الوقت الذي يعالج فيه مؤشر ترابط العامل السجل، ستكون str_array
و str_ptr
متغيرات غير صالحة.
ومع ذلك، لن يحدث مثل هذا الموقف لأن BqLog ينسخ جميع محتويات المعلمات إلى ring_buffer
الداخلي الخاص به أثناء تنفيذ وظيفة info
. بمجرد عودة وظيفة info
، لن تكون هناك حاجة للمتغيرات الخارجية مثل str_array
أو str_ptr
. علاوة على ذلك، لن يقوم ring_buffer
بتخزين عنوان مؤشر const char*
ولكنه سيخزن دائمًا السلسلة بأكملها.
تنشأ المشكلة المحتملة الحقيقية في السيناريو التالي:
static std::string global_str = "مرحبًا بالعالم"; // هذا متغير عام تم تعديله بواسطة خيوط متعددة.void thread_a() { log_obj.info("هذه معلمة اختبار: {}"، global_str); }
إذا تغير محتوى global_str
أثناء تنفيذ وظيفة info
، فقد يؤدي ذلك إلى سلوك غير محدد. سيبذل BqLog قصارى جهده لمنع حدوث أي عطل، ولكن لا يمكن ضمان صحة الإخراج النهائي.
يمثل المُلحق هدف إخراج السجل. إن مفهوم المُلحقات في bqLog هو نفسه الموجود في Log4j. حاليًا، يوفر bqLog الأنواع التالية من المُلحقات:
هدف الإخراج لهذا المُلحق هو وحدة التحكم، بما في ذلك ADB لنظام Android ووحدة التحكم المقابلة لنظام iOS. ترميز النص هو UTF-8.
يقوم هذا المُلحق بإخراج ملفات السجل مباشرة بتنسيق نص UTF-8.
يقوم هذا المُلحق بإخراج ملفات السجل بتنسيق مضغوط، وهو highly recommended format by bqLog
. إنه يتمتع بأعلى أداء بين جميع المُلحقين وينتج أصغر ملف إخراج. ومع ذلك، الملف النهائي يحتاج إلى فك التشفير. يمكن إجراء فك التشفير أثناء فك التشفير في وقت التشغيل، أو فك التشفير في وضع عدم الاتصال.
يقوم هذا الملحق بإخراج محتوى السجل الثنائي من الذاكرة مباشرة إلى ملف. أدائه أعلى من TextFileAppender، لكنه يستهلك مساحة تخزين أكبر. الملف النهائي يحتاج إلى فك التشفير. يمكن إجراء فك التشفير أثناء فك التشفير في وقت التشغيل، أو فك التشفير في وضع عدم الاتصال. لا يُنصح باستخدام هذا المُلحق.
فيما يلي مقارنة شاملة بين المُلحقات المختلفة:
اسم | هدف الإخراج | قابلة للقراءة مباشرة | أداء الإخراج | حجم الإخراج |
---|---|---|---|---|
ConsoleAppender | وحدة التحكم | ✔ | قليل | - |
TextFileAppender | ملف | ✔ | قليل | كبير |
CompressedFileAppender | ملف | ✘ | عالي | صغير |
RawFileAppender | ملف | ✘ | واسطة | كبير |
يشير التكوين إلى سلسلة التكوين في وظائف create_log وreset_config. تستخدم هذه السلسلة تنسيق ملف الخصائص وتدعم # تعليقًا (ولكن تذكر أن تبدأ سطرًا جديدًا بـ # للتعليقات).
وفيما يلي مثال كامل:
# يقوم هذا التكوين بإعداد كائن سجل بإجمالي 5 مُلحقات، بما في ذلك مُلحقان TextFileAppenders اللذان يُخرجان إلى ملفين مختلفين.# يُسمى المُلحق الأول appender_0 ونوعه هو ConsoleAppenderappenders_config.appender_0.type=console# المنطقة الزمنية لـ appender_0 هي التوقيت المحلي للنظامappenders_config.appender_0.time_zone=التوقيت المحلي الافتراضي# appender_0 سيخرج جميع المستويات الستة للسجلات (ملاحظة: يجب ألا تكون هناك مسافات بين مستويات السجل، وإلا سيفشل التحليل)appenders_config.appender_0.levels=[verbose,debug ,info,warning,error,fatal]# الملحق الثاني اسمه appender_1 ونوعه TextFileAppenderappenders_config.appender_1.type=text_file# المنطقة الزمنية لـ appender_1 هي GMT وهي UTC+0appenders_config.appender_1.time_zone=gmt# appender_1 فقط سجلات مخرجات معلومات المستوى وما فوق، سيتم تجاهل الآخرينappenders_config.appender_1.levels=[info,warning,error,fatal]# سيكون مسار appender_1 في دليل bqLog النسبي للبرنامج، مع أسماء الملفات التي تبدأ بـ عادي، متبوعة بـ التاريخ وامتداد .log# على iOS، سيتم حفظه في /var/mobile/Containers/Data/Application/[APP]/Library/Caches/bqLog# على Android، سيتم حفظه في [android.content.Context .getExternalFilesDir()]/bqLogappenders_config.appender_1.file_name=bqLog/normal# الحد الأقصى لحجم الملف هو 10,000,000 بايت؛ إذا تم تجاوزه، فسيتم إنشاء ملف جديدappenders_config.appender_1.max_file_size=10000000# سيتم تنظيف الملفات الأقدم من عشرة أيام upappenders_config.appender_1.expire_time_days=10# إذا تجاوز الحجم الإجمالي للمخرجات 100,000,000 بايت، فسيتم تنظيف الملفات بدءًا من oldappenders_config.appender_1.capacity_limit=100000000# المُلحق الثالث اسمه appender_2 ونوعه TextFileAppenderappenders_config.appender_2.type=text_file# سيخرج appender_2 جميع مستويات logsappenders_config.appender_2.levels=[all]# مسار appender_2 سيكون في دليل bqLog النسبي للبرنامج، مع أسماء الملفات التي تبدأ بـ new_normal، متبوعة بالتاريخ و.log Extensionappenders_config.appender_2.file_name=bqLog/new_normal# هذا الخيار فعال فقط على Android، حيث يتم حفظ السجلات في دليل التخزين الداخلي، وهو [android .content.Context.getFilesDir()]/bqLogappenders_config.appender_2.is_in_sandbox=true# المُلحق الرابع يُسمى appender_3 ونوعه CompressedFileAppenderappenders_config.appender_3.type=compressed_file# appender_3 سوف يُخرج جميع مستويات logsappenders_config.appender_3.levels=[all ]# مسار appender_3 سيكون في المسار المطلق ~/bqLog دليل البرنامج، مع أسماء الملفات التي تبدأ بـ Compress_log، متبوعًا بالتاريخ و.logcompr Extensionappenders_config.appender_3.file_name=~/bqLog/compress_log# تم تسمية المُلحق الخامس appender_4 ونوعه RawFileAppenderappenders_config.appender_4.type=raw_file# appender_4 معطل افتراضيًا ويمكن تمكينه لاحقًا باستخدام set_appenders_enableappenders_config.appender_4.enable=false# سيخرج appender_4 جميع مستويات logsappenders_config.appender_4.levels=[all]# المسار لـ appender_4 سيكون في دليل bqLog النسبي للبرنامج، مع أسماء الملفات التي تبدأ بـ Raw_log، متبوعة بالتاريخ و.lograw Extensionappenders_config.appender_4.file_name=bqLog/raw_log# لن تتم معالجة السجلات إلا إذا كانت فئتها تبدأ بـ ModuleA، ModuleB. SystemC، وإلا سيتم تجاهل كل شيء (سيتم شرح مفهوم الفئة بالتفصيل في موضوعات الاستخدام المتقدمة لاحقًا)appenders_config.appender_4.categories_mask=[ModuleA,ModuleB.SystemC]# إجمالي حجم المخزن المؤقت غير المتزامن هو 65535 بايت؛ تم شرح المعنى المحدد Laterlog.buffer_size=65535# مستوى موثوقية السجل طبيعي؛ تم شرح المعنى المحدد Laterlog.reliable_level=normal# لن تتم معالجة السجلات إلا إذا كانت فئتها تتطابق مع أحرف البدل الثلاثة التالية، وإلا فسيتم تجاهلها جميعًا (يتم شرح مفهوم الفئة بالتفصيل في موضوعات الاستخدام المتقدمة لاحقًا)log.categories_mask= [*default,ModuleA,ModuleB.SystemC]# هذا سجل غير متزامن؛ السجلات غير المتزامنة هي السجل الأعلى أداءً والموصى به typelog.thread_mode=async# إذا كان مستوى السجل خطأ أو فادحًا، فقم بتضمين معلومات مكدس الاستدعاءات مع كل إدخال سجلlog.print_stack_levels=[error,fatal]# تمكين وظيفة اللقطة، حجم ذاكرة التخزين المؤقت لللقطة هو 64Ksnapshot .buffer_size=65536# سيتم تسجيل السجلات التي تحتوي على المعلومات ومستويات الخطأ فقط في اللقطةnapshot.levels=[info,error]# فقط السجلات التي تبدأ فئتها بـ ModuleA، سيتم تسجيل ModuleB.SystemC في اللقطة، وإلا سيتم تجاهلهالقطة .categories_mask=[ModuleA.SystemA.ClassA,ModuleB]
appenders_config
عبارة عن مجموعة من التكوينات للملحقين. المعلمة الأولى التي تتبع appenders_config
هي اسم المُلحق، وجميع المُلحقين الذين يحملون نفس الاسم يتشاركون في نفس التكوين.
اسم | مطلوب | القيم القابلة للتكوين | تقصير | ينطبق على ConsoleAppender | تنطبق على TextFileAppender | ينطبق على CompressedFileAppender | ينطبق على RawFileAppender |
---|---|---|---|---|---|---|---|
يكتب | ✔ | وحدة التحكم، ملف نصي، ملف مضغوط، ملف_خام | ✔ | ✔ | ✔ | ✔ | |
يُمكَِن | ✘ | ما إذا كان Appender ممكّنًا بشكل افتراضي | حقيقي | ✔ | ✔ | ✔ | ✔ |
المستويات | ✘ | مجموعة من مستويات السجل | [الجميع] | ✔ | ✔ | ✔ | ✔ |
time_zone | ✘ | بتوقيت جرينتش أو أي سلسلة أخرى | التوقيت المحلي | ✔ | ✔ | ✔ | ✔ |
file_name | ✔ | المسار النسبي أو المطلق | ✘ | ✔ | ✔ | ✔ | |
is_in_sandbox | ✘ | صحيح، كاذب | خطأ شنيع | ✘ | ✔ | ✔ | ✔ |
max_file_size | ✘ | عدد صحيح موجب أو 0 | 0 | ✘ | ✔ | ✔ | ✔ |
experi_time_days | ✘ | عدد صحيح موجب أو 0 | 0 | ✘ | ✔ | ✔ | ✔ |
سعة_الحد | ✘ | عدد صحيح موجب أو 0 | 0 | ✘ | ✔ | ✔ | ✔ |
Categories_mask | ✘ | مجموعة من السلاسل المغلقة في [] | فارغ | ✔ | ✔ | ✔ | ✔ |
يحدد نوع الملحق.
console
: يمثل ConsoleAppender
text_file
: يمثل TextFileAppender
compressed_file
: يمثل CompressedFileAppender
raw_file
: يمثل RawFileAppender
الافتراضيات إلى true
. إذا تم تعيينه على false
، فسيتم تعطيل المُلحق افتراضيًا ويمكن تمكينه لاحقًا باستخدام set_appenders_enable
.
مصفوفة محاطة بـ []
، تحتوي على أي مجموعة من verbose
أو debug
أو info
أو warning
error
أو fatal
أو [all]
لقبول جميع المستويات. ملاحظة: لا تقم بتضمين مسافات بين المستويات، وإلا فسوف يفشل التحليل.
يحدد المنطقة الزمنية للسجلات. يمثل gmt
توقيت غرينتش (UTC+0)، وأي سلسلة أخرى أو تركها فارغة ستستخدم المنطقة الزمنية المحلية. تؤثر المنطقة الزمنية على شيئين:
الطابع الزمني لسجلات النص المنسق (ينطبق على ConsoleAppender وTextFileAppender)
سيتم إنشاء ملف سجل جديد عند تجاوز منتصف الليل في المنطقة الزمنية المحددة (ينطبق على TextFileAppender وCompressedFileAppender وRawFileAppender).
المسار وبادئة اسم الملف لحفظ الملفات. يمكن أن يكون المسار مطلقًا (غير مستحسن لنظامي التشغيل Android وiOS) أو نسبيًا. سيكون اسم ملف الإخراج النهائي هو هذا المسار والاسم، متبوعًا بالتاريخ ورقم الملف وامتداد المُلحق.
ذات معنى فقط على Android:
true
: يتم تخزين الملفات في دليل التخزين الداخلي (android.content.Context.getFilesDir()). إذا لم تكن متوفرة، فسيتم تخزينها في دليل التخزين الخارجي (android.content.Context.getExternalFilesDir()). إذا لم يكن ذلك متاحًا أيضًا، فسيتم تخزينها في دليل ذاكرة التخزين المؤقت (android.content.Context.getCacheDir()).
false
: يتم تخزين الملفات في دليل التخزين الخارجي بشكل افتراضي. إذا لم تكن متوفرة، يتم تخزينها في دليل التخزين الداخلي. إذا لم يكن ذلك متاحًا أيضًا، فسيتم تخزينه في دليل ذاكرة التخزين المؤقت.
الحد الأقصى لحجم الملف بالبايت. عندما يتجاوز الملف المحفوظ هذا الحجم، يتم إنشاء ملف سجل جديد، مع زيادة أرقام الملفات بشكل تسلسلي. 0
تعطيل هذه الميزة.
الحد الأقصى لعدد الأيام للاحتفاظ بالملفات. سيتم حذف الملفات الأقدم من هذا تلقائيًا. 0
تعطيل هذه الميزة.
الحد الأقصى للحجم الإجمالي للملفات التي يخرجها هذا المُلحق في دليل الإخراج. إذا تم تجاوز هذا الحد، فسيتم حذف الملفات بدءًا من الأقدم حتى يصبح الحجم الإجمالي ضمن الحد. 0
تعطيل هذه الميزة.
إذا كان كائن السجل هو كائن سجل يدعم الفئات، فيمكن استخدامه لتصفية قائمة الفئات الشبيهة بالشجرة. عندما لا يكون المصفوفة فارغة، تكون هذه الميزة نشطة. على سبيل المثال، يعني [*default,ModuleA,ModuleB.SystemC]
أن السجلات بالفئة الافتراضية