2014-03-24 17 views
17

Ich möchte Log-Ereignisse als JSON-Objekte mit parametrisierten String-Nachrichten an Loggly senden. Unser Projekt hat derzeit eine Menge Code, der wie folgt aussieht:Gibt es ein Logback-Layout, das JSON-Objekte mit Nachrichtenparametern als Attribute erstellt?

String someParameter = "1234"; 
logger.log("This is a log message with a parameter {}", someParameter); 

Wir haben zur Zeit Logback als unsere SLF4J Backend verwenden und Logback des JsonLayout unsere ILogEvent Objekte in JSON serialisiert werden. Konsequenter, indem sie unsere Protokollereignisse Loggly ausgeliefert Zeit sehen sie wie folgt aus:

{ 
    "message": "This is a log message with a parameter 1234", 
    "level": INFO, 
    .... 
} 

Während dies funktioniert, ist es eine andere message String für jeden Wert von someParameter sendet, die Loggly automatische Filter neben unbrauchbar macht .

Stattdessen würde Ich mag einen Plan haben, die JSON erstellt, die wie folgt aussieht:

{ 
    "message": "This is a log message with a parameter {}", 
    "level": INFO, 
    "parameters": [ 
     "1234" 
    ] 
} 

Dieses Format This is a log message with a parameter zusammen Loggly gruppieren alle Log-Ereignisse mit der Meldung ermöglichen würde, unabhängig von dem Wert von someParameter.

Es sieht aus wie Logstash's KV filter tut so etwas - gibt es eine Möglichkeit, diese Aufgabe mit Logback zu erreichen, kurz vor dem Schreiben meines eigenen Layout, das benutzerdefinierte Serialisierung des ILogEvent-Objekts führt?

+0

Das Problem, das ich mit Ihrem Beispiel sehe, ist, dass Sie nicht wissen, wo der Parameter in der Nachricht eingefügt werden würde. –

+0

@ LeonardBrünings das sollte nicht wichtig sein, weil die Parameter an die 'log.log (message, param1, param2);' -Funktion übergeben werden. Solange die Reihenfolge in dem Array erhalten bleibt, das in das JSON-Objekt eingefügt wird, ist alles in Ordnung. – MusikPolice

+0

aber Ihre Nachricht in der JSON hatte keine Platzhalter. Wenn das beabsichtigt und nicht ein Fehler wäre, wüssten Sie nicht, wie Sie die richtige Nachricht wiedergeben. –

Antwort

5

Sie könnten einen Mapped Diagnostic Context verwenden, um einen Stempel für jedes dieser Art von Log-Meldungen festlegen, die Sie dann in loggly einmal gefiltert werden können.

Laut der Quelle von JsonLayout wird der Stempel als ein separater Wert im JSON gespeichert.

+1

Ja, das haben wir benutzt, um willkürliche Objekte zu unseren Log-Nachrichten hinzuzufügen. – MusikPolice

4

Hier ist ein kürzlich erstelltes Projekt, das einen JSON-spezifische Logging-API bereitstellt und arbeitet mit SLF4J:

https://github.com/savoirtech/slf4j-json-logger

+0

Das ist eine nette kleine Bibliothek. Ich bezweifle, dass ich bestehende Projekte auf sie umstellen werde, da es ein gutes Stück Arbeit erfordern würde, aber ich werde es für zukünftige Projekte unbedingt im Hinterkopf behalten. – MusikPolice

+0

Vielen Dank @MusikPolice - wir freuen uns über das Feedback. – ash

+0

Ich beginne jetzt ein neues Projekt und werde es ausprobieren. Ich bin mir jedoch nicht sicher, ob ich Standardfelder für die Protokollierung konfigurieren kann (dies ist mir mit Logback gelungen, aber ich mag es nicht, MDC für die Ausgabe eines Feldes zu verwenden, daher würde ich slf4j-json-logger bevorzugen es ist API). Die Idee besteht darin, in der Konfigurationsdatei einen Feld + Wert zu konfigurieren, der automatisch allen erzeugten JSON-Protokollzeilen/-Objekten hinzugefügt wird. Ist das in slf4j-json-logger möglich? – mvmn

3

für mich Also ich habe versucht, die Ausführungszeiten zu protokollieren, habe ich eine pojo genannt ExecutionTime mit Namen , Methode, Klasse, Dauer.

war ich dann in der Lage, es zu schaffen:

ExecutionTime time = new ExecutionTime("Controller Hit", methodName, className, sw.getTotalTimeMillis()); 

Für das Einloggen Ich habe dann verwendet:

private final Logger logger = LoggerFactory.getLogger(this.getClass()); 
logger.info(append("metric", time), time.toString()); 

Stellen Sie sicher, Sie haben:

import static net.logstash.logback.marker.Markers.append; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

Dieses so etwas wie dieses log wird :

{ 
    "ts":"2017-02-16T07:41:36.680-08:00", 
    "msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]", 
    "logger":"com.xxx.services.metrics.ExecutionTimeLogger", 
    "level":"INFO", 
    "metric":{ 
     "name":"Controller Hit", 
     "method":"setupSession", 
     "className":"class com.xxx.services.controllers.SessionController", 
     "duration":3225 
    } 
} 

Könnte eine andere Gruppe sein, wie ich logback-spring.xml zur Ausgabe meiner Protokolle json verwenden wurde:

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <include resource="org/springframework/boot/logging/logback/base.xml"/> 
    <property name="PROJECT_ID" value="my_service"/> 
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <File>app/logs/${PROJECT_ID}.json.log</File> 
     <encoder class="net.logstash.logback.encoder.LogstashEncoder"> 
      <fieldNames> 
       <timestamp>ts</timestamp> 
       <message>msg</message> 
       <thread>[ignore]</thread> 
       <levelValue>[ignore]</levelValue> 
       <logger>logger</logger> 
       <version>[ignore]</version> 
      </fieldNames> 
     </encoder> 
     <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
      <maxIndex>10</maxIndex> 
      <FileNamePattern>app/logs/${PROJECT_ID}.json.log.%i</FileNamePattern> 
     </rollingPolicy> 
     <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> 
      <MaxFileSize>20MB</MaxFileSize> 
     </triggeringPolicy> 
    </appender> 
    <logger name="com.xxx" additivity="false" level="DEBUG"> 
     <appender-ref ref="FILE"/> 
     <appender-ref ref="CONSOLE"/> 
    </logger> 
    <root level="WARN"> 
     <appender-ref ref="FILE"/> 
    </root> 
</configuration> 
0

Wie bereits beantworten Sie MDC einen eindimensionalen JSON Baum erhalten werden und/oder mit einem Marker mit logstash-logback-encoder.

Wenn Sie suchen auch nach folgenden Kriterien:

  • Codebücher für die Definition von protokollierten Datentyp Schlüssel und Typ,
  • Konfiguration von Log-Aggregation-Tools (wie Elasticsearch)
  • erzeugt Java-Helfer-Code für eine effiziente und korrekte Protokollierung

dann versuchen Sie ein Projekt, das ich erstellt habe: json-log-domain. Es definiert eine einfache YAML-Formatdefinition, aus der das Obige generiert werden kann.

wäre ein Beispiel Helfer-Code-Anweisung

seine
logger.info(host("localhost").port(8080), "Hello world"); 

während erzeugt Abschlag so etwas wie this möchte.