You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NLog JsonLayout无法包含LogEvent属性:嵌套JSON结构化日志实现失败问题排查

解决NLog嵌套JSON日志中eventProperties为空及配置警告问题

咱们一步一步来解决你的问题:

问题根源分析

  1. 配置警告原因:你在嵌套的JsonLayout上设置了includeEventProperties="true",但这个属性根本不属于JsonLayout——它是EventPropertiesLayoutRenderer的专属属性,所以NLog会抛出不支持该参数的警告。
  2. eventProperties为空原因:你的日志调用Logger.Info("First: {alpha}, Second: {beta}", testObj, testObjB)中,{alpha}只是消息模板的格式化占位符,默认情况下NLog不会把这些参数自动保存为event properties,需要用特定语法触发捕获。

解决方案

1. 修正NLog配置,移除无效参数并正确输出event properties

把原来嵌套的JsonLayout替换为${all-event-properties}渲染器,它可以自动将所有event properties序列化为JSON对象,避免配置错误。修改后的配置如下:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd" autoReload="true" throwExceptions="false" internalLogLevel="TRACE" internalLogFile="c:\temp\nlog-internal.log">
  <variable name="LogLevel" value="DEBUG"/>
  <variable name="brief" value="${longdate} | ${level} | ${logger} | ${message}"/>
  <variable name="verbose" value="${longdate} | ${machinename} | ${processid} | ${processname} | ${level} | ${logger} | ${message}"/>
  <variable name="logLifetime" value="3"/>
  <targets>
    <target name="Global" xsi:type="File" fileName="Logs/GlobalLog.txt" archiveNumbering="Date" enableArchiveFileCompression="true" archiveFileName="Archive/IPSlog.{#}.zip" archiveDateFormat="yyyy-MM-dd" maxArchiveDays="${logLifetime}" archiveEvery="Day" >
      <layout xsi:type="JsonLayout">
        <attribute name="time" layout="${longdate}" />
        <attribute name="level" layout="${level:upperCase=true}"/>
        <attribute name="message" layout="${message}" />
        <!-- 使用all-event-properties渲染器输出所有事件属性 -->
        <attribute name="eventProperties" encode="false" layout="${all-event-properties:maxRecursionLimit=2}" />
      </layout>
    </target>
    <target name="Color" xsi:type="Console">
      <layout xsi:type="JsonLayout">
        <attribute name="time" layout="${longdate}" />
        <attribute name="level" layout="${level:upperCase=true}"/>
        <attribute name="message" layout="${message}" />
        <attribute name="eventProperties" encode="false" layout="${all-event-properties:maxRecursionLimit=2}" />
      </layout>
    </target>
  </targets>
  <rules>
    <logger name="Global" minlevel="${LogLevel}" writeTo="Global,Color" />
  </rules>
</nlog>

2. 修改日志调用代码,让NLog捕获参数为event properties

有两种推荐方式:

方式一:使用{@}前缀自动序列化对象(最简便)

在消息模板的占位符前加上@,告诉NLog这是一个需要序列化的对象,同时自动将其作为event property保存:

Logger.Info("First: {@alpha}, Second: {@beta}", testObj, testObjB);

方式二:手动添加event properties(适合精细控制)

如果需要更灵活地管理属性,可以用WithProperty方法显式添加:

Logger.WithProperty("alpha", testObj)
      .WithProperty("beta", testObjB)
      .Info("First: {alpha}, Second: {beta}", testObj, testObjB);

验证效果

修改完成后,你会得到符合预期的输出:

{ "time": "2022-02-09 14:21:27.7096", "level": "INFO", "message": "First: AlphaObject, Second: BetaObject", "eventProperties": { "alpha": { "A": "AlphaObject", "B": 2 }, "beta": { "A": "BetaObject", "B": 3 } } }

内容的提问来源于stack exchange,提问作者Иван Онищенко

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 12:42:41