Skip to content

Commit 13940a2

Browse files
committed
Merge branch 'main' into esql-top-n-intermediate-error
# Conflicts: # x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/aggregation/CountGroupingAggregatorFunction.java
2 parents 0562919 + 8bcb0c4 commit 13940a2

File tree

102 files changed

+1135
-801
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+1135
-801
lines changed

docs/changelog/130924.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 130924
2+
summary: Check field data type before casting when applying geo distance sort
3+
area: Search
4+
type: bug
5+
issues:
6+
- 129500

docs/reference/elasticsearch/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Elasticsearch and index management
1+
# Elasticsearch
22

33
This section contains reference information for {{es}} and index management features.
44

@@ -7,7 +7,7 @@ To learn more about {{es}} features and how to get started, refer to the [{{es}}
77
For more details about query and scripting languages, check these sections:
88
* [Query languages](../query-languages/index.md)
99
* [Scripting languages](../scripting-languages/index.md)
10-
10+
1111
{{es}} also provides the following REST APIs:
1212

1313
* [{{es}} API](https://www.elastic.co/docs/api/doc/elasticsearch)

docs/reference/elasticsearch/rest-apis/index.md

Lines changed: 664 additions & 0 deletions
Large diffs are not rendered by default.

muted-tests.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -564,18 +564,18 @@ tests:
564564
- class: org.elasticsearch.cluster.ClusterStateSerializationTests
565565
method: testSerializationPreMultiProject
566566
issue: https://github.com/elastic/elasticsearch/issues/130872
567-
- class: org.elasticsearch.cluster.coordination.votingonly.VotingOnlyNodePluginTests
568-
method: testPreferFullMasterOverVotingOnlyNodes
569-
issue: https://github.com/elastic/elasticsearch/issues/130883
570567
- class: org.elasticsearch.search.SearchWithRejectionsIT
571568
method: testOpenContextsAfterRejections
572569
issue: https://github.com/elastic/elasticsearch/issues/130821
573-
- class: org.elasticsearch.cluster.coordination.votingonly.VotingOnlyNodePluginTests
574-
method: testVotingOnlyNodesCannotBeMasterWithoutFullMasterNodes
575-
issue: https://github.com/elastic/elasticsearch/issues/130979
576570
- class: org.elasticsearch.packaging.test.DockerTests
577571
method: test082CannotUseEnvVarsAndFiles
578572
issue: https://github.com/elastic/elasticsearch/issues/129808
573+
- class: org.elasticsearch.xpack.esql.action.EsqlActionBreakerIT
574+
method: testExtractFields
575+
issue: https://github.com/elastic/elasticsearch/issues/130501
576+
- class: org.elasticsearch.xpack.esql.action.EsqlActionBreakerIT
577+
method: testRowStatsProjectGroupByInt
578+
issue: https://github.com/elastic/elasticsearch/issues/131024
579579

580580
# Examples:
581581
#

server/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -189,37 +189,46 @@ public StoredContext newEmptySystemContext() {
189189
* moving tracing-related fields to different names so that a new child span can be started. This child span will pick up
190190
* the moved fields and use them to establish the parent-child relationship.
191191
*
192+
* Response headers will be propagated. If no parent span is in progress (meaning there's no trace context), this will behave exactly
193+
* the same way as {@link #newStoredContextPreservingResponseHeaders}.
194+
*
192195
* @return a stored context, which can be restored when this context is no longer needed.
193196
*/
194197
public StoredContext newTraceContext() {
195198
final ThreadContextStruct originalContext = threadLocal.get();
196-
final Map<String, String> newRequestHeaders = new HashMap<>(originalContext.requestHeaders);
197-
final Map<String, Object> newTransientHeaders = new HashMap<>(originalContext.transientHeaders);
198199

199-
final String previousTraceParent = newRequestHeaders.remove(Task.TRACE_PARENT_HTTP_HEADER);
200-
if (previousTraceParent != null) {
201-
newTransientHeaders.put(Task.PARENT_TRACE_PARENT_HEADER, previousTraceParent);
202-
}
200+
// this is the context when this method returns
201+
final ThreadContextStruct newContext;
202+
if (originalContext.hasTraceContext() == false) {
203+
newContext = originalContext;
204+
} else {
205+
final Map<String, String> newRequestHeaders = new HashMap<>(originalContext.requestHeaders);
206+
final Map<String, Object> newTransientHeaders = new HashMap<>(originalContext.transientHeaders);
203207

204-
final String previousTraceState = newRequestHeaders.remove(Task.TRACE_STATE);
205-
if (previousTraceState != null) {
206-
newTransientHeaders.put(Task.PARENT_TRACE_STATE, previousTraceState);
207-
}
208+
final String previousTraceParent = newRequestHeaders.remove(Task.TRACE_PARENT_HTTP_HEADER);
209+
if (previousTraceParent != null) {
210+
newTransientHeaders.put(Task.PARENT_TRACE_PARENT_HEADER, previousTraceParent);
211+
}
208212

209-
final Object previousTraceContext = newTransientHeaders.remove(Task.APM_TRACE_CONTEXT);
210-
if (previousTraceContext != null) {
211-
newTransientHeaders.put(Task.PARENT_APM_TRACE_CONTEXT, previousTraceContext);
212-
}
213+
final String previousTraceState = newRequestHeaders.remove(Task.TRACE_STATE);
214+
if (previousTraceState != null) {
215+
newTransientHeaders.put(Task.PARENT_TRACE_STATE, previousTraceState);
216+
}
213217

214-
// this is the context when this method returns
215-
final ThreadContextStruct newContext = new ThreadContextStruct(
216-
newRequestHeaders,
217-
originalContext.responseHeaders,
218-
newTransientHeaders,
219-
originalContext.isSystemContext,
220-
originalContext.warningHeadersSize
221-
);
222-
threadLocal.set(newContext);
218+
final Object previousTraceContext = newTransientHeaders.remove(Task.APM_TRACE_CONTEXT);
219+
if (previousTraceContext != null) {
220+
newTransientHeaders.put(Task.PARENT_APM_TRACE_CONTEXT, previousTraceContext);
221+
}
222+
223+
newContext = new ThreadContextStruct(
224+
newRequestHeaders,
225+
originalContext.responseHeaders,
226+
newTransientHeaders,
227+
originalContext.isSystemContext,
228+
originalContext.warningHeadersSize
229+
);
230+
threadLocal.set(newContext);
231+
}
223232
// Tracing shouldn't interrupt the propagation of response headers, so in the same as
224233
// #newStoredContextPreservingResponseHeaders(), pass on any potential changes to the response headers.
225234
return () -> {
@@ -233,10 +242,11 @@ public StoredContext newTraceContext() {
233242
}
234243

235244
public boolean hasTraceContext() {
236-
final ThreadContextStruct context = threadLocal.get();
237-
return context.requestHeaders.containsKey(Task.TRACE_PARENT_HTTP_HEADER)
238-
|| context.requestHeaders.containsKey(Task.TRACE_STATE)
239-
|| context.transientHeaders.containsKey(Task.APM_TRACE_CONTEXT);
245+
return threadLocal.get().hasTraceContext();
246+
}
247+
248+
public boolean hasParentTraceContext() {
249+
return threadLocal.get().hasParentTraceContext();
240250
}
241251

242252
/**
@@ -853,6 +863,18 @@ private ThreadContextStruct putResponseHeaders(Map<String, Set<String>> headers)
853863
return new ThreadContextStruct(requestHeaders, newResponseHeaders, transientHeaders, isSystemContext);
854864
}
855865

866+
private boolean hasTraceContext() {
867+
return requestHeaders.containsKey(Task.TRACE_PARENT_HTTP_HEADER)
868+
|| requestHeaders.containsKey(Task.TRACE_STATE)
869+
|| transientHeaders.containsKey(Task.APM_TRACE_CONTEXT);
870+
}
871+
872+
private boolean hasParentTraceContext() {
873+
return transientHeaders.containsKey(Task.PARENT_TRACE_PARENT_HEADER)
874+
|| transientHeaders.containsKey(Task.PARENT_TRACE_STATE)
875+
|| transientHeaders.containsKey(Task.PARENT_APM_TRACE_CONTEXT);
876+
}
877+
856878
private void logWarningHeaderThresholdExceeded(long threshold, Setting<?> thresholdSetting) {
857879
// If available, log some selected headers to help identifying the source of the request.
858880
// Note: Only Task.HEADERS_TO_COPY are guaranteed to be preserved at this point.

server/src/main/java/org/elasticsearch/search/sort/GeoDistanceSortBuilder.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,13 @@ private IndexGeoPointFieldData fieldData(SearchExecutionContext context) {
599599
throw new IllegalArgumentException("failed to find mapper for [" + fieldName + "] for geo distance based sort");
600600
}
601601
}
602-
return context.getForField(fieldType, MappedFieldType.FielddataOperation.SEARCH);
602+
IndexFieldData<?> indexFieldData = context.getForField(fieldType, MappedFieldType.FielddataOperation.SEARCH);
603+
if (indexFieldData instanceof IndexGeoPointFieldData) {
604+
return (IndexGeoPointFieldData) indexFieldData;
605+
}
606+
throw new IllegalArgumentException(
607+
"unable to apply geo distance sort to field [" + fieldName + "] of type [" + fieldType.typeName() + "]"
608+
);
603609
}
604610

605611
private Nested nested(SearchExecutionContext context) throws IOException {

server/src/main/java/org/elasticsearch/tasks/Task.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public class Task implements Traceable {
4444
* TRACE_PARENT once parsed in RestController.tryAllHandler is not preserved
4545
* has to be declared as a header copied over from http request.
4646
* May also be used internally when APM is enabled.
47+
* https://www.w3.org/TR/trace-context-1/#traceparent-header
4748
*/
4849
public static final String TRACE_PARENT_HTTP_HEADER = "traceparent";
4950

@@ -53,6 +54,10 @@ public class Task implements Traceable {
5354
*/
5455
public static final String TRACE_ID = "trace.id";
5556

57+
/**
58+
* Optional request header carrying vendor-specific trace information.
59+
* https://www.w3.org/TR/trace-context-1/#tracestate-header
60+
*/
5661
public static final String TRACE_STATE = "tracestate";
5762

5863
public static final String TRACE_START_TIME = "trace.starttime";

server/src/main/java/org/elasticsearch/tasks/TaskManager.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,9 @@ public Task register(String type, String action, TaskAwareRequest request, boole
179179
// package private for testing
180180
void startTrace(ThreadContext threadContext, Task task) {
181181
TaskId parentTask = task.getParentTaskId();
182-
Map<String, Object> attributes = Map.of(
183-
Tracer.AttributeKeys.TASK_ID,
184-
task.getId(),
185-
Tracer.AttributeKeys.PARENT_TASK_ID,
186-
parentTask.toString()
187-
);
182+
Map<String, Object> attributes = parentTask.isSet()
183+
? Map.of(Tracer.AttributeKeys.TASK_ID, task.getId(), Tracer.AttributeKeys.PARENT_TASK_ID, parentTask.toString())
184+
: Map.of(Tracer.AttributeKeys.TASK_ID, task.getId());
188185
tracer.startTrace(threadContext, task, task.getAction(), attributes);
189186
}
190187

server/src/test/java/org/elasticsearch/common/util/concurrent/ThreadContextTests.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,14 @@
3434

3535
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomAsciiLettersOfLengthBetween;
3636
import static org.elasticsearch.tasks.Task.HEADERS_TO_COPY;
37+
import static org.hamcrest.Matchers.anEmptyMap;
3738
import static org.hamcrest.Matchers.contains;
3839
import static org.hamcrest.Matchers.containsInAnyOrder;
3940
import static org.hamcrest.Matchers.equalTo;
4041
import static org.hamcrest.Matchers.hasItem;
4142
import static org.hamcrest.Matchers.hasSize;
4243
import static org.hamcrest.Matchers.instanceOf;
44+
import static org.hamcrest.Matchers.is;
4345
import static org.hamcrest.Matchers.not;
4446
import static org.hamcrest.Matchers.nullValue;
4547
import static org.hamcrest.Matchers.sameInstance;
@@ -1161,6 +1163,75 @@ public void testNewEmptySystemContext() {
11611163
assertNotNull(threadContext.getHeader(header));
11621164
}
11631165

1166+
public void testNewTraceContext() {
1167+
final var threadContext = new ThreadContext(Settings.EMPTY);
1168+
1169+
var rootTraceContext = Map.of(Task.TRACE_PARENT_HTTP_HEADER, randomIdentifier(), Task.TRACE_STATE, randomIdentifier());
1170+
var apmTraceContext = new Object();
1171+
var responseKey = randomIdentifier();
1172+
var responseValue = randomAlphaOfLength(10);
1173+
1174+
threadContext.putHeader(rootTraceContext);
1175+
threadContext.putTransient(Task.APM_TRACE_CONTEXT, apmTraceContext);
1176+
1177+
assertThat(threadContext.hasTraceContext(), equalTo(true));
1178+
assertThat(threadContext.hasParentTraceContext(), equalTo(false));
1179+
1180+
try (var ignored = threadContext.newTraceContext()) {
1181+
assertThat(threadContext.hasTraceContext(), equalTo(false)); // no trace started yet
1182+
assertThat(threadContext.hasParentTraceContext(), equalTo(true));
1183+
1184+
assertThat(threadContext.getHeaders(), is(anEmptyMap()));
1185+
assertThat(
1186+
threadContext.getTransientHeaders(),
1187+
equalTo(
1188+
Map.of(
1189+
Task.PARENT_TRACE_PARENT_HEADER,
1190+
rootTraceContext.get(Task.TRACE_PARENT_HTTP_HEADER),
1191+
Task.PARENT_TRACE_STATE,
1192+
rootTraceContext.get(Task.TRACE_STATE),
1193+
Task.PARENT_APM_TRACE_CONTEXT,
1194+
apmTraceContext
1195+
)
1196+
)
1197+
);
1198+
// response headers shall be propagated
1199+
threadContext.addResponseHeader(responseKey, responseValue);
1200+
}
1201+
1202+
assertThat(threadContext.hasTraceContext(), equalTo(true));
1203+
assertThat(threadContext.hasParentTraceContext(), equalTo(false));
1204+
1205+
assertThat(threadContext.getHeaders(), equalTo(rootTraceContext));
1206+
assertThat(threadContext.getTransientHeaders(), equalTo(Map.of(Task.APM_TRACE_CONTEXT, apmTraceContext)));
1207+
assertThat(threadContext.getResponseHeaders(), equalTo(Map.of(responseKey, List.of(responseValue))));
1208+
}
1209+
1210+
public void testNewTraceContextWithoutParentTrace() {
1211+
final var threadContext = new ThreadContext(Settings.EMPTY);
1212+
1213+
var responseKey = randomIdentifier();
1214+
var responseValue = randomAlphaOfLength(10);
1215+
1216+
assertThat(threadContext.hasTraceContext(), equalTo(false));
1217+
assertThat(threadContext.hasParentTraceContext(), equalTo(false));
1218+
1219+
try (var ignored = threadContext.newTraceContext()) {
1220+
assertTrue(threadContext.isDefaultContext());
1221+
assertThat(threadContext.hasTraceContext(), equalTo(false));
1222+
assertThat(threadContext.hasParentTraceContext(), equalTo(false));
1223+
1224+
// discared, just making sure the context is isolated
1225+
threadContext.putTransient(randomIdentifier(), randomAlphaOfLength(10));
1226+
// response headers shall be propagated
1227+
threadContext.addResponseHeader(responseKey, responseValue);
1228+
}
1229+
1230+
assertThat(threadContext.getHeaders(), is(anEmptyMap()));
1231+
assertThat(threadContext.getTransientHeaders(), is(anEmptyMap()));
1232+
assertThat(threadContext.getResponseHeaders(), equalTo(Map.of(responseKey, List.of(responseValue))));
1233+
}
1234+
11641235
public void testRestoreExistingContext() {
11651236
final var threadContext = new ThreadContext(Settings.EMPTY);
11661237
final var header = randomIdentifier();

server/src/test/java/org/elasticsearch/search/sort/GeoDistanceSortBuilderTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.elasticsearch.index.mapper.GeoPointFieldMapper;
2424
import org.elasticsearch.index.mapper.MappedFieldType;
2525
import org.elasticsearch.index.mapper.NestedPathFieldMapper;
26+
import org.elasticsearch.index.mapper.NumberFieldMapper;
2627
import org.elasticsearch.index.query.GeoValidationMethod;
2728
import org.elasticsearch.index.query.MatchAllQueryBuilder;
2829
import org.elasticsearch.index.query.MatchNoneQueryBuilder;
@@ -99,6 +100,9 @@ public static GeoDistanceSortBuilder randomGeoDistanceSortBuilder() {
99100

100101
@Override
101102
protected MappedFieldType provideMappedFieldType(String name) {
103+
if (name.equals("double")) {
104+
return new NumberFieldMapper.NumberFieldType(name, NumberFieldMapper.NumberType.DOUBLE);
105+
}
102106
return new GeoPointFieldMapper.GeoPointFieldType(name);
103107
}
104108

@@ -531,6 +535,12 @@ public void testBuildInvalidPoints() throws IOException {
531535
);
532536
assertEquals("illegal longitude value [-360.0] for [GeoDistanceSort] for field [fieldName].", ex.getMessage());
533537
}
538+
{
539+
GeoDistanceSortBuilder sortBuilder = new GeoDistanceSortBuilder("double", 0.0, 180.0);
540+
sortBuilder.validation(GeoValidationMethod.STRICT);
541+
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> sortBuilder.build(searchExecutionContext));
542+
assertEquals("unable to apply geo distance sort to field [double] of type [double]", ex.getMessage());
543+
}
534544
}
535545

536546
/**

0 commit comments

Comments
 (0)