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

Serilog.Sinks.Map与标准ReadFrom.Configuration日志输出不一致问题

问题分析与解决方案

核心原因

直接用博客的Map代码替换loggerConfig.ReadFrom.Configuration后,相当于完全抛弃了原配置中Serilog的全局级别设置、命名空间过滤规则等关键配置,同时热重载逻辑可能未正确绑定配置变更后的Logger重建逻辑,导致三个问题同时出现。


1. 启动时多输出Microsoft.AspNetCore.*日志

原来的ReadFrom.Configuration会读取appsettings.json中Serilog节点的MinimumLevel配置(默认可能是Warning或更高),替换成纯Map代码后,Serilog会使用默认的Information级别,因此会输出更多框架级别的日志。

修复:在Map逻辑中复用原配置的基础设置
不要从零构建LoggerConfiguration,先读取原配置到基础配置对象,再在其之上添加Map逻辑:

// 先加载完整的Serilog配置(包括级别、过滤器、基础sink)
var baseLoggerConfig = new LoggerConfiguration()
    .ReadFrom.Configuration(context.Configuration);

// 再叠加博客中的Map热重载逻辑
Log.Logger = baseLoggerConfig
    .WriteTo.Map(
        // 这里填博客中的Map键,比如按环境或其他属性路由
        keyPropertyName: "Environment",
        defaultKey: "Production",
        configure: (writeTo, key) =>
        {
            // 博客中定义的sink配置逻辑,比如按key区分输出目标
            writeTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}");
            // 如果有文件sink等其他配置,也在这里添加
        })
    .CreateLogger();

2. "Nexgen.Middleware.NexgenMiddleware": "Warning"配置不生效

原配置中的MinimumLevel.Override规则是通过ReadFrom.Configuration加载的,替换成纯Map代码后这些规则丢失,导致该命名空间的日志级别未被正确限制。

验证与修复:

  • 确保appsettings.json中Serilog节点结构正确:
    "Serilog": {
      "MinimumLevel": {
        "Default": "Information",
        "Override": {
          "Microsoft.AspNetCore": "Warning",
          "Nexgen.Middleware.NexgenMiddleware": "Warning"
        }
      },
      // 其他sink配置...
    }
    
  • 复用上述的baseLoggerConfig即可自动加载这些Override规则,无需手动添加。

3. 修改配置后热重载不生效

博客中的热重载逻辑需要监听配置文件变更,并在变更时重新构建Logger并替换全局实例,你可能遗漏了配置变更的回调绑定,或者重建Logger时未读取最新配置。

修复:添加配置变更监听与Logger重建逻辑
在Program.cs中添加配置变更的回调:

var configuration = context.Configuration;

// 注册配置变更回调
void ReloadLogger()
{
    // 重新读取最新配置构建Logger
    var newLogger = new LoggerConfiguration()
        .ReadFrom.Configuration(configuration)
        .WriteTo.Map(
            keyPropertyName: "Environment",
            defaultKey: "Production",
            configure: (writeTo, key) =>
            {
                writeTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}");
            })
        .CreateLogger();

    // 替换全局Logger并刷新旧实例
    Log.CloseAndFlush();
    Log.Logger = newLogger;

    // 重新注册回调,监听下一次变更
    configuration.GetReloadToken().RegisterChangeCallback(_ => ReloadLogger(), null);
}

// 首次注册回调
configuration.GetReloadToken().RegisterChangeCallback(_ => ReloadLogger(), null);

关键注意点

  • 不要完全抛弃ReadFrom.Configuration,而是将其作为基础配置,再叠加热重载的Map逻辑,这样才能继承所有原配置的规则。
  • 确保配置文件的Serilog节点结构正确,Override规则没有拼写错误(比如命名空间大小写、日志级别字符串是否正确)。
  • 热重载时必须调用Log.CloseAndFlush()关闭旧Logger,再替换为新实例,否则旧的sink可能继续输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 10:42:36