2012-07-06 18 views
5

Tôi hiện đang làm việc để di chuyển một dự án lớn hơn để sử dụng Common.Logging và tôi đã hy vọng có thể xuất các sự kiện ghi nhật ký cho nhiều hơn một triển khai ghi nhật ký bên thứ ba.Common.Logging với nhiều bộ điều hợp nhà máy

Hiện tại chúng tôi có thư viện theo dõi được phát triển nội bộ mà chúng tôi muốn tiếp tục sử dụng để truy tìm và gỡ lỗi thư. Tôi cũng muốn bắt đầu sử dụng log4net để gửi một số thư đến cơ sở dữ liệu để báo cáo hoặc gửi thông báo qua email ở một số cấp.

Những gì tôi đang tìm kiếm là một cái gì đó như thế này:

<common> 
<logging> 
    <factoryAdapter type="CustomTraceFactoryAdapter, MyAssembly"> 
    <arg key="configType" value="INLINE"/> 
    </factoryAdapter> 
    <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net"> 
    <arg key="configType" value="INLINE"/> 
    </factoryAdapter> 
</logging> 
</common> 

Có cách nào để làm điều này với ra các tùy chọn cấu hình hộp?

Trả lời

5

AFAIK, không có gì tồn tại trong Common.Logging cho những gì bạn cần. Dưới đây là một vài lựa chọn thay thế.

1) Phát triển một vài bộ chuyển đổi nhà máy logger tùy chỉnh như được mô tả tại http://netcommon.sourceforge.net/docs/2.1.0/reference/html/ch01.html#logging-advanced-customfactoryadapter. Một nhà máy tùy chỉnh, xuất hiện mà bạn đã phát triển, sẽ dành cho thư viện truy tìm nội bộ của bạn. Nhà máy tùy chỉnh thứ hai sẽ tạo ra các đối tượng logger tổng hợp bằng cách kết hợp các logger từ một hoặc nhiều nhà máy khác.

2) Phát triển ứng dụng log4net tùy chỉnh (http://logging.apache.org/log4net/release/faq.html#custom-appender) cho thư viện theo dõi của bạn và định cấu hình Common.Logging để chỉ sử dụng nhà máy log4net.

Tôi cảm thấy tùy chọn thứ hai sẽ dễ dàng nhất vì nó sẽ không liên quan đến việc thay đổi hành vi cấu hình của Common.Logging để nó có thể cấu thành nhà máy hỗn hợp từ các nhà máy được cấu hình khác.

+1

Cảm ơn, đó là những gì tôi mong đợi. Tôi đã thấy rằng một người khác đã đưa ra điều này trên [repo GitHub] (https://github.com/net-commons/common-logging/issues/8) để nó có thể được thêm vào dự án cuối cùng. – omockler

+0

@omockler Vấn đề GitHub đã được giải quyết trong khi trở lại. Giờ đây, có nhiều bộ điều hợp có thể hiển thị. –

4

Tôi biết câu hỏi là cũ, nhưng rõ ràng vẫn không có giải pháp ngoài hộp, vì vậy đây là nhật ký tùy chỉnh phù hợp với tôi (lấy cảm hứng từ https://github.com/ramonsmits/common-logging nhưng tôi đã thay đổi hầu hết mọi thứ ở cuối). Thử nghiệm với phiên bản Common.Logging 3.1.0.

Các FactoryAdapter

/// <summary> 
/// Adapter hub for Common.Logging that can send logs to multiple other adapters 
/// </summary> 
public class MultiLoggerFactoryAdapter : AbstractCachingLoggerFactoryAdapter 
{ 
    private readonly List<ILoggerFactoryAdapter> LoggerFactoryAdapters; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="MultiFactoryLoggerFactoryAdapter"/> class. 
    /// </summary> 
    public MultiLoggerFactoryAdapter(CommonLogging.Configuration.NameValueCollection properties) 
    { 
     LoggerFactoryAdapters = new List<ILoggerFactoryAdapter>(); 

     foreach(var factoryAdapter in properties.Where(e => e.Key.EndsWith(".factoryAdapter"))) 
     { 
      string adapterName = factoryAdapter.Key.Substring(0, factoryAdapter.Key.Length - 15); 
      string adapterType = factoryAdapter.Value; 

      var adapterConfig = new CommonLogging.Configuration.NameValueCollection(); 
      foreach(var entry in properties.Where(e1 => e1.Key.StartsWith(adapterName + "."))) 
      { 
       adapterConfig.Add(entry.Key.Substring(adapterName.Length + 1), entry.Value); 
      } 

      var adapter = (ILoggerFactoryAdapter)Activator.CreateInstance(Type.GetType(adapterType), adapterConfig); 
      LoggerFactoryAdapters.Add(adapter); 
     } 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="MultiFactoryLoggerFactoryAdapter"/> class. 
    /// </summary> 
    /// <param name="factoryAdapters">The factory adapters.</param> 
    public MultiLoggerFactoryAdapter(List<ILoggerFactoryAdapter> factoryAdapters) 
    { 
     LoggerFactoryAdapters = factoryAdapters; 
    } 

    protected override ILog CreateLogger(string name) 
    { 
     var loggers = new List<ILog>(LoggerFactoryAdapters.Count); 

     foreach (var f in LoggerFactoryAdapters) 
     { 
      loggers.Add(f.GetLogger(name)); 
     } 

     return new MultiLogger(loggers); 
    } 
} 

Các logger

/// <summary> 
/// Adapter hub for Common.Logging that can send logs to multiple other adapters 
/// </summary> 
public class MultiLogger : AbstractLogger 
{ 
    private readonly List<ILog> Loggers; 

    public static readonly IDictionary<LogLevel, Action<ILog, object, Exception>> LogActions = new Dictionary<LogLevel, Action<ILog, object, Exception>>() 
    { 
     { LogLevel.Debug, (logger, message, exception) => logger.Debug(message, exception) }, 
     { LogLevel.Error, (logger, message, exception) => logger.Error(message, exception) }, 
     { LogLevel.Fatal, (logger, message, exception) => logger.Fatal(message, exception) }, 
     { LogLevel.Info, (logger, message, exception) => logger.Info(message, exception) }, 
     { LogLevel.Trace, (logger, message, exception) => logger.Trace(message, exception) }, 
     { LogLevel.Warn, (logger, message, exception) => logger.Warn(message, exception) }, 
    }; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="MultiLogger"/> class. 
    /// </summary> 
    /// <param name="loggers">The loggers.</param> 
    public MultiLogger(List<ILog> loggers) 
    { 
     Loggers = loggers; 
    } 

    public override bool IsDebugEnabled { get { return Loggers.Any(l => l.IsDebugEnabled); } } 
    public override bool IsErrorEnabled { get { return Loggers.Any(l => l.IsErrorEnabled); } } 
    public override bool IsFatalEnabled { get { return Loggers.Any(l => l.IsFatalEnabled); } } 
    public override bool IsInfoEnabled { get { return Loggers.Any(l => l.IsInfoEnabled); } } 
    public override bool IsTraceEnabled { get { return Loggers.Any(l => l.IsTraceEnabled); } } 
    public override bool IsWarnEnabled { get { return Loggers.Any(l => l.IsWarnEnabled); } } 

    protected override void WriteInternal(LogLevel level, object message, Exception exception) 
    { 
     List<Exception> exceptions = null; 
     foreach(var logger in Loggers) 
     { 
      try 
      { 
       LogActions[level](logger, message, exception); 
      } 
      catch(Exception e) 
      { 
       if(exceptions == null) 
        exceptions = new List<Exception>(); 
       exceptions.Add(e); 
      } 
     } 

     if(exceptions != null) 
      throw new AggregateException("One or more exceptions occured while forwarding log message to multiple loggers", exceptions); 
    } 
} 

Và bạn có thể cấu hình nó như thế này:

<common> 
    <logging> 
    <factoryAdapter type="MultiLoggerFactoryAdapter, YourAssemblyName"> 
     <arg key="Log4Net.factoryAdapter" value="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1213" /> 
     <arg key="Log4Net.configType" value="INLINE" /> 

     <arg key="Debug.factoryAdapter" value="Common.Logging.Simple.TraceLoggerFactoryAdapter, Common.Logging" /> 
    </factoryAdapter> 
    </logging> 
</common> 

Đó là, đối với mỗi logger, bạn thêm một dòng với phím LoggerName.factoryAdapter, và sau đó bạn có thể thêm thuộc tính cho trình ghi nhật ký này bằng cách sử dụng cùng tên cho t chìa khóa, chẳng hạn như LoggerName.someProperty.

2

Có một cách tích hợp sẵn để hỗ trợ nhiều bộ điều hợp ngay bây giờ, hãy xem Common.Logging.MultipleLogger. Có một ví dụ App.config cho biết cách sử dụng nó here.

Các vấn đề liên quan