You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 15:14:52