c++ - गंभीरता और सिंक फ़िल्टरिंग के लिए Boost.Log के चैनल hiearchy का उपयोग करें



logging boost-log (1)

मैं कुछ समय से Boost.Log का अध्ययन कर रहा था और मुझे विश्वास है कि अब मेरे लिए अपने कोड आधार को log4cxx से Boost.Log में परिवर्तित करने का समय है। मुझे विश्वास है कि Boost.Log का डिज़ाइन और कार्यान्वयन मेरे कोड रखरखाव और उपयोग में काफी सुधार करेगा। मुझे पता है कि Boost.Log FAQ में एक पृष्ठ है जो कहता है

पदानुक्रमित लॉगर्स के लिए, वर्तमान लाइब्रेरी डिज़ाइन में इस सुविधा की कोई आवश्यकता नहीं है। Log4j में प्रदान किए जाने वाले मुख्य लाभों में से एक है, इस पुस्तकालय के एपेंडरों (सिंक, इस संदर्भ में) का निर्धारण करना जिसमें एक लॉग रिकॉर्ड समाप्त हो जाएगा। यह लाइब्रेरी फ़िल्टर करके उसी परिणाम को प्राप्त करती है।

मैं वैचारिक समानता को समझता हूं और Boost.Log को log4j / log4cxx में बनाने की कोशिश नहीं कर रहा हूं। बल्कि मेरा प्रश्न यह है कि मैं Boost.Log का उपयोग कैसे करूँ जो कि मैं वर्तमान में log4cxx से उपयोग करता हूँ उसी कार्यक्षमता को प्राप्त करने के लिए? विशेष रूप से, मैं एक लॉग स्रोत या चैनल पदानुक्रम में विशिष्ट नोड्स के लिए गंभीरता थ्रेशोल्ड और सिंक सेट करना चाहता हूं। उदाहरण के लिए, मेरे पास libA.moduleB.componentC.logD द्वारा आयोजित लॉगिंग स्रोत हैं जो डॉट्स द्वारा अलग किए गए पदानुक्रम में स्तरों के साथ हैं . । Log4cxx का उपयोग करके अधिक विशिष्ट लकड़हारा, libA.moduleB साथ INFO के लिए libA की समग्र सीमा निर्धारित की जा सकती है, DEBUG की दहलीज है।

libA.threshold=INFO
libA.moduleB.threshold=DEBUG

इसी तरह कोई पदानुक्रम में मनमाने ढंग से नोड्स के लिए सिंक संलग्न कर सकता है।

मेरा मानना ​​है कि Boost.Log के साथ एक समान क्षमता संभव है लेकिन मुझे वास्तव में इसे कैसे लागू करना है इस पर मदद / मार्गदर्शन की आवश्यकता है। साथ ही, मुझे यकीन है कि अन्य लोग जो बूस्ट में बदलाव करना चाहते हैं। अन्य रूपरेखाओं से भी यही सवाल होगा।

मैं आपकी टिप्पणियों की ईमानदारी से सराहना करता हूं।


Boost.Log सिंक में (ऑब्जेक्ट जो लॉग फाइल लिखते हैं) और लॉगर (वे ऑब्जेक्ट जिनके माध्यम से आपका एप्लिकेशन लॉग रिकॉर्ड्स को उत्सर्जित करता है) सीधे कनेक्ट नहीं होते हैं, और किसी भी लॉग से किसी भी सिंक को लॉग संदेश प्राप्त हो सकता है। कुछ लॉगर से रिकॉर्ड बनाने के लिए केवल विशेष सिंक में दिखाई देते हैं, आपको सिंक में फिल्टर की व्यवस्था करनी होगी ताकि सिंक के लिए अनावश्यक रिकॉर्ड को दबा दिया जाए जो उन्हें प्राप्त नहीं करना है और दूसरों के लिए पारित हो गया है। विभिन्न लॉगर से रिकॉर्ड को अलग करने के लिए, लॉगर्स को अपने द्वारा बनाए गए प्रत्येक रिकॉर्ड में अलग-अलग विशेषताओं को जोड़ना होगा। आमतौर पर यह channels साथ हासिल किया जाता channels - लकड़हारा एक चैनल विशेषता संलग्न करेगा जिसका उपयोग फ़िल्टर, स्वरूपक या सिंक में लकड़हारा की पहचान करने के लिए किया जा सकता है। चैनलों को अन्य विशेषताओं combined साथ combined जा सकता है, जैसे कि गंभीरता का स्तर। यह ध्यान दिया जाना चाहिए कि चैनल और गंभीरता का स्तर ओर्थोगोनल है, और किसी भी चैनल के पास किसी भी स्तर के रिकॉर्ड हो सकते हैं। विभिन्न विशेषताओं के मानों का फ़िल्टर में अलग-अलग विश्लेषण किया जाता है।

इसलिए, उदाहरण के लिए, यदि आप चाहते हैं कि चैनल ए से रिकॉर्ड ए.लॉग को फाइल करने के लिए लिखा जाए, और चैनल बी - से बीलॉग तक, आपको दो सिंक बनाने होंगे - प्रत्येक फ़ाइल के लिए एक, और तदनुसार अपने फिल्टर सेट करें।

BOOST_LOG_ATTRIBUTE_KEYWORD(a_severity, "Severity", severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_channel, "Channel", std::string)

logging::add_file_log(
    keywords::file_name = "A.log",
    keywords::filter = a_channel == "A");

logging::add_file_log(
    keywords::file_name = "B.log",
    keywords::filter = a_channel == "B");

विशेषता कीवर्ड और सुविधा सेटअप फ़ंक्शन को परिभाषित करने के बारे में डॉक्स देखें। अब आप प्रत्येक चैनल के लिए लकड़हारा बना सकते हैं और लॉग रिकॉर्ड्स को फ़िल्टर द्वारा सिंक करने के लिए रूट किया जाएगा।

typedef src::severity_channel_logger< severity_level, std::string > logger_type;

logger_type lg_a(keywords::channel = "A");
logger_type lg_b(keywords::channel = "B");

BOOST_LOG_SEV(lg_a, info) << "Hello, A.log!";
BOOST_LOG_SEV(lg_b, info) << "Hello, B.log!";

आपके पास एक ही चैनल के लिए उतने ही लकड़हारे हो सकते हैं जितने की आप - उनमें से प्रत्येक से संदेश एक ही सिंक के लिए निर्देशित किए जाएंगे।

हालांकि, यहां दो समस्याएं हैं। सबसे पहले, पुस्तकालय को चैनल की प्रकृति का कोई ज्ञान नहीं है और इसे सिर्फ एक अपारदर्शी मूल्य मानता है। इसे चैनल पदानुक्रम का कोई ज्ञान नहीं है, इसलिए "ए" और "ए.बी.बी" को अलग और असंबंधित चैनल माना जाता है। दूसरा, यदि आप एक ही फ़ाइल (जैसे "A" और "A.bb") को कई चैनल लिखना चाहते हैं, तो ऊपर दिए गए फ़िल्टर सेट करना मुश्किल हो सकता है। यदि आप अलग-अलग चैनलों के लिए अलग गंभीरता स्तर चाहते हैं तो चीजें और अधिक जटिल हो जाएंगी।

यदि चैनल पदानुक्रम आपके लिए महत्वपूर्ण नहीं है, तो आप गंभीरता थ्रेशोल्ड फ़िल्टर के साथ फ़िल्टर कॉन्फ़िगरेशन को आसान बना सकते हैं। उस फ़िल्टर के साथ आप प्रत्येक संबंधित चैनल के लिए न्यूनतम गंभीरता स्तर निर्धारित कर सकते हैं। यदि आप उप-चैनलों में गंभीरता की थ्रेसहोल्ड विरासत में लेना चाहते हैं तो आपका एकमात्र तरीका अपना स्वयं का फ़िल्टर लिखना है; पुस्तकालय बॉक्स से बाहर प्रदान नहीं करता है।

फ़िल्टर बनाने के कई तरीके हैं, लेकिन यह एक फ़ंक्शन लिखने के लिए उबलता है जो लॉग रिकॉर्ड्स से विशेषता मान स्वीकार करता है और यदि यह रिकॉर्ड फ़िल्टर और अन्यथा false true तो true । शायद, सबसे आसान तरीका Tutorial में दिखाया गया है, phoenix::bind साथ उदाहरण देखें: Boost.Phoenix से Boost.Phoenix

bool my_filter(
    logging::value_ref< severity_level, tag::a_severity > const& level,
    logging::value_ref< std::string, tag::a_channel > const& channel,
    channel_hierarchy const& thresholds)
{
    // See if the log record has the severity level and the channel attributes
    if (!level || !channel)
       return false;

    std::string const& chan = channel.get();

    // Parse the channel string, look for it in the hierarchy
    // and find out the severity threshold for this channel
    severity_level threshold = thresholds.find(chan);

    return level.get() >= threshold;
}

अब अपने नए फ़िल्टर का उपयोग करने के लिए सिंक को स्थापित करना इस तरह बदलना होगा:

logging::add_file_log(
    keywords::file_name = "A.log",
    keywords::filter = phoenix::bind(&my_filter, a_severity.or_none(), a_channel.or_none(), hierarchy_A));

logging::add_file_log(
    keywords::file_name = "B.log",
    keywords::filter = phoenix::bind(&my_filter, a_severity.or_none(), a_channel.or_none(), hierarchy_B));

यहाँ hierarchy_A और hierarchy_B दो लॉग फ़ाइलों के लिए विभिन्न चैनलों के लिए गंभीरता थ्रेसहोल्ड को संग्रहीत करने के लिए उपयोग की जाने वाली आपकी डेटा संरचनाएँ हैं।