2017-05-18 5 views
1

Ich versuche herauszufinden, wie alle Eigenschaften in einem LogEventInfo-Objekt in eine JSON-formatierte Zeichenfolge protokolliert werden. Per den issue on github, habe ich versucht, so etwas zu tun:Layout NLog Eigenschaften als 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> 

... aber leider meine Eigenschaften enthalten komplexe Objekte (Ich habe zwei Eigenschaften mit den Namen von „Eigenschaften“ und „Tags“, wobei „Eigenschaften "ist ein IDictionary<string, object> und" Tags "ist ein IList<string> in der LogEventInfo.Properties Eigenschaft, die einfach nicht serialisieren. Ich am Ende mit diesem etwas wie:

{ "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]" } } 

Ich erwartete (und der Hoffnung auf) eine serialisierte JSON-Wörterbuch, das mir den Kontext der Protokollmeldung geben würde, aber klar, dass ist nicht das, was ich erhalte.

Wie kann ich die Eigenschaften in meinem LogEventInfo Objekt richtig serialisieren?

Antwort

4

Nun, es sieht so aus, als gäbe es einen Bug in NLog, also habe ich meinen eigenen Renderer gemacht. Hier ist was ich getan habe. Zuerst habe ich eine Verlängerung Methode hergestellt JSON.NET mit:

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); 
} 

... Als nächstes habe ich eine LayoutRenderer wie so:

[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); 
    } 
} 

In meiner Anwendung, beim Anfahren, registriert ich meine LayoutRenderer so wie:

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

... und schließlich konfiguriert ich das NLog Ziel wie folgt aus:

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

So läuft der JSON richtig formatiert und ich habe Zugriff auf die Eigenschaften in meinem Objekt.

+0

Wenn ich folgte erhalte ich die Ausgabe als { "correlation_id": "a03734dd-b0ca-4bcf-83f2-e9d814272e32", "env", "dev", "Eigenschaften": "{" Key1" : "value1", "key2": "value2"} " }, aber meine Anforderung ist { " correlation_id ":" a03734dd-b0ca-4bcf-83f2-e9d814272e32 ",, " env "," dev ", "Key1": "value1", "key2": "value2", "keyn": "werten" } wo KEY1-VALUE1, KEY2-VALUE2 und der Rest des Teils ist DYNAMIC Kann mir jemand weiterhelfen dies –

+0

@ Gowtham.K.Reddy Ich denke, das hat mit Ihrem JSON-Serializer zu tun. Ich benutze JSON.NET, aber ich denke, der Standard .NET DataContractJsonSerializer gibt Ihnen die Ergebnisse, die Sie beschreiben. –

+0

auch, dynamisch ist der Teufel. Bei jeder Gelegenheit zu vermeiden '' –