सबसे उपयोगी NLog कॉन्फ़िगरेशन [बंद]


348

NLog के साथ लॉगिंग के लिए सबसे अच्छा या सबसे उपयोगी विन्यास क्या हैं? (ये तब तक सरल या जटिल हो सकते हैं, जब तक ये उपयोगी हों।)

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

यहाँ कुछ लिंक दिए गए हैं:


3
यहाँ परीक्षण के आधार पर कुछ प्रदर्शन ट्यूनिंग युक्तियाँ दी गई हैं: deep-depth.blogspot.com/2014/01/…
नील

जवाबों:


391

इनमें से कुछ कड़ाई से कॉन्फ़िगरेशन सुझावों के बजाय सामान्य NLog (या लॉगिंग) युक्तियों की श्रेणी में आते हैं।

यहाँ SO पर कुछ सामान्य लॉगिंग लिंक दिए गए हैं (आप इनमें से कुछ या सभी पहले ही देख सकते हैं):

log4net बनाम Nlog

सर्वोत्तम प्रथाओं का प्रवेश

एक लॉगिंग मुखौटा की बात क्या है?

लकड़हारा वर्ग प्रति लकड़हारा उपयोग करने की सलाह क्यों देता है?

वर्ग के आधार पर अपने लकड़हारे के नामकरण के सामान्य पैटर्न का उपयोग करें Logger logger = LogManager.GetCurrentClassLogger()। यह आपको अपने लकड़हारा में उच्च श्रेणी की ग्रैन्युलैरिटी प्रदान करता है और आपको लकड़हारा के विन्यास (विश्व स्तर पर नियंत्रण, नेमस्पेस द्वारा, विशिष्ट लकड़हारा नाम, आदि) में बहुत लचीलापन देता है।

गैर-वर्गनाम-आधारित लॉगर का उपयोग करें जहां उपयुक्त हो। शायद आपके पास एक फ़ंक्शन है जिसके लिए आप वास्तव में लॉगिंग को अलग से नियंत्रित करना चाहते हैं। शायद आपके पास कुछ क्रॉस-कटिंग लॉगिंग चिंताएं (प्रदर्शन लॉगिंग) हैं।

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

Logger logger = LogManager.GetLogger("Database.Connect");
Logger logger = LogManager.GetLogger("Database.Query");
Logger logger = LogManager.GetLogger("Database.SQL");
Logger logger = LogManager.GetLogger("Analysis.Financial");
Logger logger = LogManager.GetLogger("Analysis.Personnel");
Logger logger = LogManager.GetLogger("Analysis.Inventory");

और इसी तरह। पदानुक्रमित लॉगर के साथ, आप एफए (डेटाबेस, विश्लेषण, यूआई), या सबारिया (डेटाबेस.कनेक्ट, आदि) द्वारा विश्व स्तर पर लॉगिंग ("*" या रूट लॉगर) को कॉन्फ़िगर कर सकते हैं।

लकड़हारे के पास कई विन्यास विकल्प हैं:

<logger name="Name.Space.Class1" minlevel="Debug" writeTo="f1" /> 
<logger name="Name.Space.Class1" levels="Debug,Error" writeTo="f1" /> 
<logger name="Name.Space.*" writeTo="f3,f4" />
<logger name="Name.Space.*" minlevel="Debug" maxlevel="Error" final="true" /> 

प्रत्येक विकल्प के अर्थ के बारे में अधिक जानकारी के लिए NLog सहायता देखें । संभवतः यहां सबसे उल्लेखनीय आइटम वाइल्डकार्ड लकड़हारा नियमों की क्षमता है, यह अवधारणा कि कई लकड़हारा नियम एकल लॉगिंग स्टेटमेंट के लिए "निष्पादित" कर सकते हैं, और एक लकड़हारा नियम को "अंतिम" के रूप में चिह्नित किया जा सकता है, इसलिए बाद के नियमों के लिए निष्पादित नहीं किया जाएगा। लॉगिंग स्टेटमेंट।

अपने आउटपुट में अतिरिक्त संदर्भ जोड़ने के लिए GlobalDiagnosticContext, MappedDiagnosticContext, और NestedDiagnosticContext का उपयोग करें।

सरलीकृत करने के लिए अपनी कॉन्फ़िगर फ़ाइल में "चर" का उपयोग करें। उदाहरण के लिए, आप अपने लेआउट के लिए चर को परिभाषित कर सकते हैं और फिर सीधे लेआउट निर्दिष्ट करने के बजाय लक्ष्य कॉन्फ़िगरेशन में चर को संदर्भित कर सकते हैं।

  <variable name="brief" value="${longdate} | ${level} | ${logger} | ${message}"/>
  <variable name="verbose" value="${longdate} | ${machinename} | ${processid} | ${processname} | ${level} | ${logger} | ${message}"/>
  <targets>
    <target name="file" xsi:type="File" layout="${verbose}" fileName="${basedir}/${shortdate}.log" />
    <target name="console" xsi:type="ColoredConsole" layout="${brief}" />
  </targets>

या, आप लेआउट में जोड़ने के लिए गुणों का एक "कस्टम" सेट बना सकते हैं।

  <variable name="mycontext" value="${gdc:item=appname} , ${mdc:item=threadprop}"/>
  <variable name="fmt1withcontext" value="${longdate} | ${level} | ${logger} | [${mycontext}] |${message}"/>
  <variable name="fmt2withcontext" value="${shortdate} | ${level} | ${logger} | [${mycontext}] |${message}"/>

या, आप सामान बना सकते हैं जैसे "दिन" या "महीने" लेआउट रेंडरर्स कॉन्फ़िगरेशन के माध्यम से कड़ाई से:

  <variable name="day" value="${date:format=dddd}"/>
  <variable name="month" value="${date:format=MMMM}"/>
  <variable name="fmt" value="${longdate} | ${level} | ${logger} | ${day} | ${month} | ${message}"/>
  <targets>
    <target name="console" xsi:type="ColoredConsole" layout="${fmt}" />
  </targets>

आप अपने फ़ाइलनाम को परिभाषित करने के लिए लेआउट रेंडरर्स का भी उपयोग कर सकते हैं:

  <variable name="day" value="${date:format=dddd}"/>
  <targets>
    <target name="file" xsi:type="File" layout="${verbose}" fileName="${basedir}/${day}.log" />
  </targets>

यदि आप अपनी फ़ाइल को रोज़ाना रोल करते हैं, तो प्रत्येक फ़ाइल का नाम "मंडे.लॉग", "मंगलवार.लॉग", आदि हो सकता है।

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

  [LayoutRenderer("ActivityId")]
  class ActivityIdLayoutRenderer : LayoutRenderer
  {
    int estimatedSize = Guid.Empty.ToString().Length;

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
      builder.Append(Trace.CorrelationManager.ActivityId);
    }

    protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
    {
      return estimatedSize;
    }
  }

NLog को बताएं कि आपका NLog एक्सटेंशन (किस असेंबली) इस तरह है:

  <extensions>
    <add assembly="MyNLogExtensions"/>
  </extensions>

इस तरह कस्टम लेआउट रेंडरर का उपयोग करें:

  <variable name="fmt" value="${longdate} | ${ActivityId} | ${message}"/>

Async लक्ष्य का उपयोग करें:

<nlog>
  <targets async="true">
    <!-- all targets in this section will automatically be asynchronous -->
  </targets>
</nlog>

और डिफ़ॉल्ट लक्ष्य आवरण:

<nlog>  
  <targets>  
    <default-wrapper xsi:type="BufferingWrapper" bufferSize="100"/>  
    <target name="f1" xsi:type="File" fileName="f1.txt"/>  
    <target name="f2" xsi:type="File" fileName="f2.txt"/>  
  </targets>  
  <targets>  
    <default-wrapper xsi:type="AsyncWrapper">  
      <wrapper xsi:type="RetryingWrapper"/>  
    </default-wrapper>  
    <target name="n1" xsi:type="Network" address="tcp://localhost:4001"/>  
    <target name="n2" xsi:type="Network" address="tcp://localhost:4002"/>  
    <target name="n3" xsi:type="Network" address="tcp://localhost:4003"/>  
  </targets>  
</nlog>

जहां उपयुक्त हो। उन लोगों के बारे में अधिक जानकारी के लिए NLog डॉक्स देखें।

यदि यह बदलता है, तो NLog को देखने और स्वचालित रूप से कॉन्फ़िगरेशन को फिर से लोड करने के लिए कहें:

<nlog autoReload="true" /> 

समस्या निवारण में मदद करने के लिए कई कॉन्फ़िगरेशन विकल्प हैं

<nlog throwExceptions="true" />
<nlog internalLogFile="file.txt" />
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" />
<nlog internalLogToConsole="false|true" />
<nlog internalLogToConsoleError="false|true" />

अधिक जानकारी के लिए NLog सहायता देखें।

NLog 2.0 में LayoutRenderer रैपर जुड़ते हैं जो कि लेआउट रेंडरर (जैसे व्हाट्सएप, अपरकेसिंग, लोअरस्किंग, आदि को ट्रिम करना) के आउटपुट पर अतिरिक्त प्रोसेसिंग करने की अनुमति देता है।

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

रैपिंग (या अमूर्त) NLog (या उस मामले के लिए कोई अन्य लॉगिंग फ्रेमवर्क) के लिए पेशेवरों और विपक्ष हैं। थोड़े से प्रयास से, आप दोनों पक्षों को प्रस्तुत करने वाले SO पर यहाँ बहुत सारी जानकारी पा सकते हैं।

यदि आप लपेटने पर विचार कर रहे हैं, तो Common.Logging का उपयोग करने पर विचार करें । यह बहुत अच्छी तरह से काम करता है और यदि आप ऐसा करने की इच्छा रखते हैं, तो आप आसानी से किसी अन्य लॉगिंग ढांचे में स्विच कर सकते हैं। इसके अलावा यदि आप रैपिंग पर विचार कर रहे हैं, तो इस बारे में सोचें कि आप संदर्भ वस्तुओं (जीडीसी, एमडीसी, एनडीसी) को कैसे संभालेंगे। कॉमन.लॉगिंग वर्तमान में उनके लिए एक अमूर्तता का समर्थन नहीं करता है, लेकिन इसे जोड़ने की क्षमताओं की कतार में माना जाता है।


3
बहुत बढ़िया जवाब। जोड़ने के लिए बस एक चीज, $ {मशीन} को $ {machinename} होना चाहिए। Github.com/nlog/NLog/wiki/Layout-Renderers देखें ।
लियांग

2
मैंने कॉमन.लॉगिंग को फोर्क किया और मिसिंग एब्सट्रेक्ट को जोड़ा, GitHub प्रोजेक्ट या NuGet देखें
डैनी वारोड

मैं अपने स्वयं के प्रलेखन में समस्या के बारे में सूचनात्मक रूप में कुछ भी खोजने में विफल रहा, शायद मैं गलत तरीके से जीथब उदाहरणों के माध्यम से देख रहा हूं? कौन जाने।
JARRRRG

एपीआई के साथ उस कस्टम रेंडरर का उपयोग कैसे करें (कोई कॉन्फ़िगरेशन फ़ाइल नहीं)? यहाँ मैं पूरा करने की कोशिश कर रहा हूँ।
InteXX

ठीक मिल गया। NewLineलेआउट कार्य पूरा करता है। यहाँ मैं क्या लेकर आया हूँ। मुझे यकीन है कि यह होने की अपेक्षा मैं बहुत सरल था।
InteXX

65

अपवादों को अलग तरह से मानना

हम अक्सर अपवाद होने पर अधिक जानकारी प्राप्त करना चाहते हैं। निम्नलिखित कॉन्फ़िगरेशन में दो लक्ष्य हैं, एक फ़ाइल और कंसोल, जो किसी अपवाद जानकारी को फ़िल्टर करता है या नहीं। (EDIT: Jarek ने vNext में ऐसा करने के एक नए तरीके के बारे में पोस्ट किया है ।)

कुंजी के साथ एक आवरण लक्ष्य है xsi:type="FilteringWrapper" condition="length('${exception}')>0"

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.mono2.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Warn"
      internalLogFile="nlog log.log"
      >
    <variable name="VerboseLayout" 
              value="${longdate} ${level:upperCase=true} ${message}  
                    (${callsite:includSourcePath=true})"            />
    <variable name="ExceptionVerboseLayout"  
              value="${VerboseLayout} (${stacktrace:topFrames=10})  
                     ${exception:format=ToString}"                  />

    <targets async="true">
        <target name="file" xsi:type="File" fileName="log.log"
                layout="${VerboseLayout}">
        </target>

        <target name="fileAsException"  
                xsi:type="FilteringWrapper" 
                condition="length('${exception}')>0">
            <target xsi:type="File"  
                    fileName="log.log"  
                    layout="${ExceptionVerboseLayout}" />
        </target>

        <target xsi:type="ColoredConsole"
                name="console"
                layout="${NormalLayout}"/>

        <target xsi:type="FilteringWrapper"  
                condition="length('${exception}')>0"  
                name="consoleException">
            <target xsi:type="ColoredConsole" 
                    layout="${ExceptionVerboseLayout}" />
        </target>
    </targets>

    <rules>
        <logger name="*" minlevel="Trace" writeTo="console,consoleException" />
        <logger name="*" minlevel="Warn" writeTo="file,fileAsException" />
    </rules>

</nlog>

1
अपवाद को प्रारूपित करने के लिए अलग लक्ष्य और फ़िल्टरिंगवेयर के साथ यह बहुत अच्छा है। मैंने अभी हाल ही में एक ऐसे व्यक्ति से एक सवाल का जवाब दिया है जो अपने आउटपुट में {अपवाद} लेआउट रेंडरर को शामिल करना चाहता था लेकिन वह () नहीं चाहता था कि जाहिरा तौर पर लॉग इन किया जाए अगर कोई अपवाद नहीं है। यह तकनीक शायद उसके लिए अच्छा काम करेगी।
वेजोगे

+1 बहुत अच्छा। मैंने इसे लंबे समय तक बुकमार्क किया था, और सशर्त लेआउट के संबंध में एक और SO प्रश्न से "पैट की टिप्पणी" को संदर्भित किया।
eduncan911

1
यदि कोई अपवाद लॉग किया गया है, तो इसे दो बार लॉग किया जाएगा (VerboseLayout part)।
तीजन डू

2
मैंने कल ही अपने प्रोजेक्ट में इसे आजमाया था, जब से आपने एक नियम माइनवेल = "वार्न" को "फाइल, फाइलएस्टैसेप्शन" में सेट किया, सभी लॉग पहले फाइल टार्गेट (नो फिल्टर) के साथ लॉग इन होंगे, और यदि यह अपवाद है (जैसा कि फ़िल्टर किया गया है) हालत) यह fileAsException के साथ भी लॉग इन किया जाएगा।
टीएन डू

3
@Tiendq ओह, मैं देख रहा हूँ। यह समझ में आता है, हालांकि अपवाद खुद (पूर्ण विस्तार में) केवल एक बार लॉग इन किया जाएगा (लेकिन इसका संदेश दो बार लॉग किया जाएगा)। आप संभवतः इसे जोड़कर condition="length('${exception}')=0(या शायद यह ==) ठीक कर सकते हैं target name="file"
पाट

60

जाहिरा तौर पर, आप अब विंडोज के लिए ग्रोएल के साथ NLog का उपयोग कर सकते हैं ।

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <extensions>
        <add assembly="NLog.Targets.GrowlNotify" />
    </extensions>

    <targets>
        <target name="growl" type="GrowlNotify" password="" host="" port="" />
    </targets>

    <rules>
        <logger name="*" minLevel="Trace" appendTo="growl"/>
    </rules>

</nlog>

विंडोज के लिए ग्रोएल के साथ NLog विंडोज के लिए ग्रोएल के साथ NLog ट्रेस संदेश Windows के लिए Growl के साथ NLog डिबग संदेश विंडोज के लिए Growl के साथ NLog जानकारी संदेश NLog ने विंडोज के लिए ग्रोएल के साथ चेतावनी दी है Windows के लिए Growl के साथ NLog त्रुटि संदेश विंडोज के लिए ग्रोएल के साथ NLog घातक संदेश


क्या आप मुझे बता सकते हैं कि रीमॉर्ट कनेक्शन के लिए क्या करना चाहिए? बात मेरे लिए लोकलहोस्ट के लिए काम करती है लेकिन जब मैंने होस्ट में कुछ आईपी एड्रेस दिया है तो यह काम नहीं कर रहा है !!
नील

@ नील, आपको टार्गेट कंप्यूटर पर "सिक्योरिटी" सेटिंग्स ग्रोएल में जांचनी चाहिए। आपको "लैन" सूचनाओं को स्पष्ट रूप से सक्षम करना होगा और आप एक पासवर्ड सेटअप करना चाह सकते हैं (जिसे तब आपको अपने NLog लक्ष्य में जोड़ना होगा)। लेकिन मुझे यह पसंद नहीं आया कि "स्थानीय मशीन" की "उत्पत्ति" के साथ ग्रोथल में दूरस्थ सूचनाएं दिखाई गईं; मुझे सूचनाओं की उत्पत्ति के लिए लॉग इन प्रविष्टियों में होस्ट को जोड़ना होगा।
केनी एविट

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

1
यह परियोजना 100% मर चुकी है
डेवलपर

28

XML के माध्यम से NLog कॉन्फ़िगर करें, लेकिन प्रोग्रामेटिक रूप से

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

  string xml = @"<nlog>
                   <targets>
                     <target name='console' type='Console' layout='${message}' />
                   </targets>

                   <rules>
                     <logger name='*' minlevel='Error' writeTo='console' />
                   </rules>
                 </nlog>";

  StringReader sr = new StringReader(xml);
  XmlReader xr = XmlReader.Create(sr);
  XmlLoggingConfiguration config = new XmlLoggingConfiguration(xr, null);
  LogManager.Configuration = config;
  //NLog is now configured just as if the XML above had been in NLog.config or app.config

  logger.Trace("Hello - Trace"); //Won't log
  logger.Debug("Hello - Debug"); //Won't log
  logger.Info("Hello - Info");   //Won't log
  logger.Warn("Hello - Warn");   //Won't log
  logger.Error("Hello - Error"); //Will log
  logger.Fatal("Hello - Fatal"); //Will log

  //Now let's change the config (the root logging level) ...
  string xml2 = @"<nlog>
                  <targets>
                     <target name='console' type='Console' layout='${message}' />
                   </targets>

                   <rules>
                     <logger name='*' minlevel='Trace' writeTo='console' />
                   </rules>
                 </nlog>";

  StringReader sr2 = new StringReader(xml2);
  XmlReader xr2 = XmlReader.Create(sr2);
  XmlLoggingConfiguration config2 = new XmlLoggingConfiguration(xr2, null);
  LogManager.Configuration = config2;

  logger.Trace("Hello - Trace"); //Will log
  logger.Debug("Hello - Debug"); //Will log
  logger.Info("Hello - Info");   //Will log
  logger.Warn("Hello - Warn");   //Will log
  logger.Error("Hello - Error"); //Will log
  logger.Fatal("Hello - Fatal"); //Will log

मुझे यकीन नहीं है कि यह कितना मजबूत है, लेकिन यह उदाहरण उन लोगों के लिए एक उपयोगी शुरुआती बिंदु प्रदान करता है जो इस तरह से कॉन्फ़िगर करने का प्रयास करना चाहते हैं।


यह बहुत अच्छी तरह से काम करता है ... इसके उपयोग को छोड़कर लॉगिंग सिस्टम को गतिशील रूप से फिर से कॉन्फ़िगर करना संभव नहीं है। यह विशेष रूप से ऐसा है यदि आप किसी बाहरी फ़ाइल से लिंक करते हैं (शामिल करें)
न्यूटॉपियन

2
इसने काम किया, हालाँकि मुझे "अच्छा" XML को शामिल करके लिखना था:<?xml version='1.0' encoding='utf-8' ?><nlog xmlns='http://nlog-project.org/schemas/NLog.xsd' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
Gady

1
यह केंद्रीकृत विन्यास में एक अच्छा सेगवे है। भविष्य के पाठकों, इस नमूने में हार्ड कोडित xml केवल डेमो (IMHO) के लिए है, इसे डेटाबेस या केंद्रीकृत फ़ाइल से पढ़ना वास्तविक कार्यान्वयन हो सकता है।
ग्रानैडकोडर

@wageoghe; मुझे त्रुटि क्यों मिलती है (लकड़हारा मौजूद नहीं है)? मैं सिर्फ कोड कॉपी और पेस्ट करता
हूं

22

एक त्रुटि है या नहीं, इसके आधार पर विभिन्न स्तरों को लॉग करना

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

मैंने इसे स्रोत कोड में एक उदाहरण से अनुकूलित किया है । मुझे पहली बार में फेंक दिया गया था क्योंकि मैंने बाहर छोड़ दिया था AspNetBufferingWrapper(चूंकि मेरा एएसपी ऐप नहीं है) - यह पता चला है कि पोस्टफिल्टरिंगवॉपर को कुछ बफ़र्ड लक्ष्य की आवश्यकता है। ध्यान दें कि target-refउपर्युक्त उदाहरण में प्रयुक्त तत्व NLog 1.0 में उपयोग नहीं किया जा सकता है (मैं .NET 4.0 ऐप के लिए 1.0 रीफ़्रेश का उपयोग कर रहा हूं); अपने लक्ष्य को रैपर ब्लॉक के अंदर रखना आवश्यक है। यह भी ध्यान दें कि लॉजिक सिंटैक्स (यानी बड़े-से या कम-से-कम प्रतीकों, <और>) को प्रतीकों का उपयोग करना है, न कि एक्सएमएल उन प्रतीकों (यानी &gt;और &lt;) के लिए बच जाता है या फिर एनएलओजी त्रुटि करेगा।

app.config:

<?xml version="1.0"?>
<configuration>
    <configSections>
        <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
    </configSections>

    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          throwExceptions="true" internalLogToConsole="true" internalLogLevel="Warn" internalLogFile="nlog.log">
        <variable name="appTitle" value="My app"/>
        <variable name="csvPath" value="${specialfolder:folder=Desktop:file=${appTitle} log.csv}"/>

        <targets async="true">
            <!--The following will keep the default number of log messages in a buffer and write out certain levels if there is an error and other levels if there is not. Messages that appeared before the error (in code) will be included, since they are buffered.-->
            <wrapper-target xsi:type="BufferingWrapper" name="smartLog">
                <wrapper-target xsi:type="PostFilteringWrapper">
                    <!--<target-ref name="fileAsCsv"/>-->
                    <target xsi:type="File" fileName="${csvPath}"
                    archiveAboveSize="4194304" concurrentWrites="false" maxArchiveFiles="1" archiveNumbering="Sequence"
                    >
                        <layout xsi:type="CsvLayout" delimiter="Tab" withHeader="false">
                            <column name="time" layout="${longdate}" />
                            <column name="level" layout="${level:upperCase=true}"/>
                            <column name="message" layout="${message}" />
                            <column name="callsite" layout="${callsite:includeSourcePath=true}" />
                            <column name="stacktrace" layout="${stacktrace:topFrames=10}" />
                            <column name="exception" layout="${exception:format=ToString}"/>
                            <!--<column name="logger" layout="${logger}"/>-->
                        </layout>
                    </target>

                     <!--during normal execution only log certain messages--> 
                    <defaultFilter>level >= LogLevel.Warn</defaultFilter>

                     <!--if there is at least one error, log everything from trace level--> 
                    <when exists="level >= LogLevel.Error" filter="level >= LogLevel.Trace" />
                </wrapper-target>
            </wrapper-target>

        </targets>

        <rules>
            <logger name="*" minlevel="Trace" writeTo="smartLog"/>
        </rules>
    </nlog>
</configuration>

NLog के कुछ संस्करणों में (मोनो और मुझे लगता है कि 2.0 के लिए), यह एक StackOverflowException का कारण बनता है, लेकिन दूसरों में नहीं (NLog 1 ताज़ा)।
पाट

अतिप्रवाह के बारे में - यह केवल सीएसवी प्रकार के लेआउट के कारण प्रतीत होता है - अगर मैं एक नियमित लेआउट करता हूं तो कोई समस्या नहीं है।
पाट

वहाँ के लिए fileAsCsv लक्ष्य-रेफरी क्या है? मैं NLog v2.0.0.2000 के खिलाफ काम करने के लिए इस उदाहरण को प्राप्त करने की कोशिश कर रहा हूं लेकिन अभी तक असफल रहा हूं।
पीटर मूस

@PeterMounce fileAsCsvलक्ष्य-परीक्षण मेरे परीक्षण से सिर्फ एक कलाकृति है। मेरा मानना ​​है कि NLog 2 में CsvLayouts के साथ समस्याएँ हैं जो NLog 1 / Refresh में नहीं थी।
पैट

22

मैंने इस सवाल का कुछ दिलचस्प जवाब दिया:

Nlog - लॉग फ़ाइल के लिए हेडर सेक्शन बनाना

एक हैडर जोड़ना:

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

हेडर और फ़ाइल लेआउट को परिभाषित करें:

  <variable name="HeaderLayout" value="This is the header.  Start time = ${longdate} Machine = ${machinename} Product version = ${gdc:item=version}"/>
  <variable name="FileLayout" value="${longdate} | ${logger} | ${level} | ${message}" />

लेआउट का उपयोग करके लक्ष्यों को परिभाषित करें:

<target name="fileHeader" xsi:type="File" fileName="xxx.log" layout="${HeaderLayout}" />
<target name="file" xsi:type="File" fileName="xxx.log" layout="${InfoLayout}" />

लकड़हारे को परिभाषित करें:

<rules>
  <logger name="headerlogger" minlevel="Trace" writeTo="fileHeader" final="true" />
  <logger name="*" minlevel="Trace" writeTo="file" />
</rules>

हेडर लिखें, शायद कार्यक्रम में जल्दी:

  GlobalDiagnosticsContext.Set("version", "01.00.00.25");

  LogManager.GetLogger("headerlogger").Info("It doesn't matter what this is because the header format does not include the message, although it could");

यह मोटे तौर पर "उपचार के अपवादों को अलग तरह से" विचार का सिर्फ एक और संस्करण है।

प्रत्येक लॉग स्तर को एक अलग लेआउट के साथ लॉग इन करें

इसी तरह, पोस्टर यह जानना चाहता था कि प्रति लॉगिंग स्तर पर प्रारूप को कैसे बदलना है। यह मेरे लिए स्पष्ट नहीं था कि अंतिम लक्ष्य क्या था (और क्या इसे "बेहतर" तरीके से हासिल किया जा सकता है), लेकिन मैं एक कॉन्फ़िगरेशन प्रदान करने में सक्षम था जो उसने पूछा था:

  <variable name="TraceLayout" value="This is a TRACE - ${longdate} | ${logger} | ${level} | ${message}"/> 
  <variable name="DebugLayout" value="This is a DEBUG - ${longdate} | ${logger} | ${level} | ${message}"/> 
  <variable name="InfoLayout" value="This is an INFO - ${longdate} | ${logger} | ${level} | ${message}"/> 
  <variable name="WarnLayout" value="This is a WARN - ${longdate} | ${logger} | ${level} | ${message}"/> 
  <variable name="ErrorLayout" value="This is an ERROR - ${longdate} | ${logger} | ${level} | ${message}"/> 
  <variable name="FatalLayout" value="This is a FATAL - ${longdate} | ${logger} | ${level} | ${message}"/> 
  <targets> 
    <target name="fileAsTrace" xsi:type="FilteringWrapper" condition="level==LogLevel.Trace"> 
      <target xsi:type="File" fileName="xxx.log" layout="${TraceLayout}" /> 
    </target> 
    <target name="fileAsDebug" xsi:type="FilteringWrapper" condition="level==LogLevel.Debug"> 
      <target xsi:type="File" fileName="xxx.log" layout="${DebugLayout}" /> 
    </target> 
    <target name="fileAsInfo" xsi:type="FilteringWrapper" condition="level==LogLevel.Info"> 
      <target xsi:type="File" fileName="xxx.log" layout="${InfoLayout}" /> 
    </target> 
    <target name="fileAsWarn" xsi:type="FilteringWrapper" condition="level==LogLevel.Warn"> 
      <target xsi:type="File" fileName="xxx.log" layout="${WarnLayout}" /> 
    </target> 
    <target name="fileAsError" xsi:type="FilteringWrapper" condition="level==LogLevel.Error"> 
      <target xsi:type="File" fileName="xxx.log" layout="${ErrorLayout}" /> 
    </target> 
    <target name="fileAsFatal" xsi:type="FilteringWrapper" condition="level==LogLevel.Fatal"> 
      <target xsi:type="File" fileName="xxx.log" layout="${FatalLayout}" /> 
    </target> 
  </targets> 


    <rules> 
      <logger name="*" minlevel="Trace" writeTo="fileAsTrace,fileAsDebug,fileAsInfo,fileAsWarn,fileAsError,fileAsFatal" /> 
      <logger name="*" minlevel="Info" writeTo="dbg" /> 
    </rules> 

फिर, बहुत हद तक अपवादों के उपचार के समान ।


1
ठंडा! मैंने पहले नहीं देखा था GlobalDiagnosticsContext
पैट

10

ट्विटर पर लॉग इन करें

इस पोस्ट के आधार पर एक Log4net Twitter परिशिष्ट के बारे में, मुझे लगा कि मैं एक NLog ट्विटर टारगेट (NLog 1.0 रिफ्रेश का उपयोग कर रहा हूं, 2.0 नहीं) लिखने में अपना हाथ आज़माऊंगा। काश, अब तक मैं वास्तव में सफलतापूर्वक पोस्ट करने के लिए ट्वीट नहीं कर पाया। मुझे नहीं पता कि यह मेरे कोड, ट्विटर, हमारी कंपनी के इंटरनेट कनेक्शन / फ़ायरवॉल, या क्या में कुछ गड़बड़ है। अगर कोई इसे आज़माने में दिलचस्पी रखता है तो मैं यहाँ कोड पोस्ट कर रहा हूँ। ध्यान दें कि तीन अलग-अलग "पोस्ट" विधियां हैं। पहली बार जो मैंने कोशिश की वह पोस्टमैसेजटॉइट है। PostMessageToTwitter मूलत: PostLoggingEvent के समान है। यदि मैं उपयोग करता हूं कि मुझे 401 अपवाद मिलता है। PostMessageBasic को एक ही अपवाद मिलता है। पोस्टमासेज बिना किसी त्रुटि के चलता है, लेकिन संदेश अभी भी ट्विटर पर नहीं आता है। PostMessage और PostMessageBasic उन उदाहरणों पर आधारित हैं जो मुझे SO पर यहां मिले थे।

FYI करें - मुझे अभी @Jason Diller की इस पोस्ट के जवाब में एक टिप्पणी मिली जो कहती है कि ट्विटर "अगले महीने" मूल प्रमाणीकरण बंद करने जा रहा है। यह मई 2010 में वापस आ गया था और अब यह दिसंबर 2010 है, इसलिए मुझे लगता है कि यह हो सकता है कि यह काम क्यों नहीं कर रहा है।

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.IO;

using NLog;
using NLog.Targets;
using NLog.Config;

namespace NLogExtensions
{
  [Target("TwitterTarget")]
  public class TwitterTarget : TargetWithLayout
  {
    private const string REQUEST_CONTENT_TYPE = "application/x-www-form-urlencoded";  

    private const string REQUEST_METHOD = "POST";  

    // The source attribute has been removed from the Twitter API,  
    // unless you're using OAuth.  
    // Even if you are using OAuth, there's still an approval process.  
    // Not worth it; "API" will work for now!  
    // private const string TWITTER_SOURCE_NAME = "Log4Net";  
    private const string TWITTER_UPDATE_URL_FORMAT = "http://twitter.com/statuses/update.xml?status={0}";  

    [RequiredParameter]
    public string TwitterUserName { get; set; }

    [RequiredParameter]
    public string TwitterPassword { get; set; }

    protected override void Write(LogEventInfo logEvent)
    {
      if (string.IsNullOrWhiteSpace(TwitterUserName) || string.IsNullOrWhiteSpace(TwitterPassword)) return;

      string msg = this.CompiledLayout.GetFormattedMessage(logEvent);

      if (string.IsNullOrWhiteSpace(msg)) return;

      try
      {
        //PostMessageToTwitter(msg);
        PostMessageBasic(msg);
      }
      catch (Exception ex)
      {
        //Should probably do something here ...
      }
    }

    private void PostMessageBasic(string msg)
    {
      // Create a webclient with the twitter account credentials, which will be used to set the HTTP header for basic authentication 
      WebClient client = new WebClient { Credentials = new NetworkCredential { UserName = TwitterUserName, Password = TwitterPassword } };

      // Don't wait to receive a 100 Continue HTTP response from the server before sending out the message body 
      ServicePointManager.Expect100Continue = false;

      // Construct the message body 
      byte[] messageBody = Encoding.ASCII.GetBytes("status=" + msg);

      // Send the HTTP headers and message body (a.k.a. Post the data) 
      client.UploadData(@"http://twitter.com/statuses/update.xml", messageBody);
    }

    private void PostMessage(string msg)
    {
      string user = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(TwitterUserName + ":" + TwitterPassword));
      byte [] bytes = System.Text.Encoding.UTF8.GetBytes("status=" + msg.ToTweet());
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://twitter.com/statuses/update.xml");
      request.Method = "POST";
      request.ServicePoint.Expect100Continue = false;
      request.Headers.Add("Authorization", "Basic " + user);
      request.ContentType = "application/x-www-form-urlencoded";
      request.ContentLength = bytes.Length;
      Stream reqStream = request.GetRequestStream();
      reqStream.Write(bytes, 0, bytes.Length);
      reqStream.Close();
    }

    private void PostMessageToTwitter(string msg)
    {
      var updateRequest = HttpWebRequest.Create(string.Format(TWITTER_UPDATE_URL_FORMAT,
                                                HttpUtility.UrlEncode(msg.ToTweet()))) as HttpWebRequest;
      updateRequest.ContentLength = 0;
      updateRequest.ContentType = REQUEST_CONTENT_TYPE;
      updateRequest.Credentials = new NetworkCredential(TwitterUserName, TwitterPassword);
      updateRequest.Method = REQUEST_METHOD;

      updateRequest.ServicePoint.Expect100Continue = false;

      var updateResponse = updateRequest.GetResponse() as HttpWebResponse;

      if (updateResponse.StatusCode != HttpStatusCode.OK && updateResponse.StatusCode != HttpStatusCode.Continue)
      {
        throw new Exception(string.Format("An error occurred while invoking the Twitter REST API [Response Code: {0}]", updateResponse.StatusCode));
      }
    }
  }

  public static class Extensions
  {
    public static string ToTweet(this string s)
    {
      if (string.IsNullOrEmpty(s) || s.Length < 140)
      {
        return s;
      }

      return s.Substring(0, 137) + "...";
    }
  }
}

इसे इस तरह कॉन्फ़िगर करें:

बताएं कि NLog विधानसभा में लक्ष्य है:

<extensions>
  <add assembly="NLogExtensions"/>
</extensions>

लक्ष्य कॉन्फ़िगर करें:

<targets>
    <target name="twitter" type="TwitterTarget" TwitterUserName="yourtwittername" TwitterPassword="yourtwitterpassword" layout="${longdate} ${logger} ${level} ${message}" />
</targets>

अगर कोई इसे आज़माता है और सफलता पाता है, तो अपने निष्कर्षों के साथ वापस पोस्ट करें।


ट्विटर OAuth का उपयोग करता है - .NET के पास एक प्रदाता है डॉटनेटोपेनेथ.नेट
पैट

8

आसान तरीका सशर्त लेआउट का उपयोग करके प्रत्येक लॉग स्तर को एक अलग लेआउट के साथ लॉग इन करें

<variable name="VerboseLayout" value="${level:uppercase=true}: ${longdate} | ${logger}    : 
${when:when=level == LogLevel.Trace:inner=MONITOR_TRACE ${message}} 
${when:when=level == LogLevel.Debug:inner=MONITOR_DEBUG ${message}} 
${when:when=level == LogLevel.Info:inner=MONITOR_INFO ${message}} 
${when:when=level == LogLevel.Warn:inner=MONITOR_WARN ${message}} 
${when:when=level == LogLevel.Error:inner=MONITOR_ERROR ${message}} 
${when:when=level == LogLevel.Fatal:inner=MONITOR_CRITICAL ${message}} |     
${exception:format=tostring} | ${newline} ${newline}" />

सिंटैक्स के लिए https://github.com/NLog/NLog/wiki/When-Filter देखें


7

किसी बाहरी वेबसाइट / डेटाबेस को रिपोर्ट करना

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

मैंने PHP में वेब पेज लिखा और डेटा को संग्रहीत करने के लिए एक mysql डेटाबेस, उपयोगकर्ता और तालिका बनाई। मैंने चार उपयोगकर्ता चर, एक आईडी और एक टाइमस्टैम्प पर फैसला किया। संभावित चर (या तो URL या POST डेटा के रूप में शामिल हैं):

  • app (आवेदन का नाम)
  • msg (संदेश - उदा। अपवाद हुआ ...)
  • dev (डेवलपर - जैसे पैट)
  • src(स्रोत - यह मशीन से संबंधित एक वैरिएबल से आएगा, जिस पर ऐप चल रहा था, जैसे Environment.MachineNameया कुछ और)
  • log (लॉग फ़ाइल या क्रिया संदेश)

(सभी चर वैकल्पिक हैं, लेकिन कुछ भी रिपोर्ट नहीं किया जाता है यदि उनमें से कोई भी सेट नहीं है - इसलिए यदि आप सिर्फ वेबसाइट पर जाते हैं तो URL कुछ भी डीबी को नहीं भेजा जाता है।)

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

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

MySQL सामान

(Db उपयोगकर्ता के INSERTअपने डेटाबेस में केवल इस एक टेबल पर विशेषाधिकार हैं।)

CREATE TABLE `reports` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `ts` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `applicationName` text,
  `message` text,
  `developer` text,
  `source` text,
  `logData` longtext,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='storage place for reports from external applications'

वेबसाइट कोड

(पीएचपी 5.3 या 5.2 के साथ पीडीओ सक्षम , फ़ाइल है index.phpमें /reportफ़ोल्डर)

<?php
$app = $_REQUEST['app'];
$msg = $_REQUEST['msg'];
$dev = $_REQUEST['dev'];
$src = $_REQUEST['src'];
$log = $_REQUEST['log'];

$dbData =
    array(  ':app' => $app,
            ':msg' => $msg,
            ':dev' => $dev,
            ':src' => $src,
            ':log' => $log
    );
//print_r($dbData); // For debugging only! This could allow XSS attacks.
if(isEmpty($dbData)) die("No data provided");

try {
$db = new PDO("mysql:host=$host;dbname=reporting", "reporter", $pass, array(
    PDO::ATTR_PERSISTENT => true
));
$s = $db->prepare("INSERT INTO reporting.reports 
    (
    applicationName, 
    message, 
    developer, 
    source, 
    logData
    )
    VALUES
    (
    :app, 
    :msg, 
    :dev, 
    :src, 
    :log
    );"
    );
$s->execute($dbData);
print "Added report to database";
} catch (PDOException $e) {
// Sensitive information can be displayed if this exception isn't handled
//print "Error!: " . $e->getMessage() . "<br/>";
die("PDO error");
}

function isEmpty($array = array()) {
    foreach ($array as $element) {
        if (!empty($element)) {
            return false;
        }
    }
    return true;
}
?>

ऐप कोड (NLog कॉन्फ़िग फ़ाइल)

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      throwExceptions="true" internalLogToConsole="true" internalLogLevel="Warn" internalLogFile="nlog.log">
    <variable name="appTitle" value="My External App"/>
    <variable name="csvPath" value="${specialfolder:folder=Desktop:file=${appTitle} log.csv}"/>
    <variable name="developer" value="Pat"/>

    <targets async="true">
        <!--The following will keep the default number of log messages in a buffer and write out certain levels if there is an error and other levels if there is not. Messages that appeared before the error (in code) will be included, since they are buffered.-->
        <wrapper-target xsi:type="BufferingWrapper" name="smartLog">
            <wrapper-target xsi:type="PostFilteringWrapper">
                <target xsi:type="File" fileName="${csvPath}"
                archiveAboveSize="4194304" concurrentWrites="false" maxArchiveFiles="1" archiveNumbering="Sequence"
                >
                    <layout xsi:type="CsvLayout" delimiter="Comma" withHeader="false">
                        <column name="time" layout="${longdate}" />
                        <column name="level" layout="${level:upperCase=true}"/>
                        <column name="message" layout="${message}" />
                        <column name="callsite" layout="${callsite:includeSourcePath=true}" />
                        <column name="stacktrace" layout="${stacktrace:topFrames=10}" />
                        <column name="exception" layout="${exception:format=ToString}"/>
                        <!--<column name="logger" layout="${logger}"/>-->
                    </layout>
                </target>

                 <!--during normal execution only log certain messages--> 
                <defaultFilter>level >= LogLevel.Warn</defaultFilter>

                 <!--if there is at least one error, log everything from trace level--> 
                <when exists="level >= LogLevel.Error" filter="level >= LogLevel.Trace" />
            </wrapper-target>
        </wrapper-target>

        <target xsi:type="WebService" name="web"
                url="http://example.com/report" 
                methodName=""
                namespace=""
                protocol="HttpPost"
                >
            <parameter name="app" layout="${appTitle}"/>
            <parameter name="msg" layout="${message}"/>
            <parameter name="dev" layout="${developer}"/>
            <parameter name="src" layout="${environment:variable=UserName} (${windows-identity}) on ${machinename} running os ${environment:variable=OSVersion} with CLR v${environment:variable=Version}"/>
            <parameter name="log" layout="${file-contents:fileName=${csvPath}}"/>
        </target>

    </targets>

    <rules>
        <logger name="*" minlevel="Trace" writeTo="smartLog"/>
        <logger name="*" minlevel="Error" writeTo="web"/>
    </rules>
</nlog>

नोट: लॉग फ़ाइल के आकार के साथ कुछ समस्याएँ हो सकती हैं, लेकिन मैंने इसे ट्रंक करने के लिए एक सरल तरीका नहीं निकाला है (उदाहरण के लिए एक ला * निक्स की tailकमांड )।


यह एक परियोजना के लिए काम करता है, लेकिन दूसरों में मेरे पास कुछ मुद्दे हैं url: इनर एक्ससेप्शन: सिस्टम.इंवलिडकैस्ट एक्सपेप्शन मैसेज = 'डाली जाती है। Source = mscorlib StackTrace: System.Convert.DefaultToType (IConvertible value, Type targetType, IFormatProvider प्रदाता) पर System.String.System.IConvertible.oType (टाइप प्रकार, IFormatProvider प्रदाता) System.Convert.ChangeType (मान) पर मान। , IFormatProvider प्रदाता)
पैट

एक अन्य विकल्प यदि आप लॉग की निगरानी करने में सक्षम होना चाहते हैं और एक त्रुटि की स्थिति में अधिसूचित किया जाना एक ट्विटर लक्ष्य होगा। Log4net के लिए लिखे गए ट्विटर ऐपेंडर के लिए इस लिंक को देखें: twitterappender.codeplex.com इस पर चर्चा करने वाली मूल ब्लॉग पोस्टिंग यहां है: caseywatson.com/2009/07/log4net-twitter-awesome इसके लिए कुछ समान लिखना आसान होना चाहिए NLog।
वेजोगे

मैंने NLog TwitterTarget लिखने के साथ बेवकूफ बनाया है लेकिन वास्तव में एक ट्वीट पोस्ट करने में सफलता नहीं मिली है। मैंने उत्तर के रूप में कोड पोस्ट किया है। यदि आप चाहें तो इसे आज़माने के लिए स्वतंत्र महसूस करें।
वेजोगे

4

सिल्वरलाइट से लॉग इन करें

सिल्वरलाइट के साथ NLog का उपयोग करते समय आप प्रदान की गई वेब सेवा के माध्यम से सर्वर साइड को ट्रेस भेज सकते हैं । आप आइसोलेटेड स्टोरेज में एक स्थानीय फ़ाइल भी लिख सकते हैं, जो वेब सर्वर के अनुपलब्ध होने पर काम आती है। देखें यहाँ जानकारी के लिए, यानी कुछ इस तरह का उपयोग अपने आप को एक लक्ष्य बनाने के लिए:

namespace NLogTargets
{
    [Target("IsolatedStorageTarget")]
    public sealed class IsolatedStorageTarget : TargetWithLayout
    {
        IsolatedStorageFile _storageFile = null;
        string _fileName = "Nlog.log"; // Default. Configurable through the 'filename' attribute in nlog.config

        public IsolatedStorageTarget()
        {
        }

        ~IsolatedStorageTarget()
        {
            if (_storageFile != null)
            {
                _storageFile.Dispose();
                _storageFile = null;
            }
        }

        public string filename
        {
            set
            {
                _fileName = value; 
            }
            get
            {
                return _fileName;  
            }
         }

        protected override void Write(LogEventInfo logEvent)
        {
            try
            {
                writeToIsolatedStorage(this.Layout.Render(logEvent));
            }
            catch (Exception e)
            {
                // Not much to do about his....
            }
        }

        public void writeToIsolatedStorage(string msg)
        {
            if (_storageFile == null)
                _storageFile = IsolatedStorageFile.GetUserStoreForApplication();
            using (IsolatedStorageFile isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                // The isolated storage is limited in size. So, when approaching the limit
                // simply purge the log file. (Yeah yeah, the file should be circular, I know...)
                if (_storageFile.AvailableFreeSpace < msg.Length * 100)
                {
                    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(_fileName, FileMode.Truncate, FileAccess.Write, isolatedStorage))
                    { }
                }
                // Write to isolated storage
                using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(_fileName, FileMode.Append, FileAccess.Write, isolatedStorage))
                {
                    using (TextWriter writer = new StreamWriter(stream))
                    {
                        writer.WriteLine(msg);
                    }
                }
            }
        }
    } 
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.