2017-05-18 137 views
1

我想弄清楚如何將LogEventInfo對象中的所有屬性記錄到JSON格式的字符串。每issue on github,我試圖做這樣的事情:佈局NLog屬性爲JSON?

<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> 

...但不幸的是,我的屬性包含複雜的對象(我有「性」和「標籤」,其中「屬性的名稱兩個屬性「是IDictionary<string, object>,而」tags「是LogEventInfo.Properties屬性中的IList<string>),它們不會序列化。我最終的東西類似這樣的:

{ "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對象中的屬性?

回答

4

好吧,它看起來像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對象中的屬性。

+0

當我跟着這個我得到的輸出爲{ 「CORRELATION_ID」: 「a03734dd-b0ca-4bcf-83f2-e9d814272e32」, 「ENV」, 「開發」, 「屬性」: 「{」 KEY1" :「value1」,「key2」:「value2」}「 },但我的要求是」correlation_id「:」a03734dd-b0ca-4bcf-83f2-e9d814272e32「, 」env「,」dev「, 「Key1」:「value1」, 「key2」:「value2」, 「keyn」:「valuen」 } 其中KEY1-VALUE1,KEY2-VALUE2和其餘部分是動態的任何人都可以幫助我這 –

+0

@ Gowtham.K.Reddy我認爲這與你的JSON序列化器有關。我使用JSON.NET,但我認爲標準的.NET DataContractJsonSerializer會爲您提供您描述的結果。 –

+0

另外,動態是魔鬼。要在每個機會''避免 –