diff --git a/pom.xml b/pom.xml index 1dc589b..fcc98ad 100644 --- a/pom.xml +++ b/pom.xml @@ -103,6 +103,11 @@ json-smart 1.1.1 + + com.fasterxml.jackson.core + jackson-databind + 2.8.5 + log4j log4j diff --git a/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java b/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java index aaf3228..28df3a1 100644 --- a/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java +++ b/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java @@ -1,7 +1,8 @@ package net.logstash.log4j; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import net.logstash.log4j.data.HostData; -import net.minidev.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.FastDateFormat; import org.apache.log4j.Layout; @@ -19,23 +20,14 @@ public class JSONEventLayoutV1 extends Layout { private boolean locationInfo = false; private String customUserFields; - private boolean ignoreThrowable = false; + private final String hostname = new HostData().getHostName(); + private static final int VERSION = 1; - private boolean activeIgnoreThrowable = ignoreThrowable; - private String hostname = new HostData().getHostName(); - private String threadName; - private long timestamp; - private String ndc; - private Map mdc; - private LocationInfo info; - private HashMap exceptionInformation; - private static Integer version = 1; + private static final ObjectMapper JSON_SERIALIZER = new ObjectMapper(); + private Map logstashEvent; - - private JSONObject logstashEvent; - - public static final TimeZone UTC = TimeZone.getTimeZone("UTC"); - public static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT_WITH_MILLIS = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", UTC); + private static final TimeZone UTC = TimeZone.getTimeZone("UTC"); + private static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT_WITH_MILLIS = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", UTC); public static final String ADDITIONAL_DATA_PROPERTY = "net.logstash.log4j.JSONEventLayoutV1.UserFields"; public static String dateFormat(long timestamp) { @@ -59,69 +51,74 @@ public JSONEventLayoutV1(boolean locationInfo) { this.locationInfo = locationInfo; } + @Override public String format(LoggingEvent loggingEvent) { - threadName = loggingEvent.getThreadName(); - timestamp = loggingEvent.getTimeStamp(); - exceptionInformation = new HashMap(); - mdc = loggingEvent.getProperties(); - ndc = loggingEvent.getNDC(); + String threadName = loggingEvent.getThreadName(); + long timestamp = loggingEvent.getTimeStamp(); + HashMap exceptionInformation = new HashMap(); + Map mdc = loggingEvent.getProperties(); + String ndc = loggingEvent.getNDC(); - logstashEvent = new JSONObject(); + logstashEvent = new HashMap(); String whoami = this.getClass().getSimpleName(); - /** + /* * All v1 of the event format requires is * "@timestamp" and "@version" * Every other field is arbitrary */ - logstashEvent.put("@version", version); + logstashEvent.put("@version", VERSION); logstashEvent.put("@timestamp", dateFormat(timestamp)); - /** + /* * Extract and add fields from log4j config, if defined */ if (getUserFields() != null) { - String userFlds = getUserFields(); - LogLog.debug("["+whoami+"] Got user data from log4j property: "+ userFlds); - addUserFields(userFlds); + String userFields = getUserFields(); + LogLog.debug(String.format("[%s] Got user data from log4j property: %s", whoami, userFields)); + addUserFields(userFields); } - /** + /* * Extract fields from system properties, if defined * Note that CLI props will override conflicts with log4j config */ - if (System.getProperty(ADDITIONAL_DATA_PROPERTY) != null) { + String additionalDataSystemProperty = System.getProperty(ADDITIONAL_DATA_PROPERTY); + if (additionalDataSystemProperty != null) { if (getUserFields() != null) { - LogLog.warn("["+whoami+"] Loading UserFields from command-line. This will override any UserFields set in the log4j configuration file"); + LogLog.warn(String.format("[%s] Loading UserFields from command-line. This will override any UserFields set in the log4j configuration file", whoami)); } - String userFieldsProperty = System.getProperty(ADDITIONAL_DATA_PROPERTY); - LogLog.debug("["+whoami+"] Got user data from system property: " + userFieldsProperty); - addUserFields(userFieldsProperty); + LogLog.debug(String.format("[%s] Got user data from system property: %s", whoami, additionalDataSystemProperty)); + addUserFields(additionalDataSystemProperty); } - /** + /* * Now we start injecting our own stuff. */ logstashEvent.put("source_host", hostname); logstashEvent.put("message", loggingEvent.getRenderedMessage()); - if (loggingEvent.getThrowableInformation() != null) { - final ThrowableInformation throwableInformation = loggingEvent.getThrowableInformation(); - if (throwableInformation.getThrowable().getClass().getCanonicalName() != null) { - exceptionInformation.put("exception_class", throwableInformation.getThrowable().getClass().getCanonicalName()); + final ThrowableInformation throwableInformation = loggingEvent.getThrowableInformation(); + if (throwableInformation != null) { + Throwable throwable = throwableInformation.getThrowable(); + String className = throwable.getClass().getCanonicalName(); + if (className != null) { + exceptionInformation.put("exception_class", className); } - if (throwableInformation.getThrowable().getMessage() != null) { - exceptionInformation.put("exception_message", throwableInformation.getThrowable().getMessage()); + String message = throwable.getMessage(); + if (message != null) { + exceptionInformation.put("exception_message", message); } - if (throwableInformation.getThrowableStrRep() != null) { - String stackTrace = StringUtils.join(throwableInformation.getThrowableStrRep(), "\n"); + String[] throwableStrRep = throwableInformation.getThrowableStrRep(); + if (throwableStrRep != null) { + String stackTrace = StringUtils.join(throwableStrRep, "\n"); exceptionInformation.put("stacktrace", stackTrace); } addEventData("exception", exceptionInformation); } if (locationInfo) { - info = loggingEvent.getLocationInformation(); + LocationInfo info = loggingEvent.getLocationInformation(); addEventData("file", info.getFileName()); addEventData("line_number", info.getLineNumber()); addEventData("class", info.getClassName()); @@ -134,11 +131,16 @@ public String format(LoggingEvent loggingEvent) { addEventData("level", loggingEvent.getLevel().toString()); addEventData("thread_name", threadName); - return logstashEvent.toString() + "\n"; + try { + return JSON_SERIALIZER.writeValueAsString(logstashEvent) + "\n"; + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } } + @Override public boolean ignoresThrowable() { - return ignoreThrowable; + return false; } /** @@ -163,7 +165,6 @@ public void setLocationInfo(boolean locationInfo) { public void setUserFields(String userFields) { this.customUserFields = userFields; } public void activateOptions() { - activeIgnoreThrowable = ignoreThrowable; } private void addUserFields(String data) { @@ -171,7 +172,7 @@ private void addUserFields(String data) { String[] pairs = data.split(","); for (String pair : pairs) { String[] userField = pair.split(":", 2); - if (userField[0] != null) { + if (userField.length > 1 && userField[0] != null) { String key = userField[0]; String val = userField[1]; addEventData(key, val); diff --git a/src/main/java/net/logstash/log4j/data/HostData.java b/src/main/java/net/logstash/log4j/data/HostData.java index 36bba8d..0330763 100644 --- a/src/main/java/net/logstash/log4j/data/HostData.java +++ b/src/main/java/net/logstash/log4j/data/HostData.java @@ -3,8 +3,7 @@ import java.net.UnknownHostException; public class HostData { - - public String hostName; + private String hostName; public String getHostName() { return hostName;