|
71 | 71 | import java.util.ArrayList; |
72 | 72 | import java.util.Arrays; |
73 | 73 | import java.util.Collections; |
| 74 | +import java.util.Collection; |
74 | 75 | import java.util.Date; |
75 | 76 | import java.util.HashMap; |
76 | 77 | import java.util.List; |
|
103 | 104 | import static org.mockito.Mockito.mock; |
104 | 105 | import static org.mockito.Mockito.verify; |
105 | 106 | import static org.mockito.Mockito.when; |
| 107 | +import org.mockito.ArgumentCaptor; |
106 | 108 | import static org.opensearch.dataprepper.plugins.sink.opensearch.OpenSearchIntegrationHelper.createContentParser; |
107 | 109 | import static org.opensearch.dataprepper.plugins.sink.opensearch.OpenSearchIntegrationHelper.createOpenSearchClient; |
108 | 110 | import static org.opensearch.dataprepper.plugins.sink.opensearch.OpenSearchIntegrationHelper.getHosts; |
@@ -173,6 +175,23 @@ private OpenSearchSink createObjectUnderTest(OpenSearchSinkConfig openSearchSink |
173 | 175 | return sink; |
174 | 176 | } |
175 | 177 |
|
| 178 | + private OpenSearchSink createObjectUnderTestWithDlqPipeline(OpenSearchSinkConfig openSearchSinkConfig, HeadlessPipeline dlqPipeline, boolean doInitialize) { |
| 179 | + sinkContext = mock(SinkContext.class); |
| 180 | + when(sinkContext.getTagsTargetKey()).thenReturn(null); |
| 181 | + when(sinkContext.getForwardToPipelines()).thenReturn(Map.of()); |
| 182 | + when(pipelineDescription.getPipelineName()).thenReturn(PIPELINE_NAME); |
| 183 | + when(pluginSetting.getPipelineName()).thenReturn(PIPELINE_NAME); |
| 184 | + when(pluginSetting.getName()).thenReturn(PLUGIN_NAME); |
| 185 | + OpenSearchSink sink = new OpenSearchSink( |
| 186 | + pluginSetting, sinkContext, expressionEvaluator, awsCredentialsSupplier, pipelineDescription, pluginConfigObservable, openSearchSinkConfig); |
| 187 | + sink.setFailurePipeline(dlqPipeline); |
| 188 | + if (doInitialize) { |
| 189 | + sink.doInitialize(); |
| 190 | + } |
| 191 | + sinksToShutdown.add(sink); |
| 192 | + return sink; |
| 193 | + } |
| 194 | + |
176 | 195 | private OpenSearchSink createObjectUnderTestWithSinkContext(OpenSearchSinkConfig openSearchSinkConfig, final Map<String, HeadlessPipeline> forwardPipelineMap, boolean doInitialize) { |
177 | 196 | sinkContext = mock(SinkContext.class); |
178 | 197 | testTagsTargetKey = RandomStringUtils.randomAlphabetic(5); |
@@ -906,6 +925,47 @@ void testOutputForwardsCreatedDocumentsToAPipeline() throws IOException, Interru |
906 | 925 | verify(sinkContext).forwardRecords(any(), eq(null), eq(null)); |
907 | 926 | } |
908 | 927 |
|
| 928 | + @Test |
| 929 | + @Timeout(value = 50, unit = TimeUnit.SECONDS) |
| 930 | + void testOutputFailedDocumentsToDLQPipeline() throws IOException, InterruptedException { |
| 931 | + HeadlessPipeline dlqPipeline = mock(HeadlessPipeline.class); |
| 932 | + final String testIndexAlias = "test-alias"; |
| 933 | + final String testTemplateFile = Objects.requireNonNull( |
| 934 | + getClass().getClassLoader().getResource(TEST_TEMPLATE_V1_FILE)).getFile(); |
| 935 | + final String testIdField = "someId"; |
| 936 | + final String testId = "foo"; |
| 937 | + final String testId2 = "foo2"; |
| 938 | + final Record<Event> testRecord1 = new Record(JacksonEvent.builder() |
| 939 | + .withEventType(EventType.TRACE.toString()) |
| 940 | + .withData(Map.of(testIdField, testId, "name", "value")).build()); |
| 941 | + final Record<Event> testRecord2 = new Record(JacksonEvent.builder() |
| 942 | + .withEventType(EventType.TRACE.toString()) |
| 943 | + .withData(Map.of(testIdField, testId, "name", Map.of("key", "value"))).build()); |
| 944 | + //List<Record<Event>> testRecords = Arrays.asList(testRecord1, testRecord2); |
| 945 | + List<Record<Event>> testRecords = Collections.singletonList(testRecord1); |
| 946 | + Map<String, Object> metadata = initializeConfigurationMetadata(null, testIndexAlias, testTemplateFile); |
| 947 | + metadata.put(IndexConfiguration.DOCUMENT_ID_FIELD, testIdField); |
| 948 | + final OpenSearchSinkConfig openSearchSinkConfig = generateOpenSearchSinkConfigByMetadata(metadata); |
| 949 | + final OpenSearchSink sink = createObjectUnderTestWithDlqPipeline(openSearchSinkConfig, dlqPipeline, true); |
| 950 | + sink.output(testRecords); |
| 951 | + final List<Map<String, Object>> retSources = getSearchResponseDocSources(testIndexAlias); |
| 952 | + assertThat(retSources.size(), equalTo(1)); |
| 953 | + assertThat(getDocumentCount(testIndexAlias, "_id", testId), equalTo(Integer.valueOf(1))); |
| 954 | + |
| 955 | + // verify metrics |
| 956 | + final List<Measurement> bulkRequestLatencies = MetricsTestUtil.getMeasurementList( |
| 957 | + new StringJoiner(MetricNames.DELIMITER).add(PIPELINE_NAME).add(PLUGIN_NAME) |
| 958 | + .add(OpenSearchSink.BULKREQUEST_LATENCY).toString()); |
| 959 | + assertThat(bulkRequestLatencies.size(), equalTo(3)); |
| 960 | + // COUNT |
| 961 | + Assert.assertEquals(1.0, bulkRequestLatencies.get(0).getValue(), 0); |
| 962 | + testRecords = Collections.singletonList(testRecord2); |
| 963 | + sink.output(testRecords); |
| 964 | + ArgumentCaptor<Collection<Record<Event>>> captor = ArgumentCaptor.forClass(Collection.class); |
| 965 | + verify(dlqPipeline).sendEvents(captor.capture()); |
| 966 | + assertThat(captor.getValue().size(), equalTo(1)); |
| 967 | + } |
| 968 | + |
909 | 969 | @Test |
910 | 970 | @Timeout(value = 50, unit = TimeUnit.SECONDS) |
911 | 971 | void testOutputCustomIndex() throws IOException, InterruptedException { |
|
0 commit comments