Skip to content

Commit 0b1e217

Browse files
authored
[7.x] Preserve grok pattern ordering and add sort option (#61671) (#62162)
1 parent 8d8a918 commit 0b1e217

File tree

3 files changed

+88
-8
lines changed

3 files changed

+88
-8
lines changed

libs/grok/src/main/java/org/elasticsearch/grok/Grok.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.Collections;
3939
import java.util.HashMap;
4040
import java.util.Iterator;
41+
import java.util.LinkedHashMap;
4142
import java.util.List;
4243
import java.util.Locale;
4344
import java.util.Map;
@@ -292,7 +293,7 @@ private static Map<String, String> loadBuiltinPatterns() throws IOException {
292293
"java", "junos", "linux-syslog", "maven", "mcollective-patterns", "mongodb", "nagios",
293294
"postgresql", "rails", "redis", "ruby", "squid"
294295
};
295-
Map<String, String> builtinPatterns = new HashMap<>();
296+
Map<String, String> builtinPatterns = new LinkedHashMap<>();
296297
for (String pattern : PATTERN_NAMES) {
297298
try(InputStream is = Grok.class.getResourceAsStream("/patterns/" + pattern)) {
298299
loadPatterns(builtinPatterns, is);

modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/GrokProcessorGetAction.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.elasticsearch.ingest.common;
2020

21+
import org.elasticsearch.Version;
2122
import org.elasticsearch.action.ActionListener;
2223
import org.elasticsearch.action.ActionRequest;
2324
import org.elasticsearch.action.ActionRequestValidationException;
@@ -40,6 +41,7 @@
4041
import java.io.IOException;
4142
import java.util.List;
4243
import java.util.Map;
44+
import java.util.TreeMap;
4345

4446
import static java.util.Collections.singletonList;
4547
import static org.elasticsearch.ingest.common.IngestCommonPlugin.GROK_PATTERNS;
@@ -56,16 +58,33 @@ private GrokProcessorGetAction() {
5658

5759
public static class Request extends ActionRequest {
5860

59-
Request() {}
61+
private final boolean sorted;
62+
63+
public Request(boolean sorted) {
64+
this.sorted = sorted;
65+
}
6066

6167
Request(StreamInput in) throws IOException {
6268
super(in);
69+
this.sorted = in.getVersion().onOrAfter(Version.V_7_10_0) ? in.readBoolean() : false;
6370
}
6471

6572
@Override
6673
public ActionRequestValidationException validate() {
6774
return null;
6875
}
76+
77+
@Override
78+
public void writeTo(StreamOutput out) throws IOException {
79+
super.writeTo(out);
80+
if (out.getVersion().onOrAfter(Version.V_7_10_0)) {
81+
out.writeBoolean(sorted);
82+
}
83+
}
84+
85+
public boolean sorted() {
86+
return sorted;
87+
}
6988
}
7089

7190
public static class Response extends ActionResponse implements ToXContentObject {
@@ -101,15 +120,25 @@ public void writeTo(StreamOutput out) throws IOException {
101120

102121
public static class TransportAction extends HandledTransportAction<Request, Response> {
103122

123+
private final Map<String, String> grokPatterns;
124+
private final Map<String, String> sortedGrokPatterns;
125+
104126
@Inject
105127
public TransportAction(TransportService transportService, ActionFilters actionFilters) {
128+
this(transportService, actionFilters, GROK_PATTERNS);
129+
}
130+
131+
// visible for testing
132+
TransportAction(TransportService transportService, ActionFilters actionFilters, Map<String, String> grokPatterns) {
106133
super(NAME, transportService, actionFilters, Request::new);
134+
this.grokPatterns = grokPatterns;
135+
this.sortedGrokPatterns = new TreeMap<>(this.grokPatterns);
107136
}
108137

109138
@Override
110139
protected void doExecute(Task task, Request request, ActionListener<Response> listener) {
111140
try {
112-
listener.onResponse(new Response(GROK_PATTERNS));
141+
listener.onResponse(new Response(request.sorted() ? sortedGrokPatterns : grokPatterns));
113142
} catch (Exception e) {
114143
listener.onFailure(e);
115144
}
@@ -130,7 +159,9 @@ public String getName() {
130159

131160
@Override
132161
protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) {
133-
return channel -> client.executeLocally(INSTANCE, new Request(), new RestToXContentListener<>(channel));
162+
boolean sorted = request.paramAsBoolean("s", false);
163+
Request grokPatternsRequest = new Request(sorted);
164+
return channel -> client.executeLocally(INSTANCE, grokPatternsRequest, new RestToXContentListener<>(channel));
134165
}
135166
}
136167
}

modules/ingest-common/src/test/java/org/elasticsearch/ingest/common/GrokProcessorGetActionTests.java

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
package org.elasticsearch.ingest.common;
2121

22+
import org.elasticsearch.action.ActionListener;
23+
import org.elasticsearch.action.support.ActionFilters;
2224
import org.elasticsearch.common.bytes.BytesReference;
2325
import org.elasticsearch.common.io.stream.BytesStreamOutput;
2426
import org.elasticsearch.common.io.stream.StreamInput;
@@ -27,18 +29,26 @@
2729
import org.elasticsearch.common.xcontent.XContentHelper;
2830
import org.elasticsearch.common.xcontent.json.JsonXContent;
2931
import org.elasticsearch.test.ESTestCase;
32+
import org.elasticsearch.transport.TransportService;
3033

34+
import java.util.ArrayList;
3135
import java.util.Collections;
36+
import java.util.List;
3237
import java.util.Map;
3338

39+
import static org.hamcrest.CoreMatchers.not;
3440
import static org.hamcrest.Matchers.equalTo;
41+
import static org.hamcrest.Matchers.sameInstance;
42+
import static org.hamcrest.core.IsNull.notNullValue;
3543
import static org.hamcrest.core.IsNull.nullValue;
44+
import static org.mockito.Mockito.mock;
3645

3746
public class GrokProcessorGetActionTests extends ESTestCase {
38-
private static final Map<String, String> TEST_PATTERNS = Collections.singletonMap("PATTERN", "foo");
47+
private static final Map<String, String> TEST_PATTERNS =
48+
org.elasticsearch.common.collect.Map.of("PATTERN2", "foo2", "PATTERN1", "foo1");
3949

4050
public void testRequest() throws Exception {
41-
GrokProcessorGetAction.Request request = new GrokProcessorGetAction.Request();
51+
GrokProcessorGetAction.Request request = new GrokProcessorGetAction.Request(false);
4252
BytesStreamOutput out = new BytesStreamOutput();
4353
request.writeTo(out);
4454
StreamInput streamInput = out.bytes().streamInput();
@@ -56,15 +66,53 @@ public void testResponseSerialization() throws Exception {
5666
assertThat(response.getGrokPatterns(), equalTo(otherResponse.getGrokPatterns()));
5767
}
5868

69+
public void testResponseSorting() {
70+
List<String> sortedKeys = new ArrayList<>(TEST_PATTERNS.keySet());
71+
Collections.sort(sortedKeys);
72+
GrokProcessorGetAction.TransportAction transportAction =
73+
new GrokProcessorGetAction.TransportAction(mock(TransportService.class), mock(ActionFilters.class), TEST_PATTERNS);
74+
GrokProcessorGetAction.Response[] receivedResponse = new GrokProcessorGetAction.Response[1];
75+
transportAction.doExecute(null, new GrokProcessorGetAction.Request(true), new ActionListener<GrokProcessorGetAction.Response>() {
76+
@Override
77+
public void onResponse(GrokProcessorGetAction.Response response) {
78+
receivedResponse[0] = response;
79+
}
80+
81+
@Override
82+
public void onFailure(Exception e) {
83+
fail();
84+
}
85+
});
86+
assertThat(receivedResponse[0], notNullValue());
87+
assertThat(receivedResponse[0].getGrokPatterns().keySet().toArray(), equalTo(sortedKeys.toArray()));
88+
89+
GrokProcessorGetAction.Response firstResponse = receivedResponse[0];
90+
transportAction.doExecute(null, new GrokProcessorGetAction.Request(true), new ActionListener<GrokProcessorGetAction.Response>() {
91+
@Override
92+
public void onResponse(GrokProcessorGetAction.Response response) {
93+
receivedResponse[0] = response;
94+
}
95+
96+
@Override
97+
public void onFailure(Exception e) {
98+
fail();
99+
}
100+
});
101+
assertThat(receivedResponse[0], notNullValue());
102+
assertThat(receivedResponse[0], not(sameInstance(firstResponse)));
103+
assertThat(receivedResponse[0].getGrokPatterns(), sameInstance(firstResponse.getGrokPatterns()));
104+
}
105+
59106
@SuppressWarnings("unchecked")
60107
public void testResponseToXContent() throws Exception {
61108
GrokProcessorGetAction.Response response = new GrokProcessorGetAction.Response(TEST_PATTERNS);
62109
try (XContentBuilder builder = JsonXContent.contentBuilder()) {
63110
response.toXContent(builder, ToXContent.EMPTY_PARAMS);
64111
Map<String, Object> converted = XContentHelper.convertToMap(BytesReference.bytes(builder), false, builder.contentType()).v2();
65112
Map<String, String> patterns = (Map<String, String>) converted.get("patterns");
66-
assertThat(patterns.size(), equalTo(1));
67-
assertThat(patterns.get("PATTERN"), equalTo("foo"));
113+
assertThat(patterns.size(), equalTo(2));
114+
assertThat(patterns.get("PATTERN1"), equalTo("foo1"));
115+
assertThat(patterns.get("PATTERN2"), equalTo("foo2"));
68116
}
69117
}
70118
}

0 commit comments

Comments
 (0)