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

.NET Core 3.1控制台应用使用Serilog.Sinks.Async丢失日志问题

.NET Core 3.1控制台应用中Serilog Async接收器丢失日志的问题

我在.NET Core 3.1控制台应用里按顺序读取大型文本文件的记录,借助Serilog.Sinks.Console、Serilog.Sinks.File、Serilog.Sinks.Async三个接收器记录记录编号等信息,但检查日志文件时发现部分日志(如记录编号)丢失。当移除Async接收器仅使用File接收器时,日志可按顺序完整生成,无丢失情况。


使用Async接收器的Serilog配置

"Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Async" ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "Async",
        "Args": {
          "configure": [
            {
              "Name": "Console",
              "Args": {
                "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u4}] {Message:lj} [{SourceContext}] {Exception}{NewLine}"
              }
            },
            {
              "Name": "File",
              "Args": {
                "path": "C:\\FeedReader\\Logs\\AppLog-.log",
                "rollOnFileSizeLimit": true,
                "rollingInterval": "Hour",
                "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u4}] {Message:lj} [{SourceContext}] {Exception}{NewLine}",
                "fileSizeLimitBytes": 1048576, // 10 MB
                "retainedFileCountLimit": 999,
                "shared": false, // 关闭文件共享提升性能
                "buffered": true, // 使用缓冲写入提升性能
                "flushToDiskInterval": "00:00:05" // 每5秒刷新到磁盘
              }
            }
          ]
        }
      }
    ]
}

Program.cs初始化代码

var baseDir = AppDomain.CurrentDomain.BaseDirectory;

var builder = new ConfigurationBuilder()
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

if (string.IsNullOrEmpty(environmentName) == false)
{
    builder.AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true);
}

builder.AddEnvironmentVariables();

Configuration = builder.Build();

Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(Configuration)
                .CreateLogger();

Log.Information("===================================Application is starting=================================");

仅使用File接收器的Serilog配置

"Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "C:\\FeedReader\\Logs\\AppLog.log",
          "fileSizeLimitBytes": 1048576,
          "rollingInterval": "Hour",
          "rollOnFileSizeLimit": true,
          "retainedFileCountLimit": 999,
          "flushToDiskInterval": "00:00:05",
          "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u4}] {Message:lj} [{SourceContext}] {Exception}{NewLine}"
        }
      },
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u4}] {Message:lj} [{SourceContext}] {Exception}{NewLine}"
        }
      }
    ]
}

问题原因及解决办法

  1. Async队列溢出丢弃日志
    Serilog.Sinks.Async默认使用容量为10000的有界队列,当日志生成速度超过异步处理速度时,超出队列容量的日志会被直接丢弃。可以通过以下配置调整:

    • 增大queueLimit参数提升队列容量
    • 设置blockWhenFull: true,让写入线程在队列满时等待,而非丢弃日志
  2. 应用退出未处理剩余日志
    控制台应用退出时,Async队列中未处理的日志会丢失,必须在应用结束前调用Log.CloseAndFlush()确保所有日志都被写入磁盘。

  3. 双重缓冲导致的冲突
    Async本身已做异步缓冲,再给File接收器设置buffered: true会导致双重缓冲,增加丢失风险,建议关闭File接收器的缓冲。


修改后的Async接收器配置示例

"Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Async" ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "Async",
        "Args": {
          "queueLimit": 50000, // 增大队列容量
          "blockWhenFull": true, // 队列满时阻塞等待
          "configure": [
            {
              "Name": "Console",
              "Args": {
                "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u4}] {Message:lj} [{SourceContext}] {Exception}{NewLine}"
              }
            },
            {
              "Name": "File",
              "Args": {
                "path": "C:\\FeedReader\\Logs\\AppLog-.log",
                "rollOnFileSizeLimit": true,
                "rollingInterval": "Hour",
                "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u4}] {Message:lj} [{SourceContext}] {Exception}{NewLine}",
                "fileSizeLimitBytes": 1048576,
                "retainedFileCountLimit": 999,
                "shared": false,
                "buffered": false, // 关闭File接收器的缓冲
                "flushToDiskInterval": "00:00:05"
              }
            }
          ]
        }
      }
    ]
}

补充:确保应用退出时处理日志

在Program.cs的业务逻辑结束后,添加日志关闭操作:

try
{
    // 你的业务逻辑代码(读取文本文件、记录日志等)
}
finally
{
    Log.CloseAndFlush(); // 确保所有异步日志都被写入磁盘
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 16:31:12