Skip to content

Commit 9dcab76

Browse files
authored
Preserve grok pattern ordering and add sort option (#61671)
1 parent 1b5e118 commit 9dcab76

File tree

3 files changed

+87
-8
lines changed

3 files changed

+87
-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
@@ -37,6 +37,7 @@
3737
import java.util.Collections;
3838
import java.util.HashMap;
3939
import java.util.Iterator;
40+
import java.util.LinkedHashMap;
4041
import java.util.List;
4142
import java.util.Locale;
4243
import java.util.Map;
@@ -288,7 +289,7 @@ private static Map<String, String> loadBuiltinPatterns() throws IOException {
288289
"java", "junos", "linux-syslog", "maven", "mcollective-patterns", "mongodb", "nagios",
289290
"postgresql", "rails", "redis", "ruby", "squid"
290291
};
291-
Map<String, String> builtinPatterns = new HashMap<>();
292+
Map<String, String> builtinPatterns = new LinkedHashMap<>();
292293
for (String pattern : PATTERN_NAMES) {
293294
try(InputStream is = Grok.class.getResourceAsStream("/patterns/" + pattern)) {
294295
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 org.elasticsearch.ingest.common.IngestCommonPlugin.GROK_PATTERNS;
4547
import static org.elasticsearch.rest.RestRequest.Method.GET;
@@ -55,16 +57,33 @@ private GrokProcessorGetAction() {
5557

5658
public static class Request extends ActionRequest {
5759

58-
public Request() {}
60+
private final boolean sorted;
61+
62+
public Request(boolean sorted) {
63+
this.sorted = sorted;
64+
}
5965

6066
Request(StreamInput in) throws IOException {
6167
super(in);
68+
this.sorted = in.getVersion().onOrAfter(Version.V_8_0_0) ? in.readBoolean() : false;
6269
}
6370

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

7089
public static class Response extends ActionResponse implements ToXContentObject {
@@ -100,15 +119,25 @@ public void writeTo(StreamOutput out) throws IOException {
100119

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

122+
private final Map<String, String> grokPatterns;
123+
private final Map<String, String> sortedGrokPatterns;
124+
103125
@Inject
104126
public TransportAction(TransportService transportService, ActionFilters actionFilters) {
127+
this(transportService, actionFilters, GROK_PATTERNS);
128+
}
129+
130+
// visible for testing
131+
TransportAction(TransportService transportService, ActionFilters actionFilters, Map<String, String> grokPatterns) {
105132
super(NAME, transportService, actionFilters, Request::new);
133+
this.grokPatterns = grokPatterns;
134+
this.sortedGrokPatterns = new TreeMap<>(this.grokPatterns);
106135
}
107136

108137
@Override
109138
protected void doExecute(Task task, Request request, ActionListener<Response> listener) {
110139
try {
111-
listener.onResponse(new Response(GROK_PATTERNS));
140+
listener.onResponse(new Response(request.sorted() ? sortedGrokPatterns : grokPatterns));
112141
} catch (Exception e) {
113142
listener.onFailure(e);
114143
}
@@ -129,7 +158,9 @@ public String getName() {
129158

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

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

Lines changed: 51 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,25 @@
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 = Map.of("PATTERN2", "foo2", "PATTERN1", "foo1");
3948

4049
public void testRequest() throws Exception {
41-
GrokProcessorGetAction.Request request = new GrokProcessorGetAction.Request();
50+
GrokProcessorGetAction.Request request = new GrokProcessorGetAction.Request(false);
4251
BytesStreamOutput out = new BytesStreamOutput();
4352
request.writeTo(out);
4453
StreamInput streamInput = out.bytes().streamInput();
@@ -56,15 +65,53 @@ public void testResponseSerialization() throws Exception {
5665
assertThat(response.getGrokPatterns(), equalTo(otherResponse.getGrokPatterns()));
5766
}
5867

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

0 commit comments

Comments
 (0)