diff --git a/README.md b/README.md
index d359b4c3..8d1a62bb 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ The structure of the output, and the data it contains, is fully configurable.
* [LoggingEvent Fields](#loggingevent-fields)
* [Standard Fields](#standard-fields)
* [MDC fields](#mdc-fields)
- * [KeyValuePairs fields](#keyvaluepairs-fields)
+ * [Key Value Pair fields](#key-value-pair-fields)
* [Context fields](#context-fields)
* [Caller Info Fields](#caller-info-fields)
* [Custom Fields](#custom-fields)
@@ -991,11 +991,12 @@ The field names can be customized (see [Customizing Standard Field Names](#custo
### MDC fields
-By default, each entry in the Mapped Diagnostic Context (MDC) (`org.slf4j.MDC`)
-will appear as a field in the LoggingEvent.
+By default, `LogstashEncoder`/`LogstashLayout` will write each
+[Mapped Diagnostic Context (MDC) (`org.slf4j.MDC`)](https://www.slf4j.org/api/org/slf4j/MDC.html)
+entry to the output.
-This can be fully disabled by specifying `false`,
-in the encoder/layout/appender configuration.
+To disable writing MDC entries, add `false`
+to the `LogstashEncoder`/`LogstashLayout` configuration.
You can also configure specific entries in the MDC to be included or excluded as follows:
@@ -1021,7 +1022,7 @@ It is a configuration error to specify both included and excluded key names.
By default, the MDC key is used as the field name in the output.
To use an alternative field name in the output for an MDC entry,
-specify`mdcKeyName=fieldName`:
+specify `mdcKeyName=fieldName`:
```xml
@@ -1029,20 +1030,21 @@ specify`mdcKeyName=fieldName`:
```
-### KeyValuePairs fields
+### Key Value Pair Fields
-By default, each entry in the KeyValuePairs (`org.slf4j.event.KeyValuePair`) via the Fluent Api
-will appear as a field in the LoggingEvent.
+Slf4j 2's [fluent API](https://www.slf4j.org/manual.html#fluent) supports attaching key value pairs to the log event.
-This can be fully disabled by specifying `false`,
-in the encoder/layout/appender configuration.
+`LogstashEncoder`/`LogstashLayout` will write each key value pair as a field in the output by default.
+
+To disable writing key value pairs, add `false`
+to the `LogstashEncoder`/`LogstashLayout` configuration.
-You can also configure specific entries in the KeyValuePairs to be included or excluded as follows:
+You can also configure specific key value pairs to be included or excluded as follows:
```xml
- key1ToInclude
- key2ToInclude
+ key1ToInclude
+ key2ToInclude
```
@@ -1050,22 +1052,22 @@ or
```xml
- key1ToExclude
- key2ToExclude
+ key1ToExclude
+ key2ToExclude
```
-When key names are specified for inclusion, then all other fields will be excluded.
-When key names are specified for exclusion, then all other fields will be included.
+When key names are specified for inclusion, then all other keys will be excluded.
+When key names are specified for exclusion, then all other keys will be included.
It is a configuration error to specify both included and excluded key names.
-By default, the KeyValuePairs key is used as the field name in the output.
-To use an alternative field name in the output for an KeyValuePairs entry,
-specify`kvpKeyName=fieldName`:
+By default, the key is used as the field name in the output.
+To use an alternative field name in the output for an key value pair,
+specify`keyName=fieldName`:
```xml
- key1=alternateFieldNameForKey1
+ key1=alternateFieldNameForKey1
```
@@ -2633,21 +2635,22 @@ The provider name is the xml element name to use when configuring. Each provider
that specify an alternate field name to output for specific MDC key (none)
-
+
+
keyValuePairs |
- Outputs entries from the keyValuePairs.
- Will include all entries by default.
- When key names are specified for inclusion, then all other fields will be excluded.
- When key names are specified for exclusion, then all other fields will be included.
+ Outputs key value pairs added via slf4j's fluent api.
+ Will include all key value pairs by default.
+ When key names are specified for inclusion, then all other keys will be excluded.
+ When key names are specified for exclusion, then all other keys will be included.
It is a configuration error to specify both included and excluded key names.
- fieldName - Sub-object field name (no sub-object)
- - includeKeyValuePairsKeyName - Name of keys to include (all)
- - excludeKeyValuePairsKeyName - Name of keys to exclude (none)
- - keyValuePairsKeyFieldName - Strings in the form kvpKeyName=fieldName
- that specify an alternate field name to output for specific KeyValuePairs key (none)
+ - includeKeyName - Name of keys to include (all)
+ - excludeKeyName - Name of keys to exclude (none)
+ - keyFieldName - Strings in the form keyName=fieldName
+ that specify an alternate field name to output for specific key (none)
|
diff --git a/src/main/java/net/logstash/logback/LogstashFormatter.java b/src/main/java/net/logstash/logback/LogstashFormatter.java
index a7f8f715..987e8c44 100644
--- a/src/main/java/net/logstash/logback/LogstashFormatter.java
+++ b/src/main/java/net/logstash/logback/LogstashFormatter.java
@@ -24,15 +24,29 @@
import net.logstash.logback.composite.JsonProvider;
import net.logstash.logback.composite.JsonProviders;
import net.logstash.logback.composite.LogstashVersionJsonProvider;
-import net.logstash.logback.composite.loggingevent.*;
+import net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider;
+import net.logstash.logback.composite.loggingevent.CallerDataJsonProvider;
+import net.logstash.logback.composite.loggingevent.KeyValuePairsJsonProvider;
+import net.logstash.logback.composite.loggingevent.LogLevelJsonProvider;
+import net.logstash.logback.composite.loggingevent.LogLevelValueJsonProvider;
+import net.logstash.logback.composite.loggingevent.LoggerNameJsonProvider;
+import net.logstash.logback.composite.loggingevent.LoggingEventCompositeJsonFormatter;
+import net.logstash.logback.composite.loggingevent.LoggingEventFormattedTimestampJsonProvider;
+import net.logstash.logback.composite.loggingevent.LoggingEventJsonProviders;
+import net.logstash.logback.composite.loggingevent.LoggingEventThreadNameJsonProvider;
+import net.logstash.logback.composite.loggingevent.LogstashMarkersJsonProvider;
+import net.logstash.logback.composite.loggingevent.MdcJsonProvider;
+import net.logstash.logback.composite.loggingevent.MessageJsonProvider;
+import net.logstash.logback.composite.loggingevent.StackTraceJsonProvider;
+import net.logstash.logback.composite.loggingevent.TagsJsonProvider;
import net.logstash.logback.fieldnames.LogstashFieldNames;
import ch.qos.logback.classic.pattern.ThrowableHandlingConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.spi.ContextAware;
import com.fasterxml.jackson.databind.JsonNode;
-import org.slf4j.event.KeyValuePair;
import org.slf4j.MDC;
+import org.slf4j.event.KeyValuePair;
/**
* A {@link LoggingEventCompositeJsonFormatter} that contains a common
@@ -77,9 +91,9 @@ public class LogstashFormatter extends LoggingEventCompositeJsonFormatter {
private MdcJsonProvider mdcProvider = new MdcJsonProvider();
/**
* When not null, {@link KeyValuePair} properties will be included according
- * to the logic in {@link KeyValuePairJsonProvider}.
+ * to the logic in {@link KeyValuePairsJsonProvider}.
*/
- private KeyValuePairJsonProvider kvpProvider = new KeyValuePairJsonProvider();
+ private KeyValuePairsJsonProvider keyValuePairsProvider = new KeyValuePairsJsonProvider();
private GlobalCustomFieldsJsonProvider globalCustomFieldsProvider;
/**
* When not null, markers will be included according
@@ -116,7 +130,7 @@ public LogstashFormatter(ContextAware declaredOrigin, boolean includeCallerData,
getProviders().addStackTrace(this.stackTraceProvider);
getProviders().addContext(this.contextProvider);
getProviders().addMdc(this.mdcProvider);
- getProviders().addKvp(this.kvpProvider);
+ getProviders().addKeyValuePairs(this.keyValuePairsProvider);
getProviders().addGlobalCustomFields(this.globalCustomFieldsProvider);
getProviders().addTags(this.tagsProvider);
getProviders().addLogstashMarkers(this.logstashMarkersProvider);
@@ -216,20 +230,19 @@ public void setIncludeMdc(boolean includeMdc) {
}
}
- public boolean isIncludeKvp() {
- return this.kvpProvider != null;
+ public boolean isIncludeKeyValuePairs() {
+ return this.keyValuePairsProvider != null;
}
- public void setIncludeKvp(boolean includeKvp) {
- if (isIncludeKvp() == includeKvp)
- return;
-
- if (includeKvp) {
- kvpProvider = new KeyValuePairJsonProvider();
- addProvider(kvpProvider);
- } else {
- getProviders().removeProvider(kvpProvider);
- kvpProvider = null;
+ public void setIncludeKeyValuePairs(boolean includeKeyValuePairs) {
+ if (isIncludeKeyValuePairs() != includeKeyValuePairs) {
+ if (includeKeyValuePairs) {
+ keyValuePairsProvider = new KeyValuePairsJsonProvider();
+ addProvider(keyValuePairsProvider);
+ } else {
+ getProviders().removeProvider(keyValuePairsProvider);
+ keyValuePairsProvider = null;
+ }
}
}
@@ -310,41 +323,41 @@ public void addMdcKeyFieldName(String mdcKeyFieldName) {
}
}
- public List getIncludeKvpKeyNames() {
- return isIncludeKvp()
- ? kvpProvider.getIncludeKvpKeyNames()
+ public List getIncludeKeyValueKeyNames() {
+ return isIncludeKeyValuePairs()
+ ? keyValuePairsProvider.getIncludeKeyNames()
: Collections.emptyList();
}
- public void addIncludeKvpKeyName(String includedKvpKeyName) {
- if (isIncludeKvp()) {
- kvpProvider.addIncludeKvpKeyName(includedKvpKeyName);
+ public void addIncludeKeyValueKeyName(String includedKeyValueKeyName) {
+ if (isIncludeKeyValuePairs()) {
+ keyValuePairsProvider.addIncludeKeyName(includedKeyValueKeyName);
}
}
- public void setIncludeKvpKeyNames(List includeKvpKeyNames) {
- if (isIncludeKvp()) {
- kvpProvider.setIncludeKvpKeyNames(includeKvpKeyNames);
+ public void setIncludeKeyValueKeyNames(List includeKeyValueKeyNames) {
+ if (isIncludeKeyValuePairs()) {
+ keyValuePairsProvider.setIncludeKeyNames(includeKeyValueKeyNames);
}
}
- public List getExcludeKvpKeyNames() {
- return isIncludeKvp()
- ? kvpProvider.getExcludeKvpKeyNames()
+ public List getExcludeKeyValueKeyNames() {
+ return isIncludeKeyValuePairs()
+ ? keyValuePairsProvider.getExcludeKeyNames()
: Collections.emptyList();
}
- public void addExcludeKvpKeyName(String excludedKvpKeyName) {
- if (isIncludeKvp()) {
- kvpProvider.addExcludeKvpKeyName(excludedKvpKeyName);
+ public void addExcludeKeyValueKeyName(String excludedKeyValueKeyName) {
+ if (isIncludeKeyValuePairs()) {
+ keyValuePairsProvider.addExcludeKeyName(excludedKeyValueKeyName);
}
}
- public void setExcludeKvpKeyNames(List excludeKvpKeyNames) {
- if (isIncludeKvp()) {
- kvpProvider.setExcludeKvpKeyNames(excludeKvpKeyNames);
+ public void setExcludeKeyValueKeyNames(List excludeKeyValueKeyNames) {
+ if (isIncludeKeyValuePairs()) {
+ keyValuePairsProvider.setExcludeKeyNames(excludeKeyValueKeyNames);
}
}
- public void addKvpKeyFieldName(String kvpKeyFieldName) {
- if (isIncludeKvp()) {
- kvpProvider.addKvpKeyFieldName(kvpKeyFieldName);
+ public void addKeyValueKeyFieldName(String keyValueKeyFieldName) {
+ if (isIncludeKeyValuePairs()) {
+ keyValuePairsProvider.addKeyFieldName(keyValueKeyFieldName);
}
}
@@ -437,9 +450,9 @@ public void addProvider(JsonProvider provider) {
} else if (provider instanceof MdcJsonProvider) {
getProviders().removeProvider(this.mdcProvider);
this.mdcProvider = (MdcJsonProvider) provider;
- } else if (provider instanceof KeyValuePairJsonProvider) {
- getProviders().removeProvider(this.kvpProvider);
- this.kvpProvider = (KeyValuePairJsonProvider) provider;
+ } else if (provider instanceof KeyValuePairsJsonProvider) {
+ getProviders().removeProvider(this.keyValuePairsProvider);
+ this.keyValuePairsProvider = (KeyValuePairsJsonProvider) provider;
}
getProviders().addProvider(provider);
}
diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairJsonProvider.java
deleted file mode 100644
index ec68f29d..00000000
--- a/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairJsonProvider.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2013-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package net.logstash.logback.composite.loggingevent;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import com.fasterxml.jackson.core.JsonGenerator;
-import net.logstash.logback.composite.AbstractFieldJsonProvider;
-import net.logstash.logback.composite.FieldNamesAware;
-import net.logstash.logback.fieldnames.LogstashFieldNames;
-import org.slf4j.event.KeyValuePair;
-import net.logstash.logback.argument.StructuredArguments;
-
-import java.io.IOException;
-import java.util.*;
-
-/**
- * Includes {@link KeyValuePair} properties in the JSON output according to
- * {@link #includeKvpKeyNames} and {@link #excludeKvpKeyNames}.
- *
- * There are three valid combinations of {@link #includeKvpKeyNames}
- * and {@link #excludeKvpKeyNames}:
- *
- *
- * - When {@link #includeKvpKeyNames} and {@link #excludeKvpKeyNames}
- * are both empty, then all entries will be included.
- * - When {@link #includeKvpKeyNames} is not empty and
- * {@link #excludeKvpKeyNames} is empty, then only those entries
- * with key names in {@link #includeKvpKeyNames} will be included.
- * - When {@link #includeKvpKeyNames} is empty and
- * {@link #excludeKvpKeyNames} is not empty, then all entries except those
- * with key names in {@link #excludeKvpKeyNames} will be included.
- *
- *
- * It is a configuration error for both {@link #includeKvpKeyNames}
- * and {@link #excludeKvpKeyNames} to be not empty.
- *
- * By default, for each entry in the KeyValuePair, the KeyValuePair key is output as the field name.
- * This can be changed by specifying an explicit field name to use for an KeyValuePair key
- * via {@link #addKvpKeyFieldName(String)}
- *
- * If the fieldName is set, then the properties will be written
- * to that field as a subobject.
- * Otherwise, the properties are written inline.
- */
-public class KeyValuePairJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware {
-
- /**
- * See {@link KeyValuePairJsonProvider}.
- */
- private List includeKvpKeyNames = new ArrayList<>();
-
- /**
- * See {@link KeyValuePairJsonProvider}.
- */
- private List excludeKvpKeyNames = new ArrayList<>();
-
- private final Map kvpKeyFieldNames = new HashMap<>();
-
- @Override
- public void start() {
- if (!this.includeKvpKeyNames.isEmpty() && !this.excludeKvpKeyNames.isEmpty()) {
- addError("Both includeKvpKeyNames and excludeKvpKeyNames are not empty. Only one is allowed to be not empty.");
- }
- super.start();
- }
-
- @Override
- public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException {
- List kvp = event.getKeyValuePairs();
- if (kvp == null || kvp.isEmpty())
- return;
-
- String fieldName = getFieldName();
- if (fieldName != null)
- generator.writeObjectFieldStart(getFieldName());
-
- for (KeyValuePair kv : kvp) {
- if (kv.key != null && kv.value != null
- && (includeKvpKeyNames.isEmpty() || includeKvpKeyNames.contains(kv.key))
- && (excludeKvpKeyNames.isEmpty() || !excludeKvpKeyNames.contains(kv.key))) {
-
- String key = kvpKeyFieldNames.get(kv.key);
- if (key == null) {
- key = kv.key;
- }
- StructuredArguments.keyValue(key, kv.value).writeTo(generator);
- }
- }
-
- if (fieldName != null) {
- generator.writeEndObject();
- }
- }
-
- @Override
- public void setFieldNames(LogstashFieldNames fieldNames) {
- setFieldName(fieldNames.getKeyValuePair());
- }
-
- public List getIncludeKvpKeyNames() {
- return Collections.unmodifiableList(includeKvpKeyNames);
- }
-
- public void addIncludeKvpKeyName(String includedKvpKeyName) {
- this.includeKvpKeyNames.add(includedKvpKeyName);
- }
-
- public void setIncludeKvpKeyNames(List includeKvpKeyNames) {
- this.includeKvpKeyNames = new ArrayList(includeKvpKeyNames);
- }
-
- public List getExcludeKvpKeyNames() {
- return Collections.unmodifiableList(excludeKvpKeyNames);
- }
-
- public void addExcludeKvpKeyName(String excludedKvpKeyName) {
- this.excludeKvpKeyNames.add(excludedKvpKeyName);
- }
-
- public void setExcludeKvpKeyNames(List excludeKvpKeyNames) {
- this.excludeKvpKeyNames = new ArrayList<>(excludeKvpKeyNames);
- }
-
- public Map getKvpKeyFieldNames() {
- return kvpKeyFieldNames;
- }
-
- /**
- * Adds the given kvpKeyFieldName entry in the form kvpKeyName=fieldName
- * to use an alternative field name for an KeyValuePair key.
- *
- * @param kvpKeyFieldName a string in the form kvpKeyName=fieldName that identifies what field name to use for a specific KeyValuePair key.
- */
- public void addKvpKeyFieldName(String kvpKeyFieldName) {
- String[] split = kvpKeyFieldName.split("=");
- if (split.length != 2) {
- throw new IllegalArgumentException("kvpKeyFieldName (" + kvpKeyFieldName + ") must be in the form kvpKeyName=fieldName");
- }
- kvpKeyFieldNames.put(split[0], split[1]);
- }
-
-}
diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProvider.java
new file mode 100644
index 00000000..f4e90e29
--- /dev/null
+++ b/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProvider.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2013-2022 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.logstash.logback.composite.loggingevent;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.logstash.logback.composite.AbstractFieldJsonProvider;
+import net.logstash.logback.composite.FieldNamesAware;
+import net.logstash.logback.fieldnames.LogstashFieldNames;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import com.fasterxml.jackson.core.JsonGenerator;
+import org.slf4j.event.KeyValuePair;
+
+/**
+ * Includes key value pairs added from slf4j's fluent api in the output according to
+ * {@link #includeKeyNames} and {@link #excludeKeyNames}.
+ *
+ * There are three valid combinations of {@link #includeKeyNames}
+ * and {@link #excludeKeyNames}:
+ *
+ *
+ * - When {@link #includeKeyNames} and {@link #excludeKeyNames}
+ * are both empty, then all entries will be included.
+ * - When {@link #includeKeyNames} is not empty and
+ * {@link #excludeKeyNames} is empty, then only those entries
+ * with key names in {@link #includeKeyNames} will be included.
+ * - When {@link #includeKeyNames} is empty and
+ * {@link #excludeKeyNames} is not empty, then all entries except those
+ * with key names in {@link #excludeKeyNames} will be included.
+ *
+ *
+ * It is a configuration error for both {@link #includeKeyNames}
+ * and {@link #excludeKeyNames} to be not empty.
+ *
+ * By default, for each key value pair, the key is output as the field name.
+ * This can be changed by specifying an explicit field name to use for a ke
+ * via {@link #addKeyFieldName(String)}
+ *
+ * If the fieldName is set, then the pairs will be written
+ * to that field as a subobject.
+ * Otherwise, the pairs are written inline.
+ */
+public class KeyValuePairsJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware {
+
+ /**
+ * See {@link KeyValuePairsJsonProvider}.
+ */
+ private List includeKeyNames = new ArrayList<>();
+
+ /**
+ * See {@link KeyValuePairsJsonProvider}.
+ */
+ private List excludeKeyNames = new ArrayList<>();
+
+ private final Map keyFieldNames = new HashMap<>();
+
+ @Override
+ public void start() {
+ if (!this.includeKeyNames.isEmpty() && !this.excludeKeyNames.isEmpty()) {
+ addError("Both includeKeyNames and excludeKeyNames are not empty. Only one is allowed to be not empty.");
+ }
+ super.start();
+ }
+
+ @Override
+ public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException {
+ List keyValuePairs = event.getKeyValuePairs();
+ if (keyValuePairs == null || keyValuePairs.isEmpty()) {
+ return;
+ }
+
+ String fieldName = getFieldName();
+ if (fieldName != null) {
+ generator.writeObjectFieldStart(getFieldName());
+ }
+
+ for (KeyValuePair keyValuePair : keyValuePairs) {
+ if (keyValuePair.key != null && keyValuePair.value != null
+ && (includeKeyNames.isEmpty() || includeKeyNames.contains(keyValuePair.key))
+ && (excludeKeyNames.isEmpty() || !excludeKeyNames.contains(keyValuePair.key))) {
+
+ String key = keyFieldNames.get(keyValuePair.key);
+ if (key == null) {
+ key = keyValuePair.key;
+ }
+ generator.writeFieldName(key);
+ generator.writeObject(keyValuePair.value);
+ }
+ }
+
+ if (fieldName != null) {
+ generator.writeEndObject();
+ }
+ }
+
+ @Override
+ public void setFieldNames(LogstashFieldNames fieldNames) {
+ setFieldName(fieldNames.getKeyValuePair());
+ }
+
+ public List getIncludeKeyNames() {
+ return Collections.unmodifiableList(includeKeyNames);
+ }
+
+ public void addIncludeKeyName(String includedKeyName) {
+ this.includeKeyNames.add(includedKeyName);
+ }
+
+ public void setIncludeKeyNames(List includeKeyNames) {
+ this.includeKeyNames = new ArrayList<>(includeKeyNames);
+ }
+
+ public List getExcludeKeyNames() {
+ return Collections.unmodifiableList(excludeKeyNames);
+ }
+
+ public void addExcludeKeyName(String excludedKeyName) {
+ this.excludeKeyNames.add(excludedKeyName);
+ }
+
+ public void setExcludeKeyNames(List excludeKeyNames) {
+ this.excludeKeyNames = new ArrayList<>(excludeKeyNames);
+ }
+
+ public Map getKeyFieldNames() {
+ return keyFieldNames;
+ }
+
+ /**
+ * Adds the given keyFieldName entry in the form keyName=fieldName
+ * to use an alternative field name for an KeyValuePair key.
+ *
+ * @param keyFieldName a string in the form kvpKeyName=fieldName that identifies what field name to use for a specific KeyValuePair key.
+ */
+ public void addKeyFieldName(String keyFieldName) {
+ String[] split = keyFieldName.split("=");
+ if (split.length != 2) {
+ throw new IllegalArgumentException("keyFieldName (" + keyFieldName + ") must be in the form keyName=fieldName");
+ }
+ keyFieldNames.put(split[0], split[1]);
+ }
+
+}
diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/LoggingEventJsonProviders.java b/src/main/java/net/logstash/logback/composite/loggingevent/LoggingEventJsonProviders.java
index 41c914ce..01aa3667 100644
--- a/src/main/java/net/logstash/logback/composite/loggingevent/LoggingEventJsonProviders.java
+++ b/src/main/java/net/logstash/logback/composite/loggingevent/LoggingEventJsonProviders.java
@@ -73,7 +73,7 @@ public void addContextName(ContextNameJsonProvider provider) {
public void addMdc(MdcJsonProvider provider) {
addProvider(provider);
}
- public void addKvp(KeyValuePairJsonProvider provider) {
+ public void addKeyValuePairs(KeyValuePairsJsonProvider provider) {
addProvider(provider);
}
public void addTags(TagsJsonProvider provider) {
diff --git a/src/main/java/net/logstash/logback/encoder/LogstashEncoder.java b/src/main/java/net/logstash/logback/encoder/LogstashEncoder.java
index 4245e590..90b1c4b7 100644
--- a/src/main/java/net/logstash/logback/encoder/LogstashEncoder.java
+++ b/src/main/java/net/logstash/logback/encoder/LogstashEncoder.java
@@ -112,32 +112,39 @@ public void addMdcKeyFieldName(String mdcKeyFieldName) {
public boolean isIncludeKeyValuePairs() {
- return getFormatter().isIncludeKvp();
+ return getFormatter().isIncludeKeyValuePairs();
}
- public void setIncludeKeyValuePairs(boolean includeKvp) {
- getFormatter().setIncludeKvp(includeKvp);
+ public void setIncludeKeyValuePairs(boolean includeKeyValuePairs) {
+ getFormatter().setIncludeKeyValuePairs(includeKeyValuePairs);
}
- public void addIncludeKeyValuePairsKeyName(String includedKvpKeyName) {
- getFormatter().addIncludeKvpKeyName(includedKvpKeyName);
+ public void addIncludeKeyValueKeyName(String includedKeyValueKeyName) {
+ getFormatter().addIncludeKeyValueKeyName(includedKeyValueKeyName);
}
+ public List getIncludeKeyValueKeyNames() {
+ return getFormatter().getIncludeKeyValueKeyNames();
+ }
+
+ public void setIncludeKeyValueKeyNames(List includeKeyValueKeyNames) {
+ getFormatter().setIncludeKeyValueKeyNames(includeKeyValueKeyNames);
+ }
- public List getIncludeKeyValuePairKeyNames() {
- return getFormatter().getIncludeKvpKeyNames();
+ public void addExcludeKeyValueKeyName(String excludedKeyValueKeyName) {
+ getFormatter().addExcludeKeyValueKeyName(excludedKeyValueKeyName);
}
- public void addExcludeKeyValuePairsKeyName(String excludedKvpKeyName) {
- getFormatter().addExcludeKvpKeyName(excludedKvpKeyName);
+ public List getExcludeKeyValueKeyNames() {
+ return getFormatter().getExcludeKeyValueKeyNames();
}
- public void setExcludeKeyValuePairsKeyNames(List excludeKvpKeyNames) {
- getFormatter().setExcludeKvpKeyNames(excludeKvpKeyNames);
+ public void setExcludeKeyValueKeyNames(List excludedKeyValueKeyNames) {
+ getFormatter().setExcludeKeyValueKeyNames(excludedKeyValueKeyNames);
}
- public void addKeyValuePairsKeyFieldName(String kvpKeyFieldName) {
- getFormatter().addKvpKeyFieldName(kvpKeyFieldName);
+ public void addKeyValueKeyFieldName(String keyValueKeyFieldName) {
+ getFormatter().addKeyValueKeyFieldName(keyValueKeyFieldName);
}
public boolean isIncludeTags() {
diff --git a/src/main/java/net/logstash/logback/layout/LogstashLayout.java b/src/main/java/net/logstash/logback/layout/LogstashLayout.java
index 13286b6d..d264ef1a 100644
--- a/src/main/java/net/logstash/logback/layout/LogstashLayout.java
+++ b/src/main/java/net/logstash/logback/layout/LogstashLayout.java
@@ -102,38 +102,39 @@ public void addMdcKeyFieldName(String mdcKeyFieldName) {
}
public boolean isIncludeKeyValuePairs() {
- return getFormatter().isIncludeKvp();
+ return getFormatter().isIncludeKeyValuePairs();
}
- public void setIncludeKeyValuePairs(boolean includeKvp) {
- getFormatter().setIncludeKvp(includeKvp);
+ public void setIncludeKeyValuePairs(boolean includeKeyValuePairs) {
+ getFormatter().setIncludeKeyValuePairs(includeKeyValuePairs);
}
- public List getIncludeKeyValuePairsKeyNames() {
- return getFormatter().getIncludeKvpKeyNames();
+ public void addIncludeKeyValueKeyName(String includedKeyValueKeyName) {
+ getFormatter().addIncludeKeyValueKeyName(includedKeyValueKeyName);
}
- public void addIncludeKeyValuePairsKeyName(String includedKvpKeyName) {
- getFormatter().addIncludeKvpKeyName(includedKvpKeyName);
+ public List getIncludeKeyValueKeyNames() {
+ return getFormatter().getIncludeKeyValueKeyNames();
}
- public void setIncludeKeyValuePairsKeyNames(List includeKvpKeyNames) {
- getFormatter().setIncludeKvpKeyNames(includeKvpKeyNames);
+ public void setIncludeKeyValueKeyNames(List includeKeyValueKeyNames) {
+ getFormatter().setIncludeKeyValueKeyNames(includeKeyValueKeyNames);
}
- public List getExcludeKeyValuePairsKeyNames() {
- return getFormatter().getExcludeKvpKeyNames();
+ public void addExcludeKeyValueKeyName(String excludedKeyValueKeyName) {
+ getFormatter().addExcludeKeyValueKeyName(excludedKeyValueKeyName);
}
- public void addExcludeKeyValuePairsKeyName(String excludedKvpKeyName) {
- getFormatter().addExcludeKvpKeyName(excludedKvpKeyName);
+ public List getExcludeKeyValueKeyNames() {
+ return getFormatter().getExcludeKeyValueKeyNames();
}
- public void setExcludeKeyValuePairsKeyNames(List excludeKvpKeyNames) {
- getFormatter().setExcludeKvpKeyNames(excludeKvpKeyNames);
+ public void setExcludeKeyValueKeyNames(List excludedKeyValueKeyNames) {
+ getFormatter().setExcludeKeyValueKeyNames(excludedKeyValueKeyNames);
}
- public void addKeyValuePairsKeyFieldName(String kvpKeyFieldName) {
- getFormatter().addKvpKeyFieldName(kvpKeyFieldName);
+
+ public void addKeyValueKeyFieldName(String keyValueKeyFieldName) {
+ getFormatter().addKeyValueKeyFieldName(keyValueKeyFieldName);
}
public boolean isIncludeTags() {
diff --git a/src/test/java/net/logstash/logback/ConfigurationTest.java b/src/test/java/net/logstash/logback/ConfigurationTest.java
index 3de48a36..4e381a58 100644
--- a/src/test/java/net/logstash/logback/ConfigurationTest.java
+++ b/src/test/java/net/logstash/logback/ConfigurationTest.java
@@ -37,6 +37,7 @@
import net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider;
import net.logstash.logback.composite.loggingevent.CallerDataJsonProvider;
import net.logstash.logback.composite.loggingevent.ContextNameJsonProvider;
+import net.logstash.logback.composite.loggingevent.KeyValuePairsJsonProvider;
import net.logstash.logback.composite.loggingevent.LogLevelJsonProvider;
import net.logstash.logback.composite.loggingevent.LogLevelValueJsonProvider;
import net.logstash.logback.composite.loggingevent.LoggerNameJsonProvider;
@@ -87,7 +88,7 @@ public void testLogstashEncoderAppender() throws IOException {
LoggingEventCompositeJsonEncoder encoder = getEncoder("logstashEncoderAppender");
List> providers = encoder.getProviders().getProviders();
- assertThat(providers).hasSize(19);
+ assertThat(providers).hasSize(20);
verifyCommonProviders(providers);
@@ -99,7 +100,7 @@ public void testLoggingEventCompositeJsonEncoderAppender() throws IOException {
LoggingEventCompositeJsonEncoder encoder = getEncoder("loggingEventCompositeJsonEncoderAppender");
List> providers = encoder.getProviders().getProviders();
- assertThat(providers).hasSize(23);
+ assertThat(providers).hasSize(24);
verifyCommonProviders(providers);
@@ -178,7 +179,11 @@ private void verifyCommonProviders(List> providers)
assertThat(mdcJsonProvider).isNotNull();
assertThat(mdcJsonProvider.getIncludeMdcKeyNames()).containsExactly("included");
assertThat(mdcJsonProvider.getMdcKeyFieldNames()).containsOnly(entry("key", "renamedKey"));
-
+
+ KeyValuePairsJsonProvider keyValuePairsJsonProvider = getInstance(providers, KeyValuePairsJsonProvider.class);
+ assertThat(keyValuePairsJsonProvider).isNotNull();
+ assertThat(keyValuePairsJsonProvider.getIncludeKeyNames()).containsExactly("included");
+ assertThat(keyValuePairsJsonProvider.getKeyFieldNames()).containsOnly(entry("key", "renamedKey"));
GlobalCustomFieldsJsonProvider globalCustomFieldsJsonProvider = getInstance(providers, GlobalCustomFieldsJsonProvider.class);
assertThat(globalCustomFieldsJsonProvider).isNotNull();
diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProviderTest.java
similarity index 83%
rename from src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairJsonProviderTest.java
rename to src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProviderTest.java
index 5e2adc4f..e7762cdb 100644
--- a/src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairJsonProviderTest.java
+++ b/src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProviderTest.java
@@ -15,11 +15,21 @@
*/
package net.logstash.logback.composite.loggingevent;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import net.logstash.logback.fieldnames.LogstashFieldNames;
+
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
-import net.logstash.logback.fieldnames.LogstashFieldNames;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -27,19 +37,10 @@
import org.mockito.junit.jupiter.MockitoExtension;
import org.slf4j.event.KeyValuePair;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.when;
-
@ExtendWith(MockitoExtension.class)
-public class KeyValuePairJsonProviderTest {
+public class KeyValuePairsJsonProviderTest {
- private KeyValuePairJsonProvider provider = new KeyValuePairJsonProvider();
+ private KeyValuePairsJsonProvider provider = new KeyValuePairsJsonProvider();
private ByteArrayOutputStream resultStream;
private JsonGenerator generator;
@@ -47,15 +48,15 @@ public class KeyValuePairJsonProviderTest {
@Mock
private ILoggingEvent event;
- private List kvp;
+ private List keyValuePairs;
@BeforeEach
public void setup() throws Exception {
- kvp = new ArrayList<>();
- kvp.add(new KeyValuePair("name1", "value1"));
- kvp.add(new KeyValuePair("name2", 2023));
- kvp.add(new KeyValuePair("name3", new TestValue()));
- when(event.getKeyValuePairs()).thenReturn(kvp);
+ keyValuePairs = new ArrayList<>();
+ keyValuePairs.add(new KeyValuePair("name1", "value1"));
+ keyValuePairs.add(new KeyValuePair("name2", 2023));
+ keyValuePairs.add(new KeyValuePair("name3", new TestValue()));
+ when(event.getKeyValuePairs()).thenReturn(keyValuePairs);
resultStream = new ByteArrayOutputStream();
generator = new JsonFactory().createGenerator(resultStream);
generator.setCodec(new ObjectMapper());
@@ -85,7 +86,7 @@ public void testWrappedUsingFieldNames() throws IOException {
@Test
public void testInclude() throws IOException {
- provider.setIncludeKvpKeyNames(Collections.singletonList("name1"));
+ provider.setIncludeKeyNames(Collections.singletonList("name1"));
assertThat(generateJson())
.isEqualTo("{\"name1\":\"value1\"}");
@@ -93,7 +94,7 @@ public void testInclude() throws IOException {
@Test
public void testExclude() throws IOException {
- provider.setExcludeKvpKeyNames(Collections.singletonList("name1"));
+ provider.setExcludeKeyNames(Collections.singletonList("name1"));
assertThat(generateJson())
.isEqualTo("{\"name2\":2023,\"name3\":{\"a\":1}}");
@@ -101,7 +102,7 @@ public void testExclude() throws IOException {
@Test
public void testAlternativeFieldName() throws IOException {
- provider.addKvpKeyFieldName("name1=alternativeName1");
+ provider.addKeyFieldName("name1=alternativeName1");
assertThat(generateJson())
.isEqualTo("{\"alternativeName1\":\"value1\",\"name2\":2023,\"name3\":{\"a\":1}}");
diff --git a/src/test/java/net/logstash/logback/encoder/LogstashEncoderTest.java b/src/test/java/net/logstash/logback/encoder/LogstashEncoderTest.java
index 08057534..935a50ad 100644
--- a/src/test/java/net/logstash/logback/encoder/LogstashEncoderTest.java
+++ b/src/test/java/net/logstash/logback/encoder/LogstashEncoderTest.java
@@ -30,7 +30,12 @@
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
import net.logstash.logback.composite.AbstractFormattedTimestampJsonProvider;
import net.logstash.logback.composite.loggingevent.LoggingEventJsonProviders;
@@ -317,7 +322,7 @@ public void kvpSomeIncluded() throws Exception {
LoggingEvent event = mockBasicILoggingEvent(Level.ERROR);
event.setKeyValuePairs(kvp);
- encoder.addIncludeKeyValuePairsKeyName("thing_one");
+ encoder.addIncludeKeyValueKeyName("thing_one");
encoder.start();
byte[] encoded = encoder.encode(event);
@@ -337,7 +342,7 @@ public void kvpSomeExcluded() throws Exception {
LoggingEvent event = mockBasicILoggingEvent(Level.ERROR);
event.setKeyValuePairs(kvp);
- encoder.addExcludeKeyValuePairsKeyName("thing_two");
+ encoder.addExcludeKeyValueKeyName("thing_two");
encoder.start();
byte[] encoded = encoder.encode(event);
diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml
index 98a03180..8c756cc6 100644
--- a/src/test/resources/logback-test.xml
+++ b/src/test/resources/logback-test.xml
@@ -50,6 +50,8 @@
included
key=renamedKey
+ included
+ key=renamedKey
{"customName":"customValue"}
true
@@ -139,6 +141,10 @@
included
key=renamedKey
+
+ included
+ key=renamedKey
+
{"customName":"customValue"}