跳转到主内容
极星编程网:以代码为星,赴技术山海!

C#实现日志文件滚动 C#如何按日期或大小分割日志文件

NLog按日期滚动最直接,需设archiveEvery="Day"且enableArchiveFileCompression="false";Serilog按大小滚动更可控,须设rollOnFileSizeLimit=true和fileSizeLimitBytes;手动实现需避免FileStream锁与时钟误差。 用
NLog
配置按日期滚动最直接 绝大多数 C# 项目不需要手写滚动逻辑,
NLog
内置的
FileTarget
支持开箱即用的日期滚动。关键不是“能不能”,而是“怎么配不踩坑”。 常见错误是只设
archiveEvery="Day"
却没关掉
enableArchiveFileCompression="false"
(默认为
true
),结果每天生成一堆
.zip
文件而非纯文本,排查日志时反而更麻烦。 推荐配置片段:
archiveNumbering="Rolling"
:旧文件编号递增(
app.1.log
,
app.2.log
…),比
Date
模式更易脚本清理
maxArchiveFiles="30"
:硬性限制归档数,否则磁盘可能被撑爆——这是生产环境最容易被忽略的点 路径中避免使用
${date:format=yyyy-MM-dd}
做
fileName
,会导致日志写入失败(NLog 不支持在主文件名里动态插日期) 用
Serilog
+
File sink
按大小切分更可靠 按大小滚动比按日期更可控,尤其适合高吞吐服务。Serilog 的
Serilog.Sinks.File
默认就支持,但默认行为容易误导人。 它不叫“按大小滚动”,而叫“按文件大小限制 + 自动重命名”。关键参数是
rollingInterval
和
retainedFileCountLimit
,但真正触发切割的是
fileSizeLimitBytes
。 示例代码:
Log.Logger = new LoggerConfiguration() .WriteTo.File("logs/app.log", fileSizeLimitBytes: 10_485_760, // 10MB rollOnFileSizeLimit: true, retainedFileCountLimit: 7, rollingInterval: RollingInterval.Day) // 这个值其实不影响大小滚动,仅用于命名后缀 .CreateLogger();
rollOnFileSizeLimit: true
必须显式开启,否则即使设了
fileSizeLimitBytes
也无效
retainedFileCountLimit: 7
是保留的**总文件数**(当前 + 归档),不是“最多存 7 天”——这点文档写得模糊,实际测试会发现第 8 个归档产生时,最老的就被删了 归档文件名形如
app.log.20240520.txt
或
app.log.1.txt
,取决于
rollingInterval
设置;若只想按大小切、不掺日期,设成
RollingInterval.Infinite
即可 手动实现滚动要绕开
FileStream
锁和时间判断误差 真要自己写(比如嵌入式场景或规避第三方依赖),核心难点不在逻辑,而在两个地方:
FileStream
的独占锁导致无法安全重命名正在写的文件;以及服务器时钟跳变让“是否跨天”判断出错。 解决方案不是修判断,而是换思路: C知道 CSDN推出的一款AI技术问答工具 下载 用
File.Move()
前先
stream.Dispose()
,别试图在流开着时移动文件 不依赖
DateTime.Now.Date
判断是否换日,改用“记录上一次滚动时间戳 + 24 小时检查”,避免 NTP 校时或夏令时导致误切 大小判断别用
FileInfo.Length
(可能因缓存不准),而是在每次
WriteLine
后累加已写字节数,更实时 一句话:手动滚动不是“写个计时器+判断大小”,而是“管好文件句柄生命周期 + 用增量计数替代查询”。
log4net
的
RollingFileAppender
容易卡在
StaticLogFileName
老项目还在用
log4net
的话,
RollingFileAppender
的
StaticLogFileName="false"
是开关,但默认是
true
——这意味着即使你配了
datePattern
,它也只写一个文件,不滚动。 典型错误配置:
缺了
,上面配置完全无效。加上之后还要注意:
datePattern
中的
.
会被当字面量,所以
.yyyy-MM-dd
生成的是
app.log.2024-05-20
,而不是
app.2024-05-20.log
。 真正想按日期生成
app.YYYY-MM-DD.log
,得把
设为空,靠
datePattern
构建完整文件名,且必须配合
staticLogFileName="false"
。 滚动逻辑本身不复杂,难的是边界:文件锁、时钟漂移、归档清理策略、压缩与可读性的权衡。选库时别只看“支持滚动”,要看它默认行为是否贴合你的运维习惯。

相关文章