2012-11-26 16 views
5

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

fileTarget.Layout = "${longdate} ${callsite} ${level} ${event-context:item=MyValue} ${message}";` 

मेरा वर्तमान लेआउट ऊपर जैसा है। मैंने घटना-संदर्भ का उपयोग करने की कोशिश की: आइटम लेकिन सभी संदेशों के लिए संदर्भ आइटम को प्रिंट करने का तरीका नहीं है।

मैं के रूप में

Logger log = LogManager.GetCurrentClassLogger(); 
LogEventInfo theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name); 
logger.Log(theEvent); 

इस प्रकार की कोशिश की लेकिन यह पहली पंक्ति Sim101 पर और अन्य लाइनों पर नहीं संदर्भ जानकारी के साथ केवल एक लाइन मुद्रण समाप्त हो गया।

2012-11-26 15:09:47.9777 NinjaTrader.Strategy.LODHOD.OnStartUp Debug Sim101 
2012-11-26 15:09:48.3996 NinjaTrader.Strategy.LODHOD.OnBarUpdate Trace BAR UPDATE 
2012-11-26 15:09:49.7902 NinjaTrader.Strategy.LODHOD.EntryOrders Info PLACED ENTRY ORDERS 

मैं सभी लॉग लाइनों पर सिम 101 कैसे प्रिंट करूं?

उत्तर

22

{event-context}LayoutRendererLogEventInfo ऑब्जेक्ट की Properties संपत्ति से एक मान लिखता है।

गुण एक शब्दकोश है जहां आप नामित मान स्टोर कर सकते हैं जिन्हें आप प्रत्येक लॉग संदेश में जोड़ने के लिए NLog चाहते हैं।

LogEventInfo theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name); 
theEvent.Properties["StrategyId"] = "Sim101"; 
Logger.Log(theEvent); 

आपके लेआउट को इस प्रकार दिखाई देगा:

आप "StrategyId" प्रभाव में है कि जब संदेश लॉग होता है के साथ एक लॉग संदेश टैग करना चाहते हैं, तो आप अपने LogEventInfo बनाना चाहिए कुछ इस तरह की वस्तुओं : यदि आप अपने प्रवेश कॉल साइटों कम वर्बोज़ होना चाहता हूँ

fileTarget.Layout = "${longdate} ${callsite} ${level} ${event-context:item=StrategyId} ${message}"; 

हैं, तो आप GlobalDiagnosticContext या MappedDiagnosticContext इस्तेमाल कर सकते हैं।

private void ApplyStrategyABC() 
{ 
    NLog.GlobalDiagnosticContext.Set("StrategyId","ABC"); 
    //Do some stuff 
    LogEventInfo theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name); 
    Logger.Log(theEvent); 

    NLog.GlobalDiagnosticContext.Remove("StrategyId"); 
} 

private void ApplyStrategyDEF() 
{ 
    NLog.GlobalDiagnosticContext.Set("StrategyId","DEF"); 
    //Do some stuff 
    LogEventInfo theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name); 
    Logger.Log(theEvent); 

    NLog.GlobalDiagnosticContext.Remove("StrategyId"); 
} 

इस तरह एक लेआउट का उपयोग करना:

fileTarget.Layout = "${longdate} ${callsite} ${level} ${gdc:item=StrategyId} ${message}"; 

प्रत्येक लॉग संदेश का कारण बन जाएगा वैश्विक शब्दकोश में "StrategyId" के वर्तमान मूल्य के साथ टैग किया जाना है।

मज़े के लिए आप एक धाराप्रवाह एपीआई एक्सटेंशन विधि भी बना सकते हैं जो आपके गुणों को आपके द्वारा बनाए गए LogEventInfo ऑब्जेक्ट्स पर लागू करेगा। कुछ इस तरह (untested):

var theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name).WithProperty("StrategyId", "ABC"); 

और यह:

LogEventInfo WithProperty(this LogEventInfo theEvent, string name, string value) 
{ 
    theEvent.Properties[name] = value; 
    return theEvent; 
} 

फिर आप इसे इस तरह इस्तेमाल कर सकते हैं

var theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name).WithProperty("StrategyId", "ABC").WithProperty("SomethingElse", someLocalVariable); 

आप अधिक स्पष्ट होना चाहते हैं (और संभव को कम टाइपो त्रुटियां), आप इस तरह के अधिक विशिष्ट विस्तार विधियां कर सकते हैं:

LogEventInfo WithStrategy(this LogEventInfo theEvent, string strategy) 
{ 
    theEvent.Properties["StrategyId"] = strategy; 
    return theEvent; 
} 

LogEventInfo WithCurrency(this LogEventInfo theEvent, string currency) 
{ 
    theEvent.Properties["Currency"] = currency; 
    return theEvent; 
} 

var theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", this.Account.Name).WithStrategy("ABC").WithCurrency("US dollars"); 

संपादित करें: अधिकांश लोग Logger.Info, Logger.Debug, Logger.Trace, आदि का उपयोग LogEventInfo बनाने और प्रत्येक संदेश के लिए लॉग को कॉल करने के बजाय अपने लॉग संदेश लिखने के तरीकों का उपयोग करते हैं।यदि आप अपनी LogEventInfo ऑब्जेक्ट्स स्पष्ट रूप से बनाते हैं, तो शायद अधिक लचीलापन उपलब्ध है, लेकिन यह आपके काम को और अधिक जटिल बनाता है।

यदि आप Logger.Info, Logger.Debug, आदि विधियों का उपयोग करना चाहते हैं और अतिरिक्त गुणों के साथ प्रत्येक लॉग संदेश को सजाने के लिए चाहते हैं, तो आप अभी भी ऐसा कर सकते हैं।

मान लीजिए कि आप दो तरीकों (जैसे मैं ऊपर वर्णित है) दो अलग अलग रणनीतियों को लागू करने के दो: एबीसी और डीईएफ़:

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

fileTarget.Layout = "${longdate} ${callsite} ${level} ${gdc:item=StrategyId} ${message}"; 

public class MyClass 
{ 
    private static readonly Logger logger = LogManager.GetCurrentClassLogger(); 

    private void ApplyStrategyABC() 
    { 
    NLog.GlobalDiagnosticContext.Set("StrategyId","ABC"); 
    //Do some stuff 

    logger.Debug("Hello from ABC!"); 

    var x = CalculateSomeValue(); 

    logger.Debug("Value = {0}", x); 

    NLog.GlobalDiagnosticContext.Remove("StrategyId");  
    } 

    private void ApplyStrategyDEF() 
    { 
    NLog.GlobalDiagnosticContext.Set("StrategyId","DEF"); 
    //Do some stuff 

    logger.Debug("Hello from DEF"); 

    var x = CalculateSomeValue(); 

    logger.Debug("Value = {0}", x); 

    NLog.GlobalDiagnosticContext.Remove("StrategyId");  
    } 
} 

In you program call your two strategies: 

var myClass = new MyClass(); 

myClass.ApplyStrategyABC(); 
myClass.ApplyStrategyDEF(); 

प्रत्येक मामले में, संदेशों लॉग इन "StrategyId" के साथ टैग किया जाएगा जो संबंधित फ़ंक्शन के अंदर सेट है।

यदि आप अपने संदेश बनाने के लिए LogEventInfo ऑब्जेक्ट्स बनाना और उपयोग करना चाहते हैं, तो आपको यह समझना होगा कि एक LogEventInfo ऑब्जेक्ट इंस्टेंस की गुण केवल उस उदाहरण पर लागू होती हैं। यदि आप LogEventInfo बनाते हैं, तो अपनी प्रॉपर्टी सेट करें, इसे लॉग करें, फिर Logger.Info, Logger.Debug, आदि का उपयोग करके एक संदेश लॉग करें, तो आप मूल LogEventInfo पर सेट की गई गुणों को नहीं देख पाएंगे।

उदाहरण के लिए,

var logger = LogManager.GetCurrentClassLogger(); 
var theEvent = new LogEventInfo(NLog.LogLevel.Debug, "", "Hello 1"); 
theEvent.Properties["StrategyId"] = "ABC"; 
//This message will be tagged with StrategyId = ABC if the layout uses the event-context LayoutRenderer 
logger.Log(theEvent); 

//This message will NOT be tagged with StrategyId = ABC because that value was only added to the LogEventInfo 
//object that was created above. Another way to think about this is that internally 
//NLog creates a LogEventInfo for each message that is logged via the Debug, Trace, etc 
//methods. 
logger.Debug("Hello 2"); 

मैं अपने संदेश लॉग इन करने के Logger.Info, Logger.Debug, Logger.Trace, आदि तरीकों का उपयोग कर और या तो का उपयोग कर GlobalDiagnosticsContext या MappedDiagnosticsContext में अतिरिक्त जानकारी है कि आप प्रत्येक में शामिल होना चाहते हैं निर्दिष्ट करने के लिए सिफारिश करेंगे लॉग संदेश

आम तौर पर, मुझे लगता है कि मैं भी सुझाव है कि कि आप या तो Logger.Info, Logger.Debug, Logger.Trace तरीकों या LogEventInfo + Logger.Log, लेकिन दोनों नहीं का उपयोग करें। दोनों का उपयोग करना, विशेष रूप से यदि आप अतिरिक्त संदर्भ मान जोड़ने की कोशिश कर रहे हैं (StrategyId) भ्रमित हो सकता है।

मैं सॉफ्टवेयर स्थापित करने के लिए एक समानता बना सकता हूं। आम तौर पर जब आप अपने कंप्यूटर पर सॉफ़्टवेयर इंस्टॉल करते हैं, तो आपके पास "विशिष्ट" इंस्टॉल करने का विकल्प होता है जहां आप इंस्टॉलर को उन घटकों को इंस्टॉल करते हैं जिन्हें वह इंस्टॉल करना चाहते हैं या "कस्टम" जहां आप चुनते हैं और उन घटकों को चुनते हैं जिन्हें आप इंस्टॉल करना चाहते हैं। मैं तुम्हारे बारे में नहीं जानता, लेकिन मैं आमतौर पर "विशिष्ट" स्थापना का चयन करता हूं। Logger.Info का उपयोग करना, Logger.Debug, Logger.Trace "विशिष्ट" इंस्टॉल की तरह है। लॉगिंग के लिए ये सबसे अधिक उपयोग किए जाने वाले तरीकों हैं। LogEventInfo + Logger.Log का उपयोग करना "कस्टम" इंस्टॉल करना पसंद है। यदि आप LogEventInfo का उपयोग कर रहे हैं तो निहितार्थ यह है कि "सामान्य" लॉगिंग विधियां आपकी आवश्यकताओं को पूरा नहीं करती हैं।

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

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

MappedDiagnosticsContext थ्रेड स्थानीय है (यह अपने मूल्यों को संग्रहीत करने के लिए थ्रेड स्थिर शब्दकोश का उपयोग करता है), इसलिए संभवतया बहुभाषी स्थिति में उपयोग करना बेहतर है।

आप कल्पना और स्वचालित रूप से गुंजाइश मान GlobalDiagnosticsContext (या MappedDiagnosticsContext) में डाल प्राप्त करना चाहते हैं, तो आप इस तरह एक वर्ग बना सकते हैं:

public class ScopedGlobalContext : IDisposable 
{ 
    private string n; 
    private string v; 

    public ScopedGlobalContext(string name, string value) 
    { 
    n = name; 
    v = value; 
    NLog.GlobalDiagnosticsContext.Set(n, v); 
    } 

    public void Dispose() 
    { 
    NLog.GlobalDiagnosticsContext.Remove(n); 
    } 
} 

और तुम इस तरह इसका इस्तेमाल कर सकते हैं:

private void ApplyStrategyDEF() 
    { 
    using (new ScopedGlobalContext("StrategyId", "DEF")) 
    { 
     //Do some stuff 

     logger.Debug("Hello from DEF"); 

     var x = CalculateSomeValue(); 

     logger.Debug("Value = {0}", x); 
    } 
    } 

यह जब using गुंजाइश शुरू होता है और यह जब using दायरे से बाहर निकलता है निकाल देंगे GlobalDiagnosticsContext शब्दकोश में StrategyId, DEF नाम मान युग्म डाल देंगे।

+0

मेरा पूरा प्रश्न है: क्या मुझे हर बार ट्रेस फ़ंक्शन कॉल करने से पहले एक ईवेंट जोड़ना होगा? व्हील मैं ईवेंट गुण जोड़ता हूं और logger.info (theEvent) करता हूं, यह तुरंत मेरे लॉग के लिए प्रत्यय मुद्रित करता है। जैसे 2012-11-28 के लिए 14: 18: 52.3277 NinjaTrader.Strategy.LODHOD.OnStartUp जानकारी के लिए लॉग घटना: लॉगर = '' लेवल = जानकारी संदेश = 'd4d0d3849c2440f5b41de65d744ede61' SequenceID = 270 हालांकि अगले logger.info पर कब्जा नहीं किया मेरी गुण 2012-11-28 14: 18: 52.9996 निंजा ट्रेडर .trategy.LODHOD.OnBarUpdate जानकारी बार अद्यतन मैं जिस कोड का उपयोग करता हूं वह यहां है। http://codeviewer.org/view/codeoffc95 – junkone

+0

और लॉग इन मैंने यहां उपयोग किया है। http://codeviewer.org/view/codeoffc96 – junkone

+0

आपको लॉग इन करने के लिए लॉग संदेश को लॉग इन करने के लिए LogEventInfo क्लास का उपयोग करने की आवश्यकता नहीं है। आम तौर पर, ज्यादातर लोग नहीं करते हैं। वे इन लॉग इन कोड लिखने के लिए। इन्फो, डीबग, ट्रेस, आदि विधियों का उपयोग करते हैं। मैं अपने उत्तर में कुछ उदाहरण जोड़ूंगा। – wageoghe

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