Skip to content

Commit 6a94f18

Browse files
Sending Java Throwable instead of mesage
Update: - While sending events, only exception message was sent earlier. - Throwable object will be sent instead of exception message to get more clarity of any exception raised. - Changes applied on all three appenders (Log4j2, Logback & Java Logging).
1 parent 82c4a56 commit 6a94f18

File tree

3 files changed

+76
-16
lines changed

3 files changed

+76
-16
lines changed

src/main/java/com/splunk/logging/HttpEventCollectorLog4jAppender.java

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,27 @@
1515
* under the License.
1616
*/
1717

18-
import java.io.Serializable;
19-
import java.nio.charset.StandardCharsets;
20-
import java.util.HashMap;
21-
import java.util.Map;
22-
import java.util.concurrent.TimeUnit;
23-
18+
import com.google.gson.Gson;
2419
import com.splunk.logging.hec.MetadataTags;
25-
import org.apache.logging.log4j.core.appender.AbstractAppender;
2620
import org.apache.logging.log4j.core.Filter;
2721
import org.apache.logging.log4j.core.Layout;
28-
import org.apache.logging.log4j.core.config.Property;
29-
import org.apache.logging.log4j.core.layout.PatternLayout;
3022
import org.apache.logging.log4j.core.LogEvent;
23+
import org.apache.logging.log4j.core.appender.AbstractAppender;
24+
import org.apache.logging.log4j.core.config.Property;
3125
import org.apache.logging.log4j.core.config.plugins.Plugin;
3226
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
3327
import org.apache.logging.log4j.core.config.plugins.PluginElement;
3428
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
29+
import org.apache.logging.log4j.core.impl.MutableLogEvent;
30+
import org.apache.logging.log4j.core.layout.PatternLayout;
31+
32+
import java.io.Serializable;
33+
import java.nio.charset.StandardCharsets;
34+
import java.util.Arrays;
35+
import java.util.HashMap;
36+
import java.util.LinkedHashMap;
37+
import java.util.Map;
38+
import java.util.concurrent.TimeUnit;
3539

3640
/**
3741
* Splunk Http Appender.
@@ -237,15 +241,32 @@ public static HttpEventCollectorLog4jAppender createAppender(
237241
@Override
238242
public void append(final LogEvent event)
239243
{
244+
boolean isExceptionThrown = false;
245+
// Wrapping exception throws in a map to showcase exception details in events.
246+
Map<String, String> exceptionDetailMap = new LinkedHashMap<>();
247+
if (event.getThrown() != null) {
248+
Throwable throwable = event.getThrown();
249+
isExceptionThrown = true;
250+
exceptionDetailMap.put("detailMessage", throwable.getMessage());
251+
exceptionDetailMap.put("exceptionClass", throwable.getClass().toString());
252+
253+
} else if ((((MutableLogEvent) event).getParameters()).length > 0) {
254+
isExceptionThrown = true;
255+
exceptionDetailMap.put("exceptionClass", Arrays.toString(Arrays.stream(((MutableLogEvent) event).getParameters()).toArray()));
256+
}
257+
exceptionDetailMap.put("fileName", event.getSource().getFileName());
258+
exceptionDetailMap.put("lineNumber", String.valueOf(event.getSource().getLineNumber()));
259+
exceptionDetailMap.put("methodName", event.getSource().getMethodName());
260+
240261
// if an exception was thrown
241262
this.sender.send(
242-
event.getTimeMillis(),
263+
event.getTimeMillis(),
243264
event.getLevel().toString(),
244265
getLayout().toSerializable(event).toString(),
245266
includeLoggerName ? event.getLoggerName() : null,
246267
includeThreadName ? event.getThreadName() : null,
247268
includeMDC ? event.getContextData().toMap() : null,
248-
(!includeException || event.getThrown() == null) ? null : event.getThrown().getMessage(),
269+
(includeException && isExceptionThrown) ? new Gson().toJson(exceptionDetailMap) : null,
249270
includeMarker ? event.getMarker() : null
250271
);
251272
}

src/main/java/com/splunk/logging/HttpEventCollectorLogbackAppender.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@
1717

1818
import ch.qos.logback.classic.pattern.MarkerConverter;
1919
import ch.qos.logback.classic.spi.ILoggingEvent;
20+
import ch.qos.logback.classic.spi.StackTraceElementProxy;
2021
import ch.qos.logback.core.AppenderBase;
2122
import ch.qos.logback.core.Layout;
23+
import com.google.gson.Gson;
2224
import com.splunk.logging.hec.MetadataTags;
2325

24-
import java.util.*;
26+
import java.util.HashMap;
27+
import java.util.LinkedHashMap;
28+
import java.util.Map;
2529

2630
/**
2731
* Logback Appender which writes its events to Splunk http event collector rest endpoint.
@@ -153,6 +157,21 @@ private void sendEvent(ILoggingEvent event) {
153157
event.getCallerData();
154158
}
155159

160+
// Wrapping exception throws in a map to showcase exception details in events.
161+
Map<Object, Object> exceptionDetailMap = new LinkedHashMap<>();
162+
if (event.getThrowableProxy() != null) {
163+
StackTraceElementProxy[] elements = event.getThrowableProxy().getStackTraceElementProxyArray();
164+
exceptionDetailMap.put("detailMessage", event.getThrowableProxy().getMessage());
165+
exceptionDetailMap.put("exceptionClass", event.getThrowableProxy().getClassName());
166+
167+
// Retrieving first element from elements array is because the throws exception detail would be available as a first element.
168+
if (elements != null && elements.length > 0 && elements[0] != null) {
169+
exceptionDetailMap.put("fileName", elements[0].getStackTraceElement().getFileName());
170+
exceptionDetailMap.put("lineNumber", String.valueOf(elements[0].getStackTraceElement().getLineNumber()));
171+
exceptionDetailMap.put("methodName", elements[0].getStackTraceElement().getMethodName());
172+
}
173+
}
174+
156175
MarkerConverter c = new MarkerConverter();
157176
if (this.started) {
158177
this.sender.send(
@@ -162,7 +181,7 @@ private void sendEvent(ILoggingEvent event) {
162181
_includeLoggerName ? event.getLoggerName() : null,
163182
_includeThreadName ? event.getThreadName() : null,
164183
_includeMDC ? event.getMDCPropertyMap() : null,
165-
(!_includeException || event.getThrowableProxy() == null) ? null : event.getThrowableProxy().getMessage(),
184+
(!_includeException || event.getThrowableProxy() == null) ? null : new Gson().toJson(exceptionDetailMap),
166185
c.convert(event)
167186
);
168187
}

src/main/java/com/splunk/logging/HttpEventCollectorLoggingHandler.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,13 @@
8080
* com.splunk.logging.HttpEventCollectorLoggingHandler.send_mode=sequential
8181
*/
8282

83+
import com.google.gson.Gson;
8384
import com.splunk.logging.hec.MetadataTags;
8485

85-
import java.util.*;
86+
import java.util.HashMap;
87+
import java.util.LinkedHashMap;
88+
import java.util.Locale;
89+
import java.util.Map;
8690
import java.util.logging.Handler;
8791
import java.util.logging.LogManager;
8892
import java.util.logging.LogRecord;
@@ -235,14 +239,30 @@ public HttpEventCollectorLoggingHandler() {
235239
*/
236240
@Override
237241
public void publish(LogRecord record) {
242+
243+
// Wrapping exception throws in a map to showcase exception details in events.
244+
Map<Object, Object> exceptionDetailMap = new LinkedHashMap<>();
245+
if (record.getThrown() != null) {
246+
StackTraceElement[] elements = record.getThrown().getStackTrace();
247+
exceptionDetailMap.put("detailMessage", record.getThrown().getMessage());
248+
exceptionDetailMap.put("exceptionClass", record.getThrown().getClass().toString());
249+
250+
// Retrieving first element from elements array is because the throws exception detail would be available as a first element.
251+
if (elements != null && elements.length > 0 && elements[0] != null) {
252+
exceptionDetailMap.put("fileName", elements[0].getFileName());
253+
exceptionDetailMap.put("lineNumber", String.valueOf(elements[0].getLineNumber()));
254+
exceptionDetailMap.put("methodName", elements[0].getMethodName());
255+
}
256+
}
257+
238258
this.sender.send(
239-
record.getMillis(),
259+
record.getMillis(),
240260
record.getLevel().toString(),
241261
record.getMessage(),
242262
includeLoggerName ? record.getLoggerName() : null,
243263
includeThreadName ? String.format(Locale.US, "%d", record.getThreadID()) : null,
244264
null, // no property map available
245-
(!includeException || record.getThrown() == null) ? null : record.getThrown().getMessage(),
265+
(!includeException || record.getThrown() == null) ? null : new Gson().toJson(exceptionDetailMap),
246266
null // no marker available
247267
);
248268
}

0 commit comments

Comments
 (0)