使用包装器时,Nlog Callsite错误

我正在使用NLog进行日志记录,我使用包装器来调用日志方法,我的问题是:如果我尝试打印有关调用站点( ${callsite} )的信息,它会打印包装器方法而不是原始方法导致记录器记录。

有没有办法获得调用包装器方法的原始方法?

看看我对这个问题的回答:

与特定NLog记录器名称匹配的问题

我已经从这个答案中复制了示例代码(用于缩写的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的源代码库)以获取另外两个“扩展”Logger的示例。 一个通过包装,一个通过inheritance:

https://github.com/jkowalski/NLog/tree/master/examples/ExtendingLoggers

我不是100%肯定,但我认为你不能简单地包装NLog并将Info,Debug,Warn等方法委托给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); } 

伙计经过几天的艰苦努力和搜索。最后,我只使用一个简单的类构建了Nlog Wrapper,它可以保留$ {callsite}并在创建Nlog Wrapper实例时获取正确的记录器名称。 我将把代码放在简单的注释之后。 如您所见,我使用Stacktrace来获得正确的记录器名称。 使用write和writewithex注册logevnet,以便保留callsite。 如果您有任何疑问,请告诉我。

  public class NlogWrapper { private readonly NLog.Logger _logger; //NLog logger ///  /// This is the construtor, which get the correct logger name when instance created ///  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(); } } ///  /// These two method are used to retain the ${callsite} for all the Nlog method ///  /// LogLevel. /// Passed message. /// Exception. 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 ///  /// This method writes the Debug information to trace file ///  /// The message. 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); } ///  /// This method writes the Information to trace file ///  /// The message. 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); } ///  /// This method writes the Warning information to trace file ///  /// The message. 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); } ///  /// This method writes the Error Information to trace file ///  /// The error. /// The exception. // 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); } ///  /// This method writes the Fatal exception information to trace target ///  /// The message. 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); } ///  /// This method writes the trace information to trace target ///  /// The message. /// 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 }