ILoggerFactory 根据日志类型(categoryName)调用 对应的 ILoggerProvider 获取 ILogger
- Logger 日子记录器
- ILoggerFactory 日志记录器工厂
- ILoggerProvider 日志记录器提供器
public interface ILoggerFactory : IDisposable { ILogger CreateLogger(string categoryName); void AddProvider(ILoggerProvider provider); }
public interface ILogger { void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter); bool IsEnabled(LogLevel logLevel); IDisposable BeginScope<TState>(TState state); }
/// <typeparam name="TCategoryName">The type who's name is used for the logger category name.</typeparam> public interface ILogger<out TCategoryName> : ILogger { }
Start.Configure() 方法中直接注入ILoggerFactory(ps:这个方法非常特殊,这方法的参数可以无穷多个,但是每个参数都必须是DI托管的对象。)
public static IServiceCollection AddLogging(this IServiceCollection services, Action<ILoggingBuilder> configure) { if (services == null) { throw new ArgumentNullException(nameof(services)); } services.AddOptions(); services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>()); services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>))); services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<LoggerFilterOptions>>( new DefaultLoggerLevelConfigureOptions(LogLevel.Information))); configure(new LoggingBuilder(services)); return services; } }
注入到Controller的ILooger到底是哪个Logger?难道只是某一个提供器生成Logger对象?
首先看看到底是哪个ILogger的托管到了容器里(Provider生成Logger对象并没有托管给容器,所以容器注入的Logger肯定不是日志提供器创建的ILogger对象)
在AddLogging() 中看到了
这个Logger就非常有意思, 他的成员变量里有LoggerFactory和LoggerInformation[] 引用 !!!(LoggerInformation是Logger的包装类,主要增加了一些Logger的元数据,可以理解成这就是一个Logger,这个logger就是LoggerProvider创建的Logger)
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) { if (factory == null) { throw new ArgumentNullException(nameof(factory)); } _logger = factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T))); }
public ILogger CreateLogger(string categoryName) { if (CheckDisposed()) { throw new ObjectDisposedException(nameof(LoggerFactory)); } lock (_sync) { if (!_loggers.TryGetValue(categoryName, out var logger)) { logger = new Logger(this) { 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++) { SetLoggerInformation(ref loggers[i], _providerRegistrations[i].Provider, categoryName); } ApplyRules(loggers, categoryName, 0, loggers.Length); return loggers; }
-
跟踪Trace = 0 表示仅对于开发人员调试问题有价值的信息。 这些消息可能包含敏感应用程序数据,因此不得在生产环境中启用它们。 默认情况下禁用。
-
调试Debug = 1 表示在开发和调试过程中短期有用的信息。除非要排查问题,否则通常不会在生产中启用
Debug
级别日志,因为日志数量过多。 -
信息Information = 2 用于跟踪应用程序的常规流。 这些日志通常有长期价值。
-
警告Warning = 3 表示应用程序流中的异常或意外事件。 可能包括不会中断应用程序运行但仍需调查的错误或其他条件。
Warning
日志级别常用于已处理的异常。 -
错误Error = 4 表示无法处理的错误和异常。 这些消息指示的是当前活动或操作(如当前 HTTP 请求)中的失败,而不是应用程序范围的失败。
-
严重Critical = 5 需要立即关注的失败。 例如数据丢失、磁盘空间不足。
-
None = 6 是禁用所有日志,因为没有比None更高的等级