技术笔记:EFCore中ILoggerFactory的创建流程(2020-03-29)

提纲:

  1. 日志系统依赖注入流程
    主要依靠 LoggerFactory 的一个静态方法
  2. 日志过滤

public static ILoggerFactory Create(Action<ILoggingBuilder> configure);

  1. ILoggerFactory.Create 会创建一个 ILoggerFactory的实例 (假设为 a )
  2. a 中会创建一个 ILoggerBuilder实例 ( 假设为 b )
  3. 将 b 传入到 LoggerFactory.Create 的 Action 参数中
  4. ConsoleLoggerExtensions 的扩展方法 AddConsole , 会创建一个
    Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider的实例 ( 假设为 c) ,
  5. 将 c 添加到 b的 Services 属性中 中;
  6. a 遍历 b 的 Services , 把所有 ILogProvider接口的实例通过 ILoggerFactory.AddProvider(Microsoft.Extensions.Logging.ILoggerProvider) 添加到 a 中

参看前一篇 https://www.jianshu.com/writer#/notebooks/29222457/notes/66043074

ILoggingBuilder 接口

注意, Services 属性和 日志系统无关, ILogFactory 需要遍历此 Services 属性,并将 ILogProvier 接口的实例添加到 ILogFactory 的实例中;

using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.Extensions.Logging
{
    // 摘要:
    public interface ILoggingBuilder
    {
        //     Gets the Microsoft.Extensions.DependencyInjection.IServiceCollection where Logging
        //     services are configured.
        IServiceCollection Services { get; }
    }
}

IServiceCollection 是一个很复杂的接口,暂时不介绍先;
简单来说,我们就认为当如下代码时,会走一遍上述流程

 public static readonly ILoggerFactory MyLoggerFactory
            = LoggerFactory.Create(builder => { builder.AddConsole();
            });

于是我们来验证一下,随便找一个日志文件记录包..
Karambolo.Extensions.Logging.File.
然后根据 https://github.com/adams85/filelogger 构建代码

                builder = builder.AddConsole();
                var fileoption = new FileLoggerOptions
                {
                    BasePath = ".",
                    FileAccessMode = LogFileAccessMode.KeepOpenAndAutoFlush,
                    FileEncoding = System.Text.Encoding.UTF8,
                    DateFormat = "yyyyMMdd",
                    CounterFormat = "000",
                    MaxFileSize  = 10485760,
                   // TextBuilderType = "MyApp.CustomLogEntryTextBuilder, MyApp",
                    IncludeScopes = true,
                    MaxQueueSize = 100,
                    Files = new LogFileOptions[] 
                    { 
                        new LogFileOptions { Path = @"default-<counter>.log", },
                        new LogFileOptions { Path = @"<date:yyyy>/<date:MM>/other-<counter>.log",  
                            MinLevel = new System.Collections.Generic.Dictionary<string, LogLevel>
                            {
                                {
                                    "Default", LogLevel.Trace
                                }
                            },
                            CounterFormat ="00"
                        }
                    }
                };
                var option = Microsoft.Extensions.Options.Options.Create(fileoption);
                var logfileProvider = new FileLoggerProvider(option);
                builder.AddProvider(logfileProvider); 

在 build 中添加另外一个 ILoggerProvider, 看看能否记录到日志, 果然能.

给 ILoggerBuilder 添加过滤.

注意, 只会使用最后一个添加的 Filter 来对日志进行过滤

这个过滤对于所有的 ILoggerBuilder下的所有的 ILogger 的实例都会产生过滤条件;
只需要记住一点,一个 ILoggerBuilder的实例,只会使用最后一个添加的 Filter 来对日志进行过滤,
并将过滤后的日志发给所有的日志进行处理.
而类似这样的流程, AddFilter(xFilter).AddConsole().AddFilter(yFilter).AddProvider(yProvider).AddFilter(zFilter).AddProvider(zProvider)
无法实现目标,因为 zFilter 将覆盖 xFilter \ yFilter 的过滤设置..
类似如下代码,

builder
                        .AddFilter((category, level) =>
                            category == DbLoggerCategory.Database.Command.Name
                            && level >= LogLevel.Trace).AddConsole();
 builder
                        .AddFilter((category, level) =>
                            category == DbLoggerCategory.Database.Command.Name
                            && level == LogLevel.Information).AddProvider(logfileProvider);

Console中只会输出 Infomation的日志,而不会输出所有的日志

QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利