• ASP.NET Core框架学习之日志框架


    我们平时的开发离不开记录日志,.net core框架也内置了强大的日志记录功能。

    简单示例

      创建一个控制台应用,在appsettings.json中加入如下配置

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

      引用包

    1 Microsoft.Extensions.Logging
    2 Microsoft.Extensions.Logging.Console

      注入Logging到容器中

     1 IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
     2 configurationBuilder.AddJsonFile("appsettings.json", false, false);
     3 var configuration = configurationBuilder.Build();
     4 var services = new ServiceCollection();
     5 services.AddLogging(builder =>
     6 {             
     7         builder.AddConfiguration(iconfigurationRoot.GetSection("Logging"));
     8         builder.AddConsole();
     9 });
    10 var serviceProvider = services.BuildServiceProvider();

      下面是AddLogging的源码,其中主要的部分就是将ILoggerFactory和ILogger<>注入到容器中。

     1 public static IServiceCollection AddLogging(this IServiceCollection services, Action<ILoggingBuilder> configure)
     2 {
     3     if (services == null)
     4     {
     5         throw new ArgumentNullException("services");
     6     }
     7     services.AddOptions();
     8     services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>());
     9     services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>)));
    10     services.TryAddEnumerable(ServiceDescriptor.Singleton((IConfigureOptions<LoggerFilterOptions>)new DefaultLoggerLevelConfigureOptions(LogLevel.Information)));
    11     configure(new LoggingBuilder(services));
    12     return services;
    13 }

      我们可以通过两种方式创建ILogger对象

    1 var logFactory = serviceProvider.GetService<ILoggerFactory>();
    2 var logger = logFactory.CreateLogger("Default");
    3 //
    4 var logger = serviceProvider.GetService<ILogger<Program>>();
    5 logger.LogInformation("aa");
    6 logger.LogError("bb");
    7 logger.LogDebug("cc");

      这样我们就完成了打印日志的简单示例。

    日志级别

      日志级别分为如下7种,从上往下日志级别由低到高。如在配置文件中设置日志级别为Error,那么Warning等低级别的日志都不会被打印。 

     1 public enum LogLevel
     2 {
     3     Trace,
     4     Debug,
     5     Information,
     6     Warning,
     7     Error,
     8     Critical,
     9     None
    10 }

      打印日志时推荐使用字符串模板的方式

    1 logger.LogDebug("时间:{date}",DateTime.Now);

      不推荐下面这种方式,因为我们调试时可能记录大量Debug级别日志,当项目投入生产后,我们往往会关闭Debug级别日志,字符串模板方式在记录日志时才会进行字符串拼接,所以字符串模板的方式可以防止Dubug级别日志的字符串拼接影响性能。

    1 logger.LogDebug($"时间:{DateTime.Now}");

    日志域

      使用日志域方法,可以让同一作用域下的日志带上相同的scopeId,这样可以帮助我们更好的做日志追踪和排查问题。

      在Console配置文件中添加如下配置

    1  "IncludeScopes": true

      创建日志域并记录日志

    using (logger.BeginScope("scopeId:{scopeId}", Guid.NewGuid()))
    {
        logger.LogInformation($"时间:{DateTime.Now}");
        logger.LogError("bb");
        logger.LogDebug("cc");
    }

      它的执行结果如下图所示,可以看到每条日志都记录了scopeId

     通过Serilog框架记录结构化日志

      结构化日志相比与文本日志易于检索,易于分析统计,可以用于日志告警,日志关联,以及与追踪系统的集成。下面演示Serilog的简单使用实例。

      创建一个.net core web应用项目,并引用下面的nuget包

    1 Serilog.AspNetCore

      在appsettings.json中添加如下配置

    1 "Serilog": {
    2     "MinimumLevel": {
    3       "Default": "Debug",
    4       "Override": {
    5         "Microsoft": "Warning",
    6         "Microsoft.Hosting.Lifetime": "Information"
    7       }
    8     }
    9 }

      在Program.cs中添加如下代码

     1 public class Program
     2 {
     3     public static void Main(string[] args)
     4     {
     5         var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", false, true).Build();
     6         Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration)
     7             .WriteTo.Console(new RenderedCompactJsonFormatter())
     8             .Enrich.FromLogContext()
     9             .CreateLogger();
    10 
    11         Log.Logger.Information("程序启动 {date}",DateTime.Now);
    12         CreateHostBuilder(args).Build().Run();
    13     }
    14 
    15     public static IHostBuilder CreateHostBuilder(string[] args) =>
    16         Host.CreateDefaultBuilder(args)
    17         .ConfigureWebHostDefaults(webBuilder =>
    18         {
    19             webBuilder.UseStartup<Startup>();
    20         }).UseSerilog(dispose:true);
    21 }

      在控制器中引用ILogger<>

     1 public class WeatherForecastController : ControllerBase
     2 {
     3     private readonly ILogger<WeatherForecastController> _logger;
     4     public WeatherForecastController(ILogger<WeatherForecastController> logger)
     5     {
     6         _logger = logger;
     7     }
     8 
     9     [HttpGet]
    10     public string Get()
    11     {
    12         _logger.LogInformation("hello serilog ");
    13         return "OK";
    14     }
    15 }

      运行效果如下图,可以看到日志都是以Json结构记录的。

       上面的日志记录的较多,我们可以先将无用的日志关闭,在配置文件中将 Microsoft.Hosting.Lifetime的日志级别设置成 “Fatal”,这样我们的日志就清晰多了。

       Serilog日志框架还支持多种的Sinks接收器,可以通过引用 Serilog.Sinks.Http 或 Serilog.Sinks.Elasticsearch 将日志记录到 ELK中。

  • 相关阅读:
    使用C++ 实现的 websocket 客户端 (基于easywsclient)
    ant打包报错 JRE version less than 1.8 is not suppored
    离线安装SVN 4.2.3
    maven项目使用oracle11g
    springboot 新工程报错 Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
    IP与域名绑定
    web项目如果省略端口
    Linux源码安装Python3.7服务
    Linux yum软件包安装、管理与使用
    RPM软件包管理与使用
  • 原文地址:https://www.cnblogs.com/jasonbourne3/p/14634454.html
Copyright © 2020-2023  润新知