2012-12-12 121 views
5

我正在使用Windsor日誌記錄工具和NLog集成工具將日誌記錄添加到項目中。Windsor日誌記錄工具:控制日誌名稱

我沒有按照Windsor文檔中建議的將Log屬性添加到每個我想支持日誌記錄的類的做法,而是決定嘗試使用動態攔截來實現它。到目前爲止,攔截器是相當基礎的。它只是使用構造器注入來獲得​​一個實例:

class LoggingInterceptor : IInterceptor 
{ 
    private readonly ILogger _logger; 
    public LoggingInterceptor(ILogger logger) 
    { 
     if (logger == null) throw new ArgumentNullException("logger"); 
     _logger = logger; 
    } 

    public void Intercept(IInvocation invocation) 
    { 
     // just a placeholder implementation, I'm not actually planning to do this ;) 
     _logger.Info(invocation.Method.Name); 
     invocation.Proceed(); 
    } 
} 

除此之外,所有我所做的就是最小登記攔截,並把它應用到一個組件,日誌工具負責其餘的護理。

container.Register(Component.For<LoggingInterceptor>().LifeStyle.Transient); 

container.Register(
    Component.For<IEmployeeRepository>() 
    .ImplementedBy<EmployeeRepository>() 
    .Interceptors(InterceptorReference.ForType<LoggingInterceptor>()).First); 

到目前爲止這麼好 - 有點。我得到的記錄器遵循NLog推薦的每個記錄器的練習。在這種情況下,我不認爲這是一個很好的選擇。這意味着每條消息都會轉到名爲「MyApplication.Interceptors.LoggingInterceptor」的日誌中,這不是非常有用。

我傾向於在記錄器應用到抽象後命名的日誌。例如,如果記錄器已應用於IEmployeeRepository的實現,則日誌應命名爲EmployeeRepository。這是可行的嗎?

編輯: 我試過實施自定義ILoggerFactory並指示容器使用它。然而,我很快遇到了一個障礙:當溫莎召喚進入工廠時,唯一提供的信息是正在採集記錄器的物體的類型。沒有提供有關該對象的其他信息,因此ILoggerFactory無法找到攔截器已應用到的抽象。

我注意到有兩個接受字符串作爲參數的過載ILoggerFactory.Create()。溫莎似乎沒有直接使用他們中的任何一個,但有人會認爲他們必須在那裏出於某種原因。流利註冊API中是否有可用於指定使用特定字符串的任何內容?

回答

6

這是一個與你非常相似的問題,它有一個可接受的答案。在鏈接中,發佈答案的人建議使攔截器依賴於ILoggerFactory,並在Intercept方法中使用IInvocation.TargetType作爲發送給ILoggerFactory的類型以獲取適當的記錄器。

請注意,我不使用Castle,所以我無法對此建議發表更多評論。

public class LoggingInterceptor : IInterceptor 
{ 
    private readonly ILoggerFactory _loggerFactory; 

    public LoggingInterceptor(ILoggerFactory loggerFactory) 
    { 
     _loggerFactory = loggerFactory; 
    } 

    public void Intercept(IInvocation invocation) 
    { 
     var logger = _loggerFactory.Create(invocation.TargetType); 
     if (logger.IsDebugEnabled) 
     { 
      logger.Debug(CreateInvocationLogString(invocation)); 
     } 
     try 
     { 
      invocation.Proceed(); 
     } 
     catch (Exception e) 
     { 
      logger.Warn(CreateInvocationLogString(invocation)); 
      throw; 
     } 
     logger.Info(CreateInvocationLogString(invocation)); 
    } 

    private static String CreateInvocationLogString(IInvocation invocation) 
    { 
     var sb = new StringBuilder(100); 
     sb.AppendFormat("Called: {0}.{1}(", invocation.TargetType.Name, invocation.Method.Name); 
     foreach (var argument in invocation.Arguments) 
     { 
      var argumentDescription = argument == null ? "null" : argument.ToString(); 
      sb.Append(argumentDescription).Append(","); 
     } 
     if (invocation.Arguments.Any()) 
     { 
      sb.Length--; 
     } 
     sb.Append(")"); 
     return sb.ToString(); 
    } 
} 

Castle: How can i get the correct ILogger in the logging interceptor?

你可能已經看到了這一點,但這裏是一個城堡的例子,說明如何創建一個日誌記錄攔截器和如何,顯然,打造包裝類型的記錄程序的鏈接:

http://docs.castleproject.org/Windsor.Introduction-to-AOP-With-Castle.ashx

編輯:ILoggerFactory爲n日誌的實現是ExtendedNLogFactory,它在Castle.Core-NLOG NuGet包(http://www.nuget.org/packages/Castle.Core-NLog

+1

你的Google-fu顯然比我的好。這應該是完美的 - 唯一的額外細節是獲取一個爲抽象類型而不是具體類型命名的日誌。我想我會通過搜索具體類型的接口來查找遵循約定的接口。 –

+0

很高興我能夠幫助! – wageoghe