mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-25 22:36:20 +00:00
[REST] Render REST errors in a structural way
This commit adds support for structural errors / failures / exceptions on the elasticsearch REST layer. Exceptions are rendering with at least a `type` and a `reason` corresponding to the exception name and the message. Some expcetions like the ones associated with an index or a shard will have additional information about the index the exception was triggered on or the shard respectivly. Each rendered response will also contain a list of root causes which is a list of distinct shard level errors returned for the request. Root causes are the lowest level elasticsearch exception found per shard response and are intended to be displayed to the user to indicate the soruce of the exception. Shard level response are by-default grouped by their type and reason to reduce the amount of duplicates retunred. Yet, the same exception retunred from different indices will not be grouped. Closes #3303
This commit is contained in:
parent
c9d72431a3
commit
15d58d91f1
@ -14,7 +14,7 @@
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
catch: /RoutingMissingException/
|
||||
catch: /routing_missing_exception/
|
||||
create:
|
||||
index: test_1
|
||||
type: test
|
||||
|
@ -89,7 +89,7 @@
|
||||
type: test
|
||||
id: 1
|
||||
- do:
|
||||
catch: /AlreadyExpiredException/
|
||||
catch: /already_expired_exception/
|
||||
create:
|
||||
index: test_1
|
||||
type: test
|
||||
|
@ -21,7 +21,7 @@
|
||||
body: { foo: bar }
|
||||
|
||||
- do:
|
||||
catch: /RoutingMissingException/
|
||||
catch: /routing_missing_exception/
|
||||
delete:
|
||||
index: test_1
|
||||
type: test
|
||||
|
@ -13,7 +13,7 @@
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
catch: /RoutingMissingException/
|
||||
catch: /routing_missing_exception/
|
||||
index:
|
||||
index: test_1
|
||||
type: test
|
||||
|
@ -74,7 +74,7 @@
|
||||
# with timestamp
|
||||
|
||||
- do:
|
||||
catch: /AlreadyExpiredException/
|
||||
catch: /already_expired_exception/
|
||||
index:
|
||||
index: test_1
|
||||
type: test
|
||||
|
@ -13,27 +13,27 @@
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
catch: /ActionRequestValidationException.+ id is missing/
|
||||
catch: /action_request_validation_exception.+ id is missing/
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _index: test_1, _type: test}
|
||||
|
||||
- do:
|
||||
catch: /ActionRequestValidationException.+ index is missing/
|
||||
catch: /action_request_validation_exception.+ index is missing/
|
||||
mget:
|
||||
body:
|
||||
docs:
|
||||
- { _type: test, _id: 1}
|
||||
|
||||
- do:
|
||||
catch: /ActionRequestValidationException.+ no documents to get/
|
||||
catch: /action_request_validation_exception.+ no documents to get/
|
||||
mget:
|
||||
body:
|
||||
docs: []
|
||||
|
||||
- do:
|
||||
catch: /ActionRequestValidationException.+ no documents to get/
|
||||
catch: /action_request_validation_exception.+ no documents to get/
|
||||
mget:
|
||||
body: {}
|
||||
|
||||
|
@ -59,14 +59,14 @@
|
||||
|
||||
|
||||
- do:
|
||||
catch: /ActionRequestValidationException.+ no documents to get/
|
||||
catch: /action_request_validation_exception.+ no documents to get/
|
||||
mget:
|
||||
index: test_1
|
||||
body:
|
||||
ids: []
|
||||
|
||||
- do:
|
||||
catch: /ActionRequestValidationException.+ no documents to get/
|
||||
catch: /action_request_validation_exception.+ no documents to get/
|
||||
mget:
|
||||
index: test_1
|
||||
body: {}
|
||||
|
@ -37,5 +37,5 @@
|
||||
foo: bar
|
||||
|
||||
- match: { responses.0.total: 1 }
|
||||
- match: { responses.1.error: "IndexMissingException[[percolator_index1] missing]" }
|
||||
- match: { responses.1.error: "/IndexMissingException.no.such.index./" }
|
||||
- match: { responses.2.total: 1 }
|
||||
|
@ -39,7 +39,7 @@
|
||||
match: {foo: bar}
|
||||
|
||||
- match: { responses.0.hits.total: 3 }
|
||||
- match: { responses.1.error: "IndexMissingException[[test_2] missing]" }
|
||||
- match: { responses.1.error: "/IndexMissingException.no.such.index./" }
|
||||
- match: { responses.2.hits.total: 1 }
|
||||
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
||||
|
||||
|
||||
- do:
|
||||
catch: /ElasticsearchIllegalArgumentException.Unable.to.parse.*/
|
||||
catch: /Unable.to.parse.*/
|
||||
put_script:
|
||||
id: "1"
|
||||
lang: "groovy"
|
||||
@ -74,7 +74,7 @@
|
||||
body: { "script" : "_score * doc[\"myParent.weight\"].value" }
|
||||
|
||||
- do:
|
||||
catch: /ElasticsearchIllegalArgumentException.script_lang.not.supported/
|
||||
catch: /script_lang.not.supported/
|
||||
put_script:
|
||||
id: "1"
|
||||
lang: "foobar"
|
||||
|
@ -50,7 +50,7 @@
|
||||
body: { "template": { "query": { "match{{}}_all": {}}, "size": "{{my_size}}" } }
|
||||
|
||||
- do:
|
||||
catch: /ElasticsearchIllegalArgumentException\SUnable\sto\sparse.*/
|
||||
catch: /Unable\sto\sparse.*/
|
||||
put_template:
|
||||
id: "1"
|
||||
body: { "template": { "query": { "match{{}}_all": {}}, "size": "{{my_size}}" } }
|
||||
|
@ -37,7 +37,7 @@
|
||||
- match: { hits.total: 1 }
|
||||
|
||||
- do:
|
||||
catch: /ElasticsearchIllegalArgumentException.Unable.to.find.on.disk.script.simple1/
|
||||
catch: /Unable.to.find.on.disk.script.simple1/
|
||||
search_template:
|
||||
body: { "template" : "simple1" }
|
||||
|
||||
|
@ -15,7 +15,7 @@ setup:
|
||||
"Parent":
|
||||
|
||||
- do:
|
||||
catch: /RoutingMissingException/
|
||||
catch: /routing_missing_exception/
|
||||
update:
|
||||
index: test_1
|
||||
type: test
|
||||
|
@ -81,7 +81,7 @@
|
||||
# with timestamp
|
||||
|
||||
- do:
|
||||
catch: /AlreadyExpiredException/
|
||||
catch: /already_expired_exception/
|
||||
index:
|
||||
index: test_1
|
||||
type: test
|
||||
|
@ -22,18 +22,23 @@ package org.elasticsearch;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.rest.HasRestHeaders;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A base class for all elasticsearch exceptions.
|
||||
*/
|
||||
public class ElasticsearchException extends RuntimeException {
|
||||
public class ElasticsearchException extends RuntimeException implements ToXContent {
|
||||
|
||||
public static final String REST_EXCEPTION_SKIP_CAUSE = "rest.exception.skip_cause";
|
||||
|
||||
/**
|
||||
* Construct a <code>ElasticsearchException</code> with the specified detail message.
|
||||
@ -62,12 +67,8 @@ public class ElasticsearchException extends RuntimeException {
|
||||
Throwable cause = unwrapCause();
|
||||
if (cause == this) {
|
||||
return RestStatus.INTERNAL_SERVER_ERROR;
|
||||
} else if (cause instanceof ElasticsearchException) {
|
||||
return ((ElasticsearchException) cause).status();
|
||||
} else if (cause instanceof IllegalArgumentException) {
|
||||
return RestStatus.BAD_REQUEST;
|
||||
} else {
|
||||
return RestStatus.INTERNAL_SERVER_ERROR;
|
||||
return ExceptionsHelper.status(cause);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,19 +115,6 @@ public class ElasticsearchException extends RuntimeException {
|
||||
return rootCause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the most specific cause of this exception, that is,
|
||||
* either the innermost cause (root cause) or this exception itself.
|
||||
* <p>Differs from {@link #getRootCause()} in that it falls back
|
||||
* to the present exception if there is no root cause.
|
||||
*
|
||||
* @return the most specific cause (never <code>null</code>)
|
||||
*/
|
||||
public Throwable getMostSpecificCause() {
|
||||
Throwable rootCause = getRootCause();
|
||||
return (rootCause != null ? rootCause : this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this exception contains an exception of the given type:
|
||||
* either it is of the given class itself or it contains a nested cause
|
||||
@ -175,21 +163,6 @@ public class ElasticsearchException extends RuntimeException {
|
||||
this.headers = headers(headers);
|
||||
}
|
||||
|
||||
public WithRestHeaders(String msg, @Nullable ImmutableMap<String, List<String>> headers) {
|
||||
super(msg);
|
||||
this.headers = headers != null ? headers : ImmutableMap.<String, List<String>>of();
|
||||
}
|
||||
|
||||
public WithRestHeaders(String msg, Throwable cause, Tuple<String, String[]>... headers) {
|
||||
super(msg, cause);
|
||||
this.headers = headers(headers);
|
||||
}
|
||||
|
||||
public WithRestHeaders(String msg, Throwable cause, @Nullable ImmutableMap<String, List<String>> headers) {
|
||||
super(msg, cause);
|
||||
this.headers = headers != null ? headers : ImmutableMap.<String, List<String>>of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<String, List<String>> getHeaders() {
|
||||
return headers;
|
||||
@ -215,4 +188,97 @@ public class ElasticsearchException extends RuntimeException {
|
||||
return ImmutableMap.copyOf(map);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (this instanceof ElasticsearchWrapperException) {
|
||||
toXContent(builder, params, this);
|
||||
} else {
|
||||
builder.field("type", getExceptionName(this));
|
||||
builder.field("reason", getMessage());
|
||||
innerToXContent(builder, params);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders additional per exception information into the xcontent
|
||||
*/
|
||||
protected void innerToXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
causeToXContent(builder, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a cause exception as xcontent
|
||||
*/
|
||||
protected final void causeToXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
final Throwable cause = getCause();
|
||||
if (cause != null && params.paramAsBoolean(REST_EXCEPTION_SKIP_CAUSE, false) == false) {
|
||||
builder.field("caused_by");
|
||||
builder.startObject();
|
||||
toXContent(builder, params, cause);
|
||||
builder.endObject();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Statis toXContent helper method that also renders non {@link org.elasticsearch.ElasticsearchException} instances as XContent.
|
||||
*/
|
||||
public static void toXContent(XContentBuilder builder, Params params, Throwable ex) throws IOException {
|
||||
ex = ExceptionsHelper.unwrapCause(ex);
|
||||
if (ex instanceof ElasticsearchException) {
|
||||
((ElasticsearchException) ex).toXContent(builder, params);
|
||||
} else {
|
||||
builder.field("type", getExceptionName(ex));
|
||||
builder.field("reason", ex.getMessage());
|
||||
if (ex.getCause() != null) {
|
||||
builder.field("caused_by");
|
||||
builder.startObject();
|
||||
toXContent(builder, params, ex.getCause());
|
||||
builder.endObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root cause of this exception or mupltiple if different shards caused different exceptions
|
||||
*/
|
||||
public ElasticsearchException[] guessRootCauses() {
|
||||
final Throwable cause = getCause();
|
||||
if (cause != null && cause instanceof ElasticsearchException) {
|
||||
return ((ElasticsearchException) cause).guessRootCauses();
|
||||
}
|
||||
return new ElasticsearchException[] {this};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root cause of this exception or mupltiple if different shards caused different exceptions.
|
||||
* If the given exception is not an instance of {@link org.elasticsearch.ElasticsearchException} an empty array
|
||||
* is returned.
|
||||
*/
|
||||
public static ElasticsearchException[] guessRootCauses(Throwable t) {
|
||||
Throwable ex = ExceptionsHelper.unwrapCause(t);
|
||||
if (ex instanceof ElasticsearchException) {
|
||||
return ((ElasticsearchException) ex).guessRootCauses();
|
||||
}
|
||||
return new ElasticsearchException[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a underscore case name for the given exception. This method strips <tt>Elasticsearch</tt> prefixes from exception names.
|
||||
*/
|
||||
public static String getExceptionName(Throwable ex) {
|
||||
String simpleName = ex.getClass().getSimpleName();
|
||||
if (simpleName.startsWith("Elasticsearch")) {
|
||||
simpleName = simpleName.substring("Elasticsearch".length());
|
||||
}
|
||||
return Strings.toUnderscoreCase(simpleName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ExceptionsHelper.detailedMessage(this).trim();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -54,8 +54,12 @@ public final class ExceptionsHelper {
|
||||
}
|
||||
|
||||
public static RestStatus status(Throwable t) {
|
||||
if (t instanceof ElasticsearchException) {
|
||||
return ((ElasticsearchException) t).status();
|
||||
if (t != null) {
|
||||
if (t instanceof ElasticsearchException) {
|
||||
return ((ElasticsearchException) t).status();
|
||||
} else if (t instanceof IllegalArgumentException) {
|
||||
return RestStatus.BAD_REQUEST;
|
||||
}
|
||||
}
|
||||
return RestStatus.INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
@ -19,6 +19,9 @@
|
||||
|
||||
package org.elasticsearch.action;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.bootstrap.Elasticsearch;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
@ -164,15 +167,15 @@ public abstract class ActionWriteResponse extends ActionResponse {
|
||||
private String index;
|
||||
private int shardId;
|
||||
private String nodeId;
|
||||
private String reason;
|
||||
private Throwable cause;
|
||||
private RestStatus status;
|
||||
private boolean primary;
|
||||
|
||||
public Failure(String index, int shardId, @Nullable String nodeId, String reason, RestStatus status, boolean primary) {
|
||||
public Failure(String index, int shardId, @Nullable String nodeId, Throwable cause, RestStatus status, boolean primary) {
|
||||
this.index = index;
|
||||
this.shardId = shardId;
|
||||
this.nodeId = nodeId;
|
||||
this.reason = reason;
|
||||
this.cause = cause;
|
||||
this.status = status;
|
||||
this.primary = primary;
|
||||
}
|
||||
@ -209,7 +212,7 @@ public abstract class ActionWriteResponse extends ActionResponse {
|
||||
*/
|
||||
@Override
|
||||
public String reason() {
|
||||
return reason;
|
||||
return ExceptionsHelper.detailedMessage(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,7 +236,7 @@ public abstract class ActionWriteResponse extends ActionResponse {
|
||||
index = in.readString();
|
||||
shardId = in.readVInt();
|
||||
nodeId = in.readOptionalString();
|
||||
reason = in.readString();
|
||||
cause = in.readThrowable();
|
||||
status = RestStatus.readFrom(in);
|
||||
primary = in.readBoolean();
|
||||
}
|
||||
@ -243,7 +246,7 @@ public abstract class ActionWriteResponse extends ActionResponse {
|
||||
out.writeString(index);
|
||||
out.writeVInt(shardId);
|
||||
out.writeOptionalString(nodeId);
|
||||
out.writeString(reason);
|
||||
out.writeThrowable(cause);
|
||||
RestStatus.writeTo(out, status);
|
||||
out.writeBoolean(primary);
|
||||
}
|
||||
@ -254,7 +257,10 @@ public abstract class ActionWriteResponse extends ActionResponse {
|
||||
builder.field(Fields._INDEX, index);
|
||||
builder.field(Fields._SHARD, shardId);
|
||||
builder.field(Fields._NODE, nodeId);
|
||||
builder.field(Fields.REASON, reason);
|
||||
builder.field(Fields.REASON);
|
||||
builder.startObject();
|
||||
ElasticsearchException.toXContent(builder, params, cause);
|
||||
builder.endObject();
|
||||
builder.field(Fields.STATUS, status);
|
||||
builder.field(Fields.PRIMARY, primary);
|
||||
builder.endObject();
|
||||
|
@ -51,7 +51,7 @@ public class BulkItemResponse implements Streamable {
|
||||
this.index = index;
|
||||
this.type = type;
|
||||
this.id = id;
|
||||
this.message = ExceptionsHelper.detailedMessage(t);
|
||||
this.message = t.toString();
|
||||
this.status = ExceptionsHelper.status(t);
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation
|
||||
}
|
||||
throw (ElasticsearchException) e;
|
||||
}
|
||||
if (e instanceof ElasticsearchException && ((ElasticsearchException) e).status() == RestStatus.CONFLICT) {
|
||||
if (ExceptionsHelper.status(e) == RestStatus.CONFLICT) {
|
||||
logger.trace("{} failed to execute bulk item (index) {}", e, shardRequest.shardId, indexRequest);
|
||||
} else {
|
||||
logger.debug("{} failed to execute bulk item (index) {}", e, shardRequest.shardId, indexRequest);
|
||||
@ -190,7 +190,7 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation
|
||||
}
|
||||
throw (ElasticsearchException) e;
|
||||
}
|
||||
if (e instanceof ElasticsearchException && ((ElasticsearchException) e).status() == RestStatus.CONFLICT) {
|
||||
if (ExceptionsHelper.status(e) == RestStatus.CONFLICT) {
|
||||
logger.trace("{} failed to execute bulk item (delete) {}", e, shardRequest.shardId, deleteRequest);
|
||||
} else {
|
||||
logger.debug("{} failed to execute bulk item (delete) {}", e, shardRequest.shardId, deleteRequest);
|
||||
@ -279,7 +279,7 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation
|
||||
case UPSERT:
|
||||
case INDEX:
|
||||
IndexRequest indexRequest = updateResult.request();
|
||||
if (t instanceof ElasticsearchException && ((ElasticsearchException) t).status() == RestStatus.CONFLICT) {
|
||||
if (ExceptionsHelper.status(t) == RestStatus.CONFLICT) {
|
||||
logger.trace("{} failed to execute bulk item (index) {}", t, shardRequest.shardId, indexRequest);
|
||||
} else {
|
||||
logger.debug("{} failed to execute bulk item (index) {}", t, shardRequest.shardId, indexRequest);
|
||||
@ -289,7 +289,7 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation
|
||||
break;
|
||||
case DELETE:
|
||||
DeleteRequest deleteRequest = updateResult.request();
|
||||
if (t instanceof ElasticsearchException && ((ElasticsearchException) t).status() == RestStatus.CONFLICT) {
|
||||
if (ExceptionsHelper.status(t) == RestStatus.CONFLICT) {
|
||||
logger.trace("{} failed to execute bulk item (delete) {}", t, shardRequest.shardId, deleteRequest);
|
||||
} else {
|
||||
logger.debug("{} failed to execute bulk item (delete) {}", t, shardRequest.shardId, deleteRequest);
|
||||
|
@ -20,25 +20,30 @@
|
||||
package org.elasticsearch.action.search;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.IndexException;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SearchPhaseExecutionException extends ElasticsearchException {
|
||||
|
||||
private final String phaseName;
|
||||
|
||||
private ShardSearchFailure[] shardFailures;
|
||||
|
||||
public SearchPhaseExecutionException(String phaseName, String msg, ShardSearchFailure[] shardFailures) {
|
||||
super(buildMessage(phaseName, msg, shardFailures));
|
||||
super(msg);
|
||||
this.phaseName = phaseName;
|
||||
this.shardFailures = shardFailures;
|
||||
}
|
||||
|
||||
public SearchPhaseExecutionException(String phaseName, String msg, Throwable cause, ShardSearchFailure[] shardFailures) {
|
||||
super(buildMessage(phaseName, msg, shardFailures), cause);
|
||||
super(msg, cause);
|
||||
this.phaseName = phaseName;
|
||||
this.shardFailures = shardFailures;
|
||||
}
|
||||
@ -60,10 +65,6 @@ public class SearchPhaseExecutionException extends ElasticsearchException {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String phaseName() {
|
||||
return phaseName;
|
||||
}
|
||||
|
||||
public ShardSearchFailure[] shardFailures() {
|
||||
return shardFailures;
|
||||
}
|
||||
@ -83,4 +84,90 @@ public class SearchPhaseExecutionException extends ElasticsearchException {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerToXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.field("phase", phaseName);
|
||||
final boolean group = params.paramAsBoolean("group_shard_failures", true); // we group by default
|
||||
builder.field("grouped", group); // notify that it's grouped
|
||||
builder.field("failed_shards");
|
||||
builder.startArray();
|
||||
ShardSearchFailure[] failures = params.paramAsBoolean("group_shard_failures", true) ? groupBy(shardFailures) : shardFailures;
|
||||
for (ShardSearchFailure failure : failures) {
|
||||
builder.startObject();
|
||||
failure.toXContent(builder, params);
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endArray();
|
||||
super.innerToXContent(builder, params);
|
||||
|
||||
}
|
||||
|
||||
private ShardSearchFailure[] groupBy(ShardSearchFailure[] failures) {
|
||||
List<ShardSearchFailure> uniqueFailures = new ArrayList<>();
|
||||
Set<GroupBy> reasons = new HashSet<>();
|
||||
for (ShardSearchFailure failure : failures) {
|
||||
GroupBy reason = new GroupBy(failure.getCause());
|
||||
if (reasons.contains(reason) == false) {
|
||||
reasons.add(reason);
|
||||
uniqueFailures.add(failure);
|
||||
}
|
||||
}
|
||||
return uniqueFailures.toArray(new ShardSearchFailure[0]);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElasticsearchException[] guessRootCauses() {
|
||||
ShardSearchFailure[] failures = groupBy(shardFailures);
|
||||
List<ElasticsearchException> rootCauses = new ArrayList<>(failures.length);
|
||||
for (ShardSearchFailure failure : failures) {
|
||||
ElasticsearchException[] guessRootCauses = ElasticsearchException.guessRootCauses(failure.getCause());
|
||||
rootCauses.addAll(Arrays.asList(guessRootCauses));
|
||||
}
|
||||
return rootCauses.toArray(new ElasticsearchException[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return buildMessage(phaseName, getMessage(), shardFailures);
|
||||
}
|
||||
|
||||
static class GroupBy {
|
||||
final String reason;
|
||||
final Index index;
|
||||
final Class<? extends Throwable> causeType;
|
||||
|
||||
public GroupBy(Throwable t) {
|
||||
if (t instanceof IndexException) {
|
||||
index = ((IndexException) t).index();
|
||||
} else {
|
||||
index = null;
|
||||
}
|
||||
reason = t.getMessage();
|
||||
causeType = t.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GroupBy groupBy = (GroupBy) o;
|
||||
|
||||
if (!causeType.equals(groupBy.causeType)) return false;
|
||||
if (index != null ? !index.equals(groupBy.index) : groupBy.index != null) return false;
|
||||
if (reason != null ? !reason.equals(groupBy.reason) : groupBy.reason != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = reason != null ? reason.hashCode() : 0;
|
||||
result = 31 * result + (index != null ? index.hashCode() : 0);
|
||||
result = 31 * result + causeType.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,24 +25,29 @@ import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.SearchException;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import static org.elasticsearch.search.SearchShardTarget.readSearchShardTarget;
|
||||
|
||||
/**
|
||||
* Represents a failure to search on a specific shard.
|
||||
*/
|
||||
public class ShardSearchFailure implements ShardOperationFailedException {
|
||||
public class ShardSearchFailure implements ShardOperationFailedException, ToXContent {
|
||||
|
||||
public static final ShardSearchFailure[] EMPTY_ARRAY = new ShardSearchFailure[0];
|
||||
|
||||
private SearchShardTarget shardTarget;
|
||||
private String reason;
|
||||
private RestStatus status;
|
||||
private Throwable cause;
|
||||
|
||||
private ShardSearchFailure() {
|
||||
|
||||
@ -59,12 +64,9 @@ public class ShardSearchFailure implements ShardOperationFailedException {
|
||||
} else if (shardTarget != null) {
|
||||
this.shardTarget = shardTarget;
|
||||
}
|
||||
if (actual != null && actual instanceof ElasticsearchException) {
|
||||
status = ((ElasticsearchException) actual).status();
|
||||
} else {
|
||||
status = RestStatus.INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
status = ExceptionsHelper.status(actual);
|
||||
this.reason = ExceptionsHelper.detailedMessage(t);
|
||||
this.cause = actual;
|
||||
}
|
||||
|
||||
public ShardSearchFailure(String reason, SearchShardTarget shardTarget) {
|
||||
@ -138,6 +140,7 @@ public class ShardSearchFailure implements ShardOperationFailedException {
|
||||
}
|
||||
reason = in.readString();
|
||||
status = RestStatus.readFrom(in);
|
||||
cause = in.readThrowable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -150,5 +153,26 @@ public class ShardSearchFailure implements ShardOperationFailedException {
|
||||
}
|
||||
out.writeString(reason);
|
||||
RestStatus.writeTo(out, status);
|
||||
out.writeThrowable(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.field("shard", shardId());
|
||||
builder.field("index", index());
|
||||
if (shardTarget != null) {
|
||||
builder.field("node", shardTarget.nodeId());
|
||||
}
|
||||
if (cause != null) {
|
||||
builder.field("reason");
|
||||
builder.startObject();
|
||||
ElasticsearchException.toXContent(builder, params, cause);
|
||||
builder.endObject();
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
public Throwable getCause() {
|
||||
return cause;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.action.support;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
@ -39,30 +40,25 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile
|
||||
|
||||
private int shardId;
|
||||
|
||||
private String reason;
|
||||
private Throwable reason;
|
||||
|
||||
private RestStatus status;
|
||||
|
||||
private DefaultShardOperationFailedException() {
|
||||
|
||||
}
|
||||
|
||||
public DefaultShardOperationFailedException(IndexShardException e) {
|
||||
this.index = e.shardId().index().name();
|
||||
this.shardId = e.shardId().id();
|
||||
this.reason = detailedMessage(e);
|
||||
this.reason = e;
|
||||
this.status = e.status();
|
||||
}
|
||||
|
||||
public DefaultShardOperationFailedException(String index, int shardId, Throwable t) {
|
||||
this.index = index;
|
||||
this.shardId = shardId;
|
||||
this.reason = detailedMessage(t);
|
||||
if (t != null && t instanceof ElasticsearchException) {
|
||||
status = ((ElasticsearchException) t).status();
|
||||
} else {
|
||||
status = RestStatus.INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
this.reason = t;
|
||||
status = ExceptionsHelper.status(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,7 +73,7 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile
|
||||
|
||||
@Override
|
||||
public String reason() {
|
||||
return this.reason;
|
||||
return detailedMessage(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -97,7 +93,7 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile
|
||||
index = in.readString();
|
||||
}
|
||||
shardId = in.readVInt();
|
||||
reason = in.readString();
|
||||
reason = in.readThrowable();
|
||||
status = RestStatus.readFrom(in);
|
||||
}
|
||||
|
||||
@ -110,12 +106,12 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile
|
||||
out.writeString(index);
|
||||
}
|
||||
out.writeVInt(shardId);
|
||||
out.writeString(reason);
|
||||
out.writeThrowable(reason);
|
||||
RestStatus.writeTo(out, status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + index + "][" + shardId + "] failed, reason [" + reason + "]";
|
||||
return "[" + index + "][" + shardId + "] failed, reason [" + reason() + "]";
|
||||
}
|
||||
}
|
||||
|
@ -103,14 +103,8 @@ public abstract class TransportIndexReplicationOperationAction<Request extends I
|
||||
failureCounter.getAndIncrement();
|
||||
int index = indexCounter.getAndIncrement();
|
||||
// this is a failure for an entire shard group, constructs shard info accordingly
|
||||
final RestStatus status;
|
||||
if (e != null && e instanceof ElasticsearchException) {
|
||||
status = ((ElasticsearchException) e).status();
|
||||
} else {
|
||||
status = RestStatus.INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
Failure failure = new Failure(request.index(), shardIt.shardId().id(), null,
|
||||
"Failed to execute on all shard copies [" + ExceptionsHelper.detailedMessage(e) + "]", status, true);
|
||||
final RestStatus status = ExceptionsHelper.status(e);
|
||||
Failure failure = new Failure(request.index(), shardIt.shardId().id(), null, e, status, true);
|
||||
shardsResponses.set(index, new ShardActionResult(new ActionWriteResponse.ShardInfo(shardIt.size(), 0, failure)));
|
||||
returnIfNeeded();
|
||||
}
|
||||
|
@ -495,7 +495,7 @@ public abstract class TransportShardReplicationOperationAction<Request extends S
|
||||
retry(e);
|
||||
return;
|
||||
}
|
||||
if (e instanceof ElasticsearchException && ((ElasticsearchException) e).status() == RestStatus.CONFLICT) {
|
||||
if (ExceptionsHelper.status(e) == RestStatus.CONFLICT) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(shard.shortSummary() + ": Failed to execute [" + internalRequest.request() + "]", e);
|
||||
}
|
||||
@ -822,10 +822,9 @@ public abstract class TransportShardReplicationOperationAction<Request extends S
|
||||
int slot = 0;
|
||||
failuresArray = new ActionWriteResponse.ShardInfo.Failure[shardReplicaFailures.size()];
|
||||
for (Map.Entry<String, Throwable> entry : shardReplicaFailures.entrySet()) {
|
||||
String reason = ExceptionsHelper.detailedMessage(entry.getValue());
|
||||
RestStatus restStatus = ExceptionsHelper.status(entry.getValue());
|
||||
failuresArray[slot++] = new ActionWriteResponse.ShardInfo.Failure(
|
||||
shardId.getIndex(), shardId.getId(), entry.getKey(), reason, restStatus, false
|
||||
shardId.getIndex(), shardId.getId(), entry.getKey(), entry.getValue(), restStatus, false
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -60,11 +60,6 @@ public class BytesStreamOutput extends StreamOutput implements BytesStream {
|
||||
this.bytes = bigarrays.newByteArray(expectedSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean seekPositionSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long position() throws IOException {
|
||||
return count;
|
||||
|
@ -21,6 +21,7 @@ package org.elasticsearch.common.io.stream;
|
||||
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.CharsRefBuilder;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
@ -32,6 +33,7 @@ import org.joda.time.DateTime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -463,4 +465,13 @@ public abstract class StreamInput extends InputStream {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Throwable> T readThrowable() throws IOException {
|
||||
try {
|
||||
ObjectInputStream oin = new ObjectInputStream(this);
|
||||
return (T) oin.readObject();
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IOException("failed to deserialize exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import org.elasticsearch.common.text.Text;
|
||||
import org.joda.time.ReadableInstant;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
@ -50,10 +51,6 @@ public abstract class StreamOutput extends OutputStream {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean seekPositionSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public long position() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@ -432,4 +429,10 @@ public abstract class StreamOutput extends OutputStream {
|
||||
writeBoolean(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeThrowable(Throwable throwable) throws IOException {
|
||||
ObjectOutputStream out = new ObjectOutputStream(this);
|
||||
out.writeObject(throwable);
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,9 @@
|
||||
package org.elasticsearch.index;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -32,16 +35,25 @@ public class IndexException extends ElasticsearchException {
|
||||
this(index, msg, null);
|
||||
}
|
||||
|
||||
public IndexException(Index index, String msg, Throwable cause) {
|
||||
this(index, true, msg, cause);
|
||||
}
|
||||
|
||||
protected IndexException(Index index, boolean withSpace, String msg, Throwable cause) {
|
||||
super("[" + (index == null ? "_na" : index.name()) + "]" + (withSpace ? " " : "") + msg, cause);
|
||||
protected IndexException(Index index, String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Index index() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerToXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (index != null) {
|
||||
builder.field("index", index.getName());
|
||||
}
|
||||
super.innerToXContent(builder, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + (index == null ? "_na" : index.name()) + "] " + getMessage();
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,6 @@ import org.elasticsearch.index.IndexException;
|
||||
*/
|
||||
public class PercolatorException extends IndexException {
|
||||
|
||||
public PercolatorException(Index index, String msg) {
|
||||
super(index, msg);
|
||||
}
|
||||
|
||||
public PercolatorException(Index index, String msg, Throwable cause) {
|
||||
super(index, msg, cause);
|
||||
}
|
||||
|
@ -40,4 +40,5 @@ public class QueryParsingException extends IndexException {
|
||||
public RestStatus status() {
|
||||
return RestStatus.BAD_REQUEST;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,8 +19,11 @@
|
||||
|
||||
package org.elasticsearch.index.shard;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.IndexException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -33,11 +36,24 @@ public class IndexShardException extends IndexException {
|
||||
}
|
||||
|
||||
public IndexShardException(ShardId shardId, String msg, Throwable cause) {
|
||||
super(shardId == null ? null : shardId.index(), false, "[" + (shardId == null ? "_na" : shardId.id()) + "] " + msg, cause);
|
||||
super(shardId == null ? null : shardId.index(), msg, cause);
|
||||
this.shardId = shardId;
|
||||
}
|
||||
|
||||
public ShardId shardId() {
|
||||
return shardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (shardId == null ? "_na" : shardId) + getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerToXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (shardId != null) {
|
||||
builder.field("shard", shardId.getId());
|
||||
}
|
||||
super.innerToXContent(builder, params);
|
||||
}
|
||||
}
|
||||
|
@ -27,10 +27,6 @@ import org.elasticsearch.index.IndexException;
|
||||
*/
|
||||
public class AliasFilterParsingException extends IndexException {
|
||||
|
||||
public AliasFilterParsingException(Index index, String name, String desc) {
|
||||
super(index, "[" + name + "], " + desc);
|
||||
}
|
||||
|
||||
public AliasFilterParsingException(Index index, String name, String desc, Throwable ex) {
|
||||
super(index, "[" + name + "], " + desc, ex);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ import org.elasticsearch.rest.RestStatus;
|
||||
public class IndexMissingException extends IndexException {
|
||||
|
||||
public IndexMissingException(Index index) {
|
||||
super(index, "missing");
|
||||
super(index, "no such index");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,11 +34,6 @@ public class TypeMissingException extends IndexException {
|
||||
super(index, "type[" + Arrays.toString(types) + "] missing");
|
||||
}
|
||||
|
||||
public TypeMissingException(Index index, String[] types, String message) {
|
||||
super(index, "type[" + Arrays.toString(types) + "] missing: " + message);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RestStatus status() {
|
||||
return RestStatus.NOT_FOUND;
|
||||
|
@ -20,13 +20,16 @@
|
||||
package org.elasticsearch.rest;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.ExceptionsHelper.detailedMessage;
|
||||
|
||||
public class BytesRestResponse extends RestResponse {
|
||||
|
||||
@ -78,7 +81,7 @@ public class BytesRestResponse extends RestResponse {
|
||||
}
|
||||
|
||||
public BytesRestResponse(RestChannel channel, Throwable t) throws IOException {
|
||||
this(channel, ((t instanceof ElasticsearchException) ? ((ElasticsearchException) t).status() : RestStatus.INTERNAL_SERVER_ERROR), t);
|
||||
this(channel, ExceptionsHelper.status(t), t);
|
||||
}
|
||||
|
||||
public BytesRestResponse(RestChannel channel, RestStatus status, Throwable t) throws IOException {
|
||||
@ -114,9 +117,22 @@ public class BytesRestResponse extends RestResponse {
|
||||
private static XContentBuilder convert(RestChannel channel, RestStatus status, Throwable t) throws IOException {
|
||||
XContentBuilder builder = channel.newBuilder().startObject();
|
||||
if (t == null) {
|
||||
builder.field("error", "Unknown");
|
||||
builder.field("error", "unknown");
|
||||
} else if (channel.detailedErrorsEnabled()) {
|
||||
builder.field("error", detailedMessage(t));
|
||||
builder.field("error");
|
||||
builder.startObject();
|
||||
final ElasticsearchException[] rootCauses = ElasticsearchException.guessRootCauses(t);
|
||||
builder.field("root_cause");
|
||||
builder.startArray();
|
||||
for (ElasticsearchException rootCause : rootCauses){
|
||||
builder.startObject();
|
||||
rootCause.toXContent(builder, new ToXContent.DelegatingMapParams(Collections.singletonMap(ElasticsearchException.REST_EXCEPTION_SKIP_CAUSE, "true"), channel.request()));
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endArray();
|
||||
|
||||
ElasticsearchException.toXContent(builder, channel.request(), t);
|
||||
builder.endObject();
|
||||
if (channel.request().paramAsBoolean("error_trace", false)) {
|
||||
buildErrorTrace(t, builder);
|
||||
}
|
||||
@ -128,6 +144,7 @@ public class BytesRestResponse extends RestResponse {
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
private static void buildErrorTrace(Throwable t, XContentBuilder builder) throws IOException {
|
||||
builder.startObject("error_trace");
|
||||
boolean first = true;
|
||||
|
@ -35,19 +35,6 @@ public class SearchContextException extends SearchException {
|
||||
}
|
||||
|
||||
private static String buildMessage(SearchContext context, String msg) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('[').append(context.shardTarget().index()).append("][").append(context.shardTarget().shardId()).append("]: ");
|
||||
if (context.parsedQuery() != null) {
|
||||
try {
|
||||
sb.append("query[").append(context.parsedQuery().query()).append("],");
|
||||
} catch (Exception e) {
|
||||
sb.append("query[_failed_to_string_],");
|
||||
}
|
||||
}
|
||||
sb.append("from[").append(context.from()).append("],size[").append(context.size()).append("]");
|
||||
if (context.sort() != null) {
|
||||
sb.append(",sort[").append(context.sort()).append("]");
|
||||
}
|
||||
return sb.append(": ").append(msg).toString();
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,11 @@ import org.elasticsearch.search.internal.SearchContext;
|
||||
public class SearchParseException extends SearchContextException {
|
||||
|
||||
public SearchParseException(SearchContext context, String msg) {
|
||||
super(context, "Parse Failure [" + msg + "]");
|
||||
super(context, msg);
|
||||
}
|
||||
|
||||
public SearchParseException(SearchContext context, String msg, Throwable cause) {
|
||||
super(context, "Parse Failure [" + msg + "]", cause);
|
||||
super(context, msg, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,13 +19,27 @@
|
||||
|
||||
package org.elasticsearch;
|
||||
|
||||
import org.elasticsearch.action.search.SearchPhaseExecutionException;
|
||||
import org.elasticsearch.action.search.ShardSearchFailure;
|
||||
import org.elasticsearch.common.io.BytesStream;
|
||||
import org.elasticsearch.common.io.stream.BytesStreamInput;
|
||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.query.QueryParsingException;
|
||||
import org.elasticsearch.indices.IndexMissingException;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.transport.RemoteTransportException;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class ElasticsearchExceptionTests extends ElasticsearchTestCase {
|
||||
@ -43,5 +57,203 @@ public class ElasticsearchExceptionTests extends ElasticsearchTestCase {
|
||||
|
||||
exception = new RemoteTransportException("test", new IndexMissingException(new Index("test")));
|
||||
assertThat(exception.status(), equalTo(RestStatus.NOT_FOUND));
|
||||
|
||||
exception = new RemoteTransportException("test", new IllegalArgumentException("foobar"));
|
||||
assertThat(exception.status(), equalTo(RestStatus.BAD_REQUEST));
|
||||
|
||||
exception = new RemoteTransportException("test", new IllegalStateException("foobar"));
|
||||
assertThat(exception.status(), equalTo(RestStatus.INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
|
||||
public void testGuessRootCause() {
|
||||
{
|
||||
ElasticsearchException exception = new ElasticsearchException("foo", new ElasticsearchException("bar", new ElasticsearchIllegalArgumentException("index is closed", new RuntimeException("foobar"))));
|
||||
ElasticsearchException[] rootCauses = exception.guessRootCauses();
|
||||
assertEquals(rootCauses.length, 1);
|
||||
assertEquals(ElasticsearchException.getExceptionName(rootCauses[0]), "illegal_argument_exception");
|
||||
assertEquals(rootCauses[0].getMessage(), "index is closed");
|
||||
ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1));
|
||||
ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 2));
|
||||
SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1});
|
||||
if (randomBoolean()) {
|
||||
rootCauses = (randomBoolean() ? new RemoteTransportException("remoteboom", ex) : ex).guessRootCauses();
|
||||
} else {
|
||||
rootCauses = ElasticsearchException.guessRootCauses(randomBoolean() ? new RemoteTransportException("remoteboom", ex) : ex);
|
||||
}
|
||||
assertEquals(ElasticsearchException.getExceptionName(rootCauses[0]), "query_parsing_exception");
|
||||
assertEquals(rootCauses[0].getMessage(), "foobar");
|
||||
|
||||
ElasticsearchException oneLevel = new ElasticsearchException("foo", new RuntimeException("foobar"));
|
||||
rootCauses = oneLevel.guessRootCauses();
|
||||
assertEquals(ElasticsearchException.getExceptionName(rootCauses[0]), "exception");
|
||||
assertEquals(rootCauses[0].getMessage(), "foo");
|
||||
}
|
||||
{
|
||||
ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1));
|
||||
ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 1));
|
||||
ShardSearchFailure failure2 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 2));
|
||||
SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1, failure2});
|
||||
final ElasticsearchException[] rootCauses = ex.guessRootCauses();
|
||||
assertEquals(rootCauses.length, 2);
|
||||
assertEquals(ElasticsearchException.getExceptionName(rootCauses[0]), "query_parsing_exception");
|
||||
assertEquals(rootCauses[0].getMessage(), "foobar");
|
||||
assertEquals(((QueryParsingException)rootCauses[0]).index().name(), "foo");
|
||||
assertEquals(ElasticsearchException.getExceptionName(rootCauses[1]), "query_parsing_exception");
|
||||
assertEquals(rootCauses[1].getMessage(), "foobar");
|
||||
assertEquals(((QueryParsingException)rootCauses[1]).index().name(), "foo1");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testDeduplicate() throws IOException {
|
||||
{
|
||||
ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1));
|
||||
ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 2));
|
||||
SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1});
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
builder.startObject();
|
||||
ex.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
builder.endObject();
|
||||
String expected = "{\n" +
|
||||
" \"type\" : \"search_phase_execution_exception\",\n" +
|
||||
" \"reason\" : \"all shards failed\",\n" +
|
||||
" \"phase\" : \"search\",\n" +
|
||||
" \"grouped\" : true,\n" +
|
||||
" \"failed_shards\" : [ {\n" +
|
||||
" \"shard\" : 1,\n" +
|
||||
" \"index\" : \"foo\",\n" +
|
||||
" \"node\" : \"node_1\",\n" +
|
||||
" \"reason\" : {\n" +
|
||||
" \"type\" : \"query_parsing_exception\",\n" +
|
||||
" \"reason\" : \"foobar\",\n" +
|
||||
" \"index\" : \"foo\"\n" +
|
||||
" }\n" +
|
||||
" } ]\n" +
|
||||
"}";
|
||||
assertEquals(expected, builder.string());
|
||||
}
|
||||
{
|
||||
ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1));
|
||||
ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 1));
|
||||
ShardSearchFailure failure2 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 2));
|
||||
SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1, failure2});
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
builder.startObject();
|
||||
ex.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
builder.endObject();
|
||||
String expected = "{\n" +
|
||||
" \"type\" : \"search_phase_execution_exception\",\n" +
|
||||
" \"reason\" : \"all shards failed\",\n" +
|
||||
" \"phase\" : \"search\",\n" +
|
||||
" \"grouped\" : true,\n" +
|
||||
" \"failed_shards\" : [ {\n" +
|
||||
" \"shard\" : 1,\n" +
|
||||
" \"index\" : \"foo\",\n" +
|
||||
" \"node\" : \"node_1\",\n" +
|
||||
" \"reason\" : {\n" +
|
||||
" \"type\" : \"query_parsing_exception\",\n" +
|
||||
" \"reason\" : \"foobar\",\n" +
|
||||
" \"index\" : \"foo\"\n" +
|
||||
" }\n" +
|
||||
" }, {\n" +
|
||||
" \"shard\" : 1,\n" +
|
||||
" \"index\" : \"foo1\",\n" +
|
||||
" \"node\" : \"node_1\",\n" +
|
||||
" \"reason\" : {\n" +
|
||||
" \"type\" : \"query_parsing_exception\",\n" +
|
||||
" \"reason\" : \"foobar\",\n" +
|
||||
" \"index\" : \"foo1\"\n" +
|
||||
" }\n" +
|
||||
" } ]\n" +
|
||||
"}";
|
||||
assertEquals(expected, builder.string());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetRootCause() {
|
||||
Exception root = new RuntimeException("foobar");
|
||||
ElasticsearchException exception = new ElasticsearchException("foo", new ElasticsearchException("bar", new ElasticsearchIllegalArgumentException("index is closed", root)));
|
||||
assertEquals(root, exception.getRootCause());
|
||||
assertTrue(exception.contains(RuntimeException.class));
|
||||
assertFalse(exception.contains(EOFException.class));
|
||||
}
|
||||
|
||||
public void testToString() {
|
||||
ElasticsearchException exception = new ElasticsearchException("foo", new ElasticsearchException("bar", new ElasticsearchIllegalArgumentException("index is closed", new RuntimeException("foobar"))));
|
||||
assertEquals("ElasticsearchException[foo]; nested: ElasticsearchException[bar]; nested: ElasticsearchIllegalArgumentException[index is closed]; nested: RuntimeException[foobar];", exception.toString());
|
||||
}
|
||||
|
||||
public void testToXContent() throws IOException {
|
||||
{
|
||||
ElasticsearchException ex = new ElasticsearchException("foo", new ElasticsearchException("bar", new ElasticsearchIllegalArgumentException("index is closed", new RuntimeException("foobar"))));
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
builder.startObject();
|
||||
ex.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
builder.endObject();
|
||||
|
||||
String expected = "{\n" +
|
||||
" \"type\" : \"exception\",\n" +
|
||||
" \"reason\" : \"foo\",\n" +
|
||||
" \"caused_by\" : {\n" +
|
||||
" \"type\" : \"exception\",\n" +
|
||||
" \"reason\" : \"bar\",\n" +
|
||||
" \"caused_by\" : {\n" +
|
||||
" \"type\" : \"illegal_argument_exception\",\n" +
|
||||
" \"reason\" : \"index is closed\",\n" +
|
||||
" \"caused_by\" : {\n" +
|
||||
" \"type\" : \"runtime_exception\",\n" +
|
||||
" \"reason\" : \"foobar\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
assertEquals(expected, builder.string());
|
||||
}
|
||||
|
||||
{
|
||||
Exception ex = new FileNotFoundException("foo not found");
|
||||
if (randomBoolean()) {
|
||||
// just a wrapper which is omitted
|
||||
ex = new RemoteTransportException("foobar", ex);
|
||||
}
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
builder.startObject();
|
||||
ElasticsearchException.toXContent(builder, ToXContent.EMPTY_PARAMS, ex);
|
||||
builder.endObject();
|
||||
|
||||
String expected = "{\n" +
|
||||
" \"type\" : \"file_not_found_exception\",\n" +
|
||||
" \"reason\" : \"foo not found\"\n" +
|
||||
"}";
|
||||
assertEquals(expected, builder.string());
|
||||
}
|
||||
|
||||
{ // test equivalence
|
||||
ElasticsearchException ex = new RemoteTransportException("foobar", new FileNotFoundException("foo not found"));
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
builder.startObject();
|
||||
ElasticsearchException.toXContent(builder, ToXContent.EMPTY_PARAMS, ex);
|
||||
builder.endObject();
|
||||
|
||||
XContentBuilder otherBuilder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
|
||||
otherBuilder.startObject();
|
||||
ex.toXContent(otherBuilder, ToXContent.EMPTY_PARAMS);
|
||||
otherBuilder.endObject();
|
||||
assertEquals(otherBuilder.string(), builder.string());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSerializeElasticsearchException() throws IOException {
|
||||
BytesStreamOutput out = new BytesStreamOutput();
|
||||
QueryParsingException ex = new QueryParsingException(new Index("foo"), "foobar");
|
||||
out.writeThrowable(ex);
|
||||
|
||||
BytesStreamInput in = new BytesStreamInput(out.bytes());
|
||||
QueryParsingException e = in.readThrowable();
|
||||
assertEquals(ex.index(), e.index());
|
||||
assertEquals(ex.getMessage(), e.getMessage());
|
||||
}
|
||||
|
||||
}
|
@ -48,7 +48,7 @@ public class BulkProcessorClusterSettingsTests extends ElasticsearchIntegrationT
|
||||
assertEquals(3, responses.length);
|
||||
assertFalse("Operation on existing index should succeed", responses[0].isFailed());
|
||||
assertTrue("Missing index should have been flagged", responses[1].isFailed());
|
||||
assertEquals("IndexMissingException[[wontwork] missing]", responses[1].getFailureMessage());
|
||||
assertEquals("[wontwork] no such index", responses[1].getFailureMessage());
|
||||
assertFalse("Operation on existing index should succeed", responses[2].isFailed());
|
||||
}
|
||||
}
|
||||
|
@ -441,7 +441,8 @@ public class MetaDataTests extends ElasticsearchTestCase {
|
||||
md.concreteIndices(IndicesOptions.strictSingleIndexNoExpandForbidClosed(), "foofoo-closed", "foofoobar");
|
||||
fail();
|
||||
} catch(IndexClosedException e) {
|
||||
assertThat(e.getMessage(), containsString("[foofoo-closed] closed"));
|
||||
assertThat(e.getMessage(), equalTo("closed"));
|
||||
assertEquals(e.index().getName(), "foofoo-closed");
|
||||
}
|
||||
|
||||
String[] results = md.concreteIndices(IndicesOptions.strictSingleIndexNoExpandForbidClosed(), "foo", "barbaz");
|
||||
|
@ -120,7 +120,7 @@ public class DeleteByQueryTests extends ElasticsearchIntegrationTest {
|
||||
assertThat(response.getIndices().size(), equalTo(1));
|
||||
assertThat(response.getIndices().get("test").getShardInfo().getFailures().length, equalTo(twitter.numPrimaries));
|
||||
for (ActionWriteResponse.ShardInfo.Failure failure : response.getIndices().get("test").getShardInfo().getFailures()) {
|
||||
assertThat(failure.reason(), containsString("[test] [has_child] query and filter unsupported in delete_by_query api"));
|
||||
assertThat(failure.reason(), containsString("[has_child] query and filter unsupported in delete_by_query api"));
|
||||
assertThat(failure.status(), equalTo(RestStatus.BAD_REQUEST));
|
||||
assertThat(failure.shardId(), greaterThan(-1));
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ public class BulkTests extends ElasticsearchIntegrationTest {
|
||||
assertThat(bulkResponse.getItems()[1].getResponse(), nullValue());
|
||||
assertThat(bulkResponse.getItems()[1].getFailure().getIndex(), equalTo("test"));
|
||||
assertThat(bulkResponse.getItems()[1].getFailure().getId(), equalTo("7"));
|
||||
assertThat(bulkResponse.getItems()[1].getFailure().getMessage(), containsString("DocumentMissingException"));
|
||||
assertThat(bulkResponse.getItems()[1].getFailure().getMessage(), containsString("document missing"));
|
||||
assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getId(), equalTo("2"));
|
||||
assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getIndex(), equalTo("test"));
|
||||
assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getVersion(), equalTo(3l));
|
||||
@ -173,7 +173,7 @@ public class BulkTests extends ElasticsearchIntegrationTest {
|
||||
.add(client().prepareUpdate("test", "type", "2").setDoc("field", "2"))
|
||||
.add(client().prepareUpdate("test", "type", "1").setVersion(2l).setDoc("field", "3")).get();
|
||||
|
||||
assertThat(bulkResponse.getItems()[0].getFailureMessage(), containsString("Version"));
|
||||
assertThat(bulkResponse.getItems()[0].getFailureMessage(), containsString("version conflict"));
|
||||
assertThat(((UpdateResponse) bulkResponse.getItems()[1].getResponse()).getVersion(), equalTo(2l));
|
||||
assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getVersion(), equalTo(3l));
|
||||
|
||||
@ -194,7 +194,7 @@ public class BulkTests extends ElasticsearchIntegrationTest {
|
||||
.add(client().prepareUpdate("test", "type", "e1").setDoc("field", "3").setVersion(20).setVersionType(VersionType.FORCE))
|
||||
.add(client().prepareUpdate("test", "type", "e1").setDoc("field", "3").setVersion(20).setVersionType(VersionType.INTERNAL)).get();
|
||||
|
||||
assertThat(bulkResponse.getItems()[0].getFailureMessage(), containsString("Version"));
|
||||
assertThat(bulkResponse.getItems()[0].getFailureMessage(), containsString("version conflict"));
|
||||
assertThat(((UpdateResponse) bulkResponse.getItems()[1].getResponse()).getVersion(), equalTo(20l));
|
||||
assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getVersion(), equalTo(21l));
|
||||
}
|
||||
@ -325,7 +325,7 @@ public class BulkTests extends ElasticsearchIntegrationTest {
|
||||
int id = i + (numDocs / 2);
|
||||
if (i >= (numDocs / 2)) {
|
||||
assertThat(response.getItems()[i].getFailure().getId(), equalTo(Integer.toString(id)));
|
||||
assertThat(response.getItems()[i].getFailure().getMessage(), containsString("DocumentMissingException"));
|
||||
assertThat(response.getItems()[i].getFailure().getMessage(), containsString("document missing"));
|
||||
} else {
|
||||
assertThat(response.getItems()[i].getId(), equalTo(Integer.toString(id)));
|
||||
assertThat(response.getItems()[i].getVersion(), equalTo(3l));
|
||||
|
@ -1191,7 +1191,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
|
||||
queryParser.parse(query).query();
|
||||
fail();
|
||||
} catch (QueryParsingException ex) {
|
||||
assertThat(ex.getMessage(), equalTo("[test] [terms] query does not support multiple fields"));
|
||||
assertThat(ex.getMessage(), equalTo("[terms] query does not support multiple fields"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1207,7 +1207,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
|
||||
queryParser.parse(query).query();
|
||||
fail();
|
||||
} catch (QueryParsingException ex) {
|
||||
assertThat(ex.getMessage(), equalTo("[test] [terms] filter does not support multiple fields"));
|
||||
assertThat(ex.getMessage(), equalTo("[terms] filter does not support multiple fields"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,8 +241,8 @@ public class CircuitBreakerServiceTests extends ElasticsearchIntegrationTest {
|
||||
fail("should have thrown an exception");
|
||||
} catch (Exception e) {
|
||||
String errMsg = "[fielddata] Data too large, data for [test] would be larger than limit of [10/10b]";
|
||||
assertThat("Exception: " + ExceptionsHelper.unwrapCause(e) + " should contain a CircuitBreakingException",
|
||||
ExceptionsHelper.unwrapCause(e).getMessage().contains(errMsg), equalTo(true));
|
||||
assertThat("Exception: " + e.toString() + " should contain a CircuitBreakingException",
|
||||
e.toString().contains(errMsg), equalTo(true));
|
||||
}
|
||||
|
||||
assertFailures(client.prepareSearch("cb-test").setQuery(matchAllQuery()).addSort("test", SortOrder.DESC),
|
||||
@ -263,8 +263,8 @@ public class CircuitBreakerServiceTests extends ElasticsearchIntegrationTest {
|
||||
fail("should have thrown an exception");
|
||||
} catch (Exception e) {
|
||||
String errMsg = "[parent] Data too large, data for [test] would be larger than limit of [15/15b]";
|
||||
assertThat("Exception: " + ExceptionsHelper.unwrapCause(e) + " should contain a CircuitBreakingException",
|
||||
ExceptionsHelper.unwrapCause(e).getMessage().contains(errMsg), equalTo(true));
|
||||
assertThat("Exception: " +e.toString() + " should contain a CircuitBreakingException",
|
||||
e.toString().contains(errMsg), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,8 +297,8 @@ public class CircuitBreakerServiceTests extends ElasticsearchIntegrationTest {
|
||||
fail("aggregation should have tripped the breaker");
|
||||
} catch (Exception e) {
|
||||
String errMsg = "CircuitBreakingException[[request] Data too large, data for [<reused_arrays>] would be larger than limit of [10/10b]]";
|
||||
assertThat("Exception: " + ExceptionsHelper.unwrapCause(e) + " should contain a CircuitBreakingException",
|
||||
ExceptionsHelper.unwrapCause(e).getMessage().contains(errMsg), equalTo(true));
|
||||
assertThat("Exception: " + e.toString() + " should contain a CircuitBreakingException",
|
||||
e.toString().contains(errMsg), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,7 +495,7 @@ public class SimpleIndexTemplateTests extends ElasticsearchIntegrationTest {
|
||||
} catch(ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), equalTo("failed to parse filter for alias [invalid_alias]"));
|
||||
assertThat(e.getCause(), instanceOf(QueryParsingException.class));
|
||||
assertThat(e.getCause().getMessage(), equalTo("[test] No filter registered for [invalid]"));
|
||||
assertThat(e.getCause().getMessage(), equalTo("No filter registered for [invalid]"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -530,7 +530,7 @@ public class SimpleIndexTemplateTests extends ElasticsearchIntegrationTest {
|
||||
createIndex("test");
|
||||
fail("index creation should have failed due to alias with existing index name in mathching index template");
|
||||
} catch(InvalidAliasNameException e) {
|
||||
assertThat(e.getMessage(), equalTo("[test] Invalid alias name [index], an index exists with the same name as the alias"));
|
||||
assertThat(e.getMessage(), equalTo("Invalid alias name [index], an index exists with the same name as the alias"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -707,7 +707,7 @@ public class SimpleNestedTests extends ElasticsearchIntegrationTest {
|
||||
.execute().actionGet();
|
||||
Assert.fail("SearchPhaseExecutionException should have been thrown");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("type [string] doesn't support mode [SUM]"));
|
||||
assertThat(e.toString(), containsString("type [string] doesn't support mode [SUM]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,18 @@
|
||||
package org.elasticsearch.rest;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.search.SearchPhaseExecutionException;
|
||||
import org.elasticsearch.action.search.ShardSearchFailure;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.query.QueryParsingException;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||
import org.elasticsearch.transport.RemoteTransportException;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
@ -70,8 +77,8 @@ public class BytesRestResponseTests extends ElasticsearchTestCase {
|
||||
Throwable t = new ElasticsearchException("an error occurred reading data", new FileNotFoundException("/foo/bar"));
|
||||
BytesRestResponse response = new BytesRestResponse(channel, t);
|
||||
String text = response.content().toUtf8();
|
||||
assertThat(text, containsString("ElasticsearchException[an error occurred reading data]"));
|
||||
assertThat(text, containsString("FileNotFoundException[/foo/bar]"));
|
||||
assertThat(text, containsString("{\"type\":\"exception\",\"reason\":\"an error occurred reading data\"}"));
|
||||
assertThat(text, containsString("{\"type\":\"file_not_found_exception\",\"reason\":\"/foo/bar\"}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -97,11 +104,21 @@ public class BytesRestResponseTests extends ElasticsearchTestCase {
|
||||
Throwable t = new Throwable("an error occurred reading data", new FileNotFoundException("/foo/bar"));
|
||||
BytesRestResponse response = new BytesRestResponse(channel, t);
|
||||
String text = response.content().toUtf8();
|
||||
assertThat(text, containsString("\"error\":\"Throwable[an error occurred reading data]"));
|
||||
assertThat(text, containsString("FileNotFoundException[/foo/bar]"));
|
||||
assertThat(text, containsString("\"type\":\"throwable\",\"reason\":\"an error occurred reading data\""));
|
||||
assertThat(text, containsString("{\"type\":\"file_not_found_exception\",\"reason\":\"/foo/bar\"}"));
|
||||
assertThat(text, containsString("\"error_trace\":{\"message\":\"an error occurred reading data\""));
|
||||
}
|
||||
|
||||
public void testGuessRootCause() throws IOException {
|
||||
RestRequest request = new FakeRestRequest();
|
||||
RestChannel channel = new DetailedExceptionRestChannel(request);
|
||||
|
||||
Throwable t = new ElasticsearchException("an error occurred reading data", new FileNotFoundException("/foo/bar"));
|
||||
BytesRestResponse response = new BytesRestResponse(channel, t);
|
||||
String text = response.content().toUtf8();
|
||||
assertThat(text, containsString("{\"root_cause\":[{\"type\":\"exception\",\"reason\":\"an error occurred reading data\"}]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullThrowable() throws Exception {
|
||||
RestRequest request = new FakeRestRequest();
|
||||
@ -109,10 +126,47 @@ public class BytesRestResponseTests extends ElasticsearchTestCase {
|
||||
|
||||
BytesRestResponse response = new BytesRestResponse(channel, null);
|
||||
String text = response.content().toUtf8();
|
||||
assertThat(text, containsString("\"error\":\"Unknown\""));
|
||||
assertThat(text, containsString("\"error\":\"unknown\""));
|
||||
assertThat(text, not(containsString("error_trace")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvert() throws IOException {
|
||||
RestRequest request = new FakeRestRequest();
|
||||
request.params().put("pretty", "true");
|
||||
RestChannel channel = new DetailedExceptionRestChannel(request);
|
||||
ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1));
|
||||
ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 2));
|
||||
SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[] {failure, failure1});
|
||||
BytesRestResponse response = new BytesRestResponse(channel, new RemoteTransportException("foo", ex));
|
||||
String text = response.content().toUtf8();
|
||||
String expected = "{\n" +
|
||||
" \"error\" : {\n" +
|
||||
" \"root_cause\" : [ {\n" +
|
||||
" \"type\" : \"query_parsing_exception\",\n" +
|
||||
" \"reason\" : \"foobar\",\n" +
|
||||
" \"index\" : \"foo\"\n" +
|
||||
" } ],\n" +
|
||||
" \"type\" : \"search_phase_execution_exception\",\n" +
|
||||
" \"reason\" : \"all shards failed\",\n" +
|
||||
" \"phase\" : \"search\",\n" +
|
||||
" \"grouped\" : true,\n" +
|
||||
" \"failed_shards\" : [ {\n" +
|
||||
" \"shard\" : 1,\n" +
|
||||
" \"index\" : \"foo\",\n" +
|
||||
" \"node\" : \"node_1\",\n" +
|
||||
" \"reason\" : {\n" +
|
||||
" \"type\" : \"query_parsing_exception\",\n" +
|
||||
" \"reason\" : \"foobar\",\n" +
|
||||
" \"index\" : \"foo\"\n" +
|
||||
" }\n" +
|
||||
" } ]\n" +
|
||||
" },\n" +
|
||||
" \"status\" : 400\n" +
|
||||
"}";
|
||||
assertEquals(expected.trim(), text.trim());
|
||||
}
|
||||
|
||||
private static class ExceptionWithHeaders extends ElasticsearchException.WithRestHeaders {
|
||||
|
||||
ExceptionWithHeaders() {
|
||||
|
@ -153,8 +153,7 @@ public class GroovySandboxScriptTests extends ElasticsearchIntegrationTest {
|
||||
"; doc['foo'].value + 2\", \"type\": \"number\", \"lang\": \"groovy\"}}}").get();
|
||||
fail("script: " + script + " failed to be caught be the sandbox!");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
String msg = ExceptionsHelper.detailedMessage(ExceptionsHelper.unwrapCause(e));
|
||||
assertThat("script failed, but with incorrect message: " + msg, msg.contains(failMessage), equalTo(true));
|
||||
assertThat("script failed, but with incorrect message: " + e.toString(), e.toString().contains(failMessage), equalTo(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,12 +76,12 @@ public class GroovyScriptTests extends ElasticsearchIntegrationTest {
|
||||
client().prepareSearch("test").setQuery(constantScoreQuery(scriptFilter("1 == not_found").lang(GroovyScriptEngineService.NAME))).get();
|
||||
fail("should have thrown an exception");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should not contained NotSerializableTransportException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("NotSerializableTransportException"), equalTo(false));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained GroovyScriptExecutionException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("GroovyScriptExecutionException"), equalTo(true));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained not_found",
|
||||
ExceptionsHelper.detailedMessage(e).contains("No such property: not_found"), equalTo(true));
|
||||
assertThat(e.toString()+ "should not contained NotSerializableTransportException",
|
||||
e.toString().contains("NotSerializableTransportException"), equalTo(false));
|
||||
assertThat(e.toString()+ "should have contained GroovyScriptExecutionException",
|
||||
e.toString().contains("GroovyScriptExecutionException"), equalTo(true));
|
||||
assertThat(e.toString()+ "should have contained not_found",
|
||||
e.toString().contains("No such property: not_found"), equalTo(true));
|
||||
}
|
||||
|
||||
try {
|
||||
@ -89,12 +89,12 @@ public class GroovyScriptTests extends ElasticsearchIntegrationTest {
|
||||
scriptFilter("assert false").lang("groovy"))).get();
|
||||
fail("should have thrown an exception");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should not contained NotSerializableTransportException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("NotSerializableTransportException"), equalTo(false));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained GroovyScriptExecutionException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("GroovyScriptExecutionException"), equalTo(true));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained an assert error",
|
||||
ExceptionsHelper.detailedMessage(e).contains("PowerAssertionError[assert false"), equalTo(true));
|
||||
assertThat(e.toString()+ "should not contained NotSerializableTransportException",
|
||||
e.toString().contains("NotSerializableTransportException"), equalTo(false));
|
||||
assertThat(e.toString()+ "should have contained GroovyScriptExecutionException",
|
||||
e.toString().contains("GroovyScriptExecutionException"), equalTo(true));
|
||||
assertThat(e.toString()+ "should have contained an assert error",
|
||||
e.toString().contains("PowerAssertionError[assert false"), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,8 +178,8 @@ public class IndexLookupTests extends ElasticsearchIntegrationTest {
|
||||
client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()).addScriptField("tvtest", script).execute().actionGet();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(
|
||||
"got: " + e.getDetailedMessage(),
|
||||
e.getDetailedMessage()
|
||||
"got: " + e.toString(),
|
||||
e.toString()
|
||||
.indexOf(
|
||||
"You must call get with all required flags! Instead of _index['int_payload_field'].get('b', _FREQUENCIES) and _index['int_payload_field'].get('b', _POSITIONS) call _index['int_payload_field'].get('b', _FREQUENCIES | _POSITIONS) once]"),
|
||||
Matchers.greaterThan(-1));
|
||||
|
@ -158,20 +158,20 @@ public class IndexedScriptTests extends ElasticsearchIntegrationTest {
|
||||
fail("update script should have been rejected");
|
||||
} catch(Exception e) {
|
||||
assertThat(e.getMessage(), containsString("failed to execute script"));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [indexed], operation [update] and lang [expression] are disabled"));
|
||||
assertThat(e.toString(), containsString("scripts of type [indexed], operation [update] and lang [expression] are disabled"));
|
||||
}
|
||||
try {
|
||||
String query = "{ \"script_fields\" : { \"test1\" : { \"script_id\" : \"script1\", \"lang\":\"expression\" }}}";
|
||||
client().prepareSearch().setSource(query).setIndices("test").setTypes("scriptTest").get();
|
||||
fail("search script should have been rejected");
|
||||
} catch(Exception e) {
|
||||
assertThat(e.getMessage(), containsString("scripts of type [indexed], operation [search] and lang [expression] are disabled"));
|
||||
assertThat(e.toString(), containsString("scripts of type [indexed], operation [search] and lang [expression] are disabled"));
|
||||
}
|
||||
try {
|
||||
String source = "{\"aggs\": {\"test\": { \"terms\" : { \"script_id\":\"script1\", \"script_lang\":\"expression\" } } } }";
|
||||
client().prepareSearch("test").setSource(source).get();
|
||||
} catch(Exception e) {
|
||||
assertThat(e.getMessage(), containsString("scripts of type [indexed], operation [aggs] and lang [expression] are disabled"));
|
||||
assertThat(e.toString(), containsString("scripts of type [indexed], operation [aggs] and lang [expression] are disabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public class OnDiskScriptTests extends ElasticsearchIntegrationTest {
|
||||
client().prepareSearch("test").setSource(source).get();
|
||||
fail("aggs script should have been rejected");
|
||||
} catch(Exception e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [file], operation [aggs] and lang [expression] are disabled"));
|
||||
assertThat(e.toString(), containsString("scripts of type [file], operation [aggs] and lang [expression] are disabled"));
|
||||
}
|
||||
|
||||
String query = "{ \"query\" : { \"match_all\": {}} , \"script_fields\" : { \"test1\" : { \"script_file\" : \"script1\", \"lang\":\"expression\" }}, size:1}";
|
||||
@ -128,21 +128,21 @@ public class OnDiskScriptTests extends ElasticsearchIntegrationTest {
|
||||
client().prepareSearch("test").setSource(source).get();
|
||||
fail("aggs script should have been rejected");
|
||||
} catch(Exception e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [file], operation [aggs] and lang [mustache] are disabled"));
|
||||
assertThat(e.toString(), containsString("scripts of type [file], operation [aggs] and lang [mustache] are disabled"));
|
||||
}
|
||||
String query = "{ \"query\" : { \"match_all\": {}} , \"script_fields\" : { \"test1\" : { \"script_file\" : \"script1\", \"lang\":\"mustache\" }}, size:1}";
|
||||
try {
|
||||
client().prepareSearch().setSource(query).setIndices("test").setTypes("scriptTest").get();
|
||||
fail("search script should have been rejected");
|
||||
} catch(Exception e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [file], operation [search] and lang [mustache] are disabled"));
|
||||
assertThat(e.toString(), containsString("scripts of type [file], operation [search] and lang [mustache] are disabled"));
|
||||
}
|
||||
try {
|
||||
client().prepareUpdate("test", "scriptTest", "1").setScript("script1", ScriptService.ScriptType.FILE).setScriptLang(MustacheScriptEngineService.NAME).get();
|
||||
fail("update script should have been rejected");
|
||||
} catch(Exception e) {
|
||||
assertThat(e.getMessage(), containsString("failed to execute script"));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [file], operation [update] and lang [mustache] are disabled"));
|
||||
assertThat(e.getCause().toString(), containsString("scripts of type [file], operation [update] and lang [mustache] are disabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class SandboxDisabledTests extends ElasticsearchIntegrationTest {
|
||||
"\"sort\":{\"_script\": {\"script\": \"doc['foo'].value + 2\", \"type\": \"number\", \"lang\": \"groovy\"}}}").get();
|
||||
fail("shards should fail because the sandbox and dynamic scripting are disabled");
|
||||
} catch (Exception e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [inline], operation [search] and lang [groovy] are disabled"));
|
||||
assertThat(e.toString(), containsString("scripts of type [inline], operation [search] and lang [groovy] are disabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,10 +111,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest {
|
||||
buildRequest("doc['bogus'].value").get();
|
||||
fail("Expected missing field to cause failure");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained missing field error",
|
||||
ExceptionsHelper.detailedMessage(e).contains("does not exist in mappings"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained ExpressionScriptCompilationException",
|
||||
e.toString().contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained missing field error",
|
||||
e.toString().contains("does not exist in mappings"), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,10 +141,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest {
|
||||
buildRequest("garbage%@#%@").get();
|
||||
fail("Expected expression compilation failure");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained compilation failure",
|
||||
ExceptionsHelper.detailedMessage(e).contains("Failed to parse expression"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained ExpressionScriptCompilationException",
|
||||
e.toString().contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained compilation failure",
|
||||
e.toString().contains("Failed to parse expression"), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,10 +154,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest {
|
||||
buildRequest("a", "a", "astring").get();
|
||||
fail("Expected string parameter to cause failure");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained non-numeric parameter error",
|
||||
ExceptionsHelper.detailedMessage(e).contains("must be a numeric type"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained ExpressionScriptCompilationException",
|
||||
e.toString().contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained non-numeric parameter error",
|
||||
e.toString().contains("must be a numeric type"), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,10 +167,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest {
|
||||
buildRequest("doc['text'].value").get();
|
||||
fail("Expected text field to cause execution failure");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained non-numeric field error",
|
||||
ExceptionsHelper.detailedMessage(e).contains("must be numeric"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained ExpressionScriptCompilationException",
|
||||
e.toString().contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained non-numeric field error",
|
||||
e.toString().contains("must be numeric"), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,10 +180,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest {
|
||||
buildRequest("bogus").get();
|
||||
fail("Expected bogus variable to cause execution failure");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained unknown variable error",
|
||||
ExceptionsHelper.detailedMessage(e).contains("Unknown variable"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained ExpressionScriptCompilationException",
|
||||
e.toString().contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained unknown variable error",
|
||||
e.toString().contains("Unknown variable"), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,10 +193,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest {
|
||||
buildRequest("doc").get();
|
||||
fail("Expected doc variable without field to cause execution failure");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained a missing specific field error",
|
||||
ExceptionsHelper.detailedMessage(e).contains("must be used with a specific field"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained ExpressionScriptCompilationException",
|
||||
e.toString().contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained a missing specific field error",
|
||||
e.toString().contains("must be used with a specific field"), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,10 +206,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest {
|
||||
buildRequest("doc['foo'].bogus").get();
|
||||
fail("Expected bogus field member to cause execution failure");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException",
|
||||
ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained field member error",
|
||||
ExceptionsHelper.detailedMessage(e).contains("Invalid member for field"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained ExpressionScriptCompilationException",
|
||||
e.toString().contains("ExpressionScriptCompilationException"), equalTo(true));
|
||||
assertThat(e.toString() + "should have contained field member error",
|
||||
e.toString().contains("Invalid member for field"), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,7 +260,7 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest {
|
||||
assertThat(rsp.getShardFailures().length, greaterThan(0)); // at least the shards containing the docs should have failed
|
||||
message = rsp.getShardFailures()[0].reason();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
message = ExceptionsHelper.detailedMessage(e);
|
||||
message = e.toString();
|
||||
}
|
||||
assertThat(message + "should have contained ExpressionScriptExecutionException",
|
||||
message.contains("ExpressionScriptExecutionException"), equalTo(true));
|
||||
|
@ -57,7 +57,7 @@ public class AggregationsIntegrationTests extends ElasticsearchIntegrationTest {
|
||||
client().prepareSearch("index").setSearchType(SearchType.SCAN).setScroll(new TimeValue(500)).addAggregation(terms("f").field("f")).get();
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("aggregations are not supported with search_type=scan"));
|
||||
assertTrue(e.toString(), e.toString().contains("aggregations are not supported with search_type=scan"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1314,7 +1314,7 @@ public class DateHistogramTests extends ElasticsearchIntegrationTest {
|
||||
.actionGet();
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("IllegalArgumentException"));
|
||||
assertThat(e.toString(), containsString("IllegalArgumentException"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1017,7 +1017,7 @@ public class HistogramTests extends ElasticsearchIntegrationTest {
|
||||
.addAggregation(histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(-1).minDocCount(0)).execute().actionGet();
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("Missing required field [interval]"));
|
||||
assertThat(e.toString(), containsString("Missing required field [interval]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,7 +365,7 @@ public class NestedTests extends ElasticsearchIntegrationTest {
|
||||
.execute().actionGet();
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("[nested] nested path [incorrect] is not nested"));
|
||||
assertThat(e.toString(), containsString("[nested] nested path [incorrect] is not nested"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -520,7 +520,7 @@ public class TopHitsTests extends ElasticsearchIntegrationTest {
|
||||
).get();
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("No mapping found for [xyz] in order to sort on"));
|
||||
assertThat(e.toString(), containsString("No mapping found for [xyz] in order to sort on"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,7 +553,7 @@ public class TopHitsTests extends ElasticsearchIntegrationTest {
|
||||
.get();
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("Aggregator [top_tags_hits] of type [top_hits] cannot accept sub-aggregations"));
|
||||
assertThat(e.toString(), containsString("Aggregator [top_tags_hits] of type [top_hits] cannot accept sub-aggregations"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,14 +108,7 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFa
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHit;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHits;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasId;
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -1612,13 +1605,13 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
|
||||
client().prepareIndex("test", "child1", "c1").setParent("p1").setSource("c_field", "blue").get();
|
||||
fail();
|
||||
} catch (ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), equalTo("Can't specify parent if no parent field has been configured"));
|
||||
assertThat(e.toString(), containsString("Can't specify parent if no parent field has been configured"));
|
||||
}
|
||||
try {
|
||||
client().prepareIndex("test", "child2", "c2").setParent("p1").setSource("c_field", "blue").get();
|
||||
fail();
|
||||
} catch (ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), equalTo("Can't specify parent if no parent field has been configured"));
|
||||
assertThat(e.toString(), containsString("Can't specify parent if no parent field has been configured"));
|
||||
}
|
||||
|
||||
refresh();
|
||||
@ -1645,7 +1638,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
|
||||
.endObject().endObject()).get();
|
||||
fail();
|
||||
} catch (MergeMappingException e) {
|
||||
assertThat(e.getMessage(), equalTo("Merge failed with failures {[The _parent field's type option can't be changed: [null]->[parent]]}"));
|
||||
assertThat(e.toString(), containsString("Merge failed with failures {[The _parent field's type option can't be changed: [null]->[parent]]}"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2332,7 +2325,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
|
||||
response = minMaxQuery("none", 3, 2, cutoff);
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
}
|
||||
|
||||
// Score mode = SUM
|
||||
@ -2412,7 +2405,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
|
||||
response = minMaxQuery("sum", 3, 2, cutoff);
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
}
|
||||
|
||||
// Score mode = MAX
|
||||
@ -2492,7 +2485,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
|
||||
response = minMaxQuery("max", 3, 2, cutoff);
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
}
|
||||
|
||||
// Score mode = AVG
|
||||
@ -2572,7 +2565,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
|
||||
response = minMaxQuery("avg", 3, 2, cutoff);
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
}
|
||||
|
||||
// HasChildFilter
|
||||
@ -2652,7 +2645,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest {
|
||||
response = minMaxFilter(3, 2, cutoff);
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -874,8 +874,8 @@ public class DecayFunctionScoreTests extends ElasticsearchIntegrationTest {
|
||||
searchSource().query(query))).actionGet();
|
||||
fail("Should fail with SearchPhaseExecutionException");
|
||||
} catch (SearchPhaseExecutionException failure) {
|
||||
assertTrue(failure.getMessage().contains("SearchParseException"));
|
||||
assertFalse(failure.getMessage().contains("NullPointerException"));
|
||||
assertTrue(failure.toString().contains("SearchParseException"));
|
||||
assertFalse(failure.toString().contains("NullPointerException"));
|
||||
}
|
||||
|
||||
query = "{\n" +
|
||||
@ -908,26 +908,26 @@ public class DecayFunctionScoreTests extends ElasticsearchIntegrationTest {
|
||||
searchSource().query(query))).actionGet();
|
||||
fail("Should fail with SearchPhaseExecutionException");
|
||||
} catch (SearchPhaseExecutionException failure) {
|
||||
assertTrue(failure.getMessage().contains("SearchParseException"));
|
||||
assertFalse(failure.getMessage().contains("NullPointerException"));
|
||||
assertTrue(failure.getMessage().contains("One entry in functions list is missing a function"));
|
||||
assertTrue(failure.toString().contains("SearchParseException"));
|
||||
assertFalse(failure.toString().contains("NullPointerException"));
|
||||
assertTrue(failure.toString().contains("One entry in functions list is missing a function"));
|
||||
}
|
||||
|
||||
// next test java client
|
||||
try {
|
||||
client().prepareSearch("t").setQuery(QueryBuilders.functionScoreQuery(FilterBuilders.matchAllFilter(), null)).get();
|
||||
} catch (ElasticsearchIllegalArgumentException failure) {
|
||||
assertTrue(failure.getMessage().contains("function must not be null"));
|
||||
assertTrue(failure.toString().contains("function must not be null"));
|
||||
}
|
||||
try {
|
||||
client().prepareSearch("t").setQuery(QueryBuilders.functionScoreQuery().add(FilterBuilders.matchAllFilter(), null)).get();
|
||||
} catch (ElasticsearchIllegalArgumentException failure) {
|
||||
assertTrue(failure.getMessage().contains("function must not be null"));
|
||||
assertTrue(failure.toString().contains("function must not be null"));
|
||||
}
|
||||
try {
|
||||
client().prepareSearch("t").setQuery(QueryBuilders.functionScoreQuery().add(null)).get();
|
||||
} catch (ElasticsearchIllegalArgumentException failure) {
|
||||
assertTrue(failure.getMessage().contains("function must not be null"));
|
||||
assertTrue(failure.toString().contains("function must not be null"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -483,7 +483,7 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest {
|
||||
client().prepareSearch().setQuery(matchQuery("field1", "quick brown").type(MatchQueryBuilder.Type.PHRASE).slop(0)).get();
|
||||
fail("SearchPhaseExecutionException should have been thrown");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertTrue(e.getMessage().contains("IllegalStateException[field \"field1\" was indexed without position data; cannot run PhraseQuery"));
|
||||
assertTrue(e.toString().contains("IllegalStateException[field \"field1\" was indexed without position data; cannot run PhraseQuery"));
|
||||
}
|
||||
cluster().wipeIndices("test");
|
||||
} catch (MapperParsingException ex) {
|
||||
@ -563,7 +563,7 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest {
|
||||
fail("expected SearchPhaseExecutionException (total failure)");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST));
|
||||
assertThat(e.getMessage(), containsString("unit [D] not supported for date math"));
|
||||
assertThat(e.toString(), containsString("unit [D] not supported for date math"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2493,8 +2493,8 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest {
|
||||
.get();
|
||||
fail("query is invalid and should have produced a parse exception");
|
||||
} catch (Exception e) {
|
||||
assertThat("query could not be parsed due to bad format: " + e.getMessage(),
|
||||
e.getMessage().contains("Illegal value for id, expecting a string or number, got: START_ARRAY"),
|
||||
assertThat("query could not be parsed due to bad format: " + e.toString(),
|
||||
e.toString().contains("Illegal value for id, expecting a string or number, got: START_ARRAY"),
|
||||
equalTo(true));
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ public class SimpleSearchTests extends ElasticsearchIntegrationTest {
|
||||
client().prepareSearch("idx").setFrom(Integer.MAX_VALUE).get();
|
||||
fail();
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.getMessage(), containsString("Result window is too large, from + size must be less than or equal to:"));
|
||||
assertThat(e.toString(), containsString("Result window is too large, from + size must be less than or equal to:"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1131,7 +1131,7 @@ public class SimpleSortTests extends ElasticsearchIntegrationTest {
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
//we check that it's a parse failure rather than a different shard failure
|
||||
for (ShardSearchFailure shardSearchFailure : e.shardFailures()) {
|
||||
assertThat(shardSearchFailure.reason(), containsString("Parse Failure [No mapping found for [kkk] in order to sort on]"));
|
||||
assertThat(shardSearchFailure.toString(), containsString("[No mapping found for [kkk] in order to sort on]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@ import com.carrotsearch.randomizedtesting.generators.RandomStrings;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase.SuppressCodecs;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
|
||||
import org.elasticsearch.action.admin.indices.optimize.OptimizeResponse;
|
||||
import org.elasticsearch.action.admin.indices.segments.IndexShardSegments;
|
||||
@ -50,7 +49,6 @@ import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
|
||||
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
|
||||
import org.elasticsearch.search.suggest.completion.CompletionSuggestionFuzzyBuilder;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -177,7 +175,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
).get();
|
||||
fail("Indexing with a float weight was successful, but should not be");
|
||||
} catch (MapperParsingException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e), containsString("2.5"));
|
||||
assertThat(e.toString(), containsString("2.5"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +219,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
).get();
|
||||
fail("Indexing with a non-number representing string as weight was successful, but should not be");
|
||||
} catch (MapperParsingException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e), containsString("thisIsNotValid"));
|
||||
assertThat(e.toString(), containsString("thisIsNotValid"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +237,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
).get();
|
||||
fail("Indexing with weight string representing value > Int.MAX_VALUE was successful, but should not be");
|
||||
} catch (MapperParsingException e) {
|
||||
assertThat(ExceptionsHelper.detailedMessage(e), containsString(weight));
|
||||
assertThat(e.toString(), containsString(weight));
|
||||
}
|
||||
}
|
||||
|
||||
@ -774,7 +772,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
fail("Expected an exception due to trying to sort on completion field, but did not happen");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.status().getStatus(), is(400));
|
||||
assertThat(e.getMessage(), containsString("Sorting not supported for field[" + FIELD + "]"));
|
||||
assertThat(e.toString(), containsString("Sorting not supported for field[" + FIELD + "]"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1096,7 +1094,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
// Exception must be thrown
|
||||
assertFalse(true);
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertTrue(e.getDetailedMessage().contains("found no fielddata type for field [" + FIELD + "]"));
|
||||
assertTrue(e.toString().contains("found no fielddata type for field [" + FIELD + "]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,7 @@ public class ElasticsearchAssertions {
|
||||
assertVersionSerializable(searchResponse);
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.status(), equalTo(restStatus));
|
||||
assertThat(e.getMessage(), reasonMatcher);
|
||||
assertThat(e.toString(), reasonMatcher);
|
||||
for (ShardSearchFailure shardSearchFailure : e.shardFailures()) {
|
||||
assertThat(shardSearchFailure.status(), equalTo(restStatus));
|
||||
assertThat(shardSearchFailure.reason(), reasonMatcher);
|
||||
|
Loading…
x
Reference in New Issue
Block a user