什么网站做简历模板,石家庄大型公司建站,中国万网网站建设过程,网络推广推广培训上一章#xff0c;我们介绍了日志的配置#xff0c;在熟悉了配置之后#xff0c;自然是要了解一下在应用程序中如何使用#xff0c;而本章则从最基本的使用开始#xff0c;逐步去了解去源码。 LoggerFactory 我们可以在构造函数中注入 ILoggerFactory#xff0c;来创建一… 上一章我们介绍了日志的配置在熟悉了配置之后自然是要了解一下在应用程序中如何使用而本章则从最基本的使用开始逐步去了解去源码。 LoggerFactory 我们可以在构造函数中注入 ILoggerFactory来创建一个日志记录器 public class TestController : Controller
{private readonly ILogger _logger;public TestController(ILoggerFactory factory){_logger factory.CreateLogger(nameof(TestController));}public void TestLog(){_logger.LogInformation(info);_logger.LogDebug(debug);}
} 在上一章中我们有介绍到ILoggerFactory 的默认实现是 LoggerFactory。而 LoggerFactory 中的代码较多我们慢慢来看 首先是构造函数 public LoggerFactory() : this(Enumerable.EmptyILoggerProvider()) {}public LoggerFactory(IEnumerableILoggerProvider providers) : this(providers, new StaticFilterOptionsMonitor(new LoggerFilterOptions())) {}public LoggerFactory(IEnumerableILoggerProvider providers, LoggerFilterOptions filterOptions) : this(providers, new StaticFilterOptionsMonitor(filterOptions)) {}public LoggerFactory(IEnumerableILoggerProvider providers, IOptionsMonitorLoggerFilterOptions filterOption)
{_providerRegistrations providers.Select(provider new ProviderRegistration { Provider provider }).ToList();_changeTokenRegistration filterOption.OnChange(RefreshFilters);RefreshFilters(filterOption.CurrentValue);
} 看到这里不得不先说一下 ILoggerProvider public interface ILoggerProvider : IDisposable
{ILogger CreateLogger(string categoryName);
} 而我们知道LoggerFactory 也有一个 CreateLogger 方法那他们之间有什么区别呢后面会解释。 而现在我们可以猜到在具体的 Provider 中如 AddConsole 扩展方法只是简单的将注册了一个 ILoggerProvider 的实例这样在DI系统创建 LoggerFactory 实例时便能够解析到所有注册的 Provider。再往下看一下我们所调用的 LoggerFactory 的 CreateLogger 方法 public ILogger CreateLogger(string categoryName)
{if (CheckDisposed()){throw new ObjectDisposedException(nameof(LoggerFactory));}lock (_sync){Logger logger;if (!_loggers.TryGetValue(categoryName, out logger)){logger new Logger(){Loggers CreateLoggers(categoryName)};_loggers[categoryName] logger;}return logger;}
}private LoggerInformation[] CreateLoggers(string categoryName)
{var loggers new LoggerInformation[_providerRegistrations.Count];for (int i 0; i _providerRegistrations.Count; i){var provider _providerRegistrations[i].Provider;loggers[i].Logger provider.CreateLogger(categoryName);loggers[i].ProviderType provider.GetType();}ApplyRules(loggers, categoryName, 0, loggers.Length);return loggers;
} 首先是直接 new 了一个 Logger 实例然后为其 Loggers 属性赋值而 Loggers 属性则是由注册的所有 ILoggerProvider 所创建出来的 Logger 集合。 回到刚才的问题有两种 CreateLogger 方法也就有两种 Logger一种是直接 New 出来的 Logger是 ILogger 的默认实现者也是我们记录日志时所直接调用的 Logger另外一种则是由 ILoggerProvider 所创建出来的 Logger姑且称之为 PLogger 吧。而在我们的应用程序中记录日志时只需要关注 Logger 就可以了而不需要去关注 PLogger因为 Logger 是一个日志记录器的聚合包含所有注册的 PLoggerPLogger 则是具体的执行者我们可以通过代码来更清楚的了解 internal class Logger : ILogger
{public LoggerInformation[] Loggers { get; set; }public void LogTState(LogLevel logLevel, EventId eventId, TState state, Exception exception, FuncTState, Exception, string formatter){var loggers Loggers;if (loggers null){return;}ListException exceptions null;foreach (var loggerInfo in loggers){if (!loggerInfo.IsEnabled(logLevel)){continue;}try{loggerInfo.Logger.Log(logLevel, eventId, state, exception, formatter);}catch (Exception ex){if (exceptions null){exceptions new ListException();}exceptions.Add(ex);}}if (exceptions ! null exceptions.Count 0){throw new AggregateException(message: An error occurred while writing to logger(s)., innerExceptions: exceptions);}}public bool IsEnabled(LogLevel logLevel){...}public IDisposable BeginScopeTState(TState state){...}
} 可以看到Logger 的 Log 方法只是依次调用 Loggers 属性中的 Log 方法而其本身并不具有记录日志的功能。 再继续把视线转回到 LoggerFactory 类在其 CreateLoggers 方法中最后还调用了 ApplyRules这便是我们上一章中所配置的过滤器的用武之地了。 private void ApplyRules(LoggerInformation[] loggers, string categoryName, int start, int count)
{for (var index start; index start count; index){ref var loggerInformation ref loggers[index];RuleSelector.Select(_filterOptions,loggerInformation.ProviderType,categoryName,out var minLevel,out var filter);loggerInformation.Category categoryName;loggerInformation.MinLevel minLevel;loggerInformation.Filter filter;}
} RuleSelector 中的代码我的就不贴了简单说一下其过滤规则的选择顺序 首先查找指定了 ProviderName 并与当且 Provider的名称(Alias)相同的过滤规则如果没有则选用未指定 ProviderName 的过滤规则。选择指定的 CategoryName 相符合的过滤规则如果没有则选择未指定 CategoryName 的那一条。如果符合的规则有多条则选用最后一条。如果未找到相符合的规则则使用全局的最小过滤级别。而且我们可以看到LoggerInformation 带有 MinLeve 属性和 Filter 委托两种过滤配置而这两种配置的来源在上一章中可以看到分别是从配置文件AddConfiguration和直接使用委托AddFilter来进行配置的。而他们的优先级又是怎么样的 internal struct LoggerInformation
{public ILogger Logger { get; set; }public string Category { get; set; }public Type ProviderType { get; set; }public LogLevel? MinLevel { get; set; }public Funcstring, string, LogLevel, bool Filter { get; set; }public bool IsEnabled(LogLevel level){if (MinLevel ! null level MinLevel){return false;}if (Filter ! null){return Filter(ProviderType.FullName, Category, level);}return true;}
} 无需多说通过上面的 IsEnabled 方法能够清楚的看到先使用 MinLevel 过滤再使用 Filter 进行过滤。 再总结一下其整个流程首先是注册 Provider然后 LogFactory 通过DI系统解析所有注册的 Privoder在我们调用其 CreateLogger 方法时创建一个 Logger 对象并通过这些 Provider 创建一个 LoggerInformation 集合赋予给 Logger 对象并包含 PLogger 和 经过筛选后的过滤规则最后在我们调用 Log 方法记录日志时会遍历 LoggerInformation 集合然后执行过滤方法再调用 PLogger 中的 Log 方法。 ILogger 上面介绍了使用 LogFactory 创建 ILogger 的方式其实还有一种更简单的使用方式我们可以直接在构造函数中注入 ILoggerT 来记录日志 public class TestController : Controller
{private readonly ILogger _logger;public TestController(ILoggerAccountController logger){_logger logger;}
} 是不是很神奇那么是如何实现的呢 public interface ILoggerout TCategoryName : ILogger
{} 而 ILogger 的默认实现在上一章中介绍的 AddLogging 方法中我们知道是 LoggerT。 public class LoggerT : ILoggerT
{private readonly ILogger _logger;/// summary/// Creates a new see crefLogger{T}/./// /summary/// param namefactoryThe factory./parampublic Logger(ILoggerFactory factory){if (factory null){throw new ArgumentNullException(nameof(factory));}_logger factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T)));}IDisposable ILogger.BeginScopeTState(TState state){return _logger.BeginScope(state);}bool ILogger.IsEnabled(LogLevel logLevel){return _logger.IsEnabled(logLevel);}void ILogger.LogTState(LogLevel logLevel, EventId eventId, TState state, Exception exception, FuncTState, Exception, string formatter){_logger.Log(logLevel, eventId, state, exception, formatter);}
} 可以看到在 Logger 其实是一种简写形式使用泛型的方式来获取 categoryName最后还是调用了 factory.CreateLogger。 总结 本章主要讲解了 ILogger 的创建过滤一系列过程主要关注的是 Logger 的实现方式而到此对 ASP.NET Core Logging 系统也有了一个基本的了解在我们的应用程序中对 Logging 的配置和使用也算是游刃有余。而下一章则会介绍了一下 LoggerProvider 的实现以及如何自己来写一个 LoggerProvider。 转载于:https://www.cnblogs.com/RainingNight/p/asp-net-core-logging-logger.html