直接用logmanager.getcurrentclasslogger()最快上手,自动以当前类全名为logger名,需确保nlog.config设为“始终复制”;asp.net core推荐addnlog()集成ilogger接口;手动创建logger适用于动态切换日志目标场景。

直接用 LogManager.GetCurrentClassLogger() 最快上手
不需要注册服务、不依赖 DI 容器,适合控制台、WinForms 或快速验证场景。调用 LogManager.GetCurrentClassLogger() 会自动以当前类的完整名(如 NLogDemo.Program)作为 logger name,后续日志规则能按名匹配,也方便定位来源。
常见错误是忘记把 NLog.config 文件设为「始终复制」到输出目录,导致运行时找不到配置、静默失效——此时 LogManager.Configuration 为 null,但不会报错,日志完全不输出。
- 确保
NLog.config在项目根目录,属性 → 复制到输出目录 = 始终复制 - 首次调用
GetCurrentClassLogger()时才会加载配置,所以不能在静态构造函数里提前访问LogManager.Configuration判空 - 若需自定义 logger 名(比如按模块分组),改用
LogManager.GetLogger("OrderService")
在 ASP.NET Core 中用 AddNLog() 集成 ILogger 接口
这是 Web 项目推荐方式,让 NLog 兼容 .NET 内置的 ILogger<t></t>,能和框架日志(如中间件、EF Core)统一输出、统一过滤,并支持结构化日志参数绑定。
关键点不在安装包,而在初始化顺序:必须在 builder.Host.UseNLog() 之前完成 NLog.LogManager.LoadConfiguration() 或确保 NLog.config 已就位,否则 AddNLog() 会 fallback 到空配置,日志写不进文件。
- 安装
NLog和NLog.Web.AspNetCore两个包 -
Program.cs中先调用builder.Host.UseNLog(),再builder.Services.AddNLogWebAspNetCore()(新版 SDK 可省略后者) - 注入
ILogger<homecontroller></homecontroller>后,_logger.LogInformation("order_id={OrderId}", 1001)的结构化字段会被 NLog 正确解析并写入日志文件
手动创建 Logger 并传参控制输出目标
适用于需要动态切换日志路径、级别或目标(比如按租户隔离日志文件)的场景。本质是绕过全局配置,用代码新建 LoggingConfiguration 实例,再赋值给 LogManager.Configuration。
注意:一旦手动赋值,原有 NLog.config 就被覆盖;且多线程下并发修改 LogManager.Configuration 有风险,必须加锁或只在启动时设置一次。
- 用
new FileTarget { FileName = "${basedir}/logs/${shortdate}_${tenantId}.log" }实现租户级日志分离 - 通过
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, target))控制最低输出级别 - 别忘了调用
LogManager.ReconfigExistingLoggers()让已有 logger 生效新配置
File target 中启用了 keepFileOpen="true" 且没配 concurrentWrites="true",高并发下可能因文件句柄竞争导致日志丢失——这个细节在本地测试几乎不暴露,上线后流量一上来才出问题。










