2010-10-31 27 views
8

मेरे पास एक TraceSource ऑब्जेक्ट है जिसका उपयोग मैं VB.Net एप्लिकेशन के प्रारंभ को लॉग करने के लिए करता हूं। मानक के बिना वह यह है कि, -.Net: TraceSource हेडर को दबाने के लिए कैसे करें ("SourceName TraceEventType: Id:")?

  • ConsoleTraceListener
  • TextWriterTraceListener
  • EventLogTraceListener

पहले दो मैं प्रविष्टि उत्पादन "कच्चे" होना चाहता हूँ के लिए: यह कई TraceListeners संलग्न है शीर्षलेख:

SourceName TraceEventType: Id :

,210

मैं एक आवरण है कि यह करता है जब TraceEventType वर्बोस के लिए निर्धारित है को लागू किया है:

If _buffer.EventType = TraceEventType.Verbose Then 
    For Each listener As TraceListener In _traceSource.Listeners 
     listener.Write(_buffer.Text) 
    Next 
Else 
    _traceSource.TraceEvent(_buffer.EventType, id, _buffer.Text) 
End If 

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

  • लिखें()
  • WriteLine()
  • TraceData()
  • TraceEvent()
  • TraceTransfer)
  • : जहाँ तक मैं बता सकता हूँ, TraceListener इसे करने के लिए लिखने के लिए इन विकल्पों में है

अंतिम 3 TraceEventType प्रदान करने की अनुमति देता है (जो इवेंटलॉग प्रविष्टियों को सही ढंग से लेबल करता है, लेकिन परिणामी आउटपुट कंसोल और लॉग फ़ाइल में शामिल है, फिर इसमें शामिल है उपसर्गों और (उदाहरण के लिए) इस तरह समाप्त होता है:

Bootstrapper Warning: 0 : Failed to validate assembly

वहाँ ओवरराइड करने के लिए कैसे ConsoleTraceListener और TextWriterTraceListener प्रारूप अपने उत्पादन में एक ही समय में टैग करने के लिए सक्षम किया जा रहा है, इस शीर्ष लेख शामिल नहीं करने के लिए एक रास्ता है TraceEventType के साथ प्रविष्टियां (EventLog के लिए)?

यह सबसे अच्छा मैं अब तक के साथ आए हैं है:

For Each listener As TraceListener In _traceSource.Listeners 
    If listener.GetType Is GetType(ConsoleTraceListener) OrElse listener.GetType Is GetType(TextWriterTraceListener) Then 
     listener.Write(_buffer.Text) 
    Else 
     listener.TraceEvent(Nothing, _traceSource.Name, _buffer.EventType, id, _buffer.Text) 
    End If 
Next 

यह काम करने के लिए लगता है, लेकिन Microsoft से TraceListener.TraceEvent Method पर दस्तावेज में, यह कहते हैं:

Important: This method is not intended to be called directly by application code but by members of the Debug, Trace, and TraceSource classes to write trace data to output.

..तो मुझे यकीन नहीं है कि यह करने के लिए एक अच्छी बात है?

संपादित करें:

मैं सिर्फ महसूस किया कि अगर मैं यहाँ मेरा आखिरी उदाहरण की तरह कुछ करना है, मैं TraceSource बिल्कुल, क्योंकि यह वैसे भी नजरअंदाज किया जा रहा है की जरूरत नहीं है। लेकिन इसका मतलब यह भी है कि मुझे अपनी खुद की फ़िल्टरिंग और स्विचिंग तंत्र को लागू करना है (लेकिन यह संभव है कि मैं जिस तरह से काम करना चाहता हूं उसे पाने के लिए भुगतान करने के लिए एक उचित कीमत हो)।

उत्तर

0

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

उदाहरण के लिए, आप Ukadc.Diagnostics ConsoleTraceListener कॉन्फ़िगर कर सकता है इस तरह एक स्वरूपण बयान कुछ का उपयोग करें:

{DateTime} {Source} {EventType} {Message} 
हर संदेश लॉग इन दिनांक/समय, स्रोत नाम, ईवेंट प्रकार का कारण होगा

, और संदेश।

इसे आज़माएं, मुझे लगता है कि आपको यह पसंद आएगा। मैंने इसे स्वयं कुछ उपयोग किया है (ज्यादातर प्रोटोटाइप के लिए, अभी तक "वास्तविक" उत्पाद के लिए नहीं) और अच्छी सफलता मिली है।

ध्यान दें कि कुछ टोकन (जैसे डेटटाइम) के लिए, आप मानक प्रारूपों को भी लागू कर सकते हैं जो कि प्रकार के लिए उपयुक्त हैं (उदा। डेटटाइम के लिए आप उस प्रारूप को निर्दिष्ट कर सकते हैं जिसमें तिथि/समय लिखा जाना चाहिए)।

फ़ाइल ट्रेस श्रोता जो Ukadc.Diagnostics के साथ आता है, भी अपने फ़ाइल नाम को टोकन सिस्टम का उपयोग करके निर्दिष्ट करने की अनुमति देता है।

+0

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

+0

मुझे लगता है कि पुस्तकालय वास्तव में अच्छा है, इसलिए आगे बढ़ें और इसे आज़माएं, आपको यह पसंद आएगा। एक तरीका यह आपके वर्कफ़्लो की मदद कर सकता है कि आप TraceListener वर्गों के एक ही सेट का उपयोग कर सकते हैं, लेकिन वास्तव में कॉन्फ़िगरेशन के माध्यम से जो लिखा जाता है उसे बदलें। तो, आपके पास कुछ श्रोताओं (कंसोल और टेक्स्टवाइटर) से जुड़े "कच्चे" प्रारूप और दूसरों के साथ जुड़े "ईवेंट" प्रारूप (EventLog) हो सकते हैं। यदि आप अगले सप्ताह या अगले महीने तय करते हैं कि आप किसी भी प्रारूप से कुछ जानकारी जोड़ना या निकालना चाहते हैं, तो आपको केवल app.config में प्रारूप बदलना होगा। कोई कोड नहीं बदलता है। सौभाग्य! – wageoghe

+0

d7samurai, क्या आप NotInventedHere-Antipattern से परिचित हैं? –

2

एक और इसी तरह की परियोजना जिसमें स्वरूपणीय श्रोताओं का उपयोग किया जा सकता है Essential Diagnostics है, जो वास्तव में मूल रूप से Ukadc.Diagnostics द्वारा प्रेरित था।

आपने सूचित किया है कि, हालांकि, आप बाहरी निर्भरता नहीं करना चाहते, लेकिन आप अभी भी फ्रेमवर्क के कुछ हिस्सों को फिर से लेखन के बिना कई विकल्प हैं:

(ए) के बजाय फिर से लिखने TraceSource, डिज़ाइन किया गया विस्तार .NET Framework में इंगित करें अपने स्वयं के TraceListener लिखना है।

यदि आप अपना खुद का ट्रेस श्रोताओं "कंसोल विथआउटफ्रिक्स लिस्टनर" और "फाइलविथआउटफ्रिक्स लिस्टनर" लिखते हैं, तो आप TraceWrite() (और उपसर्ग को छोड़कर) संदेश को अग्रेषित करने के लिए TraceEvent() विधियों को ओवरराइड कर सकते हैं।

वास्तव में न तो ConsoleTraceListener या TextWriterTraceListener सील कर रहे हैं, तो मुझे लगता है आप उन लोगों से वारिस और इस TraceEvent() विधि (प्लस निर्माता) की एक एक पंक्ति ओवरराइड के साथ काम मिल सकता है।

(बी) अन्य विकल्प इवेंटलॉग्रेस लिस्टनर को स्रोत के विरुद्ध कॉन्फ़िगर किया गया है, लेकिन अन्य दो श्रोताओं को नीचे स्रोत के बजाय कॉन्फ़िगर करना होगा।

इस का दोष यह है कि अपने कोड में आप दो बार हर बार प्रवेश करने की आवश्यकता है, जैसे:

_traceSource.TraceEvent (_buffer.EventType, आईडी, _buffer.Text) Trace.TraceWrite (_buffer.Text)

यदि आप उपसर्गों के साथ कुछ संदेश लिखना चाहते हैं और कुछ तो आपको दो ट्रेस स्रोतों की आवश्यकता होगी: एक जो तीनों श्रोताओं के साथ कॉन्फ़िगर किया गया है, और केवल एक ईवेंट लॉग श्रोता के साथ।

फिर, आपके रैपर में या तो स्रोत ए (सभी तीन) या स्रोत बी + ट्रेस स्थिर विधियों को लिखें।

(सी) व्यक्तिगत रूप से, मेरा मार्गदर्शन घटना लॉग में लिखने के लिए ट्रेसिंग का उपयोग नहीं करना होगा - यदि समस्या लॉग में लिखने के लिए पर्याप्त महत्वपूर्ण हैं, तो आम तौर पर उपयोगकर्ता नहीं चाहते कि उपयोगकर्ता चालू हो सके उन्हें विन्यास के माध्यम से बंद करो।

इस मामले में आपका रैपर सीधे ईवेंट लॉग (EventLog.WriteEntry या जो कुछ भी) लिखता है और फिर आपका कोड ट्रेस स्रोत और/या फ़ाइल और कंसोल के लिए ट्रेस स्थिर विधियों को लिखता है।

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

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

इस वजह से

, सामान्य रूप से आप बनाता है कि ईवेंट लॉग स्रोत दौरान (स्थापित स्थापित क्योंकि अपने कोड है, जो InstallUtil (या समतुल्य एमएसआई या जो कुछ भी) द्वारा चलाया जाता है के भाग के रूप में एक EventLogInstaller की आवश्यकता है है एक के द्वारा किया व्यवस्थापक)। फिर, जब प्रोग्राम चलाता है स्रोत मौजूद है।

तो, यह निशान के साथ लेखन के साथ क्या करना है - ठीक है, अगर आप केवल एक ही चीज को अपने कॉन्फ़िगरेशन में EventLogTraceListener को कॉन्फ़िगर करते हैं तो सामान्य उपयोगकर्ताओं के लिए यह काम नहीं करेगा; यह स्रोतों (प्रारंभिक डेटाडेटा में) को ईवेंट को आजमाएगा और लिख देगा, जो तब स्रोत बनाने का प्रयास करेगा और यदि व्यवस्थापक के रूप में नहीं चल रहा है तो विफल हो जाएगा।

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

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

1

यहां मेरा पूरा समाधान है, @Sly के उत्तर से प्रेरित है।

TraceEvent() विधि का उपयोग करते समय हेडर जानकारी को दबाने के लिए आप ConsoleTraceListener या TextWriterTraceListener (या श्रोता की जो भी स्वाद आवश्यक है) से प्राप्त हो सकते हैं;

namespace Custom.Lib { 
    public class ConsoleTraceListener : System.Diagnostics.ConsoleTraceListener { 

     // overridding this method here will suppress header information 
     // your TraceEvent() messages will still reach the listener 
     public override void Write(string message) { 
      //base.Write(message); 
     } 

    } 
} 

एनबी।TraceEventविधि को ओवरराइड करने का प्रयास करते समय मैंने देखा कि हेडर जानकारी इस बिंदु पर संदेश स्ट्रिंग में नहीं जोड़ा गया था। इसके बजाय मैंनेWrite(string)पर कॉल को चुप करने का विकल्प चुना, जो कि किसी भी अन्य नॉक-ऑन प्रभाव नहीं प्रतीत होता है, लेकिन अगर किसी के पास 'क्लीनर दृष्टिकोण' है तो मैं थोड़ा सा 'हैकिश' महसूस करता हूं, मैं इसके लिए खुला हूं।

इस ग्राहक श्रोता का उपयोग करने के लिए कॉन्फ़िगरेशन को इस तरह कुछ दिखाना चाहिए;

<system.diagnostics> 
    <sources> 
     <source name="AppTrace" switchName="sourceSwitch" switchType="System.Diagnostics.SourceSwitch"> 
     <listeners> 
      <add name="consoleListener"/> 
     </listeners> 
     </source> 
    </sources> 
    <switches> 
     <add name="sourceSwitch" value="Information"/> 
    </switches> 
    <sharedListeners> 
     <add name="consoleListener" type="Custom.Lib.ConsoleTraceListener, Custom.Lib" initializeData=""/> 
    </sharedListeners> 
    </system.diagnostics>