当前位置:   article > 正文

Serilog日志框架

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<T>()构建类型化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;

/// <summary>
/// 示例逻辑服务
/// </summary>
public class FooService {
  private readonly ILogger _logger;

  public FooService () {
    // 底层调用了CreateLogger创建了新的ILogger对象
    _logger = Log.ForContext<FooService>();
  }

  /// <summary>
  /// 构造ILogger
  /// </summary>
  public void PrintWithNewLogger () {
    _logger.Information("构建的ILoggre对象");
    _logger.Error(new Exception("发生异常"), "构建的ILoggre对象");
  }

  /// <summary>
  /// 静态的ILogger成员
  /// </summary>
  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/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/329353
推荐阅读
相关标签
  

闽ICP备14008679号