zoukankan      html  css  js  c++  java
  • [Asp.net 5] Logging-日志系统的基本架构(上)

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

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

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

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

    接口的定义源码如下:

        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
        public interface ILoggerFactory
        {
            LogLevel MinimumLevel { get; set; }
    
            ILogger CreateLogger(string categoryName);
    
            void AddProvider(ILoggerProvider provider);
        }
    ILoggerFactory
        public interface ILoggerProvider
        {
            ILogger CreateLogger(string name);
        }
    ILoggerProvider
        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实例的封装。

        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对象,进行写日志操作。

        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如下图所示:

        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
  • 相关阅读:
    【Android UI设计与开发】第03期:引导界面(三)仿微信引导界面以及动画效果
    【Android UI设计与开发】第02期:引导界面(二)使用ViewPager实现欢迎引导页面
    【Android UI设计与开发】第01期:引导界面(一)ViewPager介绍和使用详解
    【Android UI设计与开发】第15期:顶部标题栏(六)实现悬浮式顶部和底部标题栏效果
    Android 百度地图开发(一)--- 申请API Key和在项目中显示百度地图
    Android 百度地图开发(二)--- 定位功能之MyLocationOverlay,PopupOverlay的使用
    jsp生命周期,和知识点添加
    jsp 脚本,声明,用户端不可见注释
    初学jsp,1、配置myeclipse
    呃呃,才意识到
  • 原文地址:https://www.cnblogs.com/watermoon2/p/4549601.html
Copyright © 2011-2022 走看看