Skip to content

Commit a821741

Browse files
Merge pull request #161 from SAP/exceptions
Add Exceptions Type and Message
2 parents 4aa9584 + 27ec094 commit a821741

File tree

10 files changed

+174
-2
lines changed

10 files changed

+174
-2
lines changed

cf-java-logging-support-core/beats/app-logs/docs/fields.asciidoc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,28 @@ required: True
448448
The original log message that has been written by the application.
449449

450450

451+
==== exception_type
452+
453+
type: string
454+
455+
example: java.lang.NullPointerException
456+
457+
required: False
458+
459+
The Java class name of the logged exception when available.
460+
461+
462+
==== exception_message
463+
464+
type: string
465+
466+
example: Something went wrong
467+
468+
required: False
469+
470+
The message of the logged exception when available.
471+
472+
451473
==== stacktrace
452474

453475
type: array

cf-java-logging-support-core/beats/app-logs/etc/app-logs.template.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@
6363
"index": "not_analyzed",
6464
"type": "string"
6565
},
66+
"exception_message": {
67+
"doc_values": true,
68+
"index": "not_analyzed",
69+
"type": "string"
70+
},
71+
"exception_type": {
72+
"doc_values": true,
73+
"index": "not_analyzed",
74+
"type": "string"
75+
},
6676
"layer": {
6777
"doc_values": true,
6878
"index": "not_analyzed",

cf-java-logging-support-core/beats/app-logs/etc/fields.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,20 @@ app-logs:
312312
description: |
313313
The original log message that has been written by the application.
314314
315+
- name: "exception_type"
316+
type: string
317+
required: false
318+
example: "java.lang.NullPointerException"
319+
description: |
320+
The Java class name of the logged exception when available.
321+
322+
- name: "exception_message"
323+
type: string
324+
required: false
325+
example: "Something went wrong"
326+
description: |
327+
The message of the logged exception when available.
328+
315329
- name: "stacktrace"
316330
type: array
317331
required: false

cf-java-logging-support-core/beats/scripts/generate_fields_docs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def fields_to_asciidoc(input, output, beat):
7171
""".format(**dict))
7272

7373

74-
docs = yaml.load(input)
74+
docs = yaml.load(input, Loader=yaml.Loader)
7575

7676
# fields file is empty
7777
if docs is None:

cf-java-logging-support-core/beats/scripts/generate_template.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def fields_to_es_template(input, output, index):
2222
"""
2323

2424
# Custom properties
25-
docs = yaml.load(input)
25+
docs = yaml.load(input, Loader=yaml.Loader)
2626

2727
# No fields defined, can't generate template
2828
if docs is None:

cf-java-logging-support-core/src/main/java/com/sap/hcp/cf/logging/common/Fields.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public interface Fields {
4444
public String THREAD = "thread";
4545
public String LEVEL = "level";
4646
public String MSG = "msg";
47+
public String EXCEPTION_TYPE = "exception_type";
48+
public String EXCEPTION_MESSAGE = "exception_message";
4749
public String STACKTRACE = "stacktrace";
4850
public String CATEGORIES = "categories";
4951
public String CUSTOM_FIELDS = "#cf";

cf-java-logging-support-log4j2/src/main/java/com/sap/hcp/cf/log4j2/layout/supppliers/BaseFieldSupplier.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.HashMap;
55
import java.util.Map;
66

7+
import org.apache.commons.lang3.StringUtils;
78
import org.apache.logging.log4j.core.LogEvent;
89

910
import com.sap.hcp.cf.log4j2.converter.api.Log4jContextFieldSupplier;
@@ -24,6 +25,13 @@ public Map<String, Object> map(LogEvent event) {
2425
if (!LogEventUtilities.isRequestLog(event) && event.getMessage() != null) {
2526
fields.put(Fields.MSG, LogEventUtilities.getFormattedMessage(event));
2627
}
28+
if (event.getThrown() != null) {
29+
Throwable throwable = event.getThrown();
30+
fields.put(Fields.EXCEPTION_TYPE, throwable.getClass().getName());
31+
if (StringUtils.isNotBlank(throwable.getMessage())) {
32+
fields.put(Fields.EXCEPTION_MESSAGE, throwable.getMessage());
33+
}
34+
}
2735
return fields;
2836
}
2937

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.sap.hcp.cf.log4j2.layout.suppliers;
2+
3+
import com.sap.hcp.cf.log4j2.converter.api.Log4jContextFieldSupplier;
4+
import com.sap.hcp.cf.log4j2.layout.supppliers.BaseFieldSupplier;
5+
import com.sap.hcp.cf.logging.common.Fields;
6+
import org.apache.logging.log4j.core.LogEvent;
7+
import org.apache.logging.log4j.core.time.Instant;
8+
import org.junit.Before;
9+
import org.junit.Test;
10+
import org.junit.runner.RunWith;
11+
import org.mockito.Mock;
12+
import org.mockito.Mockito;
13+
import org.mockito.runners.MockitoJUnitRunner;
14+
15+
import java.time.Clock;
16+
import java.util.Map;
17+
18+
import static org.hamcrest.MatcherAssert.assertThat;
19+
import static org.junit.Assert.*;
20+
21+
import static org.hamcrest.Matchers.hasEntry;
22+
import static org.hamcrest.MatcherAssert.*;
23+
import static org.hamcrest.Matchers.*;
24+
import static org.mockito.Mockito.mock;
25+
import static org.mockito.Mockito.when;
26+
27+
@RunWith(MockitoJUnitRunner.class)
28+
public class BaseFieldSupplierTest {
29+
30+
@Mock
31+
private LogEvent event;
32+
33+
private Log4jContextFieldSupplier baseFieldSupplier = new BaseFieldSupplier();
34+
35+
@Before
36+
public void initializeEvent() {
37+
when(event.getInstant()).thenReturn(mock(Instant.class));
38+
}
39+
40+
@Test
41+
public void addsNoExceptionFieldsWithoutException() {
42+
Map<String, Object> fields = baseFieldSupplier.map(event);
43+
44+
assertThat(fields, not(hasKey(Fields.EXCEPTION_TYPE)));
45+
assertThat(fields, not(hasKey(Fields.EXCEPTION_MESSAGE)));
46+
}
47+
48+
@Test
49+
public void mapsException() {
50+
Exception exception = new RuntimeException("exception message");
51+
when(event.getThrown()).thenReturn(exception);
52+
53+
Map<String, Object> fields = baseFieldSupplier.map(event);
54+
55+
assertThat(fields, hasEntry(Fields.EXCEPTION_TYPE, RuntimeException.class.getName()));
56+
assertThat(fields, hasEntry(Fields.EXCEPTION_MESSAGE, "exception message"));
57+
}
58+
}

cf-java-logging-support-logback/src/main/java/com/sap/hcp/cf/logback/encoder/BaseFieldSupplier.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
import java.util.HashMap;
55
import java.util.Map;
66

7+
import ch.qos.logback.classic.spi.ThrowableProxy;
78
import com.sap.hcp.cf.logback.converter.api.LogbackContextFieldSupplier;
89
import com.sap.hcp.cf.logging.common.Defaults;
910
import com.sap.hcp.cf.logging.common.Fields;
1011
import com.sap.hcp.cf.logging.common.Markers;
1112

1213
import ch.qos.logback.classic.spi.ILoggingEvent;
14+
import org.apache.commons.lang3.StringUtils;
1315

1416
public class BaseFieldSupplier implements LogbackContextFieldSupplier {
1517

@@ -25,6 +27,13 @@ public Map<String, Object> map(ILoggingEvent event) {
2527
if (!isRequestLog(event)) {
2628
fields.put(Fields.MSG, event.getFormattedMessage());
2729
}
30+
if (event.getThrowableProxy() != null && event.getThrowableProxy() instanceof ThrowableProxy) {
31+
Throwable throwable = ((ThrowableProxy) event.getThrowableProxy()).getThrowable();
32+
fields.put(Fields.EXCEPTION_TYPE, throwable.getClass().getName());
33+
if (StringUtils.isNotBlank(throwable.getMessage())) {
34+
fields.put(Fields.EXCEPTION_MESSAGE, throwable.getMessage());
35+
}
36+
}
2837
return fields;
2938
}
3039

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.sap.hcp.cf.logback.encoder;
2+
3+
import ch.qos.logback.classic.spi.ILoggingEvent;
4+
import ch.qos.logback.classic.spi.ThrowableProxy;
5+
import com.sap.hcp.cf.logback.converter.api.LogbackContextFieldSupplier;
6+
import com.sap.hcp.cf.logging.common.Fields;
7+
import org.apache.commons.math3.stat.inference.GTest;
8+
import org.hamcrest.MatcherAssert;
9+
import org.hamcrest.Matchers;
10+
import org.junit.Test;
11+
import org.junit.runner.RunWith;
12+
import org.mockito.Mock;
13+
import org.mockito.Mockito;
14+
import org.mockito.runners.MockitoJUnitRunner;
15+
16+
import java.util.Map;
17+
18+
import static org.hamcrest.Matchers.hasEntry;
19+
import static org.hamcrest.MatcherAssert.*;
20+
import static org.hamcrest.Matchers.*;
21+
import static org.mockito.Mockito.when;
22+
23+
@RunWith(MockitoJUnitRunner.class)
24+
public class BaseFieldSupplierTest {
25+
26+
@Mock
27+
private ILoggingEvent event;
28+
29+
private LogbackContextFieldSupplier baseFieldSupplier = new BaseFieldSupplier();
30+
31+
@Test
32+
public void addsNoExceptionFieldsWithoutException() {
33+
Map<String, Object> fields = baseFieldSupplier.map(event);
34+
35+
assertThat(fields, not(hasKey(Fields.EXCEPTION_TYPE)));
36+
assertThat(fields, not(hasKey(Fields.EXCEPTION_MESSAGE)));
37+
}
38+
39+
@Test
40+
public void mapsException() {
41+
Exception exception = new RuntimeException("exception message");
42+
when(event.getThrowableProxy()).thenReturn(new ThrowableProxy(exception));
43+
44+
Map<String, Object> fields = baseFieldSupplier.map(event);
45+
46+
assertThat(fields, hasEntry(Fields.EXCEPTION_TYPE, RuntimeException.class.getName()));
47+
assertThat(fields, hasEntry(Fields.EXCEPTION_MESSAGE, "exception message"));
48+
}
49+
}

0 commit comments

Comments
 (0)