NLog JsonLayout无法包含LogEvent属性:嵌套JSON结构化日志实现失败问题排查
解决NLog嵌套JSON日志中eventProperties为空及配置警告问题
咱们一步一步来解决你的问题:
问题根源分析
- 配置警告原因:你在嵌套的
JsonLayout上设置了includeEventProperties="true",但这个属性根本不属于JsonLayout——它是EventPropertiesLayoutRenderer的专属属性,所以NLog会抛出不支持该参数的警告。 - 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,提问作者Иван Онищенко
相关产品推荐
相关产品推荐

