nlog配置的核心结论很简单:先定义target(日志写去哪、什么格式),再用rule把logger匹配到target上,这两条链路通了,日志自然就出来了。 大多数项目里日志“消失”的问题,都出在logger的命名空间写错、minlevel门槛设太高,或者文件路径没权限这三件事上。
nlog 配置文件怎么配置才靠谱
一个能跑的 nlog 配置,结构上只有两块:targets 和目标规则,targets 定义的是“日志写到哪里”,rules 定义的是“哪些日志可以过去”,把这两块拆开理解,配置就不会乱。
先搭一个最简可用的骨架
新建一个 nlog.config 文件,放在项目根目录或者输出目录下,内容如下:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="file" xsi:type="File"
fileName="${basedir}/logs/app-${shortdate}.log"
layout="${longdate} | ${level:uppercase=true} | ${logger} | ${message}${onexception:${newline}${exception:format=tostring}}" />
</targets>
<rules>
<logger name="" minlevel="Debug" writeTo="file" />
</rules>
</nlog>
这段配置里,target name="file" 定义了一个写入文件的日志目标,rule 里的 name="" 表示所有命名空间的日志都接收,minlevel="Debug" 表示 Debug 级别及以上的日志都会记录。
target 和 logger 的匹配机制
name=""匹配所有日志来源。name="MyApp.Business."匹配MyApp.Business命名空间及其子命名空间。minlevel="Info"的意思是,Info 及以上才会往这个 target 写。- 一个 logger 可以被多个 rule 匹配,所以日志可以同时写到文件、控制台、数据库。
业内配置经验表明,大部分初学者的配置问题不是写错格式,而是规则写得太绕,命名空间匹配的优先级高于 level,多写几条具体匹配规则,比用一条模糊的全局规则更容易维护。
nlog 不输出日志什么原因?按顺序排查

遇到过不少项目,配置文件看起来没问题,但日志就是不落盘,排查顺序很重要,几步下来通常能找到原因。
logger 名称不匹配
这是最常见的原因,比如你在代码里用 LoggerFactory.Create(builder => builder.AddNLog()),类所在的命名空间是 Company.OrderService,但 rule 里写的是 <logger name="OrderService." ... />,这个规则完全命中不了。
正确的做法是,rule 里写 name="Company.OrderService.",或者直接写 name="" 方便省事,拿不准时,先把 logger 名称设为 测通,再逐步收窄范围。
minlevel 门槛设太高
有人把 minlevel="Fatal" 写在配置里,然后测试代码里写的是 logger.Info("test"),日志当然不会输出,Info 低于 Fatal,直接被规则挡掉了。
判断方法很简单:看代码里调用的日志级别,再看规则里的 minlevel,如果只想看到 Info 及以上的日志,就写 minlevel="Info";想看到所有日志,写 minlevel="Trace"。
文件路径没有写权限
日志文件写不进去时,程序不一定会报错,尤其是 Windows 服务或部署到 IIS 的站点,站点运行账号如果没有日志目录的写入权限,nlog 会静默失败。
验证方式:手动往 logs 目录里新建一个文本文件,如果能创建成功,说明权限没问题,部署环境里,给运行账号授予该目录的修改权限即可。
配置变更没有重载
修改 nlog.config 后,如果应用没重启,默认不会自动生效,开发调试时建议每次改完配置就重启一下项目,避免“改了没反应”的错觉。
nlog 按日期生成日志文件,滚动归档的正确姿势
生产环境最常用的需求之一,就是日志按天切分,并且自动清理旧文件,避免磁盘被撑爆。
按日期和大小双条件归档
修改 fileName 里的布局渲染器,再加上归档参数:
<target name="file" xsi:type="File"
fileName="${basedir}/logs/app-${shortdate}.log"
archiveAboveSize="10485760"
maxArchiveFiles="30"
layout="${longdate} | ${level:uppercase=true} | ${logger} | ${message}" />

这里 archiveAboveSize="10485760" 表示单文件超过 10MB 就归档,maxArchiveFiles="30" 保留最近 30 个归档文件。${shortdate} 让文件名变成 app-2026-01-15.log 这种格式,天然按天切分。
和异步日志搭配
为了避免日志写入拖慢业务接口响应,target 外面可以套一个 async 包装:
<target name="fileAsync" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Block">
<target name="file" xsi:type="File"
fileName="${basedir}/logs/app-${shortdate}.log" />
</target>
queueLimit 控制队列上限,overflowAction 设置为 Block,意思是队列满了就阻塞业务线程,保证日志不丢,日志量大的项目,丢弃日志比阻塞更危险,所以这个配置多数情况下是合理的。
nlog 数据库写入配置和告警场景
除了写文件,nlog 也常用来落库或发邮件,文件日志适合排查问题,数据库日志适合做统计分析,邮件告警适合关键错误实时通知。
数据库落库的写法
以 SQL Server 为例:
<target name="db" xsi:type="Database"
connectionString="Server=.;Database=LogDB;Integrated Security=true;"
commandText="INSERT INTO Logs(LogDate, Level, Message, Source) VALUES(@logDate, @level, @message, @source)">
<parameter name="@logDate" layout="${longdate}" />
<parameter name="@level" layout="${level}" />
<parameter name="@message" layout="${message}" />
<parameter name="@source" layout="${logger}" />
</target>
相关规则里把这条 target 加进 writeTo 即可,注意数据库 target 是高开销操作,建议配合 AsyncWrapper 使用,否则接口响应时间会明显变长。
什么时候该用邮件告警
邮件适合级别为 Error 或 Fatal 的日志,不能所有条目都发邮件,配置方式是把 rule 的

minlevel="Error" 单独指向 Mail target。行业共识认为,告警日志过多会让人麻痹,只保留真正需要人工介入的错误级别就够了。
nlog 配置 需要知道的其他细节
开源免费,没有授权费用
nlog 本身是开源框架,通过 NuGet 可以免费获取,不需要考虑商业授权成本,这也是很多国内中小型团队选择它的原因。
配置来源可以灵活切换
除了 nlog.config 文件,nlog 也支持在 appsettings.json 中配置,使用 NLog.Extensions.Logging 包时,可以通过 AddNLog() 方法读取,文件方式更适合独立管理,json 方式则和现有配置体系融为一体,按项目习惯选一种就行。
多环境配置一致性
开发环境和生产环境的日志目录可能不同,配置里使用 ${basedir} 和 ${shortdate} 这类布局渲染器,可以避免绝对路径带来的环境迁移问题,日志文件永远放在程序运行目录的相对位置,部署时不用改配置。
nlog配置的最终建议
配置 nlog 的核心逻辑很简单:定义 target,绑定 logger,选对 level,先跑通最简配置,再加滚动和异步,日志不输出时按“名字、级别、权限”三步排查,多数问题都能在十分钟内定位。
nlog 配置文件放在哪里最合适?
默认放在项目的根目录或输出目录下,文件名保持 nlog.config,ASP.NET Core 项目可以保留在项目根目录,并设置“复制到输出目录”,这样部署时配置会跟着程序集走。
nlog vs log4net,差异大吗?
两者都是成熟的日志框架,log4net 历史更久,nlog 对异步支持和现代化布局渲染器更友好,新项目用 nlog 多一些,老项目沿用 log4net 也不会有明显问题,如果已经用了其中一个,没必要为了换而换。
nlog 异步写入会丢日志吗?
默认配置下,队列未满时不会丢,队列溢出后 overflowAction 决定行为:Block 会阻塞线程保证日志不丢,Discard 会丢日志但不拖慢业务,关键业务推荐 Block,并适当调大 queueLimit。
