2009-03-26 17 views
8

मैं अक्सर अपने कोड में शामिल लॉगिंग की मात्रा से निराश हूं और इससे मुझे आश्चर्य होता है कि चीजों को करने का बेहतर तरीका है या नहीं।क्या .NET में निष्क्रिय लॉगिंग संभव है?

मुझे नहीं पता कि यह किया गया है या कोई व्यक्ति बेहतर विचार के साथ आया है, लेकिन मैं सोच रहा था कि किसी को किसी एप्लिकेशन में लॉगर को "इंजेक्ट" करने के बारे में पता है, तो यह निष्क्रिय रूप से मॉनीटर करता है थ्रेड और चुपचाप प्रक्रियाओं लॉग जैसी चीज़ों के लिए बिना के रूप में वे होते हैं:

public void MyProcess(int a, string b, object c) 
{ 
    log(
    String.Format(
     "Entering process MyProcess with arguments: [a] = [{0}]; [b] = [{1}]; [c] = [{2}]", 
     a.ToString(), 
     b, 
     c.ToString() 
); 

    try 
    { 
    int d = DoStuff(a) 
    log(
     String.Format(
     "DoStuff({0}) returned value {1}", 
     a.ToString(), 
     d.ToString() 
    ) 
    ); 
    } 
    catch (Exception ex) 
    { 
    log(
     String.Format("An exception occurred during process DoStuff({0})\nException:\n{1}", 
     a.ToString(), 
     ex.ToString()) 
    ) 
    } 
} 

अगर मैं अपने लकड़हारा करने के लिए कह सकते हैं क्या बहुत अच्छा होगा है:

Monitor(MyClass.MyMethod) 

यह तो सब कुछ है कि पर चला जाता है की निगरानी करती है वाई के साथ तर्क में पारित सहित उस विधि के अंदर वें विधि कॉल और मूल्य उन विधियों में पारित किए गए हैं, अपवाद जो इत्यादि हैं।

क्या किसी ने अतीत में ऐसा कुछ लागू किया है? क्या यह लागू किया जा सकता है? इस फैशन में सिर्फ एक पाइप सपना लॉगिंग कर रहा है?

मुझे कुछ ऐसा करने के लिए अच्छा लगेगा जो ऐसा करेगा, लेकिन मुझे यह भी नहीं पता कि मैं कहां से शुरू करूंगा। बेशक, मैं पहिया को फिर से शुरू नहीं करना चाहता, अगर यह पहले से ही किया जा चुका है, तो यह अच्छा होगा अगर कोई मुझे सही दिशा में इंगित कर सके।

कोई सुझाव कृतज्ञता प्राप्त की जाएगी ...

संपादित करें: मैंने सोचा कि मैं एक जवाब जो लॉग में आवश्यक विस्तार के स्तर के रूप में पूछे पर टिप्पणी चाहते हैं। अक्सर यह आवश्यक होता है कि लॉगिंग के कॉन्फ़िगर करने योग्य स्तर प्रदान किए जाएंगे जैसे कि कॉन्फ़िगरेशन विस्तृत लॉगिंग निर्दिष्ट करता है तो सबकुछ लॉग होता है, जबकि यदि महत्वपूर्ण लॉगिंग कॉन्फ़िगर की जाती है तो अपवादों के साथ ही कुछ जानकारी लॉग होती है। यदि घातक लॉगिंग कॉन्फ़िगर किया गया है तो केवल जानकारी जो एप्लिकेशन को मरने का कारण बनती है, लॉग हो जाएगी। क्या ऐसा कुछ कॉन्फ़िगर करने योग्य होगा या क्या एओपी को लॉगिंग स्तरों की संख्या के आधार पर 3 या 4 अलग-अलग बिल्डों की आवश्यकता होगी?

मैं अक्सर 4 स्तरों का उपयोग: घातक, गंभीर, सूचना, विस्तृत

+0

यह रन-टाइम पर कॉन्फ़िगर करने योग्य हो सकता है लेकिन फिर रन-टाइम के दौरान चलने वाला लॉगर अभी भी सभी जानकारी प्राप्त करेगा और फिर यह तय करना होगा कि लॉग इन करना है। यदि आप नहीं चाहते हैं कि सभी जानकारी को लॉगर में पास किया जा रहा है, तो एकमात्र तरीका अलग-अलग निर्माण करना होगा। –

उत्तर

9

आप PostSharp उपयोग कर सकते हैं "के आसपास" विधि प्रवेश करने के लिए। यह बिल्कुल ठीक है कि एओपी अच्छा है। आप Log4PostSharp से शुरू करना चाहेंगे - विशेष रूप से लॉगिंग के लिए एक प्लगइन।

+0

मुझे अतीत में पोस्टशर्प के साथ समस्याएं थीं - यह टीम बिल्ड के साथ अच्छी तरह से मिश्रण नहीं हुआ था। यह वास्तव में कंपाइलर्स द्वारा उत्पन्न आईएल को संपादित करता है, और संपादित बाइनरी कहां लिखना है इसके बारे में भ्रमित हो गया है। शायद यह अब तक तय है। मुझे किसी भी मामले में मेरे आईएल को फिर से लिखा हुआ घबराहट बना दिया। –

+0

क्या आप ब्याज से कोड संविदाओं के बारे में समान आरक्षण महसूस करते हैं? –

+0

मुझे नहीं पता; क्या यह आईएल को फिर से लिखता है? क्या यह उन परिदृश्यों का उपयोग करता है जो माइक्रोसॉफ्ट द्वारा अच्छी तरह से परीक्षण किए जाते हैं? मैं पोस्टशर्प को चिंतित कोड के कुछ टुकड़ों में से एक या कोड के बारे में चिंतित था जो कि आईएल को फिर से लिखता है, और टीम बिल्ड इत्यादि इसे ध्यान में नहीं ले सकता है। "कोड अनुबंध" के लिए यूआरएल, कृपया? –

4

यह आस्पेक्ट ओरिएंटेड प्रोग्रामिंग का क्लासिक उदाहरण है। बहुत अच्छी सीएलआर-आधारित पुस्तकालय के लिए पोस्टशर्प देखें।

4

यह पाठ्यपुस्तक में से एक है (सुनिश्चित नहीं है कि कौन सी पाठ्यपुस्तक में एओपी है लेकिन आपको विचार मिलता है) एओपी - लॉगिंग के उदाहरण: जहां आप किसी विधि के पहले और बाद में कुछ छड़ी करना चाहते हैं।

आप एओपी मार्ग का पता लगाना चाहते हैं, PostSharp माइक्रोसॉफ्ट यूनिटी (आईओसी भी), कैसल के साथ लोकप्रिय लोगों में से एक है।

एओपी का एक सरल उदाहरण वास्तविक तरीकों के अंदर विधि कॉल जोड़ने के बजाय, आप पहले और बाद में अपना कोड जोड़ते हैं। जैसा कि आपने सी # के साथ प्रश्न टैग किया है, आप शायद इसे लॉग इन करने के लिए एक एक्सटेंशन विधि बनाना चाहते हैं, जो पहले से ही this question में है।

मैं एक व्यावहारिक दृष्टिकोण लेगा: आप कितना वास्तविक लॉगिंग कर रहे हैं?क्या आप अपने कोड को पढ़ने वाले व्यक्ति को चकाचौंध करने के बजाए सिर्फ एक विस्तार विधि से दूर हो सकते हैं। लॉगिंग built into the .NET framework पहले से ही सभ्य है।

+0

खैर, मैंने केवल विस्तार विधियों से दूर होने के बारे में सोचा था, लेकिन क्लाइंट कॉन्फ़िगरेशन फ़ाइल द्वारा परिभाषित परिवर्तनीय स्तर लॉगिंग चाहता है, इसलिए कॉन्फ़िगरेशन फ़ाइल में निर्दिष्ट लॉगिंग के स्तर के आधार पर, यह निर्भर करता है कि लॉग कितना विस्तृत होगा। किस तरह से इसे रोकता है। – BobTheBuilder

+0

यह कॉन्फ़िगरेशन फ़ाइल, जानकारी/चेतावनी/त्रुटि और एक श्रेणी –

+0

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

1

जॉन द्वारा उल्लिखित लॉगिंग विधियों के अतिरिक्त, संभवतः प्रोग्राम प्रवाह को ट्रेस करने के लिए वीएस में एक और उपयोगी विशेषता को ध्यान देने योग्य भी है, और यह गैर-ब्रेकिंग ब्रेकपॉइंट्स रखने की क्षमता है जो केवल एक संदेश आउटपुट या मैक्रो चलाएगा जब हिट करें (ध्यान दें कि आप वैरिएबल वैल्यू भी प्रिंट कर सकते हैं)

अपने ब्रेकपॉइंट पर राइट क्लिक करें और जब हिट ... संदर्भ मेनू आइटम चुनें।

और निश्चित रूप से एक अन्य बहुत उपयोगी विशेषता सिस्टम में ट्रेस ऑब्जेक्ट और ट्रेस लिस्टर्स है। डायग्नोस्टिक्स।

+0

मैं इस सुविधा का उपयोग करता हूं और विकास चरण के दौरान यह बहुत अच्छा है, लेकिन यह क्लाइंट को अपने उत्पादन वातावरण में स्वतंत्र रूप से डीबग करने में मदद नहीं करता है, जो आम तौर पर इस परिदृश्य की आवश्यकता होती है। – BobTheBuilder

0

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

using(var logger = new LogSite("methodName", new object[] { p1, p2, p3 }) 
{ 
    // code that does stuff goes here 
} 

LogSite वस्तु ऐसी MethodBase के रूप में, ताकि आप केवल पाने के लिए MethodBase.GetCurrentMethod() और उपयोग प्रतिबिंब का उपयोग कर सकते निर्माता के लिए सुविधाजनक भार के का एक समूह है: मूल रूप से, वहाँ एक LogSite डिस्पोजेबल उद्देश्य यह है कि आप इस तरह का उपयोग करें विधि और पैरामीटर का वास्तविक नाम (हार्ड-कोडेड तारों के बजाए)।

जिस तरह से यह काम करता है यह है - कन्स्ट्रक्टर में, यह ब्लॉक में प्रवेश करने के संकेत के लिए सभी ट्रेस जानकारी के साथ लॉग को लिखता है। निपटान विधि में, यह एक निकास प्रविष्टि लिखता है।

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

try { ... } 
catch (Exception ex) 
{ 
    logger.LogException(ex); 
} 

लकड़हारा पहले से ही विधि का नाम, पैरामीटर जानकारी, और वह सब जानता है, और के लिए आंतरिक तरीकों है:

इसके अलावा, एक "लकड़हारा" वस्तु अब वहाँ के बाद से उपलब्ध है, अपनी पकड़ हैंडलर बस की तरह दिखता है अपवाद जानकारी तैयार करना।

इस उच्च स्तरीय ऑब्जेक्ट के नीचे आर्किटेक्चर में पहुंचना, "लॉगडिस्पोजिशन" की एक अवधारणा है जो हमने पहले "निर्धारित/असफल" को संभाला है, और "लॉगइन्ट्री टाइप" की एक अवधारणा है जो एक फ़िल्टर है (ध्वज के साथ लागू enum) जो इंगित करता है कि किस तरह की लॉग प्रविष्टि पारित की जा रही है (त्रुटि, ट्रेस, आदि)।

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

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

यह एक बहुत अच्छी प्रणाली है, और तुलनात्मक रूप से समृद्ध लॉगिंग प्राप्त करने के लिए अपेक्षाकृत कम मात्रा में कोडिंग की आवश्यकता होती है।

यदि आप चाहते थे तो मैं आपको एक कोड नमूना दे सकता हूं ... आप मेरे (लगभग पूरी तरह से निष्क्रिय) ब्लॉग (मेरा खाता प्रोफ़ाइल देखें) के माध्यम से मुझसे संपर्क कर सकते हैं।

उम्मीद है कि मदद करता है।

0

मैं अपनी सभी परियोजनाओं में ओपनसोर्स Apache log4net का उपयोग करता हूं।

'Will print stack trace after message' 
log.err(ex.message,ex) 

log.warn("warn") 
log.info("info") 
log.debug("debug") 

लॉगिंग इस तरह के मानकों: यह एक्सटेंशन है कि आप डेटाबेस, ज़िप फ़ाइलें, रोलिंग लॉग फाइल, आरआरएस फ़ीड, टेलनेट ग्राहकों, आदि लॉगिंग करने के लिए लॉग इन करने के लिए अनुमति देते हैं के सभी प्रकार के साथ एक बहुत ही सरल कार्यान्वयन है मूल रूप से के रूप में सरल है आउटपुट प्रारूप और आउटपुट के लिए लॉग स्तर सभी रीयल टाइम पढ़ते हैं जबकि आपका ऐप रनटाइम में होता है।

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