通过 api 端点的 Serilog 级别切换器

问题描述 投票:0回答:3

我正在使用 Serilog 登录我的 .net 6 Web api,并希望公开一个端点以使我能够更改全局日志记录级别。这将使我能够通过前端切换开关切换级别。这是我到目前为止所实施的,但似乎根本没有任何效果。即使只是在启动时设置日志记录级别也不会改变“信息”的默认级别。我正在使用 .net DI 来配置一切。

这是我到目前为止所拥有的:

程序.cs

var levelSwitcher = new LoggingLevelSwitch(LogEventLevel.Verbose);

builder.Services.AddSingleton<LoggingLevelSwitch>(levelSwitcher);

var seriLogger = new LoggerConfiguration()
            .MinimumLevel.ControlledBy(levelSwitcher)
            .ReadFrom.Configuration(builder.Configuration)
            .Enrich.FromLogContext()
            .CreateLogger();

然后在我的端点控制器中

    private readonly LoggingLevelSwitch _levelSwitch;
    private readonly ILogger<DiagnosticsController> _logger;

    public DiagnosticsController(ILogger<DiagnosticsController> logger, LoggingLevelSwitch levelSwitch)
    {
        _logger = logger;
        _levelSwitch = levelSwitch;
    }

    [HttpGet(Name = "SwitchLoggingLevel")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public IActionResult SwitchLoggingLevel(string level)
    {
        if (Enum.TryParse(level, out Serilog.Events.LogEventLevel newLoggingLevel))
        {
            _levelSwitch.MinimumLevel = newLoggingLevel;
            return Ok();
        }

        return BadRequest();
    }

从我在调试器中看到的是,记录器仍然处于“信息”最低级别,即使调用端点并传入或多或少的详细级别,也没有任何效果。

我最初的想法是,我在 DI 环境中初始化切换器的方式不正确,但我不确定如何正确执行(即创建一个服务,然后立即在记录器的后续配置中使用它)。但即使这是不正确的,实际的最低级别甚至没有按照配置设置为“错误”。

c# api .net-6.0 serilog
3个回答
2
投票

(代表问题作者发布,将其移至答案空间)。

虽然@Roman Marusyk 没有完全解决问题,但他提供了足够的信息来帮助我跨越界限。这就是我在 DI 配置中最终得到的结果:

public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        var levelSwitcher = new LoggingLevelSwitch(LogEventLevel.Warning);

        builder.Host.UseSerilog((ctx, lc) => lc
            .MinimumLevel.ControlledBy(levelSwitcher)
            .ReadFrom.Configuration(ctx.Configuration));

        // Add services to the container.
        builder.Services.TryAddSingleton(levelSwitcher);

        builder.Services.AddControllers();
        // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
        builder.Services.AddEndpointsApiExplorer();
        builder.Services.AddSwaggerGen();

        var app = builder.Build();


        // Configure the HTTP request pipeline.
        if (app.Environment.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI();
        }

        app.UseHttpsRedirection();

        app.UseAuthorization();

        app.UseSerilogRequestLogging();

        app.MapControllers();

        app.Run();
    }

这还没有准备好投入生产,但现在可以按预期工作。我有一个 API 端点,我可以将 LogEventLevel 作为字符串传递,然后将其应用于记录器系统。这是我的 appSettings.json 只是为了完整性:

{
"Logging": {
"LogLevel": {
  "Default": "Information",
  "Microsoft": "Warning",
  "Microsoft.Hosting.Lifetime": "Information"
}
  },
  "AllowedHosts": "*",
  "Serilog": {
"using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"Override": {
  "Microsoft.AspNetCore": "Warning"
},
"WriteTo": [
  {
    "name": "Console"
  },
  {
    "Name": "File",
    "Args": {
      "buffered": false,
      "path": "./logs/data-logs.txt",
      "rollingInterval": "Day",
      "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
    }
  }
],
"Enrich": [
  "WithMachineName",
  "FromLogContext",
  "WithThreadId",
  "WithProcessId",
  "WithClientAgent",
  "WithClientIp"
]
}
}

最后是我的控制器进行切换

public class DiagnosticsController : ControllerBase
{
    private readonly LoggingLevelSwitch _levelSwitch;
    private readonly ILogger<DiagnosticsController> _logger;

    public DiagnosticsController(ILogger<DiagnosticsController> logger, LoggingLevelSwitch levelSwitch)
    {
        _logger = logger;
        _levelSwitch = levelSwitch;
    }

    [HttpGet(Name = "SwitchLoggingLevel")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public IActionResult SwitchLoggingLevel(string level)
    {
        if (Enum.TryParse(level, out Serilog.Events.LogEventLevel newLoggingLevel))
        {
            _levelSwitch.MinimumLevel = newLoggingLevel;
            return Ok();
        }

        return BadRequest();
    }

    [HttpGet(Name = "GetCurrentLoggingLevel")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public IActionResult CurrentLoggingLevel()
    {
        return Ok(_levelSwitch.MinimumLevel.ToString());
    }
}

1
投票

检查您是否已正确配置 Serilog,因为代码按预期工作。

将变量

seriLogger
分配给
Log.Logger

Log.Logger = new LoggerConfiguration()
   .MinimumLevel.ControlledBy(levelSwitcher)
   .ReadFrom.Configuration(builder.Configuration)
   .Enrich.FromLogContext()
   .WriteTo.Console()
   .CreateLogger();

builder.Host.UseSerilog();

请注意,您需要添加

WriteTo.Console()
或任何其他水槽。


0
投票

值得注意的是(经过多次挫折),即使您按照接受的答案以编程方式更改应用程序中的级别,我也必须从 appsettings.json 文件中删除 MaximumLevel 设置,否则在调试时并命中断点,即使记录器显示其最低级别为详细,也不会生成任何输出。

即我必须删除以下内容,然后在运行时更改日志级别才能起作用:

Show lines to remove from

"Serilog": {
// had to remove next section!!
  "MinimumLevel": {
    "Default": "Information",
    "Override": {
     "Microsoft": "Warning",
      "System": "Warning"
   }
 },
© www.soinside.com 2019 - 2024. All rights reserved.