From f59a88607742440eaddbc510cc5b843dbec36149 Mon Sep 17 00:00:00 2001 From: Harbhajan Singh Date: Tue, 6 Dec 2016 08:06:40 -0500 Subject: [PATCH 1/2] Add message object's fields to top level fields --- .../net/logstash/log4j/JSONEventLayoutV0.java | 40 +++++++++++++++++++ .../net/logstash/log4j/JSONEventLayoutV1.java | 39 +++++++++++++++++- .../logstash/log4j/JSONEventLayoutV0Test.java | 36 +++++++++++++++++ .../logstash/log4j/JSONEventLayoutV1Test.java | 34 ++++++++++++++++ 4 files changed, 148 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/logstash/log4j/JSONEventLayoutV0.java b/src/main/java/net/logstash/log4j/JSONEventLayoutV0.java index b29e3fe..bac65e8 100644 --- a/src/main/java/net/logstash/log4j/JSONEventLayoutV0.java +++ b/src/main/java/net/logstash/log4j/JSONEventLayoutV0.java @@ -9,6 +9,9 @@ import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.ThrowableInformation; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.TimeZone; @@ -68,6 +71,21 @@ public String format(LoggingEvent loggingEvent) { logstashEvent.put("@source_host", hostname); logstashEvent.put("@message", loggingEvent.getRenderedMessage()); + + /** + * Check if msg is Map, if Map add fields to log events + */ + Object messageObj = loggingEvent.getMessage(); + if (messageObj instanceof Serializable && ! (messageObj instanceof String)) { + try { + addObjectFieldData(messageObj); + } catch (Exception ex) { + logstashEvent.put("message", loggingEvent.getRenderedMessage()); + } + } else { + logstashEvent.put("message", loggingEvent.getRenderedMessage()); + } + logstashEvent.put("@timestamp", dateFormat(timestamp)); if (loggingEvent.getThrowableInformation() != null) { @@ -134,4 +152,26 @@ private void addFieldData(String keyname, Object keyval) { fieldData.put(keyname, keyval); } } + + private void addObjectFieldData(Object messageObj) throws Exception { + if (messageObj instanceof Map) { + Map messageObjMap = (Map) messageObj; + for (Object key : messageObjMap.keySet()) { + addFieldData(key.toString(), messageObjMap.get(key)); + } + } else { + Field[] fields = messageObj.getClass().getDeclaredFields(); + + for (Field field : fields) { + addFieldData(field.getName(), field.get(messageObj)); + } + Method[] methods = messageObj.getClass().getDeclaredMethods(); + for (Method m : methods) { + if (m.getName().startsWith("get")) { + addFieldData(m.getName().substring(3), m.invoke(messageObj)); + } + } + } + } + } diff --git a/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java b/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java index aaf3228..d637bbf 100644 --- a/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java +++ b/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java @@ -10,6 +10,9 @@ import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.ThrowableInformation; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.TimeZone; @@ -103,7 +106,20 @@ public String format(LoggingEvent loggingEvent) { * Now we start injecting our own stuff. */ logstashEvent.put("source_host", hostname); - logstashEvent.put("message", loggingEvent.getRenderedMessage()); + + /** + * Check if msg is Map, if Map add fields to log events + */ + Object messageObj = loggingEvent.getMessage(); + if (messageObj instanceof Serializable && ! (messageObj instanceof String)) { + try { + addObjectFieldData(messageObj); + } catch (Exception ex) { + logstashEvent.put("message", loggingEvent.getRenderedMessage()); + } + } else { + logstashEvent.put("message", loggingEvent.getRenderedMessage()); + } if (loggingEvent.getThrowableInformation() != null) { final ThrowableInformation throwableInformation = loggingEvent.getThrowableInformation(); @@ -184,4 +200,25 @@ private void addEventData(String keyname, Object keyval) { logstashEvent.put(keyname, keyval); } } + + private void addObjectFieldData(Object messageObj) throws Exception { + if (messageObj instanceof Map) { + Map messageObjMap = (Map) messageObj; + for (Object key : messageObjMap.keySet()) { + addEventData(key.toString(), messageObjMap.get(key)); + } + } else { + Field[] fields = messageObj.getClass().getDeclaredFields(); + + for (Field field : fields) { + addEventData(field.getName(), field.get(messageObj)); + } + Method[] methods = messageObj.getClass().getDeclaredMethods(); + for (Method m : methods) { + if (m.getName().startsWith("get")) { + addEventData(m.getName().substring(3), m.invoke(messageObj)); + } + } + } + } } diff --git a/src/test/java/net/logstash/log4j/JSONEventLayoutV0Test.java b/src/test/java/net/logstash/log4j/JSONEventLayoutV0Test.java index 969ccc7..63ba2df 100644 --- a/src/test/java/net/logstash/log4j/JSONEventLayoutV0Test.java +++ b/src/test/java/net/logstash/log4j/JSONEventLayoutV0Test.java @@ -12,6 +12,10 @@ import org.junit.Ignore; import org.junit.Test; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + /** * Created with IntelliJ IDEA. * User: jvincent @@ -215,4 +219,36 @@ public void testDateFormat() { long timestamp = 1364844991207L; Assert.assertEquals("format does not produce expected output", "2013-04-01T19:36:31.207Z", JSONEventLayoutV0.dateFormat(timestamp)); } + + @Test + public void testMessageObjectRendering() { + logger.info(new Serializable() { + String test = "TEST"; + int testNum = 1123; + }); + String message = appender.getMessages()[0]; + System.out.println(message); + Object obj = JSONValue.parse(message); + JSONObject jsonObject = (JSONObject) obj; + JSONObject atFields = (JSONObject) jsonObject.get("@fields"); + Assert.assertTrue(atFields.containsKey("testNum")); + Assert.assertTrue(atFields.get("testNum") instanceof Integer); + Assert.assertEquals(atFields.get("testNum"), 1123); + } + + @Test + public void testMessageObjectRenderingMap() { + Map testMap = new HashMap(); + testMap.put("test", "TEST"); + testMap.put("testNum", 12345); + + logger.info(testMap); + String message = appender.getMessages()[0]; + Object obj = JSONValue.parse(message); + JSONObject jsonObject = (JSONObject) obj; + JSONObject atFields = (JSONObject) jsonObject.get("@fields"); + Assert.assertTrue(atFields.containsKey("testNum")); + Assert.assertTrue(atFields.get("testNum") instanceof Integer); + Assert.assertEquals(atFields.get("testNum"), 12345); + } } diff --git a/src/test/java/net/logstash/log4j/JSONEventLayoutV1Test.java b/src/test/java/net/logstash/log4j/JSONEventLayoutV1Test.java index 96ad821..dde87a8 100644 --- a/src/test/java/net/logstash/log4j/JSONEventLayoutV1Test.java +++ b/src/test/java/net/logstash/log4j/JSONEventLayoutV1Test.java @@ -12,7 +12,9 @@ import org.junit.Ignore; import org.junit.Test; +import java.io.Serializable; import java.util.HashMap; +import java.util.Map; /** * Created with IntelliJ IDEA. @@ -291,4 +293,36 @@ public void testDateFormat() { long timestamp = 1364844991207L; Assert.assertEquals("format does not produce expected output", "2013-04-01T19:36:31.207Z", JSONEventLayoutV1.dateFormat(timestamp)); } + + @Test + public void testMessageObjectRendering() { + JSONEventLayoutV1 layout = (JSONEventLayoutV1) appender.getLayout(); + logger.info(new Serializable() { + String test = "TEST"; + int testNum = 12345; + }); + String message = appender.getMessages()[0]; + System.out.println(message); + Object obj = JSONValue.parse(message); + JSONObject jsonObject = (JSONObject) obj; + Assert.assertTrue(jsonObject.containsKey("testNum")); + Assert.assertTrue(jsonObject.get("testNum") instanceof Integer); + Assert.assertEquals(jsonObject.get("testNum"), 12345); + } + + @Test + public void testMessageObjectRenderingMap() { + JSONEventLayoutV1 layout = (JSONEventLayoutV1) appender.getLayout(); + Map testMap = new HashMap(); + testMap.put("test", "TEST"); + testMap.put("testNum", 12345); + + logger.info(testMap); + String message = appender.getMessages()[0]; + Object obj = JSONValue.parse(message); + JSONObject jsonObject = (JSONObject) obj; + Assert.assertTrue(jsonObject.containsKey("testNum")); + Assert.assertTrue(jsonObject.get("testNum") instanceof Integer); + Assert.assertEquals(jsonObject.get("testNum"), 12345); + } } From 94dffd95ee64fe615410e6a39661b4541bcea031 Mon Sep 17 00:00:00 2001 From: Harbhajan Singh Date: Thu, 8 Dec 2016 00:26:28 -0500 Subject: [PATCH 2/2] Update MDC properties to be top level as well --- src/main/java/net/logstash/log4j/JSONEventLayoutV0.java | 5 +++++ src/main/java/net/logstash/log4j/JSONEventLayoutV1.java | 5 +++++ src/test/java/net/logstash/log4j/JSONEventLayoutV0Test.java | 1 + src/test/java/net/logstash/log4j/JSONEventLayoutV1Test.java | 1 + 4 files changed, 12 insertions(+) diff --git a/src/main/java/net/logstash/log4j/JSONEventLayoutV0.java b/src/main/java/net/logstash/log4j/JSONEventLayoutV0.java index bac65e8..4e9d555 100644 --- a/src/main/java/net/logstash/log4j/JSONEventLayoutV0.java +++ b/src/main/java/net/logstash/log4j/JSONEventLayoutV0.java @@ -113,6 +113,11 @@ public String format(LoggingEvent loggingEvent) { addFieldData("loggerName", loggingEvent.getLoggerName()); addFieldData("mdc", mdc); + try { + addObjectFieldData(mdc); + } catch (Exception e) { + } + addFieldData("ndc", ndc); addFieldData("level", loggingEvent.getLevel().toString()); addFieldData("threadName", threadName); diff --git a/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java b/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java index d637bbf..cc45909 100644 --- a/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java +++ b/src/main/java/net/logstash/log4j/JSONEventLayoutV1.java @@ -146,6 +146,11 @@ public String format(LoggingEvent loggingEvent) { addEventData("logger_name", loggingEvent.getLoggerName()); addEventData("mdc", mdc); + try { + addObjectFieldData(mdc); + } catch (Exception e) { + } + addEventData("ndc", ndc); addEventData("level", loggingEvent.getLevel().toString()); addEventData("thread_name", threadName); diff --git a/src/test/java/net/logstash/log4j/JSONEventLayoutV0Test.java b/src/test/java/net/logstash/log4j/JSONEventLayoutV0Test.java index 63ba2df..26f3f59 100644 --- a/src/test/java/net/logstash/log4j/JSONEventLayoutV0Test.java +++ b/src/test/java/net/logstash/log4j/JSONEventLayoutV0Test.java @@ -103,6 +103,7 @@ public void testJSONEventLayoutHasMDC() { JSONObject atFields = (JSONObject) jsonObject.get("@fields"); JSONObject mdcData = (JSONObject) atFields.get("mdc"); + Assert.assertEquals("MDC is wrong","bar", atFields.get("foo")); Assert.assertEquals("MDC is wrong","bar", mdcData.get("foo")); } diff --git a/src/test/java/net/logstash/log4j/JSONEventLayoutV1Test.java b/src/test/java/net/logstash/log4j/JSONEventLayoutV1Test.java index dde87a8..078eab6 100644 --- a/src/test/java/net/logstash/log4j/JSONEventLayoutV1Test.java +++ b/src/test/java/net/logstash/log4j/JSONEventLayoutV1Test.java @@ -167,6 +167,7 @@ public void testJSONEventLayoutHasMDC() { JSONObject jsonObject = (JSONObject) obj; JSONObject mdc = (JSONObject) jsonObject.get("mdc"); + Assert.assertEquals("MDC is wrong","bar", jsonObject.get("foo")); Assert.assertEquals("MDC is wrong","bar", mdc.get("foo")); }