• Serilog日志框架


    一. Serilog介绍

    Serilog 是 .NET应用程序的诊断日志记录库。它易于设置,具有干净的 API,并且可以在所有最新的 .NET 平台上运行。虽然它即使在最简单的应用程序中也很有用,但 Serilog 对结构化日志记录的支持在检测复杂、分布式和异步应用程序和系统时大放异彩。

    1.1 安装Serilog

    dotnet add package Serilog
    dotnet add package Serilog.Extensions.Logging
    dotnet add package Serilog.Sinks.File
    dotnet add package Serilog.Sinks.Console
    dotnet add package Serilog.Sinks.Async
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.2 Serilog日志级别

    public enum LogEventLevel {
      Verbose,       // 相当于Trace
      Debug,     	 // 调试模式
      Information,   // 提示信息
      Warning,       // 警告信息
      Error,         // 错误信息
      Fatal          // 验证错误
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    二. Serilog.App项目应用

    2.1 Serilog一般应用

    • 可使用Serilog.Log.ForContext()构建类型化ILogger对象。
    • 可使用Serilog.Log类的静态ILogger成员直接打印日志内容。
    using Demo.Service;
    using Serilog;
    
    // Log.Logger是Serilog的一个静态成员,作为全局的ILogger对象
    Log.Logger = new LoggerConfiguration()
        .WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}]  {SourceContext} {Message} {Exception}{NewLine}")
        .MinimumLevel.Verbose()
        .WriteTo.File("Logs/Log.txt")
        .CreateLogger();
    
    // Main中打印日志
    Log.Information("应用程序已启动");
    
    // 其他业务代码...
    var foo = new FooService();
    foo.PrintWithNewLogger();
    foo.PrintWithStaticLogger();
    
    // 关闭日志记录器并刷新缓冲区
    Log.CloseAndFlush();
    Console.ReadKey();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    using Serilog;
    
    namespace Demo.Service;
    
    /// 
    /// 示例逻辑服务
    /// 
    public class FooService {
      private readonly ILogger _logger;
    
      public FooService () {
        // 底层调用了CreateLogger创建了新的ILogger对象
        _logger = Log.ForContext<FooService>();
      }
    
      /// 
      /// 构造ILogger
      /// 
      public void PrintWithNewLogger () {
        _logger.Information("构建的ILoggre对象");
        _logger.Error(new Exception("发生异常"), "构建的ILoggre对象");
      }
    
      /// 
      /// 静态的ILogger成员
      /// 
      public void PrintWithStaticLogger () {
        Serilog.Log.Logger.Error("使用Serilog.Log.Logger打印日志");
    
        // 可简化为Serilog.Log.XXX(内部依然使用了Serilog.Log.Logger.XXX)
        Serilog.Log.Debug("使用Serilog.Log静态方法打印日志");
        Serilog.Log.Information("使用Serilog.Log静态方法打印日志");
        Serilog.Log.Warning("使用Serilog.Log静态方法打印日志");
        Serilog.Log.Error("使用Serilog.Log静态方法打印日志");
        Serilog.Log.Fatal("使用Serilog.Log静态方法打印日志");
        Serilog.Log.Verbose("等价于Trace级别的日志");
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2.2 兼容系统日志

    using Microsoft.Extensions.Logging;
    using Serilog;
    
    // 配置Serilog日志
    var tpl = "时间: {Timestamp:yyyy-MM-dd HH:mm:ss}{NewLine}来源: {SourceContext}{NewLine}内容: [{Level:u3}] {Message}{NewLine}{Exception}{NewLine}";
    Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Console(outputTemplate: tpl)
    .WriteTo.File("Logs/Log.txt", rollingInterval: RollingInterval.Day, outputTemplate: tpl)
    .CreateLogger();
    
    // ⚠ 加入到Microsoft.Extensions.Logging 日志工厂
    var fac = LoggerFactory.Create(config => { config.AddSerilog(); });
    
    // 在具体的类型化对象中使用Logger
    var logger = fac.CreateLogger<Program>();
    logger.LogInformation("这是一条提示信息");
    logger.LogWarning("这是一条警告信息");
    logger.LogError("这是一条错误信息");
    logger.LogCritical("这是一条严重错误");
    
    Log.CloseAndFlush();
    Console.ReadKey();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    三. Serilog.Web应用

    3.1 Minimal示例

    • 可将Serilog注入到IServiceCollection中,即依赖注入。
    • Serilog可打印系统捕获的异常信息,而无需显式指定异常输出格式。
    using Serilog;
    using Serilog.Events;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // 配置Serilog日志
    var tpl = "时间: {Timestamp:yyyy-MM-dd HH:mm:ss}{NewLine}来源: {SourceContext}{NewLine}内容: [{Level:u3}] {Message}{NewLine}{Exception}{NewLine}";
    Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) 
                .WriteTo.Console(outputTemplate: tpl)
                .WriteTo.File("Logs/Log.txt", rollingInterval: RollingInterval.Day, outputTemplate: tpl)
                .CreateLogger();
    
    //将Serilog注入到应用
    builder.Services.AddLogging(opt => {
      opt.ClearProviders();
      opt.AddSerilog(dispose: true);
    });
    
    var app = builder.Build();
    app.MapGet("/", () => {
      // 动态对象
      var logger = Log.ForContext<Program>();
      logger.Error("这是一条Serilog.ILogger信息");
      logger.Fatal("这是一条Serilog.ILogger信息");
    
      // 静态方法
      Log.Information("这是一条Serilog.ILogger信息");
      Log.Warning("这是一条Serilog.ILogger信息");
    
      // 从注入容器读取
      app.Logger.LogInformation("这是一条系统ILogger信息");
      app.Logger.LogError("这是一条系统ILogger信息");
    
      return "Hello world";
    });
    
    app.MapGet("/exp", () => {
      throw new Exception("测试异常日志");
    });
    
    app.Run();
    Log.CloseAndFlush();	// 关闭日志记录器并刷新缓冲区
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    3.2 WebApi示例

    Extends

    using Serilog.Events;
    using Serilog;
    
    namespace Awesome;
    
    public static class Extends {
      const string infoPath = "Logs/info.log";
      const string warnPath = "Logs/warn.log";
      const string errorPath = "Logs/error.log";
      const string fatalPath = "Logs/fatal.log";
      const string template = "时间: {Timestamp:yyyy-MM-dd HH:mm:ss}{NewLine}来源: {SourceContext}{NewLine}内容: [{Level:u3}] {Message}{NewLine}{Exception}{NewLine}";
    
      // 可以将日志输出到控制台、文件、数据库、ES等
      public static void AddSerilog (this IServiceCollection c) {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Information()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) // 排除Dotnet自带的日志
            .Enrich.FromLogContext()
            .WriteTo.Console(outputTemplate: template)
            .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Information).WriteTo.Async(congfig => congfig.File(
                    infoPath,
                    rollingInterval: RollingInterval.Day,
                    fileSizeLimitBytes: 1024 * 1024 * 10,    //默认1GB
                    retainedFileCountLimit: 10,                   //保留最近多少个文件,默认31个
                    rollOnFileSizeLimit: true,                       //超过文件大小时,自动创建新文件  
                    shared: true,
                    outputTemplate: template)
                ))
    
            .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Warning).WriteTo.Async(congfig => congfig.File(
                    warnPath,
                    rollingInterval: RollingInterval.Day,
                    fileSizeLimitBytes: 1024 * 1024 * 10,
                    retainedFileCountLimit: 10,
                    rollOnFileSizeLimit: true,
                    shared: true,
                    outputTemplate: template)
            ))
    
            .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Error).WriteTo.Async(congfig => congfig.File(
                    errorPath,
                    rollingInterval: RollingInterval.Day,
                    fileSizeLimitBytes: 1024 * 1024 * 10,
                    retainedFileCountLimit: 10,
                    rollOnFileSizeLimit: true,
                    shared: true,
                    outputTemplate: template)
            ))
    
            .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Fatal).WriteTo.Async(congfig => congfig.File(
                    fatalPath,
                    rollingInterval: RollingInterval.Day,
                    fileSizeLimitBytes: 1024 * 1024 * 10,
                    retainedFileCountLimit: 10,
                    rollOnFileSizeLimit: true,
                    shared: true,
                    outputTemplate: template)
            )).CreateLogger();
    
        // 注入到容器
        c.AddLogging(opt => {
          opt.ClearProviders();
          opt.AddSerilog(dispose: true);
        });
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    Controllers

    using Microsoft.AspNetCore.Mvc;
    
    namespace Awesome.Controllers;
    
    [ApiController]
    [Route("[controller]/[action]")]
    public class HomeController : ControllerBase {
      private readonly ILogger<HomeController> _logger;
    
      public HomeController (ILogger<HomeController> logger) {
        _logger = logger;
      }
    
      [HttpGet]
      public IActionResult Index () {
        _logger.LogDebug("这是一条调试消息");
        _logger.LogInformation("这是一条提示消息");
        _logger.LogWarning("这是一条警告消息");
        _logger.LogError("这是一条错误消息");
        _logger.LogCritical("这是一条严重错误");
        return Ok("Hello World");
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    Program

    using Awesome;
    using Serilog;
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddControllers();
    
    // 添加Serilog日志
    builder.Services.AddSerilog();
    
    var app = builder.Build();
    app.MapControllers();
    app.Run();
    
    // 关闭日志流
    Log.CloseAndFlush();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    参考链接

    https://serilog.net/

  • 相关阅读:
    利用消球差透镜对各种偏振光束进行深聚焦
    Windows 7 安装MYSQL 错误:1067
    C++项目-数组逆置
    【Linux】实用小技巧,如何同时make多个可执行文件?
    深度探讨丨关于工作量证明的常见误解
    Electron程序逆向(asar归档解包)
    深入理解requests库和使用方法
    arm2 day6
    【操作系统笔记十五】操作系统面试问题总结
    服务网关之Spring Cloud Gateway
  • 原文地址:https://blog.csdn.net/Gusand/article/details/137091556