新建控制台应用程序👉命名LoggingSimpleDemo
    image.png

    1. using Microsoft.Extensions.Configuration;
    2. using Microsoft.Extensions.DependencyInjection;
    3. using Microsoft.Extensions.Logging;
    4. using System;
    5. namespace LoggingSimpleDemo
    6. {
    7. class Program
    8. {
    9. static void Main(string[] args)
    10. {
    11. // 利用之前的方式加载json配置
    12. var builder = new ConfigurationBuilder();
    13. builder.AddJsonFile("appsetting.json", false, true);
    14. var config = builder.Build();
    15. IServiceCollection servicesCollection = new ServiceCollection();
    16. // 使用工厂模式将配置对象注册到容器管理
    17. servicesCollection.AddSingleton<IConfiguration>(p => config);
    18. servicesCollection.AddLogging(builder =>
    19. {
    20. builder.AddConfiguration(config.GetSection("Logging"));
    21. builder.AddConsole();
    22. });
    23. }
    24. }
    25. }

    前三行代码,我们使用了之前的方式,加载json配置

    利用IServiceCollection servicesCollection = new ServiceCollection()构建了一个容器

    使用工厂模式将配置注册到容器管理servicesCollection.AddSingleton<IConfiguration>(p => config),因为使用servicesCollection.AddSingleton<IConfiguration>(config)这种方式,将config实例直接注入进去,容器是不会帮助我们管理这个对象的生命周期的。

    1. servicesCollection.AddLogging(builder =>
    2. {
    3. builder.AddConfiguration(config);
    4. builder.AddConsole();
    5. });

    我们可以看看servicesCollection.AddLogging()方法的定义
    image.png
    AddLogging往容器里注册了几个关键的对象,一个ILoggerFactory,一个ILogger的泛型模板,一个是Logger的过滤配置,最后configure就是我们整个注入的委托。

    接下来看看我们的配置文件appsettings.josn

    1. {
    2. "Logging": {
    3. "LogLevel": {
    4. "Default": "Information",
    5. "Microsoft": "Warning",
    6. "Microsoft.Hosting.Lifetime": "Information"
    7. },
    8. "Console": {
    9. "LogLevel": {
    10. "Default": "Information",
    11. "Program": "Trace",
    12. "alogger": "Trace"
    13. }
    14. }
    15. }
    16. }

    配置文件里面有一节Logging,里面定义了Log的级别。
    这里面Key就代表了我们的Logger的名称,Value就代表了我们Logger的级别。
    下面一节Console指我们针对Console的输出提供程序,配置的日志级别。

    日志级别定义

    1. namespace Microsoft.Extensions.Logging
    2. {
    3. // Defines logging severity levels.
    4. public enum LogLevel
    5. {
    6. Trace,
    7. Debug,
    8. Information,
    9. Warning,
    10. Error,
    11. Critical,
    12. None
    13. }
    14. }

    None代表不输出任何的日志

    接下来继续看代码

    1. using Microsoft.Extensions.Configuration;
    2. using Microsoft.Extensions.DependencyInjection;
    3. using Microsoft.Extensions.Logging;
    4. using System;
    5. namespace LoggingSimpleDemo
    6. {
    7. class Program
    8. {
    9. static void Main(string[] args)
    10. {
    11. // 利用之前的方式加载json配置
    12. var builder = new ConfigurationBuilder();
    13. builder.AddJsonFile("appsettings.json", false, true);
    14. var config = builder.Build();
    15. IServiceCollection servicesCollection = new ServiceCollection();
    16. // 使用工厂模式将配置对象注册到容器管理
    17. servicesCollection.AddSingleton<IConfiguration>(p => config);
    18. servicesCollection.AddLogging(builder =>
    19. {
    20. builder.AddConfiguration(config.GetSection("Logging"));
    21. builder.AddConsole();
    22. });
    23. // 将我们的容器Build出来
    24. IServiceProvider services = servicesCollection.BuildServiceProvider();
    25. // 从容器中获取ILoggerFactory
    26. ILoggerFactory loggerFactory = services.GetService<ILoggerFactory>();
    27. var alogger = loggerFactory.CreateLogger("alogger");
    28. alogger.LogDebug(10086, "Begin");
    29. alogger.LogInformation("Hello World!");
    30. var ex = new Exception("There is a bug");
    31. alogger.LogError(ex, "Error!");
    32. Console.ReadKey();
    33. }
    34. }
    35. }

    利用IServiceProvider services = servicesCollection.BuildServiceProvider();将我们的容器Build出来

    ILoggerFactory loggerFactory = services.GetService<ILoggerFactory>();ILoggerFactory对象取出来。
    ILoggerFactory里面有连个方法,一个是ILogger CreateLogger(string categoryName)输入的是Logger的名称,输出是一个ILogger对象,这个ILogger就代表我们的日志记录器。第二个方式就是void AddProvider(ILoggerProvider provider),一般我们不使用,直接在AddLogging里去注册。

    利用var alogger = loggerFactory.CreateLogger("alogger");获取一个ILogger对象,这个Logger对象的名字叫alogger。
    运行输出:image.png
    其中,alogger[10086]10086EventID,是针对每一个记录的位置,实践,我们可以为它分配一个事件ID
    如果我们把日志级别设置为Information

    1. "alogger": "Information"

    运行输出:image.png
    可以看到,DeBug级别的日志是没有输出的。

    这是使用CreateLogger的的方式来方式指定了Logger的名称,实际上我们可以借助容器来构造我们的Logger
    通常情况下,我们会定义自己的类,新建类OrderService

    1. using Microsoft.Extensions.Logging;
    2. using System;
    3. namespace LoggingSimpleDemo
    4. {
    5. public class OrderService
    6. {
    7. private readonly ILogger<OrderService> _logger;
    8. public OrderService(ILogger<OrderService> logger)
    9. {
    10. _logger = logger;
    11. }
    12. public void ShowLog()
    13. {
    14. _logger.LogInformation("OrderService.Log.ShowTime : {time}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
    15. }
    16. }
    17. }

    这里,我们使用了一个小技巧:使用模板去记录日志_logger.LogInformation("xxx : {time}", DateTime.Now)
    这样相比较使用插值运算符$_logger.LogInformation($"xxx : {DateTime.Now}"),虽然最终输出结果是一样的,但是我们字符串拼接的时机是不同的。使用模板方法,是在我们决定要输出的时候,也就是在LogInformation内部Console提供程序要输出的时候,才去做这个拼接动作。而使用第二种办法其实是将我们的字符串拼接好以后,输入给了LogInformation这个参数。如果说我们把日志等级改成None的话,模板的拼接动作是不会执行的,第二种怎么也会执行拼接的操作,这样字符串拼接操作累计下来,造成的损耗是非常大的。

    然后将我们的类注入到容器里。

    1. using Microsoft.Extensions.Configuration;
    2. using Microsoft.Extensions.DependencyInjection;
    3. using Microsoft.Extensions.Logging;
    4. using System;
    5. namespace LoggingSimpleDemo
    6. {
    7. class Program
    8. {
    9. static void Main(string[] args)
    10. {
    11. // 利用之前的方式加载json配置
    12. var builder = new ConfigurationBuilder();
    13. builder.AddJsonFile("appsettings.json", false, true);
    14. var config = builder.Build();
    15. IServiceCollection servicesCollection = new ServiceCollection();
    16. // 使用工厂模式将配置对象注册到容器管理
    17. servicesCollection.AddSingleton<IConfiguration>(p => config);
    18. servicesCollection.AddLogging(builder =>
    19. {
    20. builder.AddConfiguration(config.GetSection("Logging"));
    21. builder.AddConsole();
    22. });
    23. servicesCollection.AddSingleton<OrderService>();
    24. // 将我们的容器Build出来
    25. IServiceProvider services = servicesCollection.BuildServiceProvider();
    26. var orderService = services.GetService<OrderService>();
    27. orderService.ShowLog();
    28. Console.ReadKey();
    29. }
    30. }
    31. }

    运行输出:image.png
    这样使用的好处是,我们不需要定义名字,它会自动的把类型的名称作为记录器的名字,如上LoggingSimpleDemo.OrderService
    也就意味着我们可以使用这个名称来设置日志级别。
    配置文件添加:"LoggingSimpleDemo.OrderService": "none"

    1. {
    2. "Logging": {
    3. "LogLevel": {
    4. "Default": "Information",
    5. "Microsoft": "Warning",
    6. "Microsoft.Hosting.Lifetime": "Information"
    7. },
    8. "Console": {
    9. "LogLevel": {
    10. "Default": "Information",
    11. "Program": "Trace",
    12. "alogger": "Information",
    13. "LoggingSimpleDemo.OrderService": "none"
    14. }
    15. }
    16. }
    17. }

    运行输出:image.png
    可以看到我们将日志级别设为None之后,控制台什么都没打印出来。

    注意:记录日志的时候不要把敏感信息输出出来。