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

如何配置Serilog按日志类型输出到不同文件Sink?

ASP.NET Core Serilog按日志类型分Sink输出问题解决

问题场景

在ASP.NET Core项目中使用Serilog,需要实现:

  • 标记为Weather logs的日志输出到logs/weather-.json文件
  • 其余所有日志输出到logs/nin-.json文件

当前两个日志文件内容完全重复,已安装Serilog.AspNetCore和Serilog.Expressions依赖。

现有代码与配置

控制器代码

using Microsoft.AspNetCore.Mvc;
using Serilog;

namespace LoggerTest.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };
        private static readonly string[] nins = new[]
        {
            "1", "2", "3", "4", "6", "7", "8", "9", "10", "11"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
            _logger.LogInformation("WeatherForecast controller called ");
        }

        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            var type = "Weather logs";
            var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)],

            })
            .ToArray();
            _logger.LogInformation("Weather logs: Informantion obtained is {@Result}", result);
            type = "Nin logs";
            var test = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = nins[Random.Shared.Next(Summaries.Length)],

            })
            .ToArray();
            _logger.LogInformation("{@Type}: Informantion obtained is {@Test}", type, test[0]);
            return result;
        }
    }
}

Program.cs代码

using Serilog;

var builder = WebApplication.CreateBuilder(args);

builder.Logging.ClearProviders();

builder.Host.UseSerilog((context, configuration) =>
    configuration.ReadFrom.Configuration(context.Configuration));

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseSerilogRequestLogging();

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

appsettings.json配置

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "logs/weather-.json",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
        },
        "Filter": [
          {
            "Name": "ByIncludingOnly",
            "Args": {
              "expression": "@m like 'Weather logs%'"
            }
          }
        ]
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/nin-.json",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
        }
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
  },
  "AllowedHosts": "*"
}

当前重复日志示例

{"@t":"2024-04-01T20:59:11.4950381Z","@mt":"WeatherForecast controller called ","@tr":"4d934bc9bfd6378d3aa8837a233c28ea","@sp":"0b9630cf3e5ed876","SourceContext":"LoggerTest.Controllers.WeatherForecastController","ActionId":"4282424a-3da7-492f-8959-e11bf53f34aa","ActionName":"LoggerTest.Controllers.WeatherForecastController.Get (LoggerTest)","RequestId":"0HN2IHQ4JSE88:00000009","RequestPath":"/WeatherForecast","ConnectionId":"0HN2IHQ4JSE88"}
{"@t":"2024-04-01T20:59:11.5670441Z","@mt":"{@Type}: Weather logs: Informantion obtained is {@Result}","@tr":"4d934bc9bfd6378d3aa8837a233c28ea","@sp":"0b9630cf3e5ed876","Type":"Weather logs","Result":[{"Date":"2024-04-02","TemperatureC":7,"TemperatureF":44,"Summary":"Hot","Type":null,"$type":"WeatherForecast"},{"Date":"2024-04-03","TemperatureC":8,"TemperatureF":46,"Summary":"Chilly","Type":null,"$type":"WeatherForecast"},{"Date":"2024-04-04","TemperatureC":25,"TemperatureF":76,"Summary":"Mild","Type":null,"$type":"WeatherForecast"},{"Date":"2024-04-05","TemperatureC":-16,"TemperatureF":4,"Summary":"Bracing","Type":null,"$type":"WeatherForecast"},{"Date":"2024-04-06","TemperatureC":37,"TemperatureF":98,"Summary":"Sweltering","Type":null,"$type":"WeatherForecast"}],"SourceContext":"LoggerTest.Controllers.WeatherForecastController","ActionId":"4282424a-3da7-492f-8959-e11bf53f34aa","ActionName":"LoggerTest.Controllers.WeatherForecastController.Get (LoggerTest)","RequestId":"0HN2IHQ4JSE88:00000009","RequestPath":"/WeatherForecast","ConnectionId":"0HN2IHQ4JSE88"}
{"@t":"2024-04-01T20:59:11.5855717Z","@mt":"{@Type}: Informantion obtained is {@Test}","@tr":"4d934bc9bfd6378d3aa8837a233c28ea","@sp":"0b9630cf3e5ed876","Type":"Nin logs","Test":{"Date":"2024-04-02","TemperatureC":9,"TemperatureF":48,"Summary":"11","Type":null,"$type":"WeatherForecast"},"SourceContext":"LoggerTest.Controllers.WeatherForecastController","ActionId":"4282424a-3da7-492f-8959-e11bf53f34aa","ActionName":"LoggerTest.Controllers.WeatherForecastController.Get (LoggerTest)","RequestId":"0HN2IHQ4JSE88:00000009","RequestPath":"/WeatherForecast","ConnectionId":"0HN2IHQ4JSE88"}
{"@t":"2024-04-01T20:59:11.6216513Z","@mt":"HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms","@r":["184.2060"],"@tr":"4d934bc9bfd6378d3aa8837a233c28ea","@sp":"0b9630cf3e5ed876","RequestMethod":"GET","RequestPath":"/WeatherForecast","StatusCode":200,"Elapsed":184.206,"SourceContext":"Serilog.AspNetCore.RequestLoggingMiddleware","RequestId":"0HN2IHQ4JSE88:00000009","ConnectionId":"0HN2IHQ4JSE88"}

问题原因

  1. Nin日志Sink无过滤规则:当前仅Weather日志Sink配置了ByIncludingOnly过滤,但Nin日志Sink未设置任何过滤,导致所有日志都会写入该文件。
  2. 过滤规则不可靠:现有Weather日志过滤依赖@m like 'Weather logs%'匹配消息文本,但部分Weather日志的模板包含动态参数,实际渲染后的消息可能不满足前缀匹配,导致过滤逻辑失效。

解决方案

1. 更新appsettings.json配置

给Nin日志Sink添加ByExcluding过滤,排除Type为Weather logs的日志;同时优化Weather日志的过滤规则,直接匹配日志的Type属性,避免依赖消息文本:

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Expressions" ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "logs/weather-.json",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
        },
        "Filter": [
          {
            "Name": "ByIncludingOnly",
            "Args": {
              "expression": "Type = 'Weather logs'"
            }
          }
        ]
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/nin-.json",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
        },
        "Filter": [
          {
            "Name": "ByExcluding",
            "Args": {
              "expression": "Type = 'Weather logs'"
            }
          }
        ]
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
  },
  "AllowedHosts": "*"
}

2. 统一日志写入方式

确保所有需要分类的日志都明确传递Type属性,让过滤规则能准确匹配:

修改控制器中的日志代码:

// Weather日志写法,明确传递Type参数
_logger.LogInformation("{@Type}: Informantion obtained is {@Result}", "Weather logs", result);

// Nin日志保持原有写法即可
_logger.LogInformation("{@Type}: Informantion obtained is {@Test}", "Nin logs", test[0]);

对于控制器初始化的日志,因为不需要归类到Weather,会自动写入Nin日志文件,无需修改。

3. 验证结果

修改后:

  • logs/weather-.json仅包含Type为Weather logs的日志
  • logs/nin-.json包含所有非Weather logs的日志,包括控制器初始化日志、Nin类型日志、请求日志等

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:04:49