2016-09-22 3 views
2

Ich habe Log4j für verschiedene Arten von Projekten verwendet und habe einige Erfahrung mit Log4j2. Alle Implementierungen verwendeten den Standardappender und das Layout. Zur Zeit muss ich eine Anwendung schreiben, die im JSON-Format schreibt. Also habe ich das log4j2 JSONLayout Layout ausprobiert, indem ich einen sehr einfachen log4j2 Logger eingerichtet habe.Die beste Möglichkeit, benutzerdefinierte JSON-Nachrichten mit log4j2 zu schreiben

public class JSONLogger { 

    private static final Logger LOGGER = LogManager.getLogger(); 

    public static void main(String[] args) { 
     JSONLogger jsonlogger = new JSONLogger() ; 
    } 

    public JSONLogger() { 
     LOGGER.log(Level.FATAL, "hi mum!") ; 

     int val1 = 10, val2 = 11, val3 = 12; 

     LOGGER.log(Level.FATAL,"val1={}, val2={}, val3={}", val1, val2, val3); 
    } 

} 

jsonLoggerProperties.xml

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration status="DEBUG"> 
    <Properties> 
     <Property name="log-path">/Users/petervannes/NetBeansProjects/JSONLogger/logfiles</Property> 
    </Properties> 

    <Appenders> 
     <RollingFile name="json_file_appender" fileName="${log-path}/jsonlogger.json" 
        filePattern="${log-path}/%d{yyyyMMdd}_jsonlogger-%i.json" > 
      <JSONLayout complete="true" compact="false"/> 
      <Policies> 
       <SizeBasedTriggeringPolicy size="1 KB" /> 
      </Policies> 
      <DefaultRolloverStrategy max="4"/> 
     </RollingFile> 

    </Appenders> 


    <Loggers> 
     <root level="debug" additivity="false"> 
      <AppenderRef ref="json_file_appender"/> 
     </root> 
    </Loggers> 
</Configuration> 

in einem Logeintrag Resultierende ähnelt;

, { 
    "timeMillis" : 1474573600359, 
    "thread" : "main", 
    "level" : "FATAL", 
    "loggerName" : "JSONLogger", 
    "message" : "val1=10, val2=11, val3=12", 
    "contextStack" : [ "fieldName2" ], 
    "endOfBatch" : false, 
    "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger", 
    "threadId" : 1, 
    "threadPriority" : 5 
} 

Was ich brauche, ist in ein JSON-Format wie folgt zu protokollieren;

, { 
    "DateTime" : "08/01/2016 21:33:22.334", 
    "level" : "FATAL", 
    "Summary" : "Something has gone wrong", 
    "ChainManager" : "Manager A", 
    "Optionals" : { "Key_1": "Value1", 
        "Key_2": "Value2" } 
} 

Ist das possibile mit dem log4j2 JSONLayout oder gibt es eine andere Layout ich dieses Format bekommen kann?

Antwort

2

Ich fand eine Lösung, die für mich funktioniert; slf4j-json-logger. Es ist ein slf4j Framework, sollte also in der pom.xml enthalten sein. Beispielprojektdateien;

pom.xml

<?xml version="1.0" encoding="UTF-8"?> 
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <groupId>com.reddipped</groupId> 
    <artifactId>JSONLogger_2</artifactId> 
    <version>1.0-SNAPSHOT</version> 
    <packaging>jar</packaging> 
    <properties> 

     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <maven.compiler.source>1.6</maven.compiler.source> 
     <maven.compiler.target>1.6</maven.compiler.target> 

     <mainClass>com.reddipped.jsonlogger_2.Test</mainClass> 

     <slf4j.version>1.7.21</slf4j.version> 
     <!-- current log4j 2 release --> 
     <log4j.version>2.6.2</log4j.version> 

    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>org.slf4j</groupId> 
      <artifactId>slf4j-api</artifactId> 
      <version>${slf4j.version}</version> 
     </dependency> 
     <!-- Binding for Log4J --> 
     <dependency> 
      <groupId>org.apache.logging.log4j</groupId> 
      <artifactId>log4j-slf4j-impl</artifactId> 
      <version>${log4j.version}</version> 
     </dependency> 
     <!-- Log4j API and Core implementation required for binding --> 
     <dependency> 
      <groupId>org.apache.logging.log4j</groupId> 
      <artifactId>log4j-api</artifactId> 
      <version>${log4j.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.apache.logging.log4j</groupId> 
      <artifactId>log4j-core</artifactId> 
      <version>${log4j.version}</version> 
     </dependency> 
     <!-- Logger slf4j-json-logger --> 
     <dependency> 
      <groupId>com.savoirtech.logging</groupId> 
      <artifactId>slf4j-json-logger</artifactId> 
      <version>2.0.2</version> 
     </dependency> 
    </dependencies> 
    </project> 

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?> 

    <!-- 

    Use java property log4j.configurationFile to specify log4j2.xml location 
    if not available in classpath 

    - Dlog4j.configurationFile="/Users/petervannes/NetBeansProjects/JSONLogger_2/src/mann/java/resources/log4j2.xml" 

    --> 
    <configuration status="trace"> 
    <Properties> 
     <Property name="log-path">/Users/petervannes/NetBeansProjects/JSONLogger_2/logfiles</Property> 
    </Properties> 
    <appenders> 
     <RollingFile name="RollingFile" fileName="${log-path}/jsonlogger.json" 
        filePattern="${log-path}/%d{yyyyMMdd}_jsonlogger-%i.json" > 
      <PatternLayout> 
       <pattern>%m%n</pattern> 
      </PatternLayout> 
      <Policies> 
       <TimeBasedTriggeringPolicy /> 
       <SizeBasedTriggeringPolicy size="1 KB" /> 
      </Policies> 
      <DefaultRolloverStrategy max="4"/> 
     </RollingFile> 
    </appenders> 
    <Loggers> 
     <Logger name="JSONLogger" level="debug" additivity="false"> 
      <AppenderRef ref="RollingFile" /> 
     </Logger> 
     <Root level="debug"> 
      <AppenderRef ref="RollingFile" /> 
     </Root> 
    </Loggers> 
    </configuration> 

Beispiel Java-Code

package com.reddipped.jsonlogger_2; 

    import com.savoirtech.logging.slf4j.json.LoggerFactory; 
    import java.util.HashMap; 
    import java.util.Map; 

    /** 
    * 
    * @author petervannes 
    */ 
    public class Test { 
     public static void main(String[] args) { 
     Test t = new Test() ; 
    } 


    public Test() { 

     LoggerFactory.setIncludeLoggerName(false); 
     LoggerFactory.setDateFormatString("yyyy-MM-dd HH:mm:ss.SSS"); 

     com.savoirtech.logging.slf4j.json.logger.Logger LOGGER = LoggerFactory.getLogger("JSONLogger"); 

    Map<String, String> optionalFields = new HashMap(); 
    optionalFields.put("CaseNumber", "C12.12343"); 
    optionalFields.put("Step","Assignment") ; 
    optionalFields.put("Department","BPM") ; 

    String LOB = "Business Administration" ; 
    String Service = "DocumentService" ; 
    String Process = "AddAttachements" ; 
    String Reason = "Technical" ; 

    LOGGER.error().message("Conversion error 'incompatible PDF document'") 
      .field("LOB",LOB) 
      .field("Service", Service) 
      .field("Process",Process) 
      .field("Reason", Reason) 
      .map("OptionalFields", optionalFields).log() ; 
    } 

    } 

JSON-Protokoll-Eintrag

{ 
    "message": "Conversion error 'incompatible PDF document'", 
    "LOB": "Business Administration", 
    "Service": "DocumentService", 
    "Process": "AddAttachements", 
    "Reason": "Technical", 
    "OptionalFields": { 
    "Step": "Assignment", 
    "Department": "BPM", 
    "CaseNumber": "C12.12343" 
    }, 
    "level": "ERROR", 
    "thread_name": "main", 
    "class": "com.reddipped.jsonlogger_2.Test", 
    "@timestamp": "2016-09-23 10:18:06.623" 
    } 
+0

Schön, aber ich wünschte, ich dies ohne sl4j erreichen könnte. log4j2.8 hat noch Unterstützung – prayagupd

+0

Sie können, ich musste nach einem alternativen Pfad suchen, weil slF4j interferring war. – pcvnes

+0

Nun in meinem Kommentar, ich meine zu sagen "Log4j 2.8 hat noch keine Unterstützung von Json-Logs". Es druckt im JSON-Format, aber nicht die Nachricht, die ich hinzufüge. – prayagupd

Verwandte Themen