contextFields) {
+ contextFields.keySet().stream().filter(this::isContextField).forEach(n -> addContextField(oc, n, contextFields
+ .get(n)));
+ ;
+ }
+
+ private boolean isContextField(String name) {
+ return retainFieldMdcKeyNames.contains(name) || !customFieldMdcKeyNames.contains(name);
+ }
+
+ private void addContextField(ObjectComposer
oc, String name, Object value) {
+ try {
+ if (sendDefaultValues) {
+ put(oc, name, value);
+ } else {
+ String defaultValue = getDefaultValue(name);
+ if (!defaultValue.equals(value)) {
+ put(oc, name, value);
+ }
+ }
+ } catch (IOException ignored) {
+ try {
+ oc.put(name, "invalid value");
+ } catch (IOException cause) {
+ throw new JsonSerializationException("Cannot create field \"" + name + "\".", cause);
+ }
+ }
+ }
+
+ private
void put(ObjectComposer
oc, String name, Object value) throws IOException,
+ JsonProcessingException {
+ if (value instanceof String) {
+ oc.put(name, (String) value);
+ } else if (value instanceof Long) {
+ oc.put(name, ((Long) value).longValue());
+ } else if (value instanceof Double) {
+ oc.put(name, ((Double) value).doubleValue());
+ } else if (value instanceof Boolean) {
+ oc.put(name, ((Boolean) value).booleanValue());
+ } else if (value instanceof Integer) {
+ oc.put(name, ((Integer) value).intValue());
+ } else if (value instanceof Float) {
+ oc.put(name, ((Float) value).floatValue());
+ } else {
+ oc.put(name, String.valueOf(value));
+ }
+ }
+
+ private String getDefaultValue(String key) {
+ String defaultValue = LogContext.getDefault(key);
+ return defaultValue == null ? Defaults.UNKNOWN : defaultValue;
+ }
+
+ public
void addCustomFields(ObjectComposer
oc, Map contextFields)
+ throws IOException,
+ JsonProcessingException {
+ ArrayComposer>> customFieldComposer = null;
+ for (int i = 0; i < customFieldMdcKeyNames.size(); i++) {
+ String key = customFieldMdcKeyNames.get(i);
+ Object value = contextFields.get(key);
+ if (value != null) {
+ if (customFieldComposer == null) {
+ customFieldComposer = oc.startObjectField(Fields.CUSTOM_FIELDS).startArrayField("string");
+ }
+ customFieldComposer.startObject().put("k", key).put("v", String.valueOf(value)).put("i", i).end();
+ }
+ }
+ if (customFieldComposer != null) {
+ customFieldComposer.end().end();
+ }
+ }
+
+}
diff --git a/cf-java-logging-support-core/src/main/java/com/sap/hcp/cf/logging/common/serialization/EventContextFieldSupplier.java b/cf-java-logging-support-core/src/main/java/com/sap/hcp/cf/logging/common/serialization/EventContextFieldSupplier.java
new file mode 100644
index 00000000..940828dc
--- /dev/null
+++ b/cf-java-logging-support-core/src/main/java/com/sap/hcp/cf/logging/common/serialization/EventContextFieldSupplier.java
@@ -0,0 +1,13 @@
+package com.sap.hcp.cf.logging.common.serialization;
+
+import java.util.Map;
+
+@FunctionalInterface
+public interface EventContextFieldSupplier extends ContextFieldSupplier {
+
+ Map map(T event);
+
+ default Map get() {
+ return map(null);
+ }
+}
diff --git a/cf-java-logging-support-logback/src/main/java/com/sap/hcp/cf/logback/encoder/JsonSerializationException.java b/cf-java-logging-support-core/src/main/java/com/sap/hcp/cf/logging/common/serialization/JsonSerializationException.java
similarity index 59%
rename from cf-java-logging-support-logback/src/main/java/com/sap/hcp/cf/logback/encoder/JsonSerializationException.java
rename to cf-java-logging-support-core/src/main/java/com/sap/hcp/cf/logging/common/serialization/JsonSerializationException.java
index 17d37026..ee811b67 100644
--- a/cf-java-logging-support-logback/src/main/java/com/sap/hcp/cf/logback/encoder/JsonSerializationException.java
+++ b/cf-java-logging-support-core/src/main/java/com/sap/hcp/cf/logging/common/serialization/JsonSerializationException.java
@@ -1,8 +1,8 @@
-package com.sap.hcp.cf.logback.encoder;
+package com.sap.hcp.cf.logging.common.serialization;
public class JsonSerializationException extends RuntimeException {
- private static final long serialVersionUID = 8365183525285128131L;
+ private static final long serialVersionUID = 6529980121185308722L;
public JsonSerializationException(String message, Throwable cause) {
super(message, cause);
diff --git a/cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/converter/AbstractConverterTest.java b/cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/converter/AbstractConverterTest.java
deleted file mode 100644
index 248e8d75..00000000
--- a/cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/converter/AbstractConverterTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.sap.hcp.cf.logging.common.converter;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.jr.ob.JSON;
-import com.fasterxml.jackson.jr.ob.JSONObjectException;
-
-public abstract class AbstractConverterTest {
- protected static final String EMPTY = "";
- protected static final String STRANGE_SEQ = "}{:\",\"";
- protected static final String TEST_MSG_NO_ARGS = "This is a test ";
-
- protected String formatMsg(DefaultMessageConverter mc, String msg) {
- StringBuilder sb = new StringBuilder();
- mc.convert(msg, sb);
- return sb.toString();
- }
-
- protected String formatStacktrace(DefaultStacktraceConverter dstc, Throwable t) {
- StringBuilder sb = new StringBuilder();
- dstc.convert(t, sb);
- return sb.toString();
- }
-
- protected Object arrayElem(String serialized, int i) throws JSONObjectException, IOException {
- return arrayFrom(serialized)[i];
- }
-
- protected Object[] arrayFrom(String serialized) throws JSONObjectException, IOException {
- return JSON.std.arrayFrom(serialized);
- }
-}
diff --git a/cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/converter/DefaultCustomFieldsConverterTest.java b/cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/converter/DefaultCustomFieldsConverterTest.java
deleted file mode 100644
index 76c4e799..00000000
--- a/cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/converter/DefaultCustomFieldsConverterTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package com.sap.hcp.cf.logging.common.converter;
-
-import static com.sap.hcp.cf.logging.common.converter.CustomFieldMatchers.hasCustomField;
-import static com.sap.hcp.cf.logging.common.converter.UnmarshallUtilities.unmarshalCustomFields;
-import static com.sap.hcp.cf.logging.common.customfields.CustomField.customField;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.Matchers.hasToString;
-import static org.hamcrest.Matchers.isEmptyString;
-import static org.junit.Assert.assertThat;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class DefaultCustomFieldsConverterTest {
-
- private static final String CUSTOM_KEY_0 = "custom_key_0";
- private static final String CUSTOM_VALUE_0 = "custom_value_0";
- private static final String CUSTOM_KEY_1 = "custom_key_1";
- private static final String CUSTOM_VALUE_1 = "custom_value_1";
- private static final String UNREGISTERED_KEY = "unregistered_key";
- private static final String UNREGISTERED_VALUE = "unregistered_value";
- private static final String HACK_ATTEMPT = "}{:\",\"";
- private DefaultCustomFieldsConverter converter;
-
- @Before
- public void initConverter() {
- this.converter = new DefaultCustomFieldsConverter();
- converter.setCustomFieldKeyNames(Arrays.asList(CUSTOM_KEY_0, CUSTOM_KEY_1));
- }
-
- @Test
- public void emptyMdcAndArguments() {
- StringBuilder sb = new StringBuilder();
-
- converter.convert(sb, Collections.emptyMap());
-
- assertThat(sb, hasToString(""));
- }
-
- @Test
- public void standardArgument() throws Exception {
- StringBuilder sb = new StringBuilder();
- converter.convert(sb, Collections.emptyMap(), "an_argument");
- assertThat(sb, hasToString(""));
- }
-
- @Test
- public void singleCustomFieldArgumentEmbedded() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- converter.convert(sb, Collections.emptyMap(), customField(CUSTOM_KEY_0, CUSTOM_VALUE_0));
-
- assertThat(unmarshalCustomFields(sb), contains(hasCustomField(CUSTOM_KEY_0, CUSTOM_VALUE_0, 0)));
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void multipleCustomFieldArgumentEmbedded() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- converter.convert(sb, Collections.emptyMap(), customField(CUSTOM_KEY_1, CUSTOM_VALUE_1),
- customField(UNREGISTERED_KEY, UNREGISTERED_VALUE), customField(CUSTOM_KEY_0, CUSTOM_VALUE_0));
-
- assertThat(unmarshalCustomFields(sb), containsInAnyOrder(hasCustomField(CUSTOM_KEY_0, CUSTOM_VALUE_0, 0),
- hasCustomField(CUSTOM_KEY_1, CUSTOM_VALUE_1, 1)));
- }
-
- @Test
- public void singleCustomFieldArgumentPrefix() throws Exception {
- converter.setFieldName("prefix");
- StringBuilder sb = new StringBuilder();
-
- converter.convert(sb, Collections.emptyMap(), customField(CUSTOM_KEY_0, CUSTOM_VALUE_0));
-
- assertThat(unmarshalCustomFields(sb, "prefix"), contains(hasCustomField(CUSTOM_KEY_0, CUSTOM_VALUE_0, 0)));
- }
-
- @Test
- public void singleMdcField() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- @SuppressWarnings("serial")
- Map mdcFields = new HashMap() {
- {
- put(CUSTOM_KEY_0, CUSTOM_VALUE_0);
- }
- };
-
- converter.convert(sb, mdcFields);
-
- assertThat(unmarshalCustomFields(sb), contains(hasCustomField(CUSTOM_KEY_0, CUSTOM_VALUE_0, 0)));
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void multipleMdcFields() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- @SuppressWarnings("serial")
- Map mdcFields = new HashMap() {
- {
- put(CUSTOM_KEY_1, CUSTOM_VALUE_1);
- put(UNREGISTERED_KEY, UNREGISTERED_VALUE);
- put(CUSTOM_KEY_0, CUSTOM_VALUE_0);
- }
- };
-
- converter.convert(sb, mdcFields);
-
- assertThat(unmarshalCustomFields(sb), containsInAnyOrder(hasCustomField(CUSTOM_KEY_0, CUSTOM_VALUE_0, 0),
- hasCustomField(CUSTOM_KEY_1, CUSTOM_VALUE_1, 1)));
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void argumentsTakePrecendenceOverMdc() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- @SuppressWarnings("serial")
- Map mdcFields = new HashMap() {
- {
- put(CUSTOM_KEY_0, CUSTOM_VALUE_0);
- put(CUSTOM_KEY_1, CUSTOM_VALUE_1);
- }
- };
-
- converter.convert(sb, mdcFields, customField(CUSTOM_KEY_0, "preferred value"));
-
- assertThat(unmarshalCustomFields(sb), containsInAnyOrder(hasCustomField(CUSTOM_KEY_0, "preferred value", 0),
- hasCustomField(CUSTOM_KEY_1, CUSTOM_VALUE_1, 1)));
- }
-
- @Test
- public void doesNotWriteJsonWhenNoFieldKeysAreConfigured() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- converter.setCustomFieldKeyNames(Collections.emptyList());
- converter.convert(sb, Collections.emptyMap(), customField(CUSTOM_KEY_0, CUSTOM_VALUE_0));
-
- assertThat(sb.toString(), isEmptyString());
- }
-
- @Test
- public void properlyEscapesValues() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- converter.convert(sb, Collections.emptyMap(), customField(CUSTOM_KEY_0, HACK_ATTEMPT));
-
- assertThat(unmarshalCustomFields(sb), contains(hasCustomField(CUSTOM_KEY_0, HACK_ATTEMPT, 0)));
- }
-
- @Test
- public void properlyEscapesMdcFields() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- @SuppressWarnings("serial")
- Map mdcFields = new HashMap() {
- {
- put(CUSTOM_KEY_0, HACK_ATTEMPT);
- }
- };
-
- converter.convert(sb, mdcFields);
-
- assertThat(unmarshalCustomFields(sb), contains(hasCustomField(CUSTOM_KEY_0, HACK_ATTEMPT, 0)));
-
- }
-
- @Test
- public void properlyEscapesFieldNames() throws Exception {
- converter.setFieldName(HACK_ATTEMPT);
- StringBuilder sb = new StringBuilder();
-
- converter.convert(sb, Collections.emptyMap(), customField(CUSTOM_KEY_0, CUSTOM_VALUE_0));
-
- assertThat(unmarshalCustomFields(sb, HACK_ATTEMPT),
- contains(hasCustomField(CUSTOM_KEY_0, CUSTOM_VALUE_0, 0)));
- }
-
-}
diff --git a/cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/converter/DefaultPropertiesConverterTest.java b/cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/converter/DefaultPropertiesConverterTest.java
deleted file mode 100644
index d7b7a048..00000000
--- a/cf-java-logging-support-core/src/test/java/com/sap/hcp/cf/logging/common/converter/DefaultPropertiesConverterTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-package com.sap.hcp.cf.logging.common.converter;
-
-import static com.sap.hcp.cf.logging.common.converter.UnmarshallUtilities.unmarshal;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.hasEntry;
-import static org.hamcrest.Matchers.hasKey;
-import static org.hamcrest.Matchers.not;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.hamcrest.Matcher;
-import org.junit.Before;
-import org.junit.Test;
-import org.slf4j.MDC;
-
-import com.sap.hcp.cf.logging.common.Defaults;
-import com.sap.hcp.cf.logging.common.Fields;
-
-public class DefaultPropertiesConverterTest {
-
- private static final String HACK_ATTEMPT = "}{:\",\"";
-
- private DefaultPropertiesConverter converter;
-
- @Before
- public void initConverter() {
- this.converter = new DefaultPropertiesConverter();
- }
-
- @Before
- public void cleadMdc() {
- MDC.clear();
- }
-
- @Test
- public void emptyProperties() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- converter.convert(sb, Collections.emptyMap());
-
- assertTrue("Should have empty properties by default", unmarshal(sb).isEmpty());
- }
-
- @Test
- public void singleMdcEntry() throws Exception {
- StringBuilder sb = new StringBuilder();
- MDC.put("some key", "some value");
-
- converter.convert(sb, Collections.emptyMap());
-
- assertThat(unmarshal(sb), hasEntry("some key", "some value"));
- }
-
- @Test
- public void twoMdcEntries() throws Exception {
- StringBuilder sb = new StringBuilder();
- MDC.put("some key", "some value");
- MDC.put("other key", "other value");
-
- converter.convert(sb, Collections.emptyMap());
-
- assertThat(unmarshal(sb), allOf(hasEntry("some key", "some value"), hasEntry("other key", "other value")));
- }
-
- @Test
- public void singleExplicitEntry() throws Exception {
- StringBuilder sb = new StringBuilder();
- @SuppressWarnings("serial")
- Map explicitFields = new HashMap() {
- {
- put("explicit key", "explicit value");
- }
- };
-
- converter.convert(sb, explicitFields);
-
- assertThat(unmarshal(sb), hasEntry("explicit key", "explicit value"));
- }
-
- @Test
- public void mergesDifferentMdcAndExplicitEntries() throws Exception {
- StringBuilder sb = new StringBuilder();
- @SuppressWarnings("serial")
- Map explicitFields = new HashMap() {
- {
- put("explicit key", "explicit value");
- }
- };
- MDC.put("some key", "some value");
-
- converter.convert(sb, explicitFields);
-
- assertThat(unmarshal(sb), allOf(hasEntry("some key", "some value"), hasEntry("explicit key",
- "explicit value")));
- }
-
- @Test
- public void explicitValuesOverwritesMdc() throws Exception {
- StringBuilder sb = new StringBuilder();
- @SuppressWarnings("serial")
- Map explicitFields = new HashMap() {
- {
- put("some key", "explicit value");
- }
- };
- MDC.put("some key", "some value");
-
- converter.convert(sb, explicitFields);
-
- assertThat(unmarshal(sb), hasEntry("some key", "explicit value"));
- }
-
- @Test
- public void dropsExclusions() throws Exception {
- StringBuilder sb = new StringBuilder();
- @SuppressWarnings("serial")
- Map explicitFields = new HashMap() {
- {
- put("excluded explicit key", "excluded explicit value");
- put("retained explicit key", "retained explicit value");
- }
- };
- MDC.put("retained mdc key", "retained mdc value");
- MDC.put("excluded mdc key", "excluded mdc value");
-
- converter.setExclusions(Arrays.asList("excluded explicit key", "excluded mdc key"));
- converter.convert(sb, explicitFields);
-
- assertThat(unmarshal(sb), allOf(hasEntry("retained mdc key", "retained mdc value"), not(hasEntry(
- "excluded mdc key",
- "excluded mdc value")),
- hasEntry("retained explicit key", "retained explicit value"), not(hasEntry(
- "excluded explicit key",
- "excluded explicit value"))));
-
- }
-
- @Test
- public void properlyEscapesKeys() throws Exception {
- StringBuilder sb = new StringBuilder();
- @SuppressWarnings("serial")
- Map explicitFields = new HashMap() {
- {
- put("explicit" + HACK_ATTEMPT, "explicit value");
- }
- };
- MDC.put("mdc" + HACK_ATTEMPT, "mdc value");
-
- converter.convert(sb, explicitFields);
-
- assertThat(unmarshal(sb), allOf(hasEntry("mdc" + HACK_ATTEMPT, "mdc value"), hasEntry("explicit" + HACK_ATTEMPT,
- "explicit value")));
- }
-
- @Test
- public void properlyEscapesValues() throws Exception {
- StringBuilder sb = new StringBuilder();
- @SuppressWarnings("serial")
- Map explicitFields = new HashMap() {
- {
- put("explicit key", "explicit" + HACK_ATTEMPT);
- }
- };
- MDC.put("mdc key", "mdc" + HACK_ATTEMPT);
-
- converter.convert(sb, explicitFields);
-
- assertThat(unmarshal(sb), allOf(hasEntry("mdc key", "mdc" + HACK_ATTEMPT), hasEntry("explicit key", "explicit" +
- HACK_ATTEMPT)));
- }
-
- @Test
- public void properlyEscapesExclusions() throws Exception {
- StringBuilder sb = new StringBuilder();
- @SuppressWarnings("serial")
- Map explicitFields = new HashMap() {
- {
- put("explicit" + HACK_ATTEMPT, "explicit value");
- }
- };
- MDC.put("mdc" + HACK_ATTEMPT, "mdc value");
-
- converter.setExclusions(Arrays.asList("explicit" + HACK_ATTEMPT, "mdc" + HACK_ATTEMPT));
- converter.convert(sb, explicitFields);
-
- assertThat(unmarshal(sb), allOf(not(hasEntry("mdc" + HACK_ATTEMPT, "mdc value")), not(hasEntry("explicit" +
- HACK_ATTEMPT,
- "explicit value"))));
- }
-
- @Test
- public void fullDefaultPropertiesIfConfigured() throws Exception {
- StringBuilder sb = new StringBuilder();
-
- converter.setSendDefaultValues(true);
- converter.convert(sb, Collections.emptyMap());
-
- assertThat(unmarshal(sb), hasDefaultProperties());
-
- }
-
- @SuppressWarnings("unchecked")
- private static Matcher