0
点赞
收藏
分享

微信扫一扫

Serilog日志框架

悄然丝语 04-02 16:30 阅读 2
microsoft

文章目录

一. 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 Serilog日志级别

public enum LogEventLevel {
  Verbose,       // 相当于Trace
  Debug,     	 // 调试模式
  Information,   // 提示信息
  Warning,       // 警告信息
  Error,         // 错误信息
  Fatal          // 验证错误
}

二. 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();
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级别的日志");
  }
}

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();

三. 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();	// 关闭日志记录器并刷新缓冲区

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);
    });
  }
}

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");
  }
}

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();

参考链接

举报

相关推荐

0 条评论