|
@@ -108,6 +108,7 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|
|
|
|
|
private static final String TYPE = "type";
|
|
|
private static final String REASON = "reason";
|
|
|
+ private static final String TIMED_OUT = "timed_out";
|
|
|
private static final String CAUSED_BY = "caused_by";
|
|
|
private static final ParseField SUPPRESSED = new ParseField("suppressed");
|
|
|
public static final String STACK_TRACE = "stack_trace";
|
|
@@ -115,6 +116,8 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|
|
private static final String ERROR = "error";
|
|
|
private static final String ROOT_CAUSE = "root_cause";
|
|
|
|
|
|
+ static final String TIMED_OUT_HEADER = "X-Timed-Out";
|
|
|
+
|
|
|
private static final Map<Integer, CheckedFunction<StreamInput, ? extends ElasticsearchException, IOException>> ID_TO_SUPPLIER;
|
|
|
private static final Map<Class<? extends ElasticsearchException>, ElasticsearchExceptionHandle> CLASS_TO_ELASTICSEARCH_EXCEPTION_HANDLE;
|
|
|
private final Map<String, List<String>> metadata = new HashMap<>();
|
|
@@ -123,8 +126,10 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|
|
/**
|
|
|
* Construct a <code>ElasticsearchException</code> with the specified cause exception.
|
|
|
*/
|
|
|
+ @SuppressWarnings("this-escape")
|
|
|
public ElasticsearchException(Throwable cause) {
|
|
|
super(cause);
|
|
|
+ maybePutTimeoutHeader();
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -136,8 +141,10 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|
|
* @param msg the detail message
|
|
|
* @param args the arguments for the message
|
|
|
*/
|
|
|
+ @SuppressWarnings("this-escape")
|
|
|
public ElasticsearchException(String msg, Object... args) {
|
|
|
super(LoggerMessageFormat.format(msg, args));
|
|
|
+ maybePutTimeoutHeader();
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -151,8 +158,10 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|
|
* @param cause the nested exception
|
|
|
* @param args the arguments for the message
|
|
|
*/
|
|
|
+ @SuppressWarnings("this-escape")
|
|
|
public ElasticsearchException(String msg, Throwable cause, Object... args) {
|
|
|
super(LoggerMessageFormat.format(msg, args), cause);
|
|
|
+ maybePutTimeoutHeader();
|
|
|
}
|
|
|
|
|
|
@SuppressWarnings("this-escape")
|
|
@@ -163,6 +172,13 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|
|
metadata.putAll(in.readMapOfLists(StreamInput::readString));
|
|
|
}
|
|
|
|
|
|
+ private void maybePutTimeoutHeader() {
|
|
|
+ if (isTimeout()) {
|
|
|
+ // see https://www.rfc-editor.org/rfc/rfc8941.html#section-4.1.9 for booleans in structured headers
|
|
|
+ headers.put(TIMED_OUT_HEADER, List.of("?1"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Adds a new piece of metadata with the given key.
|
|
|
* If the provided key is already present, the corresponding metadata will be replaced
|
|
@@ -253,6 +269,13 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns whether this exception represents a timeout.
|
|
|
+ */
|
|
|
+ public boolean isTimeout() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Unwraps the actual cause from the exception for cases when the exception is a
|
|
|
* {@link ElasticsearchWrapperException}.
|
|
@@ -386,6 +409,15 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|
|
builder.field(TYPE, type);
|
|
|
builder.field(REASON, message);
|
|
|
|
|
|
+ boolean timedOut = false;
|
|
|
+ if (throwable instanceof ElasticsearchException exception) {
|
|
|
+ // TODO: we could walk the exception chain to see if _any_ causes are timeouts?
|
|
|
+ timedOut = exception.isTimeout();
|
|
|
+ }
|
|
|
+ if (timedOut) {
|
|
|
+ builder.field(TIMED_OUT, timedOut);
|
|
|
+ }
|
|
|
+
|
|
|
for (Map.Entry<String, List<String>> entry : metadata.entrySet()) {
|
|
|
headerToXContent(builder, entry.getKey().substring("es.".length()), entry.getValue());
|
|
|
}
|