2011-12-01 15 views
7

तो मेरी समस्या लॉगिंग के बारे में है, और लॉग स्टेटमेंट को कैसे संभालना है जो आपके कोड और आपके रनटाइम व्यवहार पर प्रभाव डाल सकता है।लॉगिंग सही

लॉग फाइलें ... प्रत्येक प्रोग्राम को प्रोपर समस्या हल करने के लिए उन्हें लिखना चाहिए, लेकिन यह सही तरीके से कैसे करें?

अधिकांश लॉग-स्टेटमेंट प्राप्त करने के लिए महंगे हैं क्योंकि उन्हें उपयोगी जानकारी प्रदान करनी चाहिए और वे हमेशा बनाए जाते हैं, यहां तक ​​कि लॉगिंग पूरी तरह से अक्षम होती है।

लॉगिंग xmls, inode या कुछ सेटिंग्स आदि द्वारा कॉन्फ़िगर किया जा सकता है लेकिन यह स्ट्रिंग बिल्डिंग समस्या को हल नहीं करता है।

उदाहरण के लिए निम्नलिखित कोड हमेशा एक विशाल आलसी लोड पेड़ लोड कर रहा है जो सामान्य निष्पादन के दौरान कभी भी लोड नहीं किया जाएगा।

पूरे वृक्ष केवल इस प्रवेश बयान के लिए बनाई गई है लॉग फ़ाइल में प्रदर्शित करने के लिए

(ठीक है, मुझे पता है ..., लेकिन यह सिर्फ सभी जटिल प्रवेश तरीकों कि में मौजूद है के लिए एक स्थानापन्न है ज्यादातर कार्यक्रमों जो सामान्य रिहाई निष्पादन) के दौरान कभी नहीं निष्पादित किया जाना चाहिए

public void SomeMethod(){ 
    logger.Debug(someObject.GetHeavyDescriptionFromLazyTree()); 
} 

विधि someObject.GetHeavyDescriptionFromLazyTree() हमेशा भले ही शुरू हो जाती है लॉगिंग बंद है, इसलिए वहाँ की तरह इस समस्या के लिए कुछ सामान्य समाधान हैं:

public void SomeMethod(){ 
#if DEBUG 
    logger.Debug(someObject.GetHeavyDescriptionFromLazyTree()); 
#endif  
} 

public void SomeMethod(){ 
    if(logger.DoLogDebug()) 
     logger.Debug(someObject.GetHeavyDescriptionFromLazyTree()); 
} 

मुझे लगता है कि यह स्पष्ट है कि #if DEBUG कंपाइलर ध्वज उत्पादक कोड के लिए कोई समाधान नहीं है। यदि मैं logger.DoLogDebug() का उपयोग करता हूं तो लॉगिंग सक्षम होने पर जांचने के लिए अत्यधिक कोड होगा ... इसलिए यह समाधान भी नहीं हो सकता है।

मैंने सोचा था कि ConditionalAttribute मदद कर सकता है लेकिन यह भी संकलक झंडे करने के लिए बाध्य है और यह GetHeavyDescriptionFromLazyTree

[Conditional("DEBUG")] 
public void Debug(string debugMessage) 
{ 
    Console.WriteLine(debugMessage); 
} 

करने के लिए कॉल तो मैं एक प्रवेश समाधान के लिए देख रहा हूँ निष्क्रिय नहीं है जो

  • डीबग कथन
  • के साथ मेरे स्रोत कोड को अत्यधिक बाधित नहीं कर रहा है जहां रनटाइम के दौरान लॉगिंग स्तर तय किया जाता है संकलन समय पर नहीं
  • जहां बयान केवल हल कर रहे हैं यदि आवश्यक (LogLevel> definedLogLevel)

सर्वश्रेष्ठ उत्तर ;-)

संपादित के लिए अतिरिक्त loglines: मैं .NET 2.0 में

उत्तर

5
एक समाधान के लिए देख रहा हूँ

logger.Debug(() => someObject.GetHeavyDescriptionFromLazyTree()); 

यह है:

वन 'आलसी प्रवेश' के लिए दृष्टिकोण (एक समारोह प्रतिनिधि उस संदेश देता है बनाने के लिए) के बजाय प्रत्यक्ष मूल्यांकन का उपयोग करने से एक अभिव्यक्ति का उपयोग करने के लिए है अपने स्वयं के डाउनसाइड्स (प्रतिनिधि का निर्माण), लेकिन यह महंगी विधि से सस्ता हो सकता है। आम तौर पर आप इसे एक अधिभार के रूप में प्रदान करेंगे और केवल उस मामले में इसका उपयोग करेंगे जहां आप जानते हैं कि अभिव्यक्ति का मूल्यांकन महंगा है।

+0

आपके समाधान के लिए धन्यवाद, यह बहुत अच्छा लगता है लेकिन मैं भूल गया, इसे .NET 2.0 :-( – oberfreak

+0

@oberfreak के साथ हल किया जाना चाहिए, मुझे लगता है कि मानक 'अगर' चेक आपकी सबसे अच्छी शर्त है; उम्मीद है कि आप लॉगिंग बहुत महंगा नहीं है। –

+0

अपहरण .NET 2.0 के साथ _not_ क्यों काम नहीं करना चाहिए? मैं यह हमेशा VS.NET 2010 और .NET 2.0 के साथ लक्ष्य मंच के रूप में करता हूं। –

0

आप इसे web.config या app.config द्वारा कॉन्फ़िगर करने योग्य बना सकते हैं। EnableLogging (<add key="EnableLogging" value="false"/>) नामक एक आइटम जोड़ें। फिर एक स्थिर विधि बनाएं जो .config से मान प्राप्त करे और जांच के लिए उपयोग की जाए।

+3

मुझे लगता है कि आप लगभग पूरी तरह से प्रश्न के बिंदु को याद करते हैं। –

+0

मुझे लगता है कि यह जाएगा विधि को छोड़कर उसके विकल्प दो DoLogDebug() चेक के साथ इसमें बहुत तर्क की आवश्यकता नहीं होगी। Web.config या app.config से एक ऐपसेटिंग मान प्राप्त करने से सरल होने के बाद। –

+0

"EnableLogging" एक log4net कॉन्फ़िगरेशन कुंजी भी नहीं है। जब आप log4net में पहले से ही अपनी सक्षम कॉन्फ़िगरेशन कार्यक्षमता रखते हैं तो आप ऐसा क्यों करेंगे? – Amy

4

अधिकांश लॉग-स्टेटमेंट प्राप्त करने के लिए महंगे हैं क्योंकि उन्हें उपयोगी जानकारी प्रदान करनी चाहिए और वे हमेशा बनाए जाते हैं, यहां तक ​​कि लॉगिंग पूरी तरह से अक्षम होती है।

बिल्कुल सही नहीं है। यहां देखें:

if (Log.IsDebugEnabled) 
{ 
    StackFrame f = new StackFrame(2); 
    Log.Debug("Very expensive message to put together and stuff." + f.GetMethod().Name); 
} 

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

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

EDIT2:

अगर मैं logger.DoLogDebug का उपयोग() वहाँ पता चल सके कि लॉगिंग सक्षम है के लिए अत्यधिक कोड होगा ... इसलिए इस समाधान भी नहीं हो सकता है।

यदि उपरोक्त उल्लिखित कथन मैं अत्यधिक नहीं हूं और इसका मूल्यांकन बहुत जल्दी किया जाता है। मेरा सुझाव है कि आप इसके साथ प्रयोग करें और अपने लिए मूल्यांकन करें यदि यह पर्याप्त प्रदर्शनकर्ता है। यदि आपको लगता है कि आपके पास if ब्लॉक सभी जगह पर हैं, मानक सुझाव उन्हें संभवतः समेकित करना है।

लॉग इननेट में पांच लॉगिंग स्तर हैं, जिनमें से प्रत्येक को दूसरों से पूरी तरह से स्वतंत्र रूप से माना जा सकता है। तो आपके पास एक ही स्थान पर IsDebugEnabled हो सकता है, और IsInfoEnabled किसी अन्य स्थान पर हो सकता है। आपको इसे सशर्त संकलन के साथ बहुत आसानी से नहीं मिलेगा, और यह और बोझिल साबित होगा। इस परिदृश्य कोड में वास्तव में बहुत आम मैं पर काम किया है है:

if (Log.IsDebugEnabled) 
{ 
    StackFrame f = new StackFrame(2); 
    Log.Debug("Very expensive message to put together and stuff." + f.GetMethod().Name); 
} 
if (Log.IsInfoEnabled) 
{ 
    StackFrame f = new StackFrame(2); 
    Log.Debug("Very expensive message to put together and stuff." + f.GetMethod().Name); 
} 
if (Log.IsErrorEnabled) 
{ 
    StackFrame f = new StackFrame(2); 
    Log.Debug("Very expensive message to put together and stuff." + f.GetMethod().Name); 
} 

आप लॉगिंग स्तर से और वर्ग के आधार पर आपके लॉग आउटपुट अनुरूप बनाने के लिए सक्षम होने के लिए चाहते हैं, या यहां तक ​​कि पूरे नामस्थान से, इस के लिए रास्ता है चले जाओ।

+1

लॉग 4नेट के अक्सर पूछे जाने वाले प्रश्नों के मुताबिक यह वास्तव में "सबसे तेज़" तरीका है: http://logging.apache.org/log4net/release/faq.html#perf-not-logging –

+0

आपके उत्तर के लिए धन्यवाद, लेकिन मुझे खेद है मैं अपने बिजनेसब्लॉग में लॉगिंग निर्णय कोड नहीं चाहता हूं, इसलिए इसे आसानी से विस्तारित/आदान-प्रदान किया जा सकता है। यदि बीएल में निर्णय होगा, तो प्रत्येक बार जांचने के लिए एक हजार से अधिक लाइनें होंगी (उदाहरण के लिए) एक नया लॉगिंग स्तर पेश करना चाहते हैं। तो मुझे लगता है कि मैं भविष्य में पर्याप्त लचीला नहीं होगा। (सॉफ्टवेयर में एपीआरएक्स होगा। 10-15 साल के एएलएस, इसलिए इसे विस्तार योग्य और रखरखाव योग्य होना चाहिए) – oberfreak

+0

@oberfreak, निर्णय लॉग 4नेट कॉन्फ़िगरेशन से कड़ाई से आ जाएगा, कहीं भी आपके कोड में नहीं। किसी अन्य प्रोग्राम से उपयोग की जाने वाली पुस्तकालयों का उपयोग उन प्रोग्राम कॉन्फ़िगरेशन का उपयोग करेगा, न कि स्वयं। – Amy

संबंधित मुद्दे