Skip to content

Commit c4c7fcf

Browse files
authored
allow custom name pattern prefix for S3 sink (#6193)
* allow custom name pattern for S3 sink Signed-off-by: Xun Zhang <xunzh@amazon.com> * update to allow name pattern prefix Signed-off-by: Xun Zhang <xunzh@amazon.com> --------- Signed-off-by: Xun Zhang <xunzh@amazon.com>
1 parent f59df79 commit c4c7fcf

2 files changed

Lines changed: 94 additions & 2 deletions

File tree

data-prepper-plugins/s3-sink/src/main/java/org/opensearch/dataprepper/plugins/sink/s3/configuration/ObjectKeyOptions.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,21 @@
66
package org.opensearch.dataprepper.plugins.sink.s3.configuration;
77

88
import com.fasterxml.jackson.annotation.JsonProperty;
9+
import jakarta.validation.constraints.AssertTrue;
910

1011
/**
1112
* An implementation class of path prefix and file pattern configuration Options
1213
*/
1314
public class ObjectKeyOptions {
1415
private static final String DEFAULT_OBJECT_NAME_PATTERN = "events-%{yyyy-MM-dd'T'HH-mm-ss'Z'}";
16+
private static final String DEFAULT_TIME_PATTERN = "%{yyyy-MM-dd'T'HH-mm-ss'Z'}";
1517

1618
@JsonProperty("path_prefix")
1719
private String pathPrefix;
1820

21+
@JsonProperty("name_pattern_prefix")
22+
private String namePatternPrefix;
23+
1924
/**
2025
* S3 index path configuration Option
2126
* @return path prefix.
@@ -24,11 +29,29 @@ public String getPathPrefix() {
2429
return pathPrefix;
2530
}
2631

32+
/**
33+
* S3 object name configuration Option
34+
* @return S3 object prefix.
35+
*/
36+
public String getNamePatternPrefix() {return namePatternPrefix;}
37+
2738
/**
2839
* Read s3 object index file pattern configuration.
29-
* @return default object name pattern.
40+
* @return default object name pattern if namePatternPrefix is null, empty, or blank; otherwise returns the configured namePatternPrefix with default TimePattern.
3041
*/
3142
public String getNamePattern() {
32-
return DEFAULT_OBJECT_NAME_PATTERN;
43+
if (namePatternPrefix == null || namePatternPrefix.trim().isEmpty()) {
44+
return DEFAULT_OBJECT_NAME_PATTERN;
45+
}
46+
return namePatternPrefix + "-" + DEFAULT_TIME_PATTERN;
3347
}
48+
49+
@AssertTrue(message = "Custom time pattern is not allowed in the name pattern prefix since the default time pattern will be appended.")
50+
boolean isTimePatternExcludedFromNamePatternPrefix() {
51+
if (namePatternPrefix == null || namePatternPrefix.trim().isEmpty()) {
52+
return true;
53+
}
54+
return !namePatternPrefix.contains("%{");
55+
}
56+
3457
}

data-prepper-plugins/s3-sink/src/test/java/org/opensearch/dataprepper/plugins/sink/s3/configuration/ObjectKeyOptionsTest.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@
55

66
package org.opensearch.dataprepper.plugins.sink.s3.configuration;
77

8+
import com.fasterxml.jackson.core.JsonProcessingException;
89
import org.junit.jupiter.api.Test;
910

1011
import static org.hamcrest.CoreMatchers.equalTo;
1112
import static org.hamcrest.MatcherAssert.assertThat;
13+
import static org.junit.jupiter.api.Assertions.assertFalse;
14+
import static org.junit.jupiter.api.Assertions.assertTrue;
15+
import static org.opensearch.dataprepper.model.codec.OutputCodec.objectMapper;
1216

1317
class ObjectKeyOptionsTest {
1418

1519
private static final String DEFAULT_FILE_PATTERN = "events-%{yyyy-MM-dd'T'HH-mm-ss'Z'}";
20+
private static final String DEFAULT_TIME_PATTERN = "%{yyyy-MM-dd'T'HH-mm-ss'Z'}";
1621

1722
@Test
1823
void default_file_pattern_test() {
@@ -23,4 +28,68 @@ void default_file_pattern_test() {
2328
void default_path_prefix_test() {
2429
assertThat(new ObjectKeyOptions().getPathPrefix(), equalTo(null));
2530
}
31+
32+
@Test
33+
void default_name_pattern_prefix_test() {
34+
assertThat(new ObjectKeyOptions().getNamePatternPrefix(), equalTo(null));
35+
}
36+
37+
@Test
38+
void getNamePatternPrefix_returns_configured_value() throws JsonProcessingException {
39+
String prefix = "my-custom-events";
40+
String json = String.format("{\"name_pattern_prefix\": \"%s\"}", prefix);
41+
ObjectKeyOptions options = objectMapper.readValue(json, ObjectKeyOptions.class);
42+
43+
assertThat(options.getNamePatternPrefix(), equalTo(prefix));
44+
}
45+
46+
@Test
47+
void getNamePattern_returns_default_when_prefix_is_null() {
48+
ObjectKeyOptions options = new ObjectKeyOptions();
49+
50+
assertThat(options.getNamePattern(), equalTo(DEFAULT_FILE_PATTERN));
51+
}
52+
53+
@Test
54+
void getNamePattern_returns_prefix_with_default_time_pattern_when_prefix_is_set() throws JsonProcessingException {
55+
String prefix = "custom-events";
56+
String json = String.format("{\"name_pattern_prefix\": \"%s\"}", prefix);
57+
ObjectKeyOptions options = objectMapper.readValue(json, ObjectKeyOptions.class);
58+
59+
String expected = prefix + "-" + DEFAULT_TIME_PATTERN;
60+
assertThat(options.getNamePattern(), equalTo(expected));
61+
}
62+
63+
@Test
64+
void getNamePattern_appends_default_time_pattern_correctly() throws JsonProcessingException {
65+
String prefix = "logs";
66+
String json = String.format("{\"name_pattern_prefix\": \"%s\"}", prefix);
67+
ObjectKeyOptions options = objectMapper.readValue(json, ObjectKeyOptions.class);
68+
69+
assertThat(options.getNamePattern(), equalTo("logs-%{yyyy-MM-dd'T'HH-mm-ss'Z'}"));
70+
}
71+
72+
@Test
73+
void isTimePatternExcludedFromNamePatternPrefix_returns_true_when_prefix_is_empty() throws JsonProcessingException {
74+
String json = "{\"name_pattern_prefix\": \"\"}";
75+
ObjectKeyOptions options = objectMapper.readValue(json, ObjectKeyOptions.class);
76+
77+
assertTrue(options.isTimePatternExcludedFromNamePatternPrefix());
78+
}
79+
80+
@Test
81+
void isTimePatternExcludedFromNamePatternPrefix_returns_true_for_prefix_with_hyphens() throws JsonProcessingException {
82+
String json = "{\"name_pattern_prefix\": \"my-app-logs\"}";
83+
ObjectKeyOptions options = objectMapper.readValue(json, ObjectKeyOptions.class);
84+
85+
assertTrue(options.isTimePatternExcludedFromNamePatternPrefix());
86+
}
87+
88+
@Test
89+
void isTimePatternExcludedFromNamePatternPrefix_returns_false_when_contains_full_datetime_pattern() throws JsonProcessingException {
90+
String json = "{\"name_pattern_prefix\": \"events-%{yyyy-MM-dd'T'HH-mm-ss'Z'}\"}";
91+
ObjectKeyOptions options = objectMapper.readValue(json, ObjectKeyOptions.class);
92+
93+
assertFalse(options.isTimePatternExcludedFromNamePatternPrefix());
94+
}
2695
}

0 commit comments

Comments
 (0)