【问题标题】:Layout NLog properties as JSON?将 NLog 属性布局为 JSON?
【发布时间】:2017-10-18 07:02:42
【问题描述】:

我试图弄清楚如何将LogEventInfo 对象中的所有属性记录到 JSON 格式的字符串中。根据issue on github,我尝试做这样的事情:

<target xsi:type="ColoredConsole" name="coloredConsole">
  <layout xsi:type="JsonLayout">
    <attribute name="timestamp" layout="${longdate}"/>
    <attribute name="level" layout="${level:uppercase=true}"/>
    <attribute name="exception" layout="${onexception:${exception:format=tostring}}" />
    <attribute name="properties" encode="false">
      <layout type="JsonLayout">
        <attribute name="properties" layout="${all-event-properties}" />
      </layout>
    </attribute>
  </layout>
</target>

...但不幸的是,我的属性包含复杂对象(我有两个属性,名称分别为“properties”和“tags”,其中“properties”是IDictionary&lt;string, object&gt;,“tags”是IList&lt;string&gt; LogEventInfo.Properties 属性)根本不序列化。我最终得到了类似这样的东西:

{ "timestamp": "2017-05-18 08:41:28.7730", "level": "INFO", "properties": { "properties": "properties=System.Collections.Generic.Dictionary`2[System.String,System.Object], tags=System.Collections.Generic.List`1[System.String]" } }

我期待(并希望)有一个序列化的 JSON 字典,它可以为我提供日志消息的上下文,但显然这不是我得到的。

如何正确序列化 LogEventInfo 对象中的属性?

【问题讨论】:

    标签: logging serialization nlog


    【解决方案1】:

    在这里使用 NLog 4.5.1。

    有了这个配置:

     <target xsi:type="File" name="jsonFile2" fileName="c:\temp\nlog-json-nested-${shortdate}.log">
         <layout type="JsonLayout">
             <attribute name="time" layout="${longdate}" />
             <attribute name="level" layout="${level}" />
             <attribute name="message" layout="${message}" />
             <attribute name="eventProperties" encode="false" >
                 <layout type='JsonLayout' includeAllProperties="true"  maxRecursionLimit="20"/>
             </attribute>
         </layout>
     </target>
    

    这段代码:

    var nestedData = new
    {
        A = "a value",
        B = "b value",
        Nested = new
        {
            A = "nested a value",
            B = "nested b value",
        },
        Ints = new Collection<int> { 1, 2, 3},
        Dictionary = new Dictionary<string, object>
        {
            {"nested", new { X= 'x', y = 'y' }},
            { "awesome", "nlog"}
        }
    };
    LogEventInfo eventInfo = new LogEventInfo
    {
        Level = LogLevel.Info,
        Properties = { {"nestedData", nestedData } }
    };
    logger.Log(eventInfo);
    

    输出:

    {  
       "time":"2018-04-05 18:08:01.0813",
       "level":"INFO",
       "eventProperties":{  
          "nestedData":{  
             "A":"a value",
             "B":"b value",
             "Nested":{  
                "A":"nested a value",
                "B":"nested b value"
             },
             "Ints":[  
                1,
                2,
                3
             ],
             "Dictionary":{  
                "nested":{  
                   "X":"x",
                   "y":"y"
                },
                "awesome":"nlog"
             }
          }
       }
    }
    

    实际上,它打印出丑陋的单行版本。

    查看带有结构化日志记录的嵌套 JSON on the NLog wiki

    注意maxRecursionLimit 设置。默认为 0,表示“无对象反射”,表示您将获得事件属性的 ToString() 表示。

    【讨论】:

      【解决方案2】:

      嗯,看起来 NLog 中存在错误,所以我制作了自己的渲染器。这就是我所做的。首先,我使用 JSON.NET 做了一个扩展方法:

      public static string ToJson(this object obj, bool format = false, string dateFormat = null)
      {
          var settings = new JsonSerializerSettings
          {
              NullValueHandling = NullValueHandling.Ignore
          };
      
          if (!String.IsNullOrWhiteSpace(dateFormat))
          {
              settings.Converters = new List<JsonConverter>
              {
                  new IsoDateTimeConverter {DateTimeFormat = dateFormat}
              };
      
              return JsonConvert.SerializeObject(obj, format ? Formatting.Indented : Formatting.None, settings);
          }
      
          return JsonConvert.SerializeObject(obj, format ? Formatting.Indented : Formatting.None, settings);
      }
      

      ...接下来,我像这样创建了一个 LayoutRenderer:

      [LayoutRenderer("json-event-properties")]
      public class JsonEventPropertiesLayoutRenderer : LayoutRenderer
      {
          /// <summary>
          /// Renders the specified environmental information and appends it to the specified <see cref="T:System.Text.StringBuilder" />.
          /// </summary>
          /// <param name="builder">The <see cref="T:System.Text.StringBuilder" /> to append the rendered data to.</param>
          /// <param name="logEvent">Logging event.</param>
          protected override void Append(StringBuilder builder, LogEventInfo logEvent) {
              if (logEvent.Properties == null || logEvent.Properties.Count == 0)
                  return;
              var serialized = logEvent.Properties.ToJson();
              builder.Append(serialized);
          }
      }
      

      在我的应用程序中,启动时,我注册了我的LayoutRenderer,如下所示:

      LayoutRenderer.Register<JsonEventPropertiesLayoutRenderer>("json-event-properties");
      

      ...最后,我像这样配置了 NLog 目标:

          <layout xsi:type="JsonLayout">
          <attribute name="timestamp" layout="${longdate}"/>
          <attribute name="level" layout="${level:uppercase=true}"/>
          <attribute name="exception" layout="${onexception:${exception:format=tostring}}" />
          <attribute name="message" layout="${message}" />
          <attribute name="properties" layout="${json-event-properties}" encode="false"/>
        </layout>
      

      像这样运行,JSON 格式正确,我可以访问我的 LogEventInfo 对象中的属性。

      【讨论】:

      • 当我关注这个时,我得到的输出为 { "correlation_id":"a03734dd-b0ca-4bcf-83f2-e9d814272e32", "env","dev", "properties":"{" Key1":"value1","key2":"value2"}" },但我的要求是 { "correlation_id":"a03734dd-b0ca-4bcf-83f2-e9d814272e32", , "env","dev", "Key1 ":"value1", "key2":"value2", "keyn":"valuen" } 其中 KEY1-VALUE1,KEY2-VALUE2 和其余部分是 DYNAMIC 有人可以帮我吗
      • @Gowtham.K.Reddy 我认为这与您的 JSON 序列化程序有关。我使用 JSON.NET,但我认为标准的 .NET DataContractJsonSerializer 可以为您提供所描述的结果。
      • 另外,动态是魔鬼。一有机会就避免&lt;/soapbox&gt;
      猜你喜欢
      • 2021-12-01
      • 2011-06-30
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多