Я использую Serilog для ведения журнала в моем веб-API .net 6 и хотел бы предоставить конечную точку, чтобы я мог изменить глобальный уровень ведения журнала. Это позволит мне переключать уровень через передний тумблер. Это то, что я реализовал до сих пор, но, похоже, это не имеет никакого эффекта. Даже просто установка уровня ведения журнала при запуске не отключает уровень по умолчанию от «Информация». Я использую .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 в виде строки, а затем применить к системе Logger. Я не могу расширять это, если это необходимо (уровни ведения журнала для конкретных пакетов и т.д.) Вот мой 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.AspNetCore 6.1.0 Serilog.Sinks.Console 4.1.0
ОБНОВЛЕНИЕ: кажется, что единственный способ, которым я могу успешно заставить levelSwitch даже подключиться к регистратору, - это сделать это через файл конфигурации json. Проблема в том, что я не могу получить ссылку на него, чтобы я мог ввести его как синглтон в контекст DI.





Убедитесь, что вы правильно настроили 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() или любую другую раковину.
Какую версию Serilog вы используете?