Skip to content

Commit 658a53f

Browse files
Merge pull request #39 from SAP/mdc_2_custom-field
Create Custom Fields from MDC (Log4j)
2 parents 38251db + 74ffc2b commit 658a53f

File tree

15 files changed

+731
-331
lines changed

15 files changed

+731
-331
lines changed

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ public void setFieldName(String fieldName) {
2424
}
2525
}
2626

27-
public void convert(Object[] arguments, StringBuilder appendTo) {
28-
convert(appendTo, Collections.emptyMap(), arguments);
29-
}
30-
3127
public void convert(StringBuilder appendTo, Map<String, String> mdcCustomFields, Object... arguments) {
3228
List<CustomField> customFields = getCustomFields(arguments);
3329
if (!customFields.isEmpty() || !mdcCustomFields.isEmpty()) {

cf-java-logging-support-log4j2/src/main/java/com/sap/hcp/cf/log4j2/converter/ArgsConverter.java

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.sap.hcp.cf.log4j2.converter;
2+
3+
import static java.util.Arrays.asList;
4+
import static java.util.Collections.emptyList;
5+
import static java.util.Collections.unmodifiableList;
6+
7+
import java.util.Collections;
8+
import java.util.HashMap;
9+
import java.util.List;
10+
import java.util.Map;
11+
12+
import org.apache.logging.log4j.core.LogEvent;
13+
import org.apache.logging.log4j.core.config.plugins.Plugin;
14+
import org.apache.logging.log4j.core.pattern.ConverterKeys;
15+
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
16+
import org.apache.logging.log4j.core.pattern.PatternConverter;
17+
import org.apache.logging.log4j.message.Message;
18+
import org.apache.logging.log4j.util.BiConsumer;
19+
import org.apache.logging.log4j.util.ReadOnlyStringMap;
20+
21+
import com.sap.hcp.cf.logging.common.converter.DefaultCustomFieldsConverter;
22+
import com.sap.hcp.cf.logging.common.customfields.CustomField;
23+
24+
/**
25+
* This is a simple {@link LogEventPatternConverter} implementation that
26+
* converts key/value pairs stored in {@link CustomField} instances which have
27+
* been passed as arguments.
28+
* <p>
29+
* We allow to types of addition to a log message, either <i>embedded</i>, i.e.
30+
* the key/value pairs appear as a list of JSON fields in the message, or as a
31+
* nested object where the field name has been specified as an option to this
32+
* converter.
33+
*/
34+
@Plugin(name = "ArgsConverter", category = PatternConverter.CATEGORY)
35+
@ConverterKeys({ "cf" })
36+
public class CustomFieldsConverter extends LogEventPatternConverter {
37+
38+
public static final String WORD = "cf";
39+
40+
private final List<String> customFieldMdcKeyNames;
41+
private DefaultCustomFieldsConverter converter = new DefaultCustomFieldsConverter();
42+
43+
public CustomFieldsConverter(String[] options) {
44+
super(WORD, WORD);
45+
46+
customFieldMdcKeyNames = options == null ? emptyList() : unmodifiableList(asList(options));
47+
}
48+
49+
public static CustomFieldsConverter newInstance(final String[] options) {
50+
return new CustomFieldsConverter(options);
51+
}
52+
53+
void setConverter(DefaultCustomFieldsConverter converter) {
54+
this.converter = converter;
55+
}
56+
57+
@Override
58+
public void format(LogEvent event, StringBuilder appendTo) {
59+
converter.convert(appendTo, getCustomFieldsFromMdc(event), getMessageParameters(event));
60+
}
61+
62+
private Object[] getMessageParameters(LogEvent event) {
63+
Message message = event.getMessage();
64+
return message == null ? null : message.getParameters();
65+
}
66+
67+
private Map<String, String> getCustomFieldsFromMdc(LogEvent event) {
68+
ReadOnlyStringMap contextData = event.getContextData();
69+
if (contextData == null || contextData.isEmpty()) {
70+
return Collections.emptyMap();
71+
}
72+
CustomFieldsMdcCollector mdcCollector = new CustomFieldsMdcCollector();
73+
contextData.forEach(mdcCollector);
74+
return mdcCollector.getCustomFields();
75+
}
76+
77+
private class CustomFieldsMdcCollector implements BiConsumer<String, String> {
78+
private Map<String, String> customFields = new HashMap<>(customFieldMdcKeyNames.size());
79+
80+
@Override
81+
public void accept(String key, String value) {
82+
if (customFieldMdcKeyNames.contains(key)) {
83+
customFields.put(key, value);
84+
}
85+
}
86+
87+
public Map<String, String> getCustomFields() {
88+
return customFields;
89+
}
90+
}
91+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.sap.hcp.cf.log4j2.layout;
2+
3+
import org.apache.logging.log4j.core.config.Node;
4+
import org.apache.logging.log4j.core.config.plugins.Plugin;
5+
import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
6+
import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
7+
8+
@Plugin(name = "customField", category = Node.CATEGORY, printObject = true)
9+
public class CustomField {
10+
11+
private final String key;
12+
private final boolean retainOriginal;
13+
14+
private CustomField(Builder builder) {
15+
this.key = builder.key;
16+
this.retainOriginal = builder.retainOriginal;
17+
}
18+
19+
public String getKey() {
20+
return key;
21+
}
22+
23+
public boolean isRetainOriginal() {
24+
return retainOriginal;
25+
}
26+
27+
@Override
28+
public String toString() {
29+
return key + (retainOriginal ? " (retained)" : "");
30+
}
31+
32+
@PluginBuilderFactory
33+
public static Builder newBuilder() {
34+
return new Builder();
35+
}
36+
37+
public static class Builder implements org.apache.logging.log4j.core.util.Builder<CustomField> {
38+
39+
@PluginBuilderAttribute("mdcKeyName")
40+
private String key;
41+
42+
@PluginBuilderAttribute("retainOriginal")
43+
private boolean retainOriginal;
44+
45+
public Builder setKey(String key) {
46+
this.key = key;
47+
return this;
48+
}
49+
50+
public Builder setRetainOriginal(boolean retainOriginal) {
51+
this.retainOriginal = retainOriginal;
52+
return this;
53+
}
54+
55+
@Override
56+
public CustomField build() {
57+
return new CustomField(this);
58+
}
59+
60+
}
61+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.sap.hcp.cf.log4j2.layout;
2+
3+
import static java.util.Arrays.asList;
4+
import static java.util.Collections.emptyList;
5+
6+
import java.util.ArrayList;
7+
import java.util.Collection;
8+
import java.util.List;
9+
10+
import com.sap.hcp.cf.logging.common.LogContext;
11+
12+
public class CustomFieldsAdapter {
13+
14+
private List<CustomField> customFields;
15+
16+
public CustomFieldsAdapter(CustomField... customFields) {
17+
this.customFields = customFields == null ? emptyList() : asList(customFields);
18+
}
19+
20+
public List<String> getCustomFieldKeyNames() {
21+
List<String> result = new ArrayList<>(customFields.size());
22+
for (CustomField customField : customFields) {
23+
result.add(customField.getKey());
24+
}
25+
return result;
26+
}
27+
28+
public List<String> getExcludedFieldKeyNames() {
29+
Collection<String> contextFieldsKeys = LogContext.getContextFieldsKeys();
30+
List<String> result = new ArrayList<>(customFields.size());
31+
for (CustomField customField : customFields) {
32+
if (!customField.isRetainOriginal() && !contextFieldsKeys.contains(customField.getKey())) {
33+
result.add(customField.getKey());
34+
}
35+
}
36+
return result;
37+
}
38+
39+
}

0 commit comments

Comments
 (0)