NLog 实战指南:配置灵活的 .NET 老牌日志框架

NLog 中文实战指南:nlog.config XML 配置(targets/rules/layout)、五个日志级别、文件轮转与自动重载、结构化日志 ${properties}、代码配置方式、ASP.NET Core 集成,以及观测云 DataKit 采集落地方案。

最佳实践
NLog 实战指南:配置灵活的 .NET 老牌日志框架技术指南封面

NLog 是 .NET 生态中最灵活的老牌日志框架之一:强大的路由规则、丰富的 layout 渲染器、配置文件热重载。它既能服务简单的控制台程序,也能驾驭复杂的多目标路由场景。本文覆盖 NLog 的核心配置与生产实践,并给出观测云平台接入方案。

核心要点速览

  • targets + rules 两段式配置:target 定义"写到哪、什么格式",rule 定义"哪个 logger、哪个级别、路由到哪个 target"。
  • autoReload="true" 热重载:改 nlog.config 即生效,生产调级别不重启。
  • 结构化日志logger.Info("用户 {UserId} 登录", id) 参数存为属性,${properties} 或 JsonLayout 输出。
  • 生产落地:JsonLayout 输出文件/控制台,观测云 DataKit 采集,监控器告警。

快速上手:nlog.config

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      autoReload="true"
      internalLogLevel="Warn"
      internalLogFile="logs/nlog-internal.txt">
  <targets>
    <target name="console" xsi:type="Console"
            layout="${longdate}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" />
    <target name="file" xsi:type="File"
            fileName="logs/app-${shortdate}.log"
            layout="${longdate}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Info" writeTo="console" />
    <logger name="*" minlevel="Error" writeTo="file" />
  </rules>
</nlog>

代码中使用:

var logger = NLog.LogManager.GetCurrentClassLogger();

logger.Trace("Trace message");
logger.Debug("调试细节");
logger.Info("应用启动");
logger.Warn("配置缺失");
logger.Error(ex, "数据库连接失败");   // 异常对象直接传入,自动带堆栈
logger.Fatal("系统级故障");

五个级别:Trace → Debug → Info → Warn → Error → Fatal。上面的规则实现了"控制台看全部 Info+,文件只留 Error+"的分级路由。

internalLogLevel/internalLogFile 是 NLog 自身排障的内部日志,生产建议开 Warn。

layout 渲染器与结构化属性

layout 中的 ${...} 是渲染器,常用的有:

渲染器 含义
${longdate} / ${shortdate} 完整/短日期时间
${level:uppercase=true} 级别(大写)
${logger} logger 名称(通常是类名)
${message} 日志消息
${exception:format=tostring} 异常完整信息
${machinename} ${processid} ${threadid} 机器/进程/线程

结构化参数:

logger.Info("用户 {UserId} 购买了 {Item},金额 {Price}", 42, "Orange Soda", 100.00);

参数被存为属性(properties),layout 中用 ${properties:item=UserId} 引用,或直接用 JsonLayout 全部输出。

JSON 输出:JsonLayout

<target name="jsonfile" xsi:type="File" fileName="logs/app.json">
  <layout xsi:type="JsonLayout" includeAllProperties="true">
    <attribute name="time" layout="${longdate}" />
    <attribute name="level" layout="${level:uppercase=true}" />
    <attribute name="logger" layout="${logger}" />
    <attribute name="message" layout="${message}" />
    <attribute name="exception" layout="${exception:format=tostring}" />
  </layout>
</target>

输出一行一个 JSON 对象,结构化属性自动展开为字段——这是接入日志平台的推荐格式。

文件轮转与高级路由

<target name="file" xsi:type="File"
        fileName="logs/app.log"
        archiveFileName="logs/app-{#}.log"
        archiveAboveSize="104857600"
        maxArchiveFiles="10" />

单文件超 100MB 自动归档,保留 10 个历史文件。规则还可以按 logger 名分流:

<logger name="MyApp.Payments.*" minlevel="Info" writeTo="paymentsFile" />
<logger name="Microsoft.*" maxlevel="Warning" writeTo="blackhole" final="true" />

第二条把框架噪音日志在 Warn 及以下直接丢弃(blackhole target)——降噪必备技巧。

代码配置与 ASP.NET Core 集成

不用 XML 也可以纯代码配置(NLog.LogManager.Setup() 流式 API);ASP.NET Core 安装 NLog.Web.AspNetCore 后:

builder.Logging.ClearProviders();
builder.Host.UseNLog();

NLog 接管 ILogger 体系,框架日志与业务日志统一出口。

观测云落地:NLog 日志采集与分析

  1. 应用侧:JsonLayout 输出到控制台(容器)或滚动文件(主机),字段命名遵循团队契约。
  2. DataKit 采集:容器 stdout 自动采集;主机 conf.d/log/logging.conf 配置文件采集,source: dotnet-appservice 标识服务。JSON 自动解析为字段。
  3. Pipeline 标准化level 映射标准 status(Error/Fatal → error),time 解析为事件时间。
  4. 检索告警:日志查看器按 status/service/logger 过滤,聚类分析归纳异常模式;监控器对 Error/Fatal 设阈值,告警策略路由钉钉/企业微信/飞书。
  5. 链路关联:接入观测云 APM 后 trace_id 作为属性注入(${properties} 输出),日志与链路双向跳转。
  6. 成本控制:多索引按级别拆分保留,历史数据转发归档对象存储。

常见问题(FAQ)

NLog 和 Serilog 怎么选?

两者都活跃且成熟。NLog 胜在 XML 配置的路由规则表达力与热重载;Serilog 胜在消息模板与 Sink 生态。团队熟悉度优先,新项目两者皆可,本系列倾向 Serilog 的结构化体验。

改了 nlog.config 没生效?

检查 autoReload="true" 是否开启,以及文件的"复制到输出目录"属性(CopyToOutputDirectory)是否设为 Always——常见的坑是改的是源文件、运行目录里还是旧副本。

internalLog 有什么用?

NLog 自身故障(如文件无权限、配置错误)不会抛出异常打断业务,而是写内部日志。排查"日志没输出"时先看 internalLogFile,建议生产设为 Warn。

异步写入怎么配?

用 AsyncWrapper 包一层 target:<target name="asyncFile" xsi:type="AsyncWrapper"><target xsi:type="File" .../></target>,或规则上使用异步包装。高并发场景建议开启。

系列阅读


获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台