• ASP.NET Core – Logging & Serilog


    前言

    以前就写过了 Asp.net core 学习笔记 (Logging 日志), 只是有点乱, 这篇作为整理版.

    参考:

    docs – Logging in .NET Core and ASP.NET Core

    Github – Serilog.AspNetCore

    Setting up Serilog in .NET 6

    ASP.NET Core Build-in Logging

    ASP.NET Core 提供了 Logging 的抽象接口, third party 都会依据抽象来做实现. ASP.NET Core 自己也实现了一套简单的 log, 它只能 log to console. 不能 log to file.

    所以绝大部分项目都会搭配一个 third party library, 比如 Serilog.

    我们先看看 ASP.NET Core build-in 的 log.

    Quick Example

    dotnet new webapp -o TestLog

    自带的模板首页就有 inject logger 了, 在 OnGet 使用它就可以了.

    打开 Visual Studio > View > Output, F5 run 就可以看见了

    VS Code 

    Log Category

    每个 log 都有 category 的概念, 在 appsetting.json 可以为每个 category 设置 min level

    比如某 category 在 production 的时候 min level 是 warning, 在 dev 的时候是 info.

    像上面的注入方式, 它的 category name 是 namespace + class "TestLog.Pages.IndexModel"

    如果想自定义的话可以用 factory 来创建 logger

     在 appsetting.json 声明 min level

    level 的顺序是 Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5, and None = 6.

    None 就是不要 log. Trace 就类似 track 追踪的意思

    Serilog

    安装

    dotnet add package Serilog.AspNetCore

    program.cs

    var builder = WebApplication.CreateBuilder(args);
    builder.Host.UseSerilog();
    
    Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                .Enrich.FromLogContext()
                .WriteTo.Console()
                .CreateLogger();
    try
    {
        Log.Information("Starting web host");
        app.Run(); // 把 app.Run(); 放进来
        return 0;
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "Host terminated unexpectedly");
        return 1;
    }
    finally
    {
        Log.CloseAndFlush();
    }

    Serilog 的 config 不是通过 appsetting 设置的, 如果想用 appsetting 来管理可以另外安装一个 DLL, 下面会介绍. 

    appsetting 里的 log config 是给 ASP.NET Core build-in log 的哦, Serilog 不会读取它来用.

    Request Log

    Serilog 有一个 build-in 的 request log 取代 ASP.NET Core build-in 的, 因为 ASP.NET Core log 太多了.

    先关掉 ASP.NET Core 的

    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
        .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)

    然后

    app.UseSerilogRequestLogging(options =>
    {
        options.MessageTemplate = "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0} ms";
        options.GetLevel = (httpContext, elapsed, ex) => LogEventLevel.Information;
        options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
        {
         // 这里可以加一点料, 加了 template 就可以用 {RequestHost} 这样
            // diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
            // diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
        };
    });

    通过这个 middleware 每个请求都会被记入下来. middleware 放在 static file middleware 下面, 不然 static file 也会被 log 就不好了.

    想更 customize 一下可以参考这个 Adding Useful Information to ASP.NET Core Web API Serilog Logs

    Write to File

    安装

    dotnet add package Serilog.Sinks.File

    设置

    Log.Logger = new LoggerConfiguration()
        .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)

    write to file 是马上执行的, 这对 IO 性能不太好.

    Async Write to File

    所以 Serilog 推出了一个 async 版本. 它会先写入 ram, 等一定量之后才写入 file.

    dotnet add package Serilog.Sinks.Async

    设置

    Log.Logger = new LoggerConfiguration()
     .WriteTo.Async(a => a.File("log.txt", rollingInterval: RollingInterval.Day, buffered: true), bufferSize: 500)

    wrap 起来就可以了, buffered = true, buffer size 默认是 10,000 items 那是多少我也不清楚.

    然后在 app 结束前一定要释放哦

    try
    {
        CreateHostBuilder(args).Build().Run();
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "Host terminated unexpectedly");
    }
    finally
    {
        Log.CloseAndFlush(); // 重要
    }

    Use appsetting.json as Config

    安装

    dotnet add package Serilog.Settings.Configuration

    设置

    Log.Logger = new LoggerConfiguration()
        .ReadFrom.Configuration(builder.Configuration) 

    appsetting.json

     "Serilog": {
        "Using": [ "Serilog.Sinks.File" ], // 这个在 dotnet core project 下是多余的,可以拿掉哦
        "MinimumLevel": {
          "Default": "Information",
          "Override": {
            "Microsoft": "Warning",
            "Microsoft.AspNetCore": "Warning",
            "System": "Warning"
          }
        },
        "WriteTo": [
          {
            "Name": "File",
            "Args": {
              "path": "log.txt",
              "rollingInterval": "Day",
              "outputTemplate": "[{Timestamp:hh:mm:ss tt} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}"
            }
          },
          {
            "Name": "Async",
            "Args": {
              "configure": [
                {
                  "Name": "File",
                  "Args": {
                    "path": "log-async.txt",
                    "rollingInterval": "Day",
                    "outputTemplate": "[{Timestamp:hh:mm:ss tt} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}",
                    "buffered": true
                  }
                }
              ]
            }
          }
        ],
        "Enrich": [ "FromLogContext" ]
      }
  • 相关阅读:
    Codeforces Round #603 (Div. 2)
    【bzoj1997】[Hnoi2010]Planar(平面图+2-sat)
    【poj3207】Ikki's Story IV
    【HDU1814】Peaceful Commission(2-sat+暴力染色)
    Educational Codeforces Round 77 (Rated for Div. 2)
    【hdu3311】Dig The Wells(斯坦纳树+dp)
    [USACO3.3] A Game
    [TJOI2013] 单词
    [USACO3.3] Home on the Range
    [NOI2011] 阿狸的打字机
  • 原文地址:https://www.cnblogs.com/keatkeat/p/16034231.html
Copyright © 2020-2023  润新知