2011-02-27 18 views
14

我使用NLog進行日誌記錄,我使用包裝來調用日誌方法,我的問題是:如果我嘗試打印關於調用站點(${callsite})的信息,它會打印包裝器方法而不是導致記錄器記錄的原始方法。Nlog當使用包裝器時,調用站點是錯誤的

是否有任何方法來獲得調用包裝方法的原始方法?

回答

19

見我回答這個問題:

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(超載)。

如果這不夠用,請發佈您的包裝以獲取更多幫助。

+2

當傳遞擴展方法所在的類作爲傳遞給'Log'的類型時,這對擴展方法似乎也適用。 – 2014-05-21 14:51:01

0

您也可以將其添加到您的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); 
    } 
0

傢伙 經過數天的努力工作和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 

    } 
+0

當你在你的項目中使用它。只要做到:NlogWrapper mylog = new NlogWrapper(); mylog.Error(「這是關於:」的錯誤,例如)。然後,包裝類將負責記錄器名稱和調用站點信息。當您使用$ {logger} $ {callsite}。您將獲得正確的信息,而不是logwrapper類callsite的信息 – 2016-09-21 18:28:05

相關問題