如何用NLog实现按小时/50MB分割且含创建时间戳的日志?
解决NLog按创建时间戳命名+大小/小时轮转日志的问题
需求明确
- 日志路径格式:
根目录/yyMMdd/yyMMddHHmmssSomething.log(示例:...\230525\123021Something.log) - 单个日志文件最大限制为50MB
- 触发新文件创建的条件:文件达到50MB 或 每小时整点,新文件名称需包含自身的创建时间戳
原配置问题分析
- 使用
${cached:CacheKey=${date:format=HH}}会将时间戳缓存1小时,仅在整点时刷新。当因文件大小触发归档时,缓存未到刷新时间,导致新文件仍使用旧时间戳,不符合需求。 - 将
${sequenceid}加入缓存键,会因每个日志事件的sequenceid都不同,导致缓存持续刷新,最终每秒生成新文件,完全偏离预期。
正确配置方案
无需使用${cached}布局,利用NLogFileTarget的原生特性:仅在创建新文件时解析FileName中的时间布局,即可实现需求。
代码配置示例(C#)
var fileTarget = new FileTarget("logFile") { // 日志文件名:根目录/日期文件夹/创建时间戳+后缀.log FileName = Path.Combine(rootfolder, "${date:format=yyMMdd}", "${date:format=yyMMddHHmmss}Something.log"), // 归档文件命名:在原文件名后加序号(可选,可根据旧系统调整) ArchiveFileName = Path.Combine(rootfolder, "${date:format=yyMMdd}", "${date:format=yyMMddHHmmss}Something_{#}.log"), // 单个文件最大50MB ArchiveAboveSize = 50 * 1024 * 1024, // 每小时强制归档 ArchiveEvery = FileArchivePeriod.Hour, // 归档文件按序号递增命名 ArchiveNumbering = ArchiveNumberingMode.Sequence, // 确保多线程安全写入 ConcurrentWrites = true, // 可选:保留最多多少个归档文件,按需设置 MaxArchiveFiles = 100 }; // 将目标添加到NLog配置 var config = new LoggingConfiguration(); config.AddRule(LogLevel.Info, LogLevel.Fatal, fileTarget); LogManager.Configuration = config;
配置文件示例(NLog.config)
<targets> <target name="logFile" xsi:type="File" fileName="${basedir}/${date:format=yyMMdd}/${date:format=yyMMddHHmmss}Something.log" archiveFileName="${basedir}/${date:format=yyMMdd}/${date:format=yyMMddHHmmss}Something_{#}.log" archiveAboveSize="52428800" <!-- 50MB = 50*1024*1024 --> archiveEvery="Hour" archiveNumbering="Sequence" concurrentWrites="true" maxArchiveFiles="100" /> </targets> <rules> <logger name="*" minlevel="Info" writeTo="logFile" /> </rules>
效果说明
- 当文件达到50MB时,NLog会自动归档当前文件,并创建新文件,新文件名使用创建时的时间戳。
- 每小时整点时,无论文件大小,都会归档当前文件并创建新的时间戳命名文件。
- 归档后的文件会在原文件名基础上添加序号(如
230525123021Something_1.log),可根据旧系统需求调整ArchiveFileName的格式。
内容的提问来源于stack exchange,提问作者Nicolas Grinschgl
相关产品推荐
相关产品推荐

