99
1010package org .elasticsearch .index .reindex ;
1111
12+ import org .elasticsearch .ElasticsearchStatusException ;
13+ import org .elasticsearch .common .bytes .BytesArray ;
14+ import org .elasticsearch .common .settings .Settings ;
1215import org .elasticsearch .index .query .QueryBuilders ;
1316import org .elasticsearch .plugins .Plugin ;
1417import org .elasticsearch .plugins .PluginsService ;
1518import org .elasticsearch .reindex .BulkIndexByScrollResponseMatcher ;
1619import org .elasticsearch .reindex .ReindexPlugin ;
20+ import org .elasticsearch .reindex .TransportReindexAction ;
21+ import org .elasticsearch .rest .root .MainRestPlugin ;
1722import org .elasticsearch .search .sort .SortOrder ;
1823import org .elasticsearch .telemetry .Measurement ;
1924import org .elasticsearch .telemetry .TestTelemetryPlugin ;
2025import org .elasticsearch .test .ESIntegTestCase ;
2126
27+ import java .net .InetSocketAddress ;
2228import java .util .Arrays ;
2329import java .util .Collection ;
2430import java .util .List ;
31+ import java .util .Map ;
2532
2633import static org .elasticsearch .index .query .QueryBuilders .termQuery ;
2734import static org .elasticsearch .reindex .DeleteByQueryMetrics .DELETE_BY_QUERY_TIME_HISTOGRAM ;
35+ import static org .elasticsearch .reindex .ReindexMetrics .ATTRIBUTE_NAME_ERROR_TYPE ;
36+ import static org .elasticsearch .reindex .ReindexMetrics .ATTRIBUTE_NAME_SOURCE ;
37+ import static org .elasticsearch .reindex .ReindexMetrics .ATTRIBUTE_VALUE_SOURCE_LOCAL ;
38+ import static org .elasticsearch .reindex .ReindexMetrics .ATTRIBUTE_VALUE_SOURCE_REMOTE ;
39+ import static org .elasticsearch .reindex .ReindexMetrics .REINDEX_COMPLETION_HISTOGRAM ;
2840import static org .elasticsearch .reindex .ReindexMetrics .REINDEX_TIME_HISTOGRAM ;
2941import static org .elasticsearch .reindex .UpdateByQueryMetrics .UPDATE_BY_QUERY_TIME_HISTOGRAM ;
3042import static org .elasticsearch .test .hamcrest .ElasticsearchAssertions .assertHitCount ;
3143import static org .hamcrest .Matchers .equalTo ;
44+ import static org .hamcrest .Matchers .greaterThanOrEqualTo ;
3245
3346@ ESIntegTestCase .ClusterScope (numDataNodes = 0 , numClientNodes = 0 , scope = ESIntegTestCase .Scope .TEST )
3447public class ReindexPluginMetricsIT extends ESIntegTestCase {
3548 @ Override
3649 protected Collection <Class <? extends Plugin >> nodePlugins () {
37- return Arrays .asList (ReindexPlugin .class , TestTelemetryPlugin .class );
50+ return Arrays .asList (ReindexPlugin .class , TestTelemetryPlugin .class , MainRestPlugin .class );
51+ }
52+
53+ @ Override
54+ protected boolean addMockHttpTransport () {
55+ return false ;
56+ }
57+
58+ @ Override
59+ protected Settings nodeSettings (int nodeOrdinal , Settings otherSettings ) {
60+ return Settings .builder ()
61+ .put (super .nodeSettings (nodeOrdinal , otherSettings ))
62+ .put (TransportReindexAction .REMOTE_CLUSTER_WHITELIST .getKey (), "*:*" )
63+ .build ();
3864 }
3965
4066 protected ReindexRequestBuilder reindex () {
@@ -53,6 +79,62 @@ public static BulkIndexByScrollResponseMatcher matcher() {
5379 return new BulkIndexByScrollResponseMatcher ();
5480 }
5581
82+ public void testReindexFromRemoteMetrics () throws Exception {
83+ final String dataNodeName = internalCluster ().startNode ();
84+
85+ InetSocketAddress remoteAddress = randomFrom (cluster ().httpAddresses ());
86+ RemoteInfo remote = new RemoteInfo (
87+ "http" ,
88+ remoteAddress .getHostString (),
89+ remoteAddress .getPort (),
90+ null ,
91+ new BytesArray ("{\" match_all\" :{}}" ),
92+ null ,
93+ null ,
94+ Map .of (),
95+ RemoteInfo .DEFAULT_SOCKET_TIMEOUT ,
96+ RemoteInfo .DEFAULT_CONNECT_TIMEOUT
97+ );
98+
99+ final TestTelemetryPlugin testTelemetryPlugin = internalCluster ().getInstance (PluginsService .class , dataNodeName )
100+ .filterPlugins (TestTelemetryPlugin .class )
101+ .findFirst ()
102+ .orElseThrow ();
103+
104+ var expectedException = assertThrows (
105+ "Source index not created yet, should throw not found exception" ,
106+ ElasticsearchStatusException .class ,
107+ () -> reindex ().source ("source" ).setRemoteInfo (remote ).destination ("dest" ).get ()
108+ );
109+
110+ // assert failure metrics
111+ assertBusy (() -> {
112+ testTelemetryPlugin .collect ();
113+ assertThat (testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM ).size (), equalTo (1 ));
114+ List <Measurement > completions = testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_COMPLETION_HISTOGRAM );
115+ assertThat (completions .size (), equalTo (1 ));
116+ assertThat (completions .getFirst ().attributes ().get (ATTRIBUTE_NAME_ERROR_TYPE ), equalTo (expectedException .status ().name ()));
117+ assertThat (completions .getFirst ().attributes ().get (ATTRIBUTE_NAME_SOURCE ), equalTo (ATTRIBUTE_VALUE_SOURCE_REMOTE ));
118+ });
119+
120+ // now create the source index
121+ indexRandom (true , prepareIndex ("source" ).setId ("1" ).setSource ("foo" , "a" ));
122+ assertHitCount (prepareSearch ("source" ).setSize (0 ), 1 );
123+
124+ reindex ().source ("source" ).setRemoteInfo (remote ).destination ("dest" ).get ();
125+
126+ // assert success metrics
127+ assertBusy (() -> {
128+ testTelemetryPlugin .collect ();
129+ assertThat (testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM ).size (), equalTo (2 ));
130+ List <Measurement > completions = testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_COMPLETION_HISTOGRAM );
131+ assertThat (completions .size (), equalTo (2 ));
132+ assertNull (completions .get (1 ).attributes ().get (ATTRIBUTE_NAME_ERROR_TYPE ));
133+ assertThat (completions .get (1 ).attributes ().get (ATTRIBUTE_NAME_SOURCE ), equalTo (ATTRIBUTE_VALUE_SOURCE_REMOTE ));
134+ });
135+
136+ }
137+
56138 public void testReindexMetrics () throws Exception {
57139 final String dataNodeName = internalCluster ().startNode ();
58140
@@ -75,33 +157,67 @@ public void testReindexMetrics() throws Exception {
75157 // Use assertBusy to wait for all threads to complete so we get deterministic results
76158 assertBusy (() -> {
77159 testTelemetryPlugin .collect ();
78- List < Measurement > measurements = testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM );
79- assertThat (measurements .size (), equalTo (1 ));
160+ assertThat ( testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM ). size (), equalTo ( 1 ) );
161+ assertThat (testTelemetryPlugin . getLongHistogramMeasurement ( REINDEX_COMPLETION_HISTOGRAM ) .size (), equalTo (1 ));
80162 });
81163
82164 // Now none of them
83165 createIndex ("none" );
84166 reindex ().source ("source" ).destination ("none" ).filter (termQuery ("foo" , "no_match" )).get ();
85167 assertBusy (() -> {
86168 testTelemetryPlugin .collect ();
87- List < Measurement > measurements = testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM );
88- assertThat (measurements .size (), equalTo (2 ));
169+ assertThat ( testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM ). size (), equalTo ( 2 ) );
170+ assertThat (testTelemetryPlugin . getLongHistogramMeasurement ( REINDEX_COMPLETION_HISTOGRAM ) .size (), equalTo (2 ));
89171 });
90172
91173 // Now half of them
92174 reindex ().source ("source" ).destination ("dest_half" ).filter (termQuery ("foo" , "a" )).get ();
93175 assertBusy (() -> {
94176 testTelemetryPlugin .collect ();
95- List < Measurement > measurements = testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM );
96- assertThat (measurements .size (), equalTo (3 ));
177+ assertThat ( testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM ). size (), equalTo ( 3 ) );
178+ assertThat (testTelemetryPlugin . getLongHistogramMeasurement ( REINDEX_COMPLETION_HISTOGRAM ) .size (), equalTo (3 ));
97179 });
98180
99181 // Limit with maxDocs
100182 reindex ().source ("source" ).destination ("dest_size_one" ).maxDocs (1 ).get ();
101183 assertBusy (() -> {
102184 testTelemetryPlugin .collect ();
103- List <Measurement > measurements = testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM );
104- assertThat (measurements .size (), equalTo (4 ));
185+ assertThat (testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM ).size (), equalTo (4 ));
186+ assertThat (testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_COMPLETION_HISTOGRAM ).size (), equalTo (4 ));
187+
188+ // asset all metric attributes are correct
189+ testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_COMPLETION_HISTOGRAM ).forEach (m -> {
190+ assertNull (m .attributes ().get (ATTRIBUTE_NAME_ERROR_TYPE ));
191+ assertThat (m .attributes ().get (ATTRIBUTE_NAME_SOURCE ), equalTo (ATTRIBUTE_VALUE_SOURCE_LOCAL ));
192+ });
193+ });
194+ }
195+
196+ public void testReindexMetricsWithBulkFailure () throws Exception {
197+ final String dataNodeName = internalCluster ().startNode ();
198+ final TestTelemetryPlugin testTelemetryPlugin = internalCluster ().getInstance (PluginsService .class , dataNodeName )
199+ .filterPlugins (TestTelemetryPlugin .class )
200+ .findFirst ()
201+ .orElseThrow ();
202+
203+ // source and destination have conflicting mappings to cause bulk failures
204+ indexRandom (true , prepareIndex ("source" ).setId ("2" ).setSource ("test" , "words words" ));
205+ indexRandom (true , prepareIndex ("dest" ).setId ("1" ).setSource ("test" , 10 ));
206+
207+ var response = reindex ().source ("source" ).destination ("dest" ).get ();
208+ assertThat (response .getBulkFailures ().size (), greaterThanOrEqualTo (1 ));
209+
210+ assertBusy (() -> {
211+ testTelemetryPlugin .collect ();
212+ assertThat (testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_TIME_HISTOGRAM ).size (), equalTo (1 ));
213+ assertThat (testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_COMPLETION_HISTOGRAM ).size (), equalTo (1 ));
214+ assertThat (
215+ testTelemetryPlugin .getLongHistogramMeasurement (REINDEX_COMPLETION_HISTOGRAM )
216+ .getFirst ()
217+ .attributes ()
218+ .get (ATTRIBUTE_NAME_ERROR_TYPE ),
219+ equalTo ("org.elasticsearch.index.mapper.DocumentParsingException" )
220+ );
105221 });
106222 }
107223
0 commit comments