NLog के दस्तावेज के अनुसार:
अधिकांश एप्लिकेशन प्रति वर्ग एक लकड़हारे का उपयोग करेंगे, जहां लकड़हारा का नाम कक्षा के नाम के समान है।
यह वही तरीका है जो log4net संचालित करता है। यह एक अच्छा अभ्यास क्यों है?
NLog के दस्तावेज के अनुसार:
अधिकांश एप्लिकेशन प्रति वर्ग एक लकड़हारे का उपयोग करेंगे, जहां लकड़हारा का नाम कक्षा के नाम के समान है।
यह वही तरीका है जो log4net संचालित करता है। यह एक अच्छा अभ्यास क्यों है?
जवाबों:
Log4net के साथ, प्रति वर्ग एक लकड़हारा का उपयोग करके लॉग संदेश के स्रोत (यानी लॉग में कक्षा लेखन) को पकड़ना आसान हो जाता है। यदि आपके पास प्रति कक्षा एक लकड़हारा नहीं है, लेकिन इसके बजाय पूरे एप्लिकेशन के लिए एक लकड़हारा है, तो आपको यह जानने के लिए अधिक प्रतिबिंब चाल का सहारा लेना होगा कि लॉग संदेश कहां से आ रहे हैं।
निम्नलिखित की तुलना करें:
using System.Reflection;
private static readonly ILog _logger =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public void SomeMethod()
{
_logger.DebugFormat("File not found: {0}", _filename);
}
Logger.DebugFormat("File not found: {0}", _filename); // Logger determines caller
-- or --
Logger.DebugFormat(this, "File not found: {0}", _filename); // Pass in the caller
दूसरे उदाहरण का उपयोग करते हुए, लकड़हारे को यह देखने के लिए स्टैक ट्रेस बनाने की आवश्यकता होगी कि कौन उसे बुला रहा था या आपके कोड को हमेशा कॉलर में पास करना होगा। लकड़हारा-प्रति-वर्ग शैली के साथ, आप अभी भी ऐसा करते हैं, लेकिन आप इसे प्रति कॉल के बजाय एक बार प्रति कक्षा में कर सकते हैं और एक गंभीर प्रदर्शन समस्या को समाप्त कर सकते हैं।
NLog में "प्रति फ़ाइल लकड़हारा" का उपयोग करने के लिए लाभ: आपको नामस्थान और वर्ग नाम से लॉग्स को प्रबंधित / फ़िल्टर करने की संभावना है। उदाहरण:
<logger name="A.NameSpace.MyClass" minlevel="Debug" writeTo="ImportantLogs" />
<logger name="A.NameSpace.MyOtherClass" minlevel="Trace" writeTo="ImportantLogs" />
<logger name="StupidLibrary.*" minlevel="Error" writeTo="StupidLibraryLogs" />
<!-- Hide other messages from StupidLibrary -->
<logger name="StupidLibrary.*" final="true" />
<!-- Log all but hidden messages -->
<logger name="*" writeTo="AllLogs" />
ऐसा करने के लिए NLogger के पास बहुत उपयोगी कोड स्निपेट है। nlogger
टुकड़ा निम्नलिखित कोड का निर्माण करेगा:
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
तो केवल कुछ कीस्ट्रोक्स और आपके पास प्रति वर्ग लकड़हारा है। यह लकड़हारे के नाम के रूप में नाम स्थान और वर्ग नाम का उपयोग करेगा। अपने वर्ग लकड़हारे को अलग नाम सेट करने के लिए, आप इसका उपयोग कर सकते हैं:
private static NLog.Logger logger = NLog.LogManager.GetLogger("MyLib.MyName");
और, जैसा कि @JeremyWiebe ने कहा, आपको उस वर्ग का नाम प्राप्त करने के लिए ट्रिक्स का उपयोग करने की आवश्यकता नहीं है जो एक संदेश को लॉग करने की कोशिश कर रहा है: लकड़हारा का नाम (जो आमतौर पर वर्ग का नाम होता है) को फाइल करने में आसान हो सकता है (या अन्य लक्ष्य) ${logger}
लेआउट में उपयोग करके ।
मैं इस पसंद के लिए कुछ कारण देख सकता हूं।
ज्यादातर मामलों में, वर्ग का नाम लकड़हारे के लिए एक अच्छा नाम प्रदान करता है। लॉग फ़ाइलों को स्कैन करते समय, आप लॉग संदेश देख सकते हैं और इसे सीधे कोड की एक पंक्ति के साथ जोड़ सकते हैं।
एक अच्छा उदाहरण जहां यह सबसे अच्छा तरीका नहीं है, हाइबरनेट का SQL लॉग है। एक साझा लकड़हारा है जिसका नाम "Hibernate.SQL" या ऐसा ही कुछ है, जहाँ कई अलग-अलग वर्ग एक एकल लकड़हारा वर्ग के लिए कच्चा SQL लिखते हैं।
यदि आप हर बार एक लकड़हारा वस्तु बनाने की जरूरत नहीं है, तो विकास के दृष्टिकोण से, यह सबसे आसान है। दूसरी ओर, यदि आप नहीं करते हैं, बल्कि आप इसे गतिशील रूप से प्रतिबिंब का उपयोग करके बनाते हैं, तो यह प्रदर्शन को धीमा कर देगा। इसे हल करने के लिए, आप निम्न कोड का उपयोग कर सकते हैं जो लकड़हारे को गतिशील रूप से अतुल्यकालिक बनाता है:
using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WinForms
{
class log
{
public static async void Log(int severity, string message)
{
await Task.Run(() => LogIt(severity, message));
}
private static void LogIt(int severity, string message)
{
StackTrace st = new StackTrace();
StackFrame x = st.GetFrame(2); //the third one goes back to the original caller
Type t = x.GetMethod().DeclaringType;
Logger theLogger = LogManager.GetLogger(t.FullName);
//https://github.com/NLog/NLog/wiki/Log-levels
string[] levels = { "Off", "Trace", "Debug", "Info", "Warn", "Error", "Fatal" };
int level = Math.Min(levels.Length, severity);
theLogger.Log(LogLevel.FromOrdinal(level), message);
}
}
}
दो कारणों से तुरंत वसंत:
शायद इसलिए कि आप उन तरीकों को लॉग इन करने में सक्षम होना चाहते हैं जो केवल बिना एनकैप्सुलेशन को तोड़ने के वर्ग के लिए दिखाई देते हैं, इससे लॉगिंग कार्यक्षमता को तोड़ने के बिना किसी अन्य एप्लिकेशन में कक्षा का उपयोग करना आसान हो जाता है।
यदि आप एनएलओजी का उपयोग कर रहे हैं, तो आप कॉल को कॉन्फ़िगर में निर्दिष्ट कर सकते हैं, यह वर्ग नाम और विधि रिकॉर्ड करेगा जहां लॉगिंग स्टेटमेंट स्थित था।
<property name="CallSite" value="${callsite}" />
फिर आप अपने लकड़हारे के नाम या असेंबली के नाम के लिए एक स्थिरांक का उपयोग कर सकते हैं।
अस्वीकरण: मुझे नहीं पता कि एनएलओजी इस जानकारी को कैसे एकत्र करता है, मेरा अनुमान प्रतिबिंब होगा, इसलिए आपको प्रदर्शन पर विचार करने की आवश्यकता हो सकती है। यदि आप NLOG v4.4 या बाद के संस्करण का उपयोग नहीं कर रहे हैं, तो Async विधियों के साथ कुछ समस्याएँ हैं।