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

如何在使用ILogger.BeginScope时让NLog将数据格式化为JSON?

解决ILogger.BeginScope中NLog无法将对象序列化为JSON的问题

我来帮你搞定这个头疼的问题——其实核心是NLog对BeginScope里的对象处理逻辑和日志消息模板的@语法完全是两回事,咱们一步步捋清楚:

问题根源

你之前试着在BeginScope的键名里加@或者{@},但NLog根本不买账——因为@是日志消息模板(比如LogInfo("xxx {@Prop}", value))里的专属语法,用来告诉框架序列化参数对象,但这套逻辑并不适用于BeginScope的字典键名。默认情况下,NLog对BeginScope传递的对象只会调用ToString(),自然就只能看到类名或者默认字符串了。

解决方案

要让BeginScope里的对象变成可检索的结构化JSON,需要两步:调整NLog配置,然后用正确的代码写法。

第一步:修改NLog配置,开启Scope对象的序列化

打开你的nlog.config文件,针对Seq目标做以下配置(确保你用的是最新版的NLog和NLog.Extensions.Logging包):

方式1:用JsonLayout输出完整结构化日志(推荐)

这种方式会把所有日志内容(包括Scope属性)都序列化为JSON,Seq能完美识别:

<target name="seq" xsi:type="Seq" serverUrl="http://你的Seq地址">
  <layout xsi:type="JsonLayout">
    <attribute name="message" layout="${message}" />
    <attribute name="level" layout="${level}" />
    <attribute name="timestamp" layout="${date:format=o}" />
    <!-- 自动包含所有Scope/MDLC属性,并序列化为JSON -->
    <attribute name="properties" xsi:type="JsonLayout" includeAllProperties="true" />
  </layout>
</target>

方式2:单独指定某个Scope属性的序列化

如果你只需要处理CacheValue这一个属性,可以在普通布局里单独配置:

<target name="seq" xsi:type="Seq" serverUrl="http://你的Seq地址">
  <layout>
    ${message}
    <!-- 把CacheValue序列化为JSON输出 -->
    ${mdlc:item=CacheValue:format=json}
  </layout>
</target>

第二步:正确使用BeginScope

现在不需要在键名里加任何特殊符号,直接用普通键名或者匿名对象就行:

写法1:字典方式

using (_logger.BeginScope(new Dictionary<string, object> { ["CacheValue"] = value }))
{
    _logger.LogInformation("howdy");
}

写法2:匿名对象(更简洁)

using (_logger.BeginScope(new { CacheValue = value }))
{
    _logger.LogInformation("howdy");
}

验证效果

配置完成后再跑代码,去Seq里看日志:

  • CacheValue不再是类名字符串,而是完整的JSON对象
  • 你可以直接用CacheValue.Success = true或者CacheValue.TraceId = 'xxx'这样的条件检索日志,完全符合你的需求——JSON数据关联到日志但不显示在消息里。

内容的提问来源于stack exchange,提问作者TugboatCaptain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 22:27:47