我正在使用 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 环境中初始化切换器的方式不正确,但我不确定如何正确执行(即创建一个服务,然后立即在记录器的后续配置中使用它)。但即使这是不正确的,实际的最低级别甚至没有按照配置设置为“错误”。
(代表问题作者发布,将其移至答案空间)。
虽然@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());
}
}
检查您是否已正确配置 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()
或任何其他水槽。
值得注意的是(经过多次挫折),即使您按照接受的答案以编程方式更改应用程序中的级别,我也必须从 appsettings.json 文件中删除 MaximumLevel 设置,否则在调试时并命中断点,即使记录器显示其最低级别为详细,也不会生成任何输出。
即我必须删除以下内容,然后在运行时更改日志级别才能起作用:
"Serilog": {
// had to remove next section!!
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},