如何在自定义ILogger实现中获取Microsoft.Extensions.Logging的CategoryName?
获取Microsoft.Extensions.Logging中的CategoryName
当你使用ILogger<TCategoryName>时,TCategoryName对应的全限定类名就是CategoryName,这个值是在Logger实例创建阶段传递的,而非在Log方法的TState中存储。正确的做法是在自定义Logger的构造函数中接收并保存这个值,具体实现步骤如下:
1. 自定义Logger类,保存CategoryName
在自定义Logger的构造函数中引入CategoryName参数,将其存储为私有字段,后续在Log方法中直接使用:
public class CustomDbLogger : ILogger { private readonly string _categoryName; private readonly IDbConnection _dbConnection; public CustomDbLogger(string categoryName, IDbConnection dbConnection) { _categoryName = categoryName; _dbConnection = dbConnection; } public IDisposable BeginScope<TState>(TState state) => NullScope.Instance; public bool IsEnabled(LogLevel logLevel) => true; // 可根据需求调整启用逻辑 public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) { // 直接使用保存的_categoryName,对应log4net中的Logger名称(类名) string message = formatter(state, exception); // 写入数据库示例 _dbConnection.Execute( "INSERT INTO Logs (Logger, Level, Message, Exception) VALUES (@Logger, @Level, @Message, @Exception)", new { Logger = _categoryName, Level = logLevel.ToString(), Message = message, Exception = exception?.ToString() }); } }
2. 实现LoggerProvider,传递CategoryName
自定义ILoggerProvider,在CreateLogger方法中接收框架传入的categoryName,并以此创建CustomDbLogger实例:
public class CustomDbLoggerProvider : ILoggerProvider { private readonly IDbConnection _dbConnection; public CustomDbLoggerProvider(IDbConnection dbConnection) { _dbConnection = dbConnection; } public ILogger CreateLogger(string categoryName) { // 框架自动传入ILogger<TCategoryName>对应的TCategoryName全限定名作为categoryName return new CustomDbLogger(categoryName, _dbConnection); } public void Dispose() { } }
3. 注册自定义LoggerProvider
在应用启动时(如Program.cs),将自定义Provider注册到日志系统:
var builder = WebApplication.CreateBuilder(args); // 注册数据库连接(根据实际情况调整) builder.Services.AddScoped<IDbConnection>(sp => new SqlConnection(builder.Configuration.GetConnectionString("LogDb"))); // 添加自定义日志Provider builder.Logging.AddProvider( new CustomDbLoggerProvider(builder.Services.BuildServiceProvider().GetRequiredService<IDbConnection>())); var app = builder.Build(); // 后续启动逻辑...
关键说明
ILogger<TCategoryName>本质是框架通过CreateLogger(typeof(TCategoryName).FullName)创建的实例,因此categoryName会自动传入Provider的CreateLogger方法。TState仅存储日志消息的格式化参数(如LogInformation("User {Id} logged in", userId)中的Id和userId),不会包含CategoryName——因为CategoryName是Logger实例的固有属性,与单条日志消息无关。
内容的提问来源于stack exchange,提问作者ksja
相关产品推荐
相关产品推荐

