|
19 | 19 |
|
20 | 20 | package org.elasticsearch.cluster.allocation;
|
21 | 21 |
|
| 22 | +import org.apache.logging.log4j.Level; |
22 | 23 | import org.apache.logging.log4j.Logger;
|
23 | 24 | import org.apache.lucene.util.IOUtils;
|
24 | 25 | import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
25 | 26 | import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteResponse;
|
| 27 | +import org.elasticsearch.action.admin.cluster.reroute.TransportClusterRerouteAction; |
26 | 28 | import org.elasticsearch.action.support.ActiveShardCount;
|
27 | 29 | import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
28 | 30 | import org.elasticsearch.cluster.ClusterState;
|
29 | 31 | import org.elasticsearch.cluster.health.ClusterHealthStatus;
|
| 32 | +import org.elasticsearch.cluster.metadata.IndexMetaData; |
30 | 33 | import org.elasticsearch.cluster.node.DiscoveryNode;
|
31 | 34 | import org.elasticsearch.cluster.routing.ShardRouting;
|
32 | 35 | import org.elasticsearch.cluster.routing.ShardRoutingState;
|
33 | 36 | import org.elasticsearch.cluster.routing.allocation.RerouteExplanation;
|
34 | 37 | import org.elasticsearch.cluster.routing.allocation.RoutingExplanations;
|
35 | 38 | import org.elasticsearch.cluster.routing.allocation.command.AllocateEmptyPrimaryAllocationCommand;
|
| 39 | +import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand; |
36 | 40 | import org.elasticsearch.cluster.routing.allocation.command.MoveAllocationCommand;
|
37 | 41 | import org.elasticsearch.cluster.routing.allocation.decider.Decision;
|
38 | 42 | import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
|
|
50 | 54 | import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
51 | 55 | import org.elasticsearch.test.ESIntegTestCase.Scope;
|
52 | 56 | import org.elasticsearch.test.InternalTestCluster;
|
| 57 | +import org.elasticsearch.test.MockLogAppender; |
53 | 58 |
|
54 | 59 | import java.nio.file.Path;
|
55 | 60 | import java.util.Arrays;
|
|
63 | 68 | import static org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_ENABLE_SETTING;
|
64 | 69 | import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
65 | 70 | import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertBlocked;
|
| 71 | +import static org.hamcrest.Matchers.containsString; |
66 | 72 | import static org.hamcrest.Matchers.equalTo;
|
67 | 73 | import static org.hamcrest.Matchers.hasSize;
|
68 | 74 |
|
@@ -304,6 +310,84 @@ public void testRerouteExplain() {
|
304 | 310 | assertThat(explanation.decisions().type(), equalTo(Decision.Type.YES));
|
305 | 311 | }
|
306 | 312 |
|
| 313 | + public void testMessageLogging() throws Exception{ |
| 314 | + final Settings settings = Settings.builder() |
| 315 | + .put(EnableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_ENABLE_SETTING.getKey(), Allocation.NONE.name()) |
| 316 | + .put(EnableAllocationDecider.CLUSTER_ROUTING_REBALANCE_ENABLE_SETTING.getKey(), EnableAllocationDecider.Rebalance.NONE.name()) |
| 317 | + .build(); |
| 318 | + |
| 319 | + final String nodeName1 = internalCluster().startNode(settings); |
| 320 | + assertThat(cluster().size(), equalTo(1)); |
| 321 | + ClusterHealthResponse healthResponse = client().admin().cluster().prepareHealth().setWaitForNodes("1") |
| 322 | + .execute().actionGet(); |
| 323 | + assertThat(healthResponse.isTimedOut(), equalTo(false)); |
| 324 | + |
| 325 | + final String nodeName2 = internalCluster().startNode(settings); |
| 326 | + assertThat(cluster().size(), equalTo(2)); |
| 327 | + healthResponse = client().admin().cluster().prepareHealth().setWaitForNodes("2").execute().actionGet(); |
| 328 | + assertThat(healthResponse.isTimedOut(), equalTo(false)); |
| 329 | + |
| 330 | + final String indexName = "test_index"; |
| 331 | + client().admin().indices().prepareCreate(indexName).setWaitForActiveShards(ActiveShardCount.NONE) |
| 332 | + .setSettings(Settings.builder() |
| 333 | + .put(IndexMetaData.INDEX_NUMBER_OF_SHARDS_SETTING.getKey(), 2) |
| 334 | + .put(IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey(), 1)) |
| 335 | + .execute().actionGet(); |
| 336 | + |
| 337 | + Logger actionLogger = Loggers.getLogger(TransportClusterRerouteAction.class); |
| 338 | + |
| 339 | + MockLogAppender dryRunMockLog = new MockLogAppender(); |
| 340 | + dryRunMockLog.start(); |
| 341 | + dryRunMockLog.addExpectation( |
| 342 | + new MockLogAppender.UnseenEventExpectation("no completed message logged on dry run", |
| 343 | + TransportClusterRerouteAction.class.getName(), Level.INFO, "allocated an empty primary*") |
| 344 | + ); |
| 345 | + Loggers.addAppender(actionLogger, dryRunMockLog); |
| 346 | + |
| 347 | + AllocationCommand dryRunAllocation = new AllocateEmptyPrimaryAllocationCommand(indexName, 0, nodeName1, true); |
| 348 | + ClusterRerouteResponse dryRunResponse = client().admin().cluster().prepareReroute() |
| 349 | + .setExplain(randomBoolean()) |
| 350 | + .setDryRun(true) |
| 351 | + .add(dryRunAllocation) |
| 352 | + .execute().actionGet(); |
| 353 | + |
| 354 | + // during a dry run, messages exist but are not logged or exposed |
| 355 | + assertThat(dryRunResponse.getExplanations().getYesDecisionMessages(), hasSize(1)); |
| 356 | + assertThat(dryRunResponse.getExplanations().getYesDecisionMessages().get(0), containsString("allocated an empty primary")); |
| 357 | + |
| 358 | + dryRunMockLog.assertAllExpectationsMatched(); |
| 359 | + dryRunMockLog.stop(); |
| 360 | + Loggers.removeAppender(actionLogger, dryRunMockLog); |
| 361 | + |
| 362 | + MockLogAppender allocateMockLog = new MockLogAppender(); |
| 363 | + allocateMockLog.start(); |
| 364 | + allocateMockLog.addExpectation( |
| 365 | + new MockLogAppender.SeenEventExpectation("message for first allocate empty primary", |
| 366 | + TransportClusterRerouteAction.class.getName(), Level.INFO, "allocated an empty primary*" + nodeName1 + "*") |
| 367 | + ); |
| 368 | + allocateMockLog.addExpectation( |
| 369 | + new MockLogAppender.UnseenEventExpectation("no message for second allocate empty primary", |
| 370 | + TransportClusterRerouteAction.class.getName(), Level.INFO, "allocated an empty primary*" + nodeName2 + "*") |
| 371 | + ); |
| 372 | + Loggers.addAppender(actionLogger, allocateMockLog); |
| 373 | + |
| 374 | + AllocationCommand yesDecisionAllocation = new AllocateEmptyPrimaryAllocationCommand(indexName, 0, nodeName1, true); |
| 375 | + AllocationCommand noDecisionAllocation = new AllocateEmptyPrimaryAllocationCommand("noexist", 1, nodeName2, true); |
| 376 | + ClusterRerouteResponse response = client().admin().cluster().prepareReroute() |
| 377 | + .setExplain(true) // so we get a NO decision back rather than an exception |
| 378 | + .add(yesDecisionAllocation) |
| 379 | + .add(noDecisionAllocation) |
| 380 | + .execute().actionGet(); |
| 381 | + |
| 382 | + assertThat(response.getExplanations().getYesDecisionMessages(), hasSize(1)); |
| 383 | + assertThat(response.getExplanations().getYesDecisionMessages().get(0), containsString("allocated an empty primary")); |
| 384 | + assertThat(response.getExplanations().getYesDecisionMessages().get(0), containsString(nodeName1)); |
| 385 | + |
| 386 | + allocateMockLog.assertAllExpectationsMatched(); |
| 387 | + allocateMockLog.stop(); |
| 388 | + Loggers.removeAppender(actionLogger, allocateMockLog); |
| 389 | + } |
| 390 | + |
307 | 391 | public void testClusterRerouteWithBlocks() throws Exception {
|
308 | 392 | List<String> nodesIds = internalCluster().startNodes(2);
|
309 | 393 |
|
|
0 commit comments