美文网首页ABP
ABP 源码解析 七. 日志

ABP 源码解析 七. 日志

作者: 诸葛_小亮 | 来源:发表于2018-08-27 20:41 被阅读12次

    介绍

    此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。
    通过解读ABP源码,可以提升ABP使用方式,可以提升编码意识,提高面向对象编程思想。

    本篇文章主要介绍ABP框架的日志实现机制。

    ABP使用 Castle Windsor 提供的日志工厂类,它可以与不同的日志库一起工作: Log4Net、NLog、Serilog等等。castle为所有记录器库提供了一个通用接口。这样,你就独立于一个特定的日志库,如果需要的话,以后可以很容易地改变它。


    UML

    UML
    • LogHelper:可以用来在某些无法直接依赖ILogger的地方写日志
    • Log4NetLoggerFactory:使用log4net实现castle提供的AbstractLoggerFactory类,提供具体的日志类
    • Log4NetLogger:使用log4net实现castle提供的ILogger接口

    源码解析

    Log4NetLogger

    使用log4net实现castle提供的ILogger接口

    [Serializable]
        public class Log4NetLogger :
            MarshalByRefObject,
            ILogger
        {
            private static readonly Type DeclaringType = typeof(Log4NetLogger);
    
            public Log4NetLogger(log4net.Core.ILogger logger, Log4NetLoggerFactory factory)
            {
                Logger = logger;
                Factory = factory;
            }
    
            internal Log4NetLogger()
            {
            }
    
            internal Log4NetLogger(ILog log, Log4NetLoggerFactory factory)
                : this(log.Logger, factory)
            {
            }
    
            public bool IsDebugEnabled
            {
                get { return Logger.IsEnabledFor(Level.Debug); }
            }
    
            public bool IsErrorEnabled
            {
                get { return Logger.IsEnabledFor(Level.Error); }
            }
    
            public bool IsFatalEnabled
            {
                get { return Logger.IsEnabledFor(Level.Fatal); }
            }
    
            public bool IsInfoEnabled
            {
                get { return Logger.IsEnabledFor(Level.Info); }
            }
    
            public bool IsWarnEnabled
            {
                get { return Logger.IsEnabledFor(Level.Warn); }
            }
    
            protected internal Log4NetLoggerFactory Factory { get; set; }
    
            protected internal log4net.Core.ILogger Logger { get; set; }
    
            public override string ToString()
            {
                return Logger.ToString();
            }
    
            public virtual global::Castle.Core.Logging.ILogger CreateChildLogger(string name)
            {
                return Factory.Create(Logger.Name + "." + name);
            }
    
            public void Debug(string message)
            {
                if (IsDebugEnabled)
                {
                    Logger.Log(DeclaringType, Level.Debug, message, null);
                }
            }
    
            public void Debug(Func<string> messageFactory)
            {
                if (IsDebugEnabled)
                {
                    Logger.Log(DeclaringType, Level.Debug, messageFactory.Invoke(), null);
                }
            }
    
            public void Debug(string message, Exception exception)
            {
                if (IsDebugEnabled)
                {
                    Logger.Log(DeclaringType, Level.Debug, message, exception);
                }
            }
    
            public void DebugFormat(string format, params Object[] args)
            {
                if (IsDebugEnabled)
                {
                    Logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
                }
            }
    
            public void DebugFormat(Exception exception, string format, params Object[] args)
            {
                if (IsDebugEnabled)
                {
                    Logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
                }
            }
    
            public void DebugFormat(IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsDebugEnabled)
                {
                    Logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(formatProvider, format, args), null);
                }
            }
    
            public void DebugFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsDebugEnabled)
                {
                    Logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(formatProvider, format, args), exception);
                }
            }
    
            public void Error(string message)
            {
                if (IsErrorEnabled)
                {
                    Logger.Log(DeclaringType, Level.Error, message, null);
                }
            }
    
            public void Error(Func<string> messageFactory)
            {
                if (IsErrorEnabled)
                {
                    Logger.Log(DeclaringType, Level.Error, messageFactory.Invoke(), null);
                }
            }
    
            public void Error(string message, Exception exception)
            {
                if (IsErrorEnabled)
                {
                    Logger.Log(DeclaringType, Level.Error, message, exception);
                }
            }
    
            public void ErrorFormat(string format, params Object[] args)
            {
                if (IsErrorEnabled)
                {
                    Logger.Log(DeclaringType, Level.Error, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
                }
            }
    
            public void ErrorFormat(Exception exception, string format, params Object[] args)
            {
                if (IsErrorEnabled)
                {
                    Logger.Log(DeclaringType, Level.Error, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
                }
            }
    
            public void ErrorFormat(IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsErrorEnabled)
                {
                    Logger.Log(DeclaringType, Level.Error, new SystemStringFormat(formatProvider, format, args), null);
                }
            }
    
            public void ErrorFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsErrorEnabled)
                {
                    Logger.Log(DeclaringType, Level.Error, new SystemStringFormat(formatProvider, format, args), exception);
                }
            }
    
            public void Fatal(string message)
            {
                if (IsFatalEnabled)
                {
                    Logger.Log(DeclaringType, Level.Fatal, message, null);
                }
            }
    
            public void Fatal(Func<string> messageFactory)
            {
                if (IsFatalEnabled)
                {
                    Logger.Log(DeclaringType, Level.Fatal, messageFactory.Invoke(), null);
                }
            }
    
            public void Fatal(string message, Exception exception)
            {
                if (IsFatalEnabled)
                {
                    Logger.Log(DeclaringType, Level.Fatal, message, exception);
                }
            }
    
            public void FatalFormat(string format, params Object[] args)
            {
                if (IsFatalEnabled)
                {
                    Logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
                }
            }
    
            public void FatalFormat(Exception exception, string format, params Object[] args)
            {
                if (IsFatalEnabled)
                {
                    Logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
                }
            }
    
            public void FatalFormat(IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsFatalEnabled)
                {
                    Logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(formatProvider, format, args), null);
                }
            }
    
            public void FatalFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsFatalEnabled)
                {
                    Logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(formatProvider, format, args), exception);
                }
            }
    
            public void Info(string message)
            {
                if (IsInfoEnabled)
                {
                    Logger.Log(DeclaringType, Level.Info, message, null);
                }
            }
    
            public void Info(Func<string> messageFactory)
            {
                if (IsInfoEnabled)
                {
                    Logger.Log(DeclaringType, Level.Info, messageFactory.Invoke(), null);
                }
            }
    
            public void Info(string message, Exception exception)
            {
                if (IsInfoEnabled)
                {
                    Logger.Log(DeclaringType, Level.Info, message, exception);
                }
            }
    
            public void InfoFormat(string format, params Object[] args)
            {
                if (IsInfoEnabled)
                {
                    Logger.Log(DeclaringType, Level.Info, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
                }
            }
    
            public void InfoFormat(Exception exception, string format, params Object[] args)
            {
                if (IsInfoEnabled)
                {
                    Logger.Log(DeclaringType, Level.Info, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
                }
            }
    
            public void InfoFormat(IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsInfoEnabled)
                {
                    Logger.Log(DeclaringType, Level.Info, new SystemStringFormat(formatProvider, format, args), null);
                }
            }
    
            public void InfoFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsInfoEnabled)
                {
                    Logger.Log(DeclaringType, Level.Info, new SystemStringFormat(formatProvider, format, args), exception);
                }
            }
    
            public void Warn(string message)
            {
                if (IsWarnEnabled)
                {
                    Logger.Log(DeclaringType, Level.Warn, message, null);
                }
            }
    
            public void Warn(Func<string> messageFactory)
            {
                if (IsWarnEnabled)
                {
                    Logger.Log(DeclaringType, Level.Warn, messageFactory.Invoke(), null);
                }
            }
    
            public void Warn(string message, Exception exception)
            {
                if (IsWarnEnabled)
                {
                    Logger.Log(DeclaringType, Level.Warn, message, exception);
                }
            }
    
            public void WarnFormat(string format, params Object[] args)
            {
                if (IsWarnEnabled)
                {
                    Logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
                }
            }
    
            public void WarnFormat(Exception exception, string format, params Object[] args)
            {
                if (IsWarnEnabled)
                {
                    Logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
                }
            }
    
            public void WarnFormat(IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsWarnEnabled)
                {
                    Logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(formatProvider, format, args), null);
                }
            }
    
            public void WarnFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
            {
                if (IsWarnEnabled)
                {
                    Logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(formatProvider, format, args), exception);
                }
            }
        }
    

    Log4NetLoggerFactory

    实现castle提供的抽象日志工厂,生成log4net日志组件

    public class Log4NetLoggerFactory : AbstractLoggerFactory
        {
            internal const string DefaultConfigFileName = "log4net.config";
            private readonly ILoggerRepository _loggerRepository;
    
            public Log4NetLoggerFactory()
                : this(DefaultConfigFileName)
            {
            }
    
            public Log4NetLoggerFactory(string configFileName)
            {
                _loggerRepository = LogManager.CreateRepository(
                    typeof(Log4NetLoggerFactory).GetAssembly(),
                    typeof(log4net.Repository.Hierarchy.Hierarchy)
                );
    
                var log4NetConfig = new XmlDocument();
                log4NetConfig.Load(File.OpenRead(configFileName));
                XmlConfigurator.Configure(_loggerRepository, log4NetConfig["log4net"]);
            }
    
            public Log4NetLoggerFactory(string configFileName, bool reloadOnChange)
            {
                _loggerRepository = LogManager.CreateRepository(
                    typeof(Log4NetLoggerFactory).GetAssembly(),
                    typeof(log4net.Repository.Hierarchy.Hierarchy)
                );
    
                if (reloadOnChange)
                {
                    XmlConfigurator.ConfigureAndWatch(_loggerRepository, new FileInfo(configFileName));
                }
                else
                {
                    var log4NetConfig = new XmlDocument();
                    log4NetConfig.Load(File.OpenRead(configFileName));
                    XmlConfigurator.Configure(_loggerRepository, log4NetConfig["log4net"]);
                }
            }
    
            public override ILogger Create(string name)
            {
                if (name == null)
                {
                    throw new ArgumentNullException(nameof(name));
                }
    
                return new Log4NetLogger(LogManager.GetLogger(_loggerRepository.Name, name), this);
            }
    
            public override ILogger Create(string name, LoggerLevel level)
            {
                throw new NotSupportedException("Logger levels cannot be set at runtime. Please review your configuration file.");
            }
        }
    

    LogHelper

    在一些无法通过依赖注入的地方使用日志

    /// <summary>
        /// This class can be used to write logs from somewhere where it's a hard to get a reference to the <see cref="ILogger"/>.
        /// Normally, use <see cref="ILogger"/> with property injection wherever it's possible.
        /// 这个类可以用来在某些无法直接依赖ILogger的地方写日志。
        /// 通常情况下,在任何可能的情况下使用属性注入ILogger
        /// </summary>
        public static class LogHelper
        {
            /// <summary>
            /// A reference to the logger.
            /// 引用logger
            /// </summary>
            public static ILogger Logger { get; private set; }
    
            static LogHelper()
            {
                Logger = IocManager.Instance.IsRegistered(typeof(ILoggerFactory))
                    ? IocManager.Instance.Resolve<ILoggerFactory>().Create(typeof(LogHelper))
                    : NullLogger.Instance;
            }
    
            public static void LogException(Exception ex)
            {
                LogException(Logger, ex);
            }
    
            public static void LogException(ILogger logger, Exception ex)
            {
                var severity = (ex as IHasLogSeverity)?.Severity ?? LogSeverity.Error;
    
                logger.Log(severity, ex.Message, ex);
    
                LogValidationErrors(logger, ex);
            }
    
            private static void LogValidationErrors(ILogger logger, Exception exception)
            {
                //Try to find inner validation exception
                if (exception is AggregateException && exception.InnerException != null)
                {
                    var aggException = exception as AggregateException;
                    if (aggException.InnerException is AbpValidationException)
                    {
                        exception = aggException.InnerException;
                    }
                }
    
                if (!(exception is AbpValidationException))
                {
                    return;
                }
    
                var validationException = exception as AbpValidationException;
                if (validationException.ValidationErrors.IsNullOrEmpty())
                {
                    return;
                }
    
                logger.Log(validationException.Severity, "There are " + validationException.ValidationErrors.Count + " validation errors:");
                foreach (var validationResult in validationException.ValidationErrors)
                {
                    var memberNames = "";
                    if (validationResult.MemberNames != null && validationResult.MemberNames.Any())
                    {
                        memberNames = " (" + string.Join(", ", validationResult.MemberNames) + ")";
                    }
    
                    logger.Log(validationException.Severity, validationResult.ErrorMessage + memberNames);
                }
            }
        }
    

    设计模式


    我的公众号

    相关文章

      网友评论

        本文标题:ABP 源码解析 七. 日志

        本文链接:https://www.haomeiwen.com/subject/dexvvftx.html