转载

[Asp.net 5] Logging-日志系统的基本架构(上)

本节主要介绍解决方案中的Microsoft.Framework.Logging.Abstractions、Microsoft.Framework.Logging俩个工程。

这俩个工程中所有类的关系如下图所示:

[Asp.net 5] Logging-日志系统的基本架构(上)

首先我们可以发现处于核心的是中间的四个接口:ILogger、ILoggerFactory、ILoggerProvider、ILogValues。

  • ILogger:记录日志的接口,所以写日志的类都该实现该接口,工程中有俩个类实现了该接口:Logger、Logger<T>
  • ILoggerFactory:创建ILogger的工厂。负责创建工厂的逻辑,但是一般不直接创建,而是调用内部ILoggerProvider去完成。
  • ILoggerProvider:能够直接创建ILogger实例,做为属性添加到ILoggerFactory中,ILogger的具体逻辑受控制ILoggerFactory。
  • ILogValues:在Logger的扩展方法中作为特殊类型的object传入,作为日志的数据源。

接口的定义源码如下:

[Asp.net 5] Logging-日志系统的基本架构(上)
public interface ILogger     {         void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter);          bool IsEnabled(LogLevel logLevel);                  IDisposable BeginScopeImpl(object state);     }
ILogger
[Asp.net 5] Logging-日志系统的基本架构(上)
public interface ILoggerFactory     {         LogLevel MinimumLevel { get; set; }          ILogger CreateLogger(string categoryName);          void AddProvider(ILoggerProvider provider);     }
ILoggerFactory
[Asp.net 5] Logging-日志系统的基本架构(上)
public interface ILoggerProvider     {         ILogger CreateLogger(string name);     }
ILoggerProvider
[Asp.net 5] Logging-日志系统的基本架构(上)
public interface ILogValues     {         IEnumerable<KeyValuePair<string, object>> GetValues();     }
ILogValues

ILogger以及实现类

ILogger接口、ILogger<TCategoryName>(没有任何定义)、Logger<T>这种泛型继承是否有相识之感,之前的博客文章中已经对于这种情况有所介绍( [Asp.net 5] Localization-resx资源文件的管理 中 IStringLocalizer 、 IStringLocalizer<T>StringLocalizer<TResourceSource>是一致的 )。实际Logger<T>中T是ILogger的实例子类,实际就是使用代理模式,内部包含ILogger实例,并且所有对外的方法都仅仅是内部ILogger实例的封装。

[Asp.net 5] Logging-日志系统的基本架构(上)
public class Logger<T> : ILogger<T> {  private readonly ILogger _logger;  /// <summary>  /// Creates a new <see cref="Logger{T}"/>.  /// </summary>  /// <param name="factory">The factory.</param>  public Logger(ILoggerFactory factory)  {   _logger = factory.CreateLogger<T>();  }  IDisposable ILogger.BeginScopeImpl(object state)  {   return _logger.BeginScopeImpl(state);  }  bool ILogger.IsEnabled(LogLevel logLevel)  {   return _logger.IsEnabled(logLevel);  }  void ILogger.Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)  {   _logger.Log(logLevel, eventId, state, exception, formatter);  } } 
Logger

Logger类同样实现了ILogger接口,也同样使用了代理模式,不过不同于Logger<T>泛型,Logger类有自己的内部逻辑。而是在内部封装了 ILogger[] _loggers对象。使得Logger更像LoggerManage。但是由于Logger同样实现Logger接口,所以Logger类是管理其它Logger类的代理。而Logger内部的_loggers是通过LoggerFactory对象封装的。当记录日志时,依次遍历内部的 _loggers对象,进行写日志操作。

[Asp.net 5] Logging-日志系统的基本架构(上)
internal class Logger : ILogger  {   private readonly LoggerFactory _loggerFactory;   private readonly string _name;   private ILogger[] _loggers = new ILogger[0];   public Logger(LoggerFactory loggerFactory, string name)   {    _loggerFactory = loggerFactory;    _name = name;    var providers = loggerFactory.GetProviders();    _loggers = new ILogger[providers.Length];    for (var index = 0; index != providers.Length; index++)    {     _loggers[index] = providers[index].CreateLogger(name);    }   }   public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)   {    if (logLevel >= _loggerFactory.MinimumLevel)    {     foreach (var logger in _loggers)     {      logger.Log(logLevel, eventId, state, exception, formatter);     }    }   }   public bool IsEnabled(LogLevel logLevel)   {    if (logLevel < _loggerFactory.MinimumLevel)    {     return false;    }    foreach (var logger in _loggers)    {     if (logger.IsEnabled(logLevel))     {      return true;     }    }    return false;   }   public IDisposable BeginScopeImpl(object state)   {    var loggers = _loggers;    var scope = new Scope(loggers.Length);    for (var index = 0; index != loggers.Length; index++)    {     scope.SetDisposable(index, loggers[index].BeginScopeImpl(state));    }    return scope;   }   internal void AddProvider(ILoggerProvider provider)   {    var logger = provider.CreateLogger(_name);    _loggers = _loggers.Concat(new[] { logger }).ToArray();   }   private class Scope : IDisposable   {    private bool _isDisposed;    private IDisposable _disposable0;    private IDisposable _disposable1;    private readonly IDisposable[] _disposable;    public Scope(int count)    {     if (count > 2)     {      _disposable = new IDisposable[count - 2];     }    }    public void SetDisposable(int index, IDisposable disposable)    {     if (index == 0)     {      _disposable0 = disposable;     }     else if (index == 1)     {      _disposable1 = disposable;     }     else     {      _disposable[index - 2] = disposable;     }    }    protected virtual void Dispose(bool disposing)    {     if (!_isDisposed)     {      if (disposing)      {       if (_disposable0 != null)       {        _disposable0.Dispose();       }       if (_disposable1 != null)       {        _disposable1.Dispose();       }       if (_disposable != null)       {        var count = _disposable.Length;        for (var index = 0; index != count; ++index)        {         if (_disposable[index] != null)         {          _disposable[index].Dispose();         }        }       }      }      _isDisposed = true;     }    }    // This code added to correctly implement the disposable pattern.    public void Dispose()    {     // Do not change this code. Put cleanup code in Dispose(bool disposing) above.     Dispose(true);     // TODO: tell GC not to call its finalizer when the above finalizer is overridden.     // GC.SuppressFinalize(this);    }    internal void Add(IDisposable disposable)    {     throw new NotImplementedException();    }   }  } 
Logger

ILoggerFactory以及实现类

ILoggerFactory主要有俩个作用,添加新的ILoggerProvider,创建ILogger。而ILoggerFactory的唯一实现类LoggerFactory,简单实现了上面两个功能,并且在LoggerFactory内部额外维护_loggers副本,该处loggers都是Logger类型(非泛型),只是categoryName不同。所以通过LoggerFactory创建的Logger如下图所示:

[Asp.net 5] Logging-日志系统的基本架构(上)

[Asp.net 5] Logging-日志系统的基本架构(上)
public class LoggerFactory : ILoggerFactory {  private readonly Dictionary<string, Logger> _loggers = new Dictionary<string, Logger>(StringComparer.Ordinal);  private ILoggerProvider[] _providers = new ILoggerProvider[0];  private readonly object _sync = new object();  public ILogger CreateLogger(string categoryName)  {   Logger logger;   lock (_sync)   {    if (!_loggers.TryGetValue(categoryName, out logger))    {     logger = new Logger(this, categoryName);     _loggers[categoryName] = logger;    }   }   return logger;  }  public LogLevel MinimumLevel { get; set; } = LogLevel.Verbose;  public void AddProvider(ILoggerProvider provider)  {   lock (_sync)   {    _providers = _providers.Concat(new[] { provider }).ToArray();    foreach (var logger in _loggers)    {     logger.Value.AddProvider(provider);    }   }  }  internal ILoggerProvider[] GetProviders()  {   return _providers;  } } 
LoggerFactory
正文到此结束
Loading...