我使用NLog進行日誌記錄,我使用包裝來調用日誌方法,我的問題是:如果我嘗試打印關於調用站點(${callsite}
)的信息,它會打印包裝器方法而不是導致記錄器記錄的原始方法。Nlog當使用包裝器時,調用站點是錯誤的
是否有任何方法來獲得調用包裝方法的原始方法?
我使用NLog進行日誌記錄,我使用包裝來調用日誌方法,我的問題是:如果我嘗試打印關於調用站點(${callsite}
)的信息,它會打印包裝器方法而不是導致記錄器記錄的原始方法。Nlog當使用包裝器時,調用站點是錯誤的
是否有任何方法來獲得調用包裝方法的原始方法?
見我回答這個問題:
Problem matching specific NLog logger name
我已經從這裏的答案複製的範例代碼(縮寫NLOG包裝),以節省一些麻煩:
class NLogLogger : ILogger
{
private NLog.Logger logger;
//The Type that is passed in is ultimately the type of the current object that
//Ninject is creating. In the case of my example, it is Class1 and Class1 is
//dependent on ILogger.
public NLogLogger(Type t)
{
logger = NLog.LogManager.GetLogger(t.FullName);
}
//Trace, Warn, Error, Fatal eliminated for brevity
public bool IsInfoEnabled
{
get { return logger.IsInfoEnabled; }
}
public bool IsDebugEnabled
{
get { return logger.IsDebugEnabled; }
}
public void Info(string format, params object [] args)
{
if (logger.IsInfoEnabled)
{
Write(LogLevel.Info, format, args);
}
}
public void Debug(string format, params object [] args)
{
if (logger.IsDebugEnabled)
{
Write(LogLevel.Debug, format, args);
}
}
private void Write(LogLevel level, string format, params object [] args)
{
LogEventInfo le = new LogEventInfo(level, logger.Name, null, format, args);
logger.Log(typeof(NLogLogger), le);
}
}
注這個答案是在NInject的背景下給出的。即使您沒有使用NInject,同樣的原理也適用於包裝NLog。關鍵是與NLog通信你的包裝類型。
這是關於如何正確編寫NLog包裝的例子(即維護呼叫站點信息)。關鍵在於Write方法。注意它如何使用NLog的Log方法。另請注意,傳遞包裝類的類型作爲第一個參數。 NLog使用類型信息導航調用堆棧。只要它看到DeclaringType是傳入類型(即包裝類型)的方法,它就知道堆棧中的下一幀是調用方法。
另請參閱此鏈接(到NLog的源代碼庫),以獲得另外兩個「擴展」記錄器的示例。一個通過包裝,一個由繼承:
https://github.com/jkowalski/NLog/tree/master/examples/ExtendingLoggers
我不是100%肯定,但我認爲你不能簡單地包裹NLOG和委託信息,調試,警告等方法來NLOG這樣的:
class MyNLogWrapper
{
private readonly Logger logger = LogManager.GetCurrentClassLogger();
public void Info(string msg)
{
logger.Info(msg);
}
}
您需要一種方法來告訴你NLOG包裝的類型,我認爲你只能做到這一點通過Logger.Log方法調用NLOG(超載)。
如果這不夠用,請發佈您的包裝以獲取更多幫助。
您也可以將其添加到您的NLogLogger類中,並在Write方法的第一行中調用它。
protected void GetCurrentClassLogger()
{
//This should take you back to the previous frame and context of the Log call
StackTrace trace = new StackTrace();
if (trace.FrameCount > 1)
{
logger = LogManager.GetLogger(trace.GetFrame(1).GetMethod().ReflectedType.FullName);
}
else //This would go back to the stated problem
{
logger = LogManager.GetCurrentClassLogger();
}
}
private void Write(LogLevel level, string format, params object[] args)
{
//added code
GetCurrentClassLogger();
LogEventInfo le = new LogEventInfo(level, logger.Name, null, format, args);
logger.Log(typeof(NLogLogger), le);
}
傢伙 經過數天的努力工作和search.Finally,我只是用一個簡單的類建立了NLOG包裝可以保留$ {}調用點,創造NLOG包裝的實例時得到正確的記錄器名稱。我將把代碼放在簡單的評論之後。正如你所看到的,我使用Stacktrace來獲取正確的記錄器名稱。使用write和writewithex來註冊logevnet,以便保留callsite。如果您有任何問題,請告訴我。
public class NlogWrapper
{
private readonly NLog.Logger _logger; //NLog logger
/// <summary>
/// This is the construtor, which get the correct logger name when instance created
/// </summary>
public NlogWrapper()
{
StackTrace trace = new StackTrace();
if (trace.FrameCount > 1)
{
_logger = LogManager.GetLogger(trace.GetFrame(1).GetMethod().ReflectedType.FullName);
}
else //This would go back to the stated problem
{
_logger = LogManager.GetCurrentClassLogger();
}
}
/// <summary>
/// These two method are used to retain the ${callsite} for all the Nlog method
/// </summary>
/// <param name="level">LogLevel.</param>
/// <param name="format">Passed message.</param>
/// <param name="ex">Exception.</param>
private void Write(LogLevel level, string format, params object[] args)
{
LogEventInfo le = new LogEventInfo(level, _logger.Name, null, format, args);
_logger.Log(typeof(NlogWrapper), le);
}
private void WriteWithEx(LogLevel level, string format,Exception ex, params object[] args)
{
LogEventInfo le = new LogEventInfo(level, _logger.Name, null, format, args);
le.Exception = ex;
_logger.Log(typeof(NlogWrapper), le);
}
#region Methods
/// <summary>
/// This method writes the Debug information to trace file
/// </summary>
/// <param name="message">The message.</param>
public void Debug(String message)
{
if (!_logger.IsDebugEnabled) return;
Write(LogLevel.Debug, message);
}
public void Debug(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Debug, message, exception);
}
/// <summary>
/// This method writes the Information to trace file
/// </summary>
/// <param name="message">The message.</param>
public void Info(String message)
{
if (!_logger.IsInfoEnabled) return;
Write(LogLevel.Info, message);
}
public void Info(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Info, message, exception);
}
/// <summary>
/// This method writes the Warning information to trace file
/// </summary>
/// <param name="message">The message.</param>
public void Warn(String message)
{
if (!_logger.IsWarnEnabled) return;
Write(LogLevel.Warn, message);
}
public void Warn(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Warn, message, exception);
}
/// <summary>
/// This method writes the Error Information to trace file
/// </summary>
/// <param name="error">The error.</param>
/// <param name="exception">The exception.</param>
// public static void Error(string message)
// {
// if (!_logger.IsErrorEnabled) return;
// _logger.Error(message);
//}
public void Error(String message)
{
if (!_logger.IsWarnEnabled) return;
//_logger.Warn(message);
Write(LogLevel.Error, message);
}
public void Error(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Error, message, exception);
}
/// <summary>
/// This method writes the Fatal exception information to trace target
/// </summary>
/// <param name="message">The message.</param>
public void Fatal(String message)
{
if (!_logger.IsFatalEnabled) return;
Write(LogLevel.Fatal, message);
}
public void Fatal(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Fatal, message, exception);
}
/// <summary>
/// This method writes the trace information to trace target
/// </summary>
/// <param name="message">The message.</param>
///
public void Trace(string message, Exception exception, params object[] args)
{
if (!_logger.IsFatalEnabled) return;
WriteWithEx(LogLevel.Trace, message, exception);
}
public void Trace(String message)
{
if (!_logger.IsTraceEnabled) return;
Write(LogLevel.Trace, message);
}
#endregion
}
當你在你的項目中使用它。只要做到:NlogWrapper mylog = new NlogWrapper(); mylog.Error(「這是關於:」的錯誤,例如)。然後,包裝類將負責記錄器名稱和調用站點信息。當您使用$ {logger} $ {callsite}。您將獲得正確的信息,而不是logwrapper類callsite的信息 – 2016-09-21 18:28:05
當傳遞擴展方法所在的類作爲傳遞給'Log'的類型時,這對擴展方法似乎也適用。 – 2014-05-21 14:51:01