mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-17 10:25:15 +00:00
Merge pull request #14432 from s1monw/add_shard_failure_as_suppressed
Deduplicate cause if already contained in shard failures
This commit is contained in:
commit
d76ae6718e
@ -38,13 +38,11 @@ public class SearchPhaseExecutionException extends ElasticsearchException {
|
||||
private final ShardSearchFailure[] shardFailures;
|
||||
|
||||
public SearchPhaseExecutionException(String phaseName, String msg, ShardSearchFailure[] shardFailures) {
|
||||
super(msg);
|
||||
this.phaseName = phaseName;
|
||||
this.shardFailures = shardFailures;
|
||||
this(phaseName, msg, null, shardFailures);
|
||||
}
|
||||
|
||||
public SearchPhaseExecutionException(String phaseName, String msg, Throwable cause, ShardSearchFailure[] shardFailures) {
|
||||
super(msg, cause);
|
||||
super(msg, deduplicateCause(cause, shardFailures));
|
||||
this.phaseName = phaseName;
|
||||
this.shardFailures = shardFailures;
|
||||
}
|
||||
@ -63,12 +61,26 @@ public class SearchPhaseExecutionException extends ElasticsearchException {
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeOptionalString(phaseName);
|
||||
out.writeVInt(shardFailures == null ? 0 : shardFailures.length);
|
||||
if (shardFailures != null) {
|
||||
out.writeVInt(shardFailures.length);
|
||||
for (ShardSearchFailure failure : shardFailures) {
|
||||
failure.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Throwable deduplicateCause(Throwable cause, ShardSearchFailure[] shardFailures) {
|
||||
if (shardFailures == null) {
|
||||
throw new IllegalArgumentException("shardSearchFailures must not be null");
|
||||
}
|
||||
// if the cause of this exception is also the cause of one of the shard failures we don't add it
|
||||
// to prevent duplication in stack traces rendered to the REST layer
|
||||
if (cause != null) {
|
||||
for (ShardSearchFailure failure : shardFailures) {
|
||||
failure.writeTo(out);
|
||||
if (failure.getCause() == cause) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cause;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -114,7 +114,7 @@ public class TransportSearchScrollQueryAndFetchAction extends AbstractComponent
|
||||
|
||||
public void start() {
|
||||
if (scrollId.getContext().length == 0) {
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "no nodes to search on", null));
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "no nodes to search on", ShardSearchFailure.EMPTY_ARRAY));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ public class TransportSearchScrollQueryAndFetchAction extends AbstractComponent
|
||||
successfulOps.decrementAndGet();
|
||||
if (counter.decrementAndGet() == 0) {
|
||||
if (successfulOps.get() == 0) {
|
||||
listener.onFailure(new SearchPhaseExecutionException("query_fetch", "all shards failed", buildShardFailures()));
|
||||
listener.onFailure(new SearchPhaseExecutionException("query_fetch", "all shards failed", t, buildShardFailures()));
|
||||
} else {
|
||||
finishHim();
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ public class TransportSearchScrollQueryThenFetchAction extends AbstractComponent
|
||||
|
||||
public void start() {
|
||||
if (scrollId.getContext().length == 0) {
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "no nodes to search on", null));
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "no nodes to search on", ShardSearchFailure.EMPTY_ARRAY));
|
||||
return;
|
||||
}
|
||||
final AtomicInteger counter = new AtomicInteger(scrollId.getContext().length);
|
||||
@ -143,7 +143,7 @@ public class TransportSearchScrollQueryThenFetchAction extends AbstractComponent
|
||||
try {
|
||||
executeFetchPhase();
|
||||
} catch (Throwable e) {
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "Fetch failed", e, null));
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "Fetch failed", e, ShardSearchFailure.EMPTY_ARRAY));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -181,12 +181,12 @@ public class TransportSearchScrollQueryThenFetchAction extends AbstractComponent
|
||||
successfulOps.decrementAndGet();
|
||||
if (counter.decrementAndGet() == 0) {
|
||||
if (successfulOps.get() == 0) {
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "all shards failed", buildShardFailures()));
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "all shards failed", t, buildShardFailures()));
|
||||
} else {
|
||||
try {
|
||||
executeFetchPhase();
|
||||
} catch (Throwable e) {
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "Fetch failed", e, null));
|
||||
listener.onFailure(new SearchPhaseExecutionException("query", "Fetch failed", e, ShardSearchFailure.EMPTY_ARRAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -220,17 +220,19 @@ public abstract class TransportSearchTypeAction extends TransportAction<SearchRe
|
||||
logger.trace("{}: Failed to execute [{}]", t, shard, request);
|
||||
}
|
||||
}
|
||||
final ShardSearchFailure[] shardSearchFailures = buildShardFailures();
|
||||
if (successfulOps.get() == 0) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("All shards failed for phase: [{}]", t, firstPhaseName());
|
||||
}
|
||||
|
||||
// no successful ops, raise an exception
|
||||
raiseEarlyFailure(new SearchPhaseExecutionException(firstPhaseName(), "all shards failed", buildShardFailures()));
|
||||
raiseEarlyFailure(new SearchPhaseExecutionException(firstPhaseName(), "all shards failed", t, shardSearchFailures));
|
||||
} else {
|
||||
try {
|
||||
innerMoveToSecondPhase();
|
||||
} catch (Throwable e) {
|
||||
raiseEarlyFailure(new ReduceSearchPhaseException(firstPhaseName(), "", e, buildShardFailures()));
|
||||
raiseEarlyFailure(new ReduceSearchPhaseException(firstPhaseName(), "", e, shardSearchFailures));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -140,7 +140,7 @@ public class ESExceptionTests extends ESTestCase {
|
||||
new SearchShardTarget("node_1", "foo", 1));
|
||||
ShardSearchFailure failure1 = new ShardSearchFailure(new ParsingException(1, 2, "foobar", null),
|
||||
new SearchShardTarget("node_1", "foo", 2));
|
||||
SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1});
|
||||
SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", randomBoolean() ? failure1.getCause() : failure.getCause(), new ShardSearchFailure[]{failure, failure1});
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject();
|
||||
ex.toXContent(builder, PARAMS);
|
||||
@ -163,6 +163,21 @@ public class ESExceptionTests extends ESTestCase {
|
||||
String expected = "{\"type\":\"search_phase_execution_exception\",\"reason\":\"all shards failed\",\"phase\":\"search\",\"grouped\":true,\"failed_shards\":[{\"shard\":1,\"index\":\"foo\",\"node\":\"node_1\",\"reason\":{\"type\":\"parsing_exception\",\"reason\":\"foobar\",\"line\":1,\"col\":2}},{\"shard\":1,\"index\":\"foo1\",\"node\":\"node_1\",\"reason\":{\"type\":\"query_shard_exception\",\"reason\":\"foobar\",\"index\":\"foo1\"}}]}";
|
||||
assertEquals(expected, builder.string());
|
||||
}
|
||||
{
|
||||
ShardSearchFailure failure = new ShardSearchFailure(new ParsingException(1, 2, "foobar", null),
|
||||
new SearchShardTarget("node_1", "foo", 1));
|
||||
ShardSearchFailure failure1 = new ShardSearchFailure(new ParsingException(1, 2, "foobar", null),
|
||||
new SearchShardTarget("node_1", "foo", 2));
|
||||
NullPointerException nullPointerException = new NullPointerException();
|
||||
SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", nullPointerException, new ShardSearchFailure[]{failure, failure1});
|
||||
assertEquals(nullPointerException, ex.getCause());
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject();
|
||||
ex.toXContent(builder, PARAMS);
|
||||
builder.endObject();
|
||||
String expected = "{\"type\":\"search_phase_execution_exception\",\"reason\":\"all shards failed\",\"phase\":\"search\",\"grouped\":true,\"failed_shards\":[{\"shard\":1,\"index\":\"foo\",\"node\":\"node_1\",\"reason\":{\"type\":\"parsing_exception\",\"reason\":\"foobar\",\"line\":1,\"col\":2}}],\"caused_by\":{\"type\":\"null_pointer_exception\",\"reason\":null}}";
|
||||
assertEquals(expected, builder.string());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetRootCause() {
|
||||
|
@ -307,7 +307,7 @@ public class TemplateQueryIT extends ESIntegTestCase {
|
||||
templateParams)).get();
|
||||
fail("Expected SearchPhaseExecutionException");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getCause().getMessage(), containsString("Illegal index script format"));
|
||||
assertThat(e.toString(), containsString("Illegal index script format"));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user