如何用NLog实现单条JSON日志存唯一文件并避免内存泄漏?
用NLog实现单条JSON消息独立存储+自动归档清理
别折腾动态创建/删除NLog Target了,不仅容易内存泄漏,完全没必要——NLog本身就支持你要的所有需求,直接用自带功能搞定就行:
核心方案:用布局渲染器生成唯一文件名,配合NLog归档规则
1. 配置NLog FileTarget
不管是用XML配置还是代码配置,都可以通过${guid}布局渲染器自动生成唯一文件名,同时开启归档和自动清理:
XML配置示例
<configuration> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="SingleJsonFile" xsi:type="File" <!-- 每条消息生成一个带GUID的独立JSON文件 --> fileName="${basedir}/json-logs/${guid}.json" <!-- 归档到压缩包,避免零散文件过多 --> archiveFileName="${basedir}/json-logs/archive/json-archive_{#}.zip" <!-- 每条文件写完立即归档(因为单条JSON文件体积极小) --> archiveAboveSize="0" <!-- 归档文件按序号命名 --> archiveNumbering="Sequence" <!-- 最多保留30个归档包,超过自动删除最旧的 --> maxArchiveFiles="30" <!-- 启用压缩节省空间 --> enableArchiveFileCompression="true" /> </targets> <rules> <logger name="*" minlevel="Info" writeTo="SingleJsonFile" /> </rules> </nlog> </configuration>
代码配置示例
var fileTarget = new FileTarget("SingleJsonFile") { FileName = "${basedir}/json-logs/${guid}.json", ArchiveFileName = "${basedir}/json-logs/archive/json-archive_{#}.zip", ArchiveAboveSize = 0, // 每条文件触发归档 ArchiveNumbering = ArchiveNumberingMode.Sequence, MaxArchiveFiles = 30, EnableArchiveFileCompression = true }; // 把Target加入NLog配置 var config = LogManager.Configuration ?? new LoggingConfiguration(); config.AddTarget(fileTarget); config.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, fileTarget)); LogManager.Configuration = config;
2. 写入JSON消息
直接把收到的JSON字符串作为日志内容输出即可,NLog会自动为每条消息生成独立文件,写完后自动归档,超过保留数量的旧归档会被删除:
var logger = LogManager.GetCurrentClassLogger(); // 收到JSON消息后直接打日志 logger.Info(jsonMsg);
额外灵活配置
如果需要按时间维度清理,比如保留最近7天的归档,只需调整配置:
<!-- 替换之前的归档相关配置 --> archiveEvery="Day" maxArchiveDays="7"
这样NLog会每天生成一个归档包,自动删除7天前的旧文件。
为什么不推荐动态创建Target
动态添加/删除Target会导致NLog内部的资源(比如文件句柄、缓存)无法及时释放,长期运行必然出现内存泄漏,而且完全没必要——NLog的布局渲染器已经能完美生成唯一文件名,自带的归档清理逻辑也比自己写的更稳定可靠。
内容的提问来源于stack exchange,提问作者theateist
相关产品推荐
相关产品推荐

