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

.NET Core 7.0中Serilog多全局日志器的注册实现方案咨询

解决方案:Serilog 多场景日志配置(无需多个全局日志器)

Serilog 本身不支持多个全局 Log.Logger 实例——它是静态单例设计,后续赋值会直接覆盖之前的实例。但你完全不需要为这个问题头疼,通过以下两种简洁方式就能实现你的需求,比子日志器过滤简单得多:

方式一:单全局日志器 + 多Sink带过滤(推荐)

直接在主日志配置中为每个Sink单独设置过滤规则,一个全局日志器就能搞定所有场景,无需拆分多个实例。

配置示例

builder.Host.UseSerilog((context, config) =>
{
    config
        // 读取基础配置(如输出模板、最低级别等)
        .ReadFrom.Configuration(context.Configuration)
        // Slack Sink:仅转发Fatal/Critical级别日志
        .WriteTo.Slack(webhookUrl: "你的Slack Webhook地址")
        .Filter.ByIncludingOnly(evt => 
            evt.Level == LogEventLevel.Fatal || 
            evt.Level == LogEventLevel.Critical)
        
        // 用户操作日志Sink:写入指定数据库表,通过自定义属性过滤
        .WriteTo.MSSqlServer(
            connectionString: "你的数据库连接字符串",
            sinkOptions: new MSSqlServerSinkOptions { TableName = "UserOperationLogs" })
        .Filter.ByIncludingOnly(evt => 
            evt.Properties.TryGetValue("LogType", out var type) && 
            type.ToString() == "\"Operation\"")
        
        // 会话日志Sink:写入另一张表,同样用自定义属性过滤
        .WriteTo.MSSqlServer(
            connectionString: "你的数据库连接字符串",
            sinkOptions: new MSSqlServerSinkOptions { TableName = "SessionLogs" })
        .Filter.ByIncludingOnly(evt => 
            evt.Properties.TryGetValue("LogType", out var type) && 
            type.ToString() == "\"Session\"");
});

写日志时区分场景

在记录不同类型日志时,通过添加自定义属性LogType来触发对应的Sink:

// 用户操作日志
Log.Information("用户{UserId}执行了{Action}操作", 
    userId, action, 
    new { LogType = "Operation" });

// 会话日志
Log.Information("用户{UserId}登录系统", 
    userId, 
    new { LogType = "Session" });

// 错误日志(自动触发Slack通知)
Log.Fatal("系统发生致命错误:{Message}", exception.Message);
Log.Critical("系统发生严重错误:{Message}", exception.Message);

方式二:创建多个日志实例并注册到DI

如果你确实需要独立的日志实例,可以创建多个ILogger实例,然后注册到依赖注入容器中,通过命名服务区分。

配置示例

// 创建操作日志器
var auditLogger = new LoggerConfiguration()
    .WriteTo.MSSqlServer(
        "你的数据库连接字符串",
        new MSSqlServerSinkOptions { TableName = "UserOperationLogs" })
    .CreateLogger();

// 创建会话日志器
var sessionLogger = new LoggerConfiguration()
    .WriteTo.MSSqlServer(
        "你的数据库连接字符串",
        new MSSqlServerSinkOptions { TableName = "SessionLogs" })
    .CreateLogger();

// 创建Slack日志器
var slackLogger = new LoggerConfiguration()
    .WriteTo.Slack("你的Slack Webhook地址")
    .Filter.ByIncludingOnly(evt => 
        evt.Level == LogEventLevel.Fatal || 
        evt.Level == LogEventLevel.Critical)
    .CreateLogger();

// 注册到DI容器(使用命名服务区分)
builder.Services.AddKeyedSingleton<ILogger>("AuditLogger", auditLogger);
builder.Services.AddKeyedSingleton<ILogger>("SessionLogger", sessionLogger);
builder.Services.AddKeyedSingleton<ILogger>("SlackLogger", slackLogger);

使用时注入指定日志器

在需要的地方通过[FromKeyedServices]特性注入对应的日志实例:

public class UserService
{
    private readonly ILogger _auditLogger;

    public UserService([FromKeyedServices("AuditLogger")] ILogger auditLogger)
    {
        _auditLogger = auditLogger;
    }

    public void RecordUserAction(string userId, string action)
    {
        _auditLogger.LogInformation("用户{UserId}执行了{Action}", userId, action);
    }
}

总结

推荐使用方式一,它符合Serilog的单例设计理念,配置和使用都更简洁,不需要额外管理多个日志实例。方式二更适合完全独立、无关联的日志场景,但会增加DI管理的复杂度。

内容的提问来源于stack exchange,提问作者Mauro Alvarez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 20:17:23