将 NLog 移动到它自己的记录器服务项目并保持当前的记录器语法



我有一个.Net 6 Web API项目,按照开始使用ASP.Net Core 6中的步骤配置了NLog。我想将NLog引用移到它自己的类库中。我在关注一篇关于ASP.NET核心Web API的文章——使用NLog进行日志记录。问题是,这种方法需要我从更改所有控制器

private readonly ILogger<MyController> _logger;
public MyController(ILogger<MyController> logger) {...}

private readonly ILoggerManager _logger;
public MyController(ILoggerManager logger) {...}

有没有一种方法可以在它自己的类库中获得NLog,同时保留API内置的当前语法?

这是我当前的program.cs文件:

using NLog;
var logger = LogManager
.LoadConfiguration(string.Concat(Directory.GetCurrentDirectory(), "/Configs/NLog/nlog.config"))
.Setup()
.SetupExtensions(x => x.RegisterLayoutRenderer<BuildConfigLayoutRenderer>("BuildConfiguration"))
.GetCurrentClassLogger();
logger.Debug("init main");
try {
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// NLog: Setup NLog for Dependency injection
/********************************************
the 2 lines below are:
1) the default taken from NLog docs and
2) the code from the article I was following (currently disabled)
********************************************/
builder.Host.UseNLog(); // 1
//builder.ConfigureLoggerService(); // 2
/********************************************/
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.MapControllers();
app.Run();
} catch (Exception exception) {
logger.Error(exception, "Stopped program because of exception");
throw;
} finally {
LogManager.Shutdown();
}

在Microsoft的文章《在.NET中实现自定义日志记录提供程序》之后,我提出了以下实现。

创建了新项目创建了4个文件,完全如文章中所列

LoggerServiceConfiguration.cs

public class LoggerServiceConfiguration {
public int EventId { get; set; }
public Dictionary<LogLevel, ConsoleColor> LogLevels { get; set; } = new() {
[LogLevel.Information] = ConsoleColor.Green,
[LogLevel.Critical] = ConsoleColor.DarkRed
};
}

LoggerServiceProvider.cs

[UnsupportedOSPlatform("browser")]
[ProviderAlias("LoggerService")]
public sealed class LoggerServiceProvider : ILoggerProvider {
private readonly IDisposable _onChangeToken;
private LoggerServiceConfiguration _currentConfig;
private readonly ConcurrentDictionary<string, LoggerService> _loggers =
new(StringComparer.OrdinalIgnoreCase);
public LoggerServiceProvider(IOptionsMonitor<LoggerServiceConfiguration> config) {
_currentConfig = config.CurrentValue;
_onChangeToken = config.OnChange(updatedConfig => _currentConfig = updatedConfig);
}
public ILogger CreateLogger(string categoryName) => _loggers.GetOrAdd(categoryName, name => new LoggerService(name, GetCurrentConfig));
private LoggerServiceConfiguration GetCurrentConfig() => _currentConfig;
public void Dispose() {
_loggers.Clear();
_onChangeToken.Dispose();
}
}

LoggerService.cs

我确实修改了这里的Log方法

public sealed class LoggerService : Microsoft.Extensions.Logging.ILogger {
private readonly string _name;
private readonly Func<LoggerServiceConfiguration> _getCurrentConfig;
private static NLog.ILogger _logger = LogManager.GetCurrentClassLogger();
public LoggerService(string name, Func<LoggerServiceConfiguration> getCurrentConfig) => (_name, _getCurrentConfig) = (name, getCurrentConfig);
public IDisposable BeginScope<TState>(TState state) => default!;
public bool IsEnabled(Microsoft.Extensions.Logging.LogLevel logLevel) => _getCurrentConfig().LogLevels.ContainsKey(logLevel);
public void Log<TState>(Microsoft.Extensions.Logging.LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) {
switch (logLevel) {
case Microsoft.Extensions.Logging.LogLevel.Trace:
_logger.Trace($"{formatter(state, exception)}");
break;
case Microsoft.Extensions.Logging.LogLevel.Debug:
_logger.Debug($"{formatter(state, exception)}");
break;
case Microsoft.Extensions.Logging.LogLevel.Information:
_logger.Info($"{formatter(state, exception)}");
break;
case Microsoft.Extensions.Logging.LogLevel.Warning:
_logger.Warn($"{formatter(state, exception)}");
break;
case Microsoft.Extensions.Logging.LogLevel.Error:
_logger.Error($"{formatter(state, exception)}");
break;
case Microsoft.Extensions.Logging.LogLevel.Critical:
_logger.Fatal($"{formatter(state, exception)}");
break;
case Microsoft.Extensions.Logging.LogLevel.None:
_logger.Trace($"{formatter(state, exception)}");
break;
default:
throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null);
}
}
}

程序.cs

using NLog;
var logger = LogManager
.LoadConfiguration(string.Concat(Directory.GetCurrentDirectory(), "/Configs/NLog/nlog.config"))
.Setup()
.SetupExtensions(x => x.RegisterLayoutRenderer<BuildConfigLayoutRenderer>("BuildConfiguration"))
.GetCurrentClassLogger();
logger.Debug("init main");
try {
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// NLog: Setup NLog for Dependency injection
/********************************************/
// Call our custom logger
builder.Logging.AddLoggerService();
/********************************************/
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.MapControllers();
app.Run();
} catch (Exception exception) {
logger.Error(exception, "Stopped program because of exception");
throw;
} finally {
LogManager.Shutdown();
}

我不确定这样做是否正确,但它有效。我不喜欢它,因为我不知道记录调用了哪个控制器和动作的最佳方式,所以我会暂时搁置它,直到我研究更多。

最新更新