• 【Serilog】具有完全结构化事件的简单.NET日志记录


    结构化

    与 .NET 的其他日志库不同,与日志消息一起传递的参数不会破坏性地呈现为文本格式。相反,它们被保存为结构化数据,可以以文档形式写入 NoSQL 数据存储。

    var input = new { Latitude = 25, Longitude = 134 };
    var time = 34;
    log.Information("Processed {@SensorInput} in {TimeMS:000} ms.", input, time);
    
    • 1
    • 2
    • 3

    Event and Level [事件和级别]

    log events

    和一些老的日志类库相比(如log4net),在使用Serilog时,你需要做的就是最大改变就是思考日志事件[log events],而不是日志消息[log message],一条事件[event]由以下几个内容组成:

    • 事件发生时的时间戳[timestamp]
    • 描述何时应该捕获事件的级别[level]
    • 记录事件的消息[message]内容]
    • 描述事件的命名属性[properties]
    • 还可能有一个Exception对象

    您可以将日志事件格式化为控制台的可读文本

    11:33:01 [INF] Hello, Serilog!  
    
    • 1

    或者,您可以将相同的事件格式化为JSON并将其发送到远程日志服务器:

    json {"@t":"2017-11-20T11:33:01.22138","@m":"Hello, Serilog!"}
    
    • 1

    Logging levels

    Serilog速度很快,但始终构建和记录详细的日志事件会浪费CPU,磁盘和网络资源。为了管理这个,Serilog事件被赋予了多种级别。对应的有一个Log.*()方法来对应各个级别。

    • Verbose
    • Debug
    • Information
    • Warning
    • Error
    • Fatal

    大多数的日志也是这样5级,只是有的名称叫的不同(NLog第1级叫Trace,其它的一致),每一级别对应一个写Log的函数:

    log.Verbose("verbose");
    log.Information("info");
    log.Debug("debug");
    log.Warning("warning");
    log.Error("err");
    log.Fatal("fatal");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    另外,ILogger对象还有一个Dispose方法,用于关闭日志对象。

    在开发过程中,可能会打开调试级别的事件:

    Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug() // <- Set the minimum level
    .WriteTo.Console()
    .CreateLogger();
    
    // In a tight loop...
    Log.Debug("Processing item {ItemNumber} of {ItemCount}", itemNumber, itemCount);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在生成环境中,通常关闭调试的日志,并将最小的日志级别设置成Information,以便只记录重要的事件,在这篇文档中可以获得有关Serilog Logger Lever的更多信息

    Tip: Serilog has special handling for Exception objects; methods like Log.Error() take the exception as the first parameter, e.g. [ 提示:Serilog对Exception对象有特殊的处理;] Log.Error(ex, "Task {TaskName} was canceled", task). [ Log.Error(例如,“任务{任务名称}被取消”,任务)。] Don’t include exceptions in the log message itself. [ 不要在日志消息本身中包含异常。]

    接收器

    Serilog的输出对象称之为Sink(水槽),github上提供了大量的第三方的可用sinks,这里简单的列举几个常用的:

    • Console 输出到控制台
    • Debug 输出到VS的Debug窗口
    • File 输出到文件
    • MongoDB 输出到MongoDB
    • LiteDB 输出到文件数据库LiteDB
    • SQLite 输出到文件数据库SQLite
    • SignalR 输出为SignalR服务
    • HTTP 输出到REST服务

    Finding needles in the haystack

    如果我们已经知道如何使用Serilog调用消息模板和enrichment结构化日志的两个支柱,那么第三个支柱就是隐式事件类型的概念。

    结构化日志适合有效处理大量日志数据。关于大型日志流的一个有趣的观察是,真实产生的事件比编写日志语句代码块时要多的多

    Log.Debug("Processing item {ItemNumber} of {ItemCount}", itemNumber, itemCount);  
    
    • 1

    这意味着,尽管生成了许多独特的消息字符串,如"Processing item 31 of 4159",但由此日志记录语句生成的每个事件共享相同的消息模板,即"Processing item {ItemNumber} of {ItemCount}"

    Serilog及其许多sinks 利用这一事实从根本上改进了查询和过滤日志事件的体验。如果消息模板与事件一起保存,则下面的过滤器可以立即从嘈杂的日志记录语句中排除成千上万的事件,从而更容易看到否则会被淹没的有趣事件:

    @MessageTemplate <> 'Processing item {ItemNumber} of {ItemCount}'
    
    • 1

    反转也适用 - 放大事件类型可以从单个日志记录语句中查找所有事件

    如何利用此功能取决于您存储和搜索日志的位置。接下来我们会看看细节。

    Tip:字符串链接,C#内插字符串,以及其他技术手段来预格式化传递给Serilog的消息内容,会取消此功能。详细请看 How (not) to parameterize Serilog events

    使用

    1、Nuget添加Serilog.AspNetCore,还需要安装一个或多个接收器

    在这里插入图片描述

    2、Startup.cs添加如下代码

    public void ConfigureServices(IServiceCollection services){
       //使用serilog替换自带的log实现         
       Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(Configuration)          	               		  
       .MinimumLevel.Debug()                    
       .Enrich.FromLogContext()                 
       .WriteTo.Console(new RenderedCompactJsonFormatter())
       .WriteTo.File(formatter: new CompactJsonFormatter(), "logs/mylog.log", rollingInterval: RollingInterval.Day)                   
       .CreateLogger();
       services.AddControllersWithViews();      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3、Program.cs添加如下代码

            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    }).UseSerilog(dispose: true);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4、调用

    public class HomeController : Controller
        {     //构造函数注入
            private readonly ILogger<HomeController> _logger;
    
            public HomeController(ILogger<HomeController> logger)
            {
                _logger = logger;
            }
    
            public IActionResult Index()
            {
                _logger.LogInformation("我能成功");
                return View();
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    来源

    .NET CORE使用SERILOG
    Serilog简介
    结构化日志类库 ---- Serilog库

  • 相关阅读:
    京东API接口(商品详情页采集+关键词搜索商品列表):开启电商业务的新篇章
    分布式锁2:基于redis实现分布式锁
    Adaptive AUTOSAR Diagnostic Manager模块介绍(一)
    redis相关知识点
    RDD算子操作(基本算子和常见算子)
    Charles抓包工具常用操作
    strings包详细文档+示例
    【华为OD机试python】拔河比赛【2023 B卷|100分】
    【HuggingFace轻松上手】基于Wikipedia的知识增强预训练
    检查两个字符串数组是否相等
  • 原文地址:https://blog.csdn.net/weixin_44231544/article/details/126240321