Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,26 @@

import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.action.search.MultiSearchRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.Request;
import org.elasticsearch.search.ErrorTraceHelper;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.transport.TransportMessageListener;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xcontent.XContentType;
import org.junit.Before;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;

import static org.elasticsearch.index.query.QueryBuilders.simpleQueryStringQuery;

public class SearchErrorTraceIT extends HttpSmokeTestCase {
private AtomicBoolean hasStackTrace;
private BooleanSupplier hasStackTrace;

@Before
private void setupMessageListener() {
internalCluster().getDataNodeInstances(TransportService.class).forEach(ts -> {
ts.addMessageListener(new TransportMessageListener() {
@Override
public void onResponseSent(long requestId, String action, Exception error) {
TransportMessageListener.super.onResponseSent(requestId, action, error);
if (action.startsWith("indices:data/read/search")) {
Optional<Throwable> throwable = ExceptionsHelper.unwrapCausesAndSuppressed(
error,
t -> t.getStackTrace().length > 0
);
hasStackTrace.set(throwable.isPresent());
}
}
});
});
public void setupMessageListener() {
hasStackTrace = ErrorTraceHelper.setupErrorTraceListener(internalCluster());
}

private void setupIndexWithDocs() {
Expand All @@ -61,7 +44,6 @@ private void setupIndexWithDocs() {
}

public void testSearchFailingQueryErrorTraceDefault() throws IOException {
hasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_search");
Expand All @@ -76,11 +58,10 @@ public void testSearchFailingQueryErrorTraceDefault() throws IOException {
}
""");
getRestClient().performRequest(searchRequest);
assertFalse(hasStackTrace.get());
assertFalse(hasStackTrace.getAsBoolean());
}

public void testSearchFailingQueryErrorTraceTrue() throws IOException {
hasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_search");
Expand All @@ -96,11 +77,10 @@ public void testSearchFailingQueryErrorTraceTrue() throws IOException {
""");
searchRequest.addParameter("error_trace", "true");
getRestClient().performRequest(searchRequest);
assertTrue(hasStackTrace.get());
assertTrue(hasStackTrace.getAsBoolean());
}

public void testSearchFailingQueryErrorTraceFalse() throws IOException {
hasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_search");
Expand All @@ -116,11 +96,10 @@ public void testSearchFailingQueryErrorTraceFalse() throws IOException {
""");
searchRequest.addParameter("error_trace", "false");
getRestClient().performRequest(searchRequest);
assertFalse(hasStackTrace.get());
assertFalse(hasStackTrace.getAsBoolean());
}

public void testMultiSearchFailingQueryErrorTraceDefault() throws IOException {
hasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

XContentType contentType = XContentType.JSON;
Expand All @@ -133,11 +112,10 @@ public void testMultiSearchFailingQueryErrorTraceDefault() throws IOException {
new NByteArrayEntity(requestBody, ContentType.create(contentType.mediaTypeWithoutParameters(), (Charset) null))
);
getRestClient().performRequest(searchRequest);
assertFalse(hasStackTrace.get());
assertFalse(hasStackTrace.getAsBoolean());
}

public void testMultiSearchFailingQueryErrorTraceTrue() throws IOException {
hasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

XContentType contentType = XContentType.JSON;
Expand All @@ -151,11 +129,10 @@ public void testMultiSearchFailingQueryErrorTraceTrue() throws IOException {
);
searchRequest.addParameter("error_trace", "true");
getRestClient().performRequest(searchRequest);
assertTrue(hasStackTrace.get());
assertTrue(hasStackTrace.getAsBoolean());
}

public void testMultiSearchFailingQueryErrorTraceFalse() throws IOException {
hasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

XContentType contentType = XContentType.JSON;
Expand All @@ -170,6 +147,6 @@ public void testMultiSearchFailingQueryErrorTraceFalse() throws IOException {
searchRequest.addParameter("error_trace", "false");
getRestClient().performRequest(searchRequest);

assertFalse(hasStackTrace.get());
assertFalse(hasStackTrace.getAsBoolean());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

package org.elasticsearch.search;

import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.test.InternalTestCluster;
import org.elasticsearch.transport.TransportMessageListener;
import org.elasticsearch.transport.TransportService;

import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;

/**
* Utilities around testing the `error_trace` message header in search.
*/
public enum ErrorTraceHelper {
;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, remove ;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't do that :) it's the empty enum as a utility class here :D still need to delineate the absence of values.


public static BooleanSupplier setupErrorTraceListener(InternalTestCluster internalCluster) {
final AtomicBoolean transportMessageHasStackTrace = new AtomicBoolean(false);
internalCluster.getDataNodeInstances(TransportService.class).forEach(ts -> ts.addMessageListener(new TransportMessageListener() {
@Override
public void onResponseSent(long requestId, String action, Exception error) {
TransportMessageListener.super.onResponseSent(requestId, action, error);
if (action.startsWith("indices:data/read/search")) {
Optional<Throwable> throwable = ExceptionsHelper.unwrapCausesAndSuppressed(error, t -> t.getStackTrace().length > 0);
transportMessageHasStackTrace.set(throwable.isPresent());
}
}
}));
return transportMessageHasStackTrace::get;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,21 @@

package org.elasticsearch.xpack.search;

import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.search.ErrorTraceHelper;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.transport.TransportMessageListener;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xcontent.XContentType;
import org.junit.Before;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;

public class AsyncSearchErrorTraceIT extends ESIntegTestCase {

Expand All @@ -38,25 +35,11 @@ protected Collection<Class<? extends Plugin>> nodePlugins() {
return List.of(AsyncSearch.class);
}

private AtomicBoolean transportMessageHasStackTrace;
private BooleanSupplier transportMessageHasStackTrace;

@Before
private void setupMessageListener() {
internalCluster().getDataNodeInstances(TransportService.class).forEach(ts -> {
ts.addMessageListener(new TransportMessageListener() {
@Override
public void onResponseSent(long requestId, String action, Exception error) {
TransportMessageListener.super.onResponseSent(requestId, action, error);
if (action.startsWith("indices:data/read/search")) {
Optional<Throwable> throwable = ExceptionsHelper.unwrapCausesAndSuppressed(
error,
t -> t.getStackTrace().length > 0
);
transportMessageHasStackTrace.set(throwable.isPresent());
}
}
});
});
public void setupMessageListener() {
transportMessageHasStackTrace = ErrorTraceHelper.setupErrorTraceListener(internalCluster());
}

private void setupIndexWithDocs() {
Expand All @@ -70,7 +53,6 @@ private void setupIndexWithDocs() {
}

public void testAsyncSearchFailingQueryErrorTraceDefault() throws IOException, InterruptedException {
transportMessageHasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_async_search");
Expand All @@ -93,11 +75,10 @@ public void testAsyncSearchFailingQueryErrorTraceDefault() throws IOException, I
responseEntity = performRequestAndGetResponseEntityAfterDelay(request, TimeValue.timeValueSeconds(1L));
}
// check that the stack trace was not sent from the data node to the coordinating node
assertFalse(transportMessageHasStackTrace.get());
assertFalse(transportMessageHasStackTrace.getAsBoolean());
}

public void testAsyncSearchFailingQueryErrorTraceTrue() throws IOException, InterruptedException {
transportMessageHasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_async_search");
Expand All @@ -122,11 +103,10 @@ public void testAsyncSearchFailingQueryErrorTraceTrue() throws IOException, Inte
responseEntity = performRequestAndGetResponseEntityAfterDelay(request, TimeValue.timeValueSeconds(1L));
}
// check that the stack trace was sent from the data node to the coordinating node
assertTrue(transportMessageHasStackTrace.get());
assertTrue(transportMessageHasStackTrace.getAsBoolean());
}

public void testAsyncSearchFailingQueryErrorTraceFalse() throws IOException, InterruptedException {
transportMessageHasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_async_search");
Expand All @@ -151,11 +131,10 @@ public void testAsyncSearchFailingQueryErrorTraceFalse() throws IOException, Int
responseEntity = performRequestAndGetResponseEntityAfterDelay(request, TimeValue.timeValueSeconds(1L));
}
// check that the stack trace was not sent from the data node to the coordinating node
assertFalse(transportMessageHasStackTrace.get());
assertFalse(transportMessageHasStackTrace.getAsBoolean());
}

public void testAsyncSearchFailingQueryErrorTraceFalseOnSubmitAndTrueOnGet() throws IOException, InterruptedException {
transportMessageHasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_async_search");
Expand All @@ -180,11 +159,10 @@ public void testAsyncSearchFailingQueryErrorTraceFalseOnSubmitAndTrueOnGet() thr
responseEntity = performRequestAndGetResponseEntityAfterDelay(request, TimeValue.timeValueSeconds(1L));
}
// check that the stack trace was not sent from the data node to the coordinating node
assertFalse(transportMessageHasStackTrace.get());
assertFalse(transportMessageHasStackTrace.getAsBoolean());
}

public void testAsyncSearchFailingQueryErrorTraceTrueOnSubmitAndFalseOnGet() throws IOException, InterruptedException {
transportMessageHasStackTrace = new AtomicBoolean();
setupIndexWithDocs();

Request searchRequest = new Request("POST", "/_async_search");
Expand All @@ -209,7 +187,7 @@ public void testAsyncSearchFailingQueryErrorTraceTrueOnSubmitAndFalseOnGet() thr
responseEntity = performRequestAndGetResponseEntityAfterDelay(request, TimeValue.timeValueSeconds(1L));
}
// check that the stack trace was sent from the data node to the coordinating node
assertTrue(transportMessageHasStackTrace.get());
assertTrue(transportMessageHasStackTrace.getAsBoolean());
}

private Map<String, Object> performRequestAndGetResponseEntityAfterDelay(Request r, TimeValue sleep) throws IOException,
Expand Down