ABP 源码解析 七. 日志
2018-08-27 本文已影响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);
}
}
}
设计模式
无
我的公众号