Я новичок в управлении версиями моего API. Я использую ASP.NET 6.0 и Serilog для записи в файл журнала.
Теперь, когда я реализовал управление версиями, я хочу, чтобы версия 1.0 приложения записывалась в «Logs/V1.0/logfile.json», а версия 2.0 записывалась в «Logs/v2.0/logfile.json».
Я могу без проблем получить номер версии «1.0» или «2.0» внутри своих контроллеров.
[ApiController]
[Route("/v{version:apiVersion}/[controller]")]
[ApiVersion("2.0")]
public class MainController : Controller
[HttpGet]
public void MyMethod(ApiVersion version)
{
_logger.LogInformation("APIVersion: {ApiVersion}", version);
}
}
Я вижу, что Serilog сохранит эту переменную «ApiVersion» в свойствах журнала.
"Properties":{
"ApiVersion":"2.0",
"RequestPath":"/v2.0/Main/MyMethod",
...
Итак, как мне собрать все это вместе, чтобы Serilog сохранял журналы в разных местах файлов?
Я думаю, что это может иметь какое-то отношение к «Log.Logger = new LoggerConfiguration ()» в Program.cs? Я читал о различных вариантах, таких как .WriteTo.Map или Write.To.Conditional?
Все, кажется, связано с записью журналов разных уровней (информационных, предупреждений, предупреждений) в разные места. Я также понятия не имею, какой будет лучшая практика для этой настройки.
Любая помощь приветствуется!





Вы можете использовать Serilog.Sinks.Map.
Ниже приведена рабочая демонстрация, вы можете обратиться к ней.
Установите Serilog.AspNetCore , Serilog.Sinks.Map и Microsoft.AspNetCore.Mvc.Versioning NuGet Package.
Добавьте Serilog в файл appsetting.json:
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Error",
"System": "Debug"
}
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ]
}
В Program.cs:
var logger = new LoggerConfiguration().WriteTo.Map(
"ApiVersion",
"(None)",
(ApiV, wt) =>
wt.File($"Your Path\\Logs\\{ApiV}\\logfile.json")
)
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(logger);
builder.Services.AddApiVersioning();
//...
Контроллер:
[Route("/v{version:apiVersion}/[controller]")]
[ApiVersion("2.0")]
[ApiController]
public class MainController : ControllerBase
{
private readonly ILogger<MainController> _logger;
public MainController(ILogger<MainController> logger)
{
_logger = logger;
}
[HttpGet]
public void MyMethod(ApiVersion version)
{
_logger.LogInformation("APIVersion: {ApiVersion}", "V"+version);
}
}
Результат испытаний:
Обновлять:
Пожалуйста, подтвердите, заканчивается ли ваш basePath на \\, если нет, то вам нужно вручную добавить символ \\:
var basePath = "C:\\...Path\\ProjectName";
var logger = new LoggerConfiguration().WriteTo.Map(
"ApiVersion",
"(None)",
(ApiV, wt) =>
wt.File($"{basePath}\\Logs\\{ApiV}\\logfile.json")
)
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.CreateLogger();
Завтра поеду еще :)
Привет @Scottish Smile, я обновил ответ на основе кода, который вы прокомментировали. Пожалуйста, проверь это.
Спасибо, это работает! У меня было две проблемы: 1) некоторый дополнительный код serilog из моего старого внедрения в другом месте в program.cs, который мне пришлось удалить 2) Правильное написание пути к файлу. Ты спас меня, Чен, я с ума сходил! Еще раз спасибо :)
Я сделал это так (я не добавлял .Map, как указано выше)
var version = GetVersion();
//Logger configuration
.WriteTo.Logger(lc => lc
.MinimumLevel.Verbose()
.WriteTo.File(
path: Path.Combine(AppContext.BaseDirectory, "Logs", version, "Log.log"),
//...rest
Спасибо, Джаз, но мне нужны два отдельных пути (с двумя отдельными файлами) по одному для каждой из разных версий API. Ваш код будет регистрировать все версии в один и тот же файл?
Я не понимаю, почему. Вы можете получить версию в методе GetVersion(). Вы можете сделать это через контроллер или значение атрибута. Почему вы имеете в виду, что это будет одно и то же значение?
Ах, извините, я не заметил переменную версии.
Как будет работать GetVersion()? Я понятия не имею, как на самом деле получить номер версии внутри Program.cs
Большое спасибо за подробный ответ. Я просто не могу заставить его работать, хотя, ха-ха-ха, я думаю, что это может быть связано с используемым путем к файлу. var basePath = AppContext.BaseDirectory; а затем wt.File($"{basePath}Logs\\{ApiV}\\logfile.json")