nlog写入文件需配置filename(推荐${basedir}/logs/${shortdate}.log)、archiveevery="day"实现按日滚动、encoding="utf-8"解决中文乱码;createdirs="true"可自动创建目录,避免静默失败。

怎么配置NLog写入文件(含路径、滚动、编码)
默认情况下NLog不会自动创建日志目录,NLog.config 里写的 fileName 路径如果父目录不存在,日志就静默失败——连错误提示都不会打出来。
推荐用相对路径配合 ${basedir} 变量,比如:fileName="${basedir}/logs/${shortdate}.log";注意 logs 目录得手动建好,或在程序启动时用 Directory.CreateDirectory 预热。
- 滚动策略用
archiveEvery="Day"比archiveAboveSize更可控,避免单文件爆炸 - 中文乱码?加
encoding="utf-8"到target配置里,Windows 默认是 ANSI - 想按小时归档?把
${shortdate}换成${date:format=yyyy-MM-dd-HH}
怎么把异常堆栈完整写进日志(不是只记 ex.Message)
logger.Error(ex, "用户登录失败") 才会把整个 StackTrace 和 InnerException 链写进去;只写 logger.Error(ex.ToString()) 看似一样,实则丢失了 NLog 的结构化上下文(比如 level、time、call site),而且 ToString() 在某些 .NET 版本里还可能触发异常。
- 别在
catch块里手动拼接字符串传给Error(),交给 NLog 处理 - 如果用了
async/await,确保logger实例是线程安全的(NLog 本身是,但你自己封装的静态类可能不是) - 想额外记录 HTTP 请求 ID 或 TraceId?在
Layout里加${aspnet-traceidentifier}或${activityid}
怎么往 SQL Server 写日志(不卡主线程、防连接泄漏)
直接配 DatabaseTarget 很容易踩坑:没设 keepConnection="false" 会导致连接池耗尽;没开 commandTimeout,慢查询会拖垮日志线程;更麻烦的是,如果数据库连不上,NLog 默认会重试 3 次并阻塞当前线程。
- 务必设
keepConnection="false",每次写日志都新建连接再释放 - 加
commandTimeout="10",超时就丢弃,别让日志拖死业务 - 用异步目标:
async="true"+queueLimit="10000",避免 DB 慢时堆积内存 - 表结构必须包含
Time(datetime2)、Level(nvarchar(10))、Message(nvarchar(max))等基础字段,NLog 不会自动建表
为什么 GetCurrentClassLogger() 有时返回空或报错
常见原因是调用位置在静态构造函数、模块初始化器(.NET 6+)或 AssemblyLoadContext 卸载后,此时 typeof(T).Assembly 可能不可用,GetCurrentClassLogger() 就会返回 null 或抛 NullReferenceException。
- 稳妥做法是显式传入类型:
LogManager.GetLogger(typeof(Program)) - 在 ASP.NET Core 里,优先用 DI 注入
ILogger<t></t>,它底层可桥接到 NLog,且生命周期受容器管理 - 如果用了
NLog.Web.AspNetCore,别忘了在Program.cs调用builder.Host.UseNLog(),否则ILogger不走 NLog
最易被忽略的一点:NLog 配置文件修改后不会热重载,改完得重启进程,或者手动调用 LogManager.ReconfigExistingLoggers() —— 但后者在多线程环境下有小概率导致日志丢失。










