Skip to content

Commit 21e9bd2

Browse files
fix(map_entries): Improve edge case handling for missing keys and empty filtered results
- Change missing source key from warn+tags_on_failure to silent debug log, consistent with other mutate-event processors - Remove early return when all elements are filtered out by exclude_null_empty_values, ensuring consistent List<Map> output type - Update test and README to reflect new behavior
1 parent 8c5bba7 commit 21e9bd2

3 files changed

Lines changed: 7 additions & 35 deletions

File tree

data-prepper-plugins/mutate-event-processors/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -749,10 +749,10 @@ After `add_entries`:
749749
* `tags_on_failure` - (optional) - A list of tags to add to the event metadata when the event fails to process
750750

751751
### Edge Case Behavior
752-
* If the `source` key does not exist in the event, the processor skips the event (no-op) and adds `tags_on_failure` if configured.
752+
* If the `source` key does not exist in the event, the processor silently skips the event (no-op). A debug-level log is emitted.
753753
* If the `source` value is not a list (e.g., a string or number), the processor skips the event (no-op) and adds `tags_on_failure` if configured.
754754
* If the `source` list is empty, the processor does nothing — the empty list remains as-is.
755-
* If no elements remain after filtering (when `exclude_null_empty_values` is `true` and all elements are null or empty), the original list is left unchanged.
755+
* If no elements remain after filtering (when `exclude_null_empty_values` is `true` and all elements are null or empty), the target is written as an empty list `[]`.
756756
* Null elements within the list are wrapped like any other value by default: `[null]` becomes `[{"key": null}]`. Use `exclude_null_empty_values: true` to filter them out.
757757

758758
___

data-prepper-plugins/mutate-event-processors/src/main/java/org/opensearch/dataprepper/plugins/processor/mutateevent/MapEntriesProcessor.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
import org.slf4j.LoggerFactory;
2121

2222
import java.util.ArrayList;
23+
import java.util.Collections;
2324
import java.util.Collection;
24-
import java.util.HashMap;
2525
import java.util.List;
2626
import java.util.Map;
2727

@@ -53,13 +53,6 @@ public MapEntriesProcessor(final PluginMetrics pluginMetrics,
5353
"for valid expression syntax", config.getMapEntriesWhen()));
5454
}
5555

56-
if (config.getTagsOnFailure() != null) {
57-
for (final String tag : config.getTagsOnFailure()) {
58-
if (tag == null || tag.isEmpty()) {
59-
throw new InvalidPluginConfigurationException("tags_on_failure must not contain null or empty strings.");
60-
}
61-
}
62-
}
6356
}
6457

6558
@Override
@@ -92,8 +85,7 @@ private void processEvent(final Event event) {
9285
final String source = config.getSource();
9386

9487
if (!event.containsKey(source)) {
95-
LOG.warn(EVENT, "Source key [{}] does not exist in event [{}], skipping.", source, event);
96-
addTagsOnFailure(event);
88+
LOG.debug(EVENT, "Source key [{}] does not exist in event [{}], skipping.", source, event);
9789
return;
9890
}
9991

@@ -123,14 +115,9 @@ private void processEvent(final Event event) {
123115
continue;
124116
}
125117
}
126-
final Map<String, Object> wrapped = new HashMap<>(1);
127-
wrapped.put(key, element);
128-
result.add(wrapped);
118+
result.add(Collections.singletonMap(key, element));
129119
}
130120

131-
if (result.isEmpty()) {
132-
return;
133-
}
134121

135122
final String effectiveTarget = config.getEffectiveTarget();
136123

data-prepper-plugins/mutate-event-processors/src/test/java/org/opensearch/dataprepper/plugins/processor/mutateevent/MapEntriesProcessorTest.java

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,6 @@ void constructor_with_empty_target_throws_InvalidPluginConfigurationException()
9696
assertThrows(InvalidPluginConfigurationException.class, this::createObjectUnderTest);
9797
}
9898

99-
@Test
100-
void constructor_with_empty_string_in_tags_on_failure_throws_InvalidPluginConfigurationException() {
101-
when(config.getTagsOnFailure()).thenReturn(List.of(""));
102-
103-
assertThrows(InvalidPluginConfigurationException.class, this::createObjectUnderTest);
104-
}
105-
106-
@Test
107-
void constructor_with_null_element_in_tags_on_failure_throws_InvalidPluginConfigurationException() {
108-
final List<String> tags = new ArrayList<>();
109-
tags.add(null);
110-
when(config.getTagsOnFailure()).thenReturn(tags);
111-
112-
assertThrows(InvalidPluginConfigurationException.class, this::createObjectUnderTest);
113-
}
11499

115100
// --- Basic wrapping ---
116101

@@ -192,7 +177,7 @@ void doExecute_with_exclude_enabled_filters_out_null_and_empty_elements() {
192177
}
193178

194179
@Test
195-
void doExecute_with_all_null_empty_and_exclude_enabled_leaves_original_list_unchanged() {
180+
void doExecute_with_all_null_empty_and_exclude_enabled_writes_empty_list() {
196181
when(config.getExcludeNullEmptyValues()).thenReturn(true);
197182

198183
final List<String> input = new ArrayList<>();
@@ -204,7 +189,7 @@ void doExecute_with_all_null_empty_and_exclude_enabled_leaves_original_list_unch
204189

205190
final Object output = result.get(0).getData().get("/names", Object.class);
206191
assertThat(output instanceof List, is(true));
207-
assertThat(((List<?>) output).size(), is(2));
192+
assertThat(((List<?>) output).size(), is(0));
208193
}
209194

210195
// --- Skip conditions ---

0 commit comments

Comments
 (0)