C# Serilog文件日志配置 C#如何将结构化日志输出到滚动文件

来源:这里教程网 时间:2026-02-21 17:42:11 作者:

为什么 Serilog 的
WriteTo.File
默认不输出结构化日志?

Serilog 默认用

WriteTo.File
写入的是纯文本(
RenderedCompactJsonFormatter
以外的格式),JSON 字段被展平成字符串,丢失结构。想保留
Log.Information("User {@User} logged in", user)
中的
@User
对象结构,必须显式指定 JSON 序列化器和格式器。

不配置格式器 → 日志是可读字符串,但无法被 ELK、Seq 等工具解析字段
JsonFormatter()
→ 输出标准 JSON 行,每行一个日志事件,支持结构化消费
注意:.NET 6+ 默认使用
System.Text.Json
,若对象含
DateTimeOffset
、循环引用或自定义 converter,需传入
JsonSerializerOptions

如何配置滚动文件(按大小/日期轮转)?

Serilog 本身不内置滚动逻辑,依赖

Serilog.Sinks.File
扩展包的
rollingInterval
rollOnFileSizeLimit
参数。滚动行为由文件名模板和策略共同决定,不是“自动清理旧文件”——旧文件仍保留在磁盘上,除非手动加
retainedFileCountLimit

path: "logs/app-.log"
→ 滚动后生成
app-20240501.log
app-20240502.log
(按天)
rollingInterval: RollingInterval.Day
RollingInterval.Hour
RollingInterval.Infinite
rollOnFileSizeLimit: true
+
fileSizeLimitBytes: 10_485_760
(10MB)→ 触发按大小切分
retainedFileCountLimit: 7
→ 只保留最近 7 个滚动文件(需 NuGet v5.0+)

完整可运行的结构化滚动文件配置示例

以下代码在

Program.cs
(.NET 6+)中直接生效,输出带时间戳、级别、消息、属性(含嵌套对象)、异常堆栈的 JSON 行:

using Serilog;
using Serilog.Events;
using Serilog.Formatting.Json;
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .WriteTo.File(
        new JsonFormatter(renderMessage: true),
        path: "logs/app-.log",
        rollingInterval: RollingInterval.Day,
        rollOnFileSizeLimit: true,
        fileSizeLimitBytes: 10_485_760,
        retainedFileCountLimit: 7,
        shared: true, // 多进程写入时必需
        flushToDiskInterval: TimeSpan.FromSeconds(1))
    .CreateLogger();

关键点:

shared: true
必须开启,否则多线程/多实例写同一目录会抛
IOException
flushToDiskInterval
控制刷盘频率,避免日志延迟过高。

常见错误和绕过坑

结构化日志落地失败,90% 出现在这几个地方:

忘了安装
Serilog.Sinks.File
NuGet 包(仅装
Serilog
基础包不行)
路径含中文或空格且未用双引号包裹(Windows 下可能报
DirectoryNotFoundException
没设
shared: true
,IIS 或 Windows Service 多工作进程时写日志失败
Console.WriteLine
风格写日志(如
Log.Information("User " + user.Name + " logged in")
),
@
符号被忽略,结构丢失
滚动后查不到最新日志 → 检查实际生成的文件名(
app-20240501.log
而非
app.log

滚动文件的“结构化”本质是每行一个合法 JSON 对象,不是把整个日志塞进一个大 JSON 文件里——这点容易误解。

相关推荐