2008-10-01 30 views
24

我在一個靜態的包裝包裹log4net的,並希望記錄如何在包裝Log4net時記錄MethodName?

loggingEvent.LocationInformation.MethodName 
loggingEvent.LocationInformation.ClassName 

但是我得到的是我的包裝的名稱。

我如何使用forwardingappender和靜態包裝類像

Logger.Debug("Logging to Debug"); 
Logger.Info("Logging to Info"); 
Logger.Warn("Logging to Warn"); 
Logger.Error(ex); 
Logger.Fatal(ex); 
+0

如果我記得很清楚,log4net的填充`LocationInformation`從(Type)調用的`Type`,所以從你的包裝器提供信息是合理的(我假設你的包裝器是這樣做的:`ILog log = LogManager.GetLogger(typeof MyLogWrapper)`)。 – Panos 2008-10-01 13:37:42

+1

其實我像LoggerManager.GetLogger(Asse mbly.GetCallingAssembly(),「MyDefaultLoggger」),以避免它 – 2008-10-01 14:02:46

+0

[當使用包裝,如何保留類和方法名稱Log4Net登錄?](http://stackoverflow.com/questions/2049992/when-using-wrapper-how-to-preserve-class-and-method-name-for-log4net-to-log) – 2017-02-04 10:18:50

回答

21

那麼錯誤是在某個地方我附加目的地,但出於完整性病包括答案我所知:你需要換行ILogger和NOT ILog的

public static class Logger 
{ 
    private readonly static Type ThisDeclaringType = typeof(Logger); 
    private static readonly ILogger defaultLogger; 

    static Logger() 
    { 
     defaultLogger = 
     LoggerManager.GetLogger(Assembly.GetCallingAssembly(),"MyDefaultLoggger"); 

的門面...

public static void Info(string message) 
    { 
     if (defaultLogger.IsEnabledFor(infoLevel)) 
     { 
      defaultLogger.Log(typeof(Logger), infoLevel, message, null); 
     } 
    } 
0

我能想到這樣做的唯一的事情(因爲我不目前使用log4net的)是請求堆棧跟蹤日誌信息(新的堆棧跟蹤),然後返回一個框架以獲取所需的信息。但是,我不確定此運行時性能的影響。

+0

log4net allready在LocationInformation類中有這個,但它在包裝Ilog時不起作用 – 2008-10-01 12:04:31

+1

log4net在後面當模式佈局包含%m和%c變量時,場景執行相同的操作。他們警告不要因爲明顯的性能原因使用它們。 – bryanbcook 2010-08-22 20:15:25

7

就宣佈你這樣的日誌變量...

private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

然後你可以正常使用它。

4

這篇文章幫助我瞭解如何編寫自己的封裝程序,以便作爲回報,我認爲您可能會喜歡我的完整類來包裝記錄器,這似乎很好地工作,實際上只需要使用一半的時間直!

所有的需要的是相應的XML來設置日誌記錄在配置文件中,並

[assembly: log4net.Config.XmlConfigurator(Watch = true)] 
在你的AssemblyInfo.cs

,它應該輕鬆地工作。

其中一個注意事項:我使用Log4NetDash進行非常簡單的設置,因此欺騙並將一些信息放在錯誤的字段中(例如,域字段中的堆棧跟蹤),這對我仍然有效,因爲我不在乎那裏顯示的信息,但如果你空閒時間你正在設置的東西,你可能想要解決這個問題!

using System; 
using System.ComponentModel; 
using System.Diagnostics; 
using System.Reflection; 
using System.Threading; 
using log4net; 
using log4net.Core; 

namespace Utility 
{ 
    public class Logger 
    { 
     static Logger() 
     { 
      LogManager.GetLogger(typeof(Logger)); 
     } 

     public static void Debug(string message, params object[] parameters) 
     { 
      Log(message, Level.Debug, null, parameters); 
     } 

     public static void Info(string message, params object[] parameters) 
     { 
      Log(message, Level.Info, null, parameters); 
     } 

     public static void Warn(string message, params object[] parameters) 
     { 
      Log(message, Level.Warn, null, parameters); 
     } 

     public static void Error(string message, params object[] parameters) 
     { 
      Error(message, null, parameters); 
     } 

     public static void Error(Exception exception) 
     { 
      if (exception==null) 
       return; 
      Error(exception.Message, exception); 
     } 

     public static void Error(string message, Exception exception, params object[] parameters) 
     { 
      string exceptionStack = ""; 

      if (exception != null) 
      { 
       exceptionStack = exception.GetType().Name + " : " + exception.Message + Environment.NewLine; 
       Exception loopException = exception; 
       while (loopException.InnerException != null) 
       { 
        loopException = loopException.InnerException; 
        exceptionStack += loopException.GetType().Name + " : " + loopException.Message + Environment.NewLine; 
       } 
      } 

      Log(message, Level.Error, exceptionStack, parameters); 
     } 



     private static void Log(string message, Level logLevel, string exceptionMessage, params object[] parameters) 
     { 
      BackgroundWorker worker = new BackgroundWorker(); 
      worker.DoWork += LogEvent; 
      worker.RunWorkerAsync(new LogMessageSpec 
             { 
              ExceptionMessage = exceptionMessage, 
              LogLevel = logLevel, 
              Message = message, 
              Parameters = parameters, 
              Stack = new StackTrace(), 
              LogTime = DateTime.Now 
             }); 
     } 

     private static void LogEvent(object sender, DoWorkEventArgs e) 
     { 
      try 
      { 
       LogMessageSpec messageSpec = (LogMessageSpec) e.Argument; 

       StackFrame frame = messageSpec.Stack.GetFrame(2); 
       MethodBase method = frame.GetMethod(); 
       Type reflectedType = method.ReflectedType; 

       ILogger log = LoggerManager.GetLogger(reflectedType.Assembly, reflectedType); 
       Level currenLoggingLevel = ((log4net.Repository.Hierarchy.Logger) log).Parent.Level; 

       if (messageSpec.LogLevel<currenLoggingLevel) 
        return; 

       messageSpec.Message = string.Format(messageSpec.Message, messageSpec.Parameters); 
       string stackTrace = ""; 
       StackFrame[] frames = messageSpec.Stack.GetFrames(); 
       if (frames != null) 
       { 
        foreach (StackFrame tempFrame in frames) 
        { 

         MethodBase tempMethod = tempFrame.GetMethod(); 
         stackTrace += tempMethod.Name + Environment.NewLine; 
        } 
       } 
       string userName = Thread.CurrentPrincipal.Identity.Name; 
       LoggingEventData evdat = new LoggingEventData 
              { 
               Domain = stackTrace, 
               Identity = userName, 
               Level = messageSpec.LogLevel, 
               LocationInfo = new LocationInfo(reflectedType.FullName, 
                       method.Name, 
                       frame.GetFileName(), 
                       frame.GetFileLineNumber().ToString()), 
               LoggerName = reflectedType.Name, 
               Message = messageSpec.Message, 
               TimeStamp = messageSpec.LogTime, 
               UserName = userName, 
               ExceptionString = messageSpec.ExceptionMessage 
              }; 
       log.Log(new LoggingEvent(evdat)); 
      } 
      catch (Exception) 
      {}//don't throw exceptions on background thread especially about logging! 
     } 

     private class LogMessageSpec 
     { 
      public StackTrace Stack { get; set; } 
      public string Message { get; set; } 
      public Level LogLevel { get; set; } 
      public string ExceptionMessage { get; set; } 
      public object[] Parameters { get; set; } 
      public DateTime LogTime { get; set; } 
     } 
    } 
} 
3

我只想使用類似%stacktrace{2}作爲轉換模式。輸出的

實施例:

MyNamespace.ClassName。法> Common.Log.Warning

其中MyNamespace.ClassName.Method是叫我的包裝和Common.Log.Warning是包裝類的方法的方法。

轉換模式可以找到here

0

我只是寫克勞斯

的正確答案更多的代碼在包裝類

public static class Logger 
{ 
    private static readonly ILogger DefaultLogger; 

    static Logger() 
    { 
     defaultLogger = LoggerManager.GetLogger(Assembly.GetCallingAssembly(), "MyDefaultLoggger"); // MyDefaultLoggger is the name of Logger 
    } 

    public static void LogError(object message) 
    { 
     Level errorLevel = Level.Error; 
     if (DefaultLogger.IsEnabledFor(errorLevel)) 
     { 
      DefaultLogger.Log(typeof(Logger), errorLevel, message, null); 
     } 
    } 

    public static void LogError(object message, Exception exception) 
    { 
     Level errorLevel = Level.Error; 
     if (DefaultLogger.IsEnabledFor(errorLevel)) 
     { 
      DefaultLogger.Log(typeof(Logger), errorLevel, message, exception); 
     } 
    } 

等的方法的其餘部分。

在web.config中或app.config中log4net.Layout.PatternLayout 你可以使用一些轉換模式,如:

%location %method %line 

<layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern value="%date{dd/MM/yyyy hh:mm:ss.fff tt} [%thread] %level %logger [%location %method %line] [%C %M] - %newline%message%newline%exception"/> 
    </layout>