Skip to content

Commit e2281a1

Browse files
Introduce an IndexSettingsProvider to inject logsdb index mode (#113505)
Here we introduce a new implementation of `IndexSettingProvider` whose goal is to "inject" the `index.mode` setting with value `logsdb` when a cluster setting `cluster.logsdb.enabled` is `true`. We also make sure that: * the existing `index.mode` is not set * the datastream name matches the `logs-*-*` pattern * `logs@settings` component template is used
1 parent fc9954e commit e2281a1

File tree

13 files changed

+648
-32
lines changed

13 files changed

+648
-32
lines changed

modules/data-streams/src/javaRestTest/java/org/elasticsearch/datastreams/logsdb/LogsIndexModeDisabledRestTestIT.java

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import org.elasticsearch.client.RestClient;
1313
import org.elasticsearch.index.IndexMode;
14+
import org.elasticsearch.index.IndexSettings;
1415
import org.elasticsearch.test.cluster.ElasticsearchCluster;
1516
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
1617
import org.hamcrest.Matchers;
@@ -23,6 +24,22 @@
2324

2425
public class LogsIndexModeDisabledRestTestIT extends LogsIndexModeRestTestIT {
2526

27+
private static final String MAPPINGS = """
28+
{
29+
"template": {
30+
"mappings": {
31+
"properties": {
32+
"@timestamp": {
33+
"type": "date"
34+
},
35+
"message": {
36+
"type": "text"
37+
}
38+
}
39+
}
40+
}
41+
}""";
42+
2643
@ClassRule()
2744
public static ElasticsearchCluster cluster = ElasticsearchCluster.local()
2845
.distribution(DistributionType.DEFAULT)
@@ -50,8 +67,59 @@ public void setup() throws Exception {
5067

5168
public void testLogsSettingsIndexModeDisabled() throws IOException {
5269
assertOK(createDataStream(client, "logs-custom-dev"));
53-
final String indexMode = (String) getSetting(client, getDataStreamBackingIndex(client, "logs-custom-dev", 0), "index.mode");
70+
final String indexMode = (String) getSetting(
71+
client,
72+
getDataStreamBackingIndex(client, "logs-custom-dev", 0),
73+
IndexSettings.MODE.getKey()
74+
);
5475
assertThat(indexMode, Matchers.not(equalTo(IndexMode.LOGSDB.getName())));
5576
}
5677

78+
public void testTogglingLogsdb() throws IOException {
79+
putComponentTemplate(client, "logs@settings", MAPPINGS);
80+
assertOK(createDataStream(client, "logs-custom-dev"));
81+
final String indexModeBefore = (String) getSetting(
82+
client,
83+
getDataStreamBackingIndex(client, "logs-custom-dev", 0),
84+
IndexSettings.MODE.getKey()
85+
);
86+
assertThat(indexModeBefore, Matchers.not(equalTo(IndexMode.LOGSDB.getName())));
87+
assertOK(putClusterSetting(client, "cluster.logsdb.enabled", "true"));
88+
final String indexModeAfter = (String) getSetting(
89+
client,
90+
getDataStreamBackingIndex(client, "logs-custom-dev", 0),
91+
IndexSettings.MODE.getKey()
92+
);
93+
assertThat(indexModeAfter, Matchers.not(equalTo(IndexMode.LOGSDB.getName())));
94+
assertOK(rolloverDataStream(client, "logs-custom-dev"));
95+
final String indexModeLater = (String) getSetting(
96+
client,
97+
getDataStreamBackingIndex(client, "logs-custom-dev", 1),
98+
IndexSettings.MODE.getKey()
99+
);
100+
assertThat(indexModeLater, equalTo(IndexMode.LOGSDB.getName()));
101+
assertOK(putClusterSetting(client, "cluster.logsdb.enabled", "false"));
102+
assertOK(rolloverDataStream(client, "logs-custom-dev"));
103+
final String indexModeFinal = (String) getSetting(
104+
client,
105+
getDataStreamBackingIndex(client, "logs-custom-dev", 2),
106+
IndexSettings.MODE.getKey()
107+
);
108+
assertThat(indexModeFinal, Matchers.not(equalTo(IndexMode.LOGSDB.getName())));
109+
110+
}
111+
112+
public void testEnablingLogsdb() throws IOException {
113+
putComponentTemplate(client, "logs@settings", MAPPINGS);
114+
assertOK(putClusterSetting(client, "cluster.logsdb.enabled", true));
115+
assertOK(createDataStream(client, "logs-custom-dev"));
116+
final String indexMode = (String) getSetting(
117+
client,
118+
getDataStreamBackingIndex(client, "logs-custom-dev", 0),
119+
IndexSettings.MODE.getKey()
120+
);
121+
assertThat(indexMode, equalTo(IndexMode.LOGSDB.getName()));
122+
assertOK(putClusterSetting(client, "cluster.logsdb.enabled", false));
123+
}
124+
57125
}

modules/data-streams/src/javaRestTest/java/org/elasticsearch/datastreams/logsdb/LogsIndexModeEnabledRestTestIT.java

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
package org.elasticsearch.datastreams.logsdb;
1111

1212
import org.elasticsearch.client.Response;
13+
import org.elasticsearch.client.ResponseException;
1314
import org.elasticsearch.client.RestClient;
1415
import org.elasticsearch.index.IndexMode;
16+
import org.elasticsearch.index.IndexSettings;
1517
import org.elasticsearch.test.cluster.ElasticsearchCluster;
1618
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
1719
import org.hamcrest.Matchers;
@@ -179,7 +181,11 @@ public void setup() throws Exception {
179181
public void testCreateDataStream() throws IOException {
180182
assertOK(putComponentTemplate(client, "logs@custom", MAPPINGS));
181183
assertOK(createDataStream(client, "logs-custom-dev"));
182-
final String indexMode = (String) getSetting(client, getDataStreamBackingIndex(client, "logs-custom-dev", 0), "index.mode");
184+
final String indexMode = (String) getSetting(
185+
client,
186+
getDataStreamBackingIndex(client, "logs-custom-dev", 0),
187+
IndexSettings.MODE.getKey()
188+
);
183189
assertThat(indexMode, equalTo(IndexMode.LOGSDB.getName()));
184190
}
185191

@@ -224,4 +230,83 @@ public void testRolloverDataStream() throws IOException {
224230
assertThat(firstBackingIndex, Matchers.not(equalTo(secondBackingIndex)));
225231
assertThat(getDataStreamBackingIndices(client, "logs-custom-dev").size(), equalTo(2));
226232
}
233+
234+
public void testLogsAtSettingWithStandardOverride() throws IOException {
235+
assertOK(putComponentTemplate(client, "logs@custom", """
236+
{
237+
"template": {
238+
"settings": {
239+
"index": {
240+
"mode": "standard"
241+
}
242+
}
243+
}
244+
}
245+
"""));
246+
assertOK(createDataStream(client, "logs-custom-dev"));
247+
final String indexMode = (String) getSetting(
248+
client,
249+
getDataStreamBackingIndex(client, "logs-custom-dev", 0),
250+
IndexSettings.MODE.getKey()
251+
);
252+
assertThat(indexMode, equalTo(IndexMode.STANDARD.getName()));
253+
}
254+
255+
public void testLogsAtSettingWithTimeSeriesOverride() throws IOException {
256+
assertOK(putComponentTemplate(client, "logs@custom", """
257+
{
258+
"template": {
259+
"settings": {
260+
"index": {
261+
"routing_path": [ "hostname" ],
262+
"mode": "time_series",
263+
"sort.field": [],
264+
"sort.order": []
265+
}
266+
},
267+
"mappings": {
268+
"properties": {
269+
"hostname": {
270+
"type": "keyword",
271+
"time_series_dimension": true
272+
}
273+
}
274+
}
275+
}
276+
}
277+
"""));
278+
assertOK(createDataStream(client, "logs-custom-dev"));
279+
final String indexMode = (String) getSetting(
280+
client,
281+
getDataStreamBackingIndex(client, "logs-custom-dev", 0),
282+
IndexSettings.MODE.getKey()
283+
);
284+
assertThat(indexMode, equalTo(IndexMode.TIME_SERIES.getName()));
285+
}
286+
287+
public void testLogsAtSettingWithTimeSeriesOverrideFailure() {
288+
// NOTE: apm@settings defines sorting on @timestamp and template composition results in index.mode "time_series"
289+
// with a non-allowed index.sort.field '@timestamp'. This fails at template composition stage before the index is even created.
290+
final ResponseException ex = assertThrows(ResponseException.class, () -> putComponentTemplate(client, "logs@custom", """
291+
{
292+
"template": {
293+
"settings": {
294+
"index": {
295+
"routing_path": [ "hostname" ],
296+
"mode": "time_series"
297+
}
298+
},
299+
"mappings": {
300+
"properties": {
301+
"hostname": {
302+
"type": "keyword",
303+
"time_series_dimension": true
304+
}
305+
}
306+
}
307+
}
308+
}
309+
"""));
310+
assertTrue(ex.getMessage().contains("[index.mode=time_series] is incompatible with [index.sort.field]"));
311+
}
227312
}

modules/data-streams/src/javaRestTest/java/org/elasticsearch/datastreams/logsdb/LogsIndexModeRestTestIT.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,16 @@ protected static void waitForLogs(RestClient client) throws Exception {
3333
});
3434
}
3535

36-
protected static Response putComponentTemplate(final RestClient client, final String templateName, final String mappings)
36+
protected static Response putComponentTemplate(final RestClient client, final String componentTemplate, final String contends)
3737
throws IOException {
38-
final Request request = new Request("PUT", "/_component_template/" + templateName);
39-
request.setJsonEntity(mappings);
38+
final Request request = new Request("PUT", "/_component_template/" + componentTemplate);
39+
request.setJsonEntity(contends);
40+
return client.performRequest(request);
41+
}
42+
43+
protected static Response putTemplate(final RestClient client, final String template, final String contents) throws IOException {
44+
final Request request = new Request("PUT", "/_index_template/" + template);
45+
request.setJsonEntity(contents);
4046
return client.performRequest(request);
4147
}
4248

@@ -87,4 +93,11 @@ protected static Response bulkIndex(final RestClient client, final String dataSt
8793
bulkRequest.addParameter("refresh", "true");
8894
return client.performRequest(bulkRequest);
8995
}
96+
97+
protected static Response putClusterSetting(final RestClient client, final String settingName, final Object settingValue)
98+
throws IOException {
99+
final Request request = new Request("PUT", "/_cluster/settings");
100+
request.setJsonEntity("{ \"transient\": { \"" + settingName + "\": " + settingValue + " } }");
101+
return client.performRequest(request);
102+
}
90103
}

x-pack/plugin/core/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@
228228
exports org.elasticsearch.xpack.core.watcher.trigger;
229229
exports org.elasticsearch.xpack.core.watcher.watch;
230230
exports org.elasticsearch.xpack.core.watcher;
231+
exports org.elasticsearch.xpack.cluster.settings;
231232

232233
provides org.elasticsearch.action.admin.cluster.node.info.ComponentVersionNumber
233234
with
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.cluster.settings;
9+
10+
import org.elasticsearch.common.settings.Setting;
11+
12+
public class ClusterSettings {
13+
public static final Setting<Boolean> CLUSTER_LOGSDB_ENABLED = Setting.boolSetting(
14+
"cluster.logsdb.enabled",
15+
false,
16+
Setting.Property.Dynamic,
17+
Setting.Property.NodeScope
18+
);
19+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"template": {
3+
"settings": {
4+
"index": {
5+
"lifecycle": {
6+
"name": "logs"
7+
},
8+
"mode": "logsdb",
9+
"codec": "best_compression",
10+
"mapping": {
11+
"ignore_malformed": true,
12+
"total_fields": {
13+
"ignore_dynamic_beyond_limit": true
14+
}
15+
},
16+
"default_pipeline": "logs@default-pipeline"
17+
}
18+
}
19+
},
20+
"_meta": {
21+
"description": "default settings for the logs index template installed by x-pack",
22+
"managed": true
23+
},
24+
"version": ${xpack.stack.template.version},
25+
"deprecated": ${xpack.stack.template.deprecated}
26+
}

x-pack/plugin/core/template-resources/src/main/resources/[email protected]

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"lifecycle": {
66
"name": "logs"
77
},
8-
"mode": "${xpack.stack.template.logsdb.index.mode}",
98
"codec": "best_compression",
109
"mapping": {
1110
"ignore_malformed": true,

x-pack/plugin/logsdb/src/main/java/org/elasticsearch/xpack/logsdb/LogsDBPlugin.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,31 @@
1717
import java.util.Collection;
1818
import java.util.List;
1919

20+
import static org.elasticsearch.xpack.cluster.settings.ClusterSettings.CLUSTER_LOGSDB_ENABLED;
2021
import static org.elasticsearch.xpack.logsdb.SyntheticSourceLicenseService.FALLBACK_SETTING;
2122

2223
public class LogsDBPlugin extends Plugin {
2324

2425
private final Settings settings;
2526
private final SyntheticSourceLicenseService licenseService;
2627

28+
private final LogsdbIndexModeSettingsProvider logsdbIndexModeSettingsProvider;
29+
2730
public LogsDBPlugin(Settings settings) {
2831
this.settings = settings;
2932
this.licenseService = new SyntheticSourceLicenseService(settings);
33+
this.logsdbIndexModeSettingsProvider = new LogsdbIndexModeSettingsProvider(settings);
3034
}
3135

3236
@Override
3337
public Collection<?> createComponents(PluginServices services) {
3438
licenseService.setLicenseState(XPackPlugin.getSharedLicenseState());
3539
var clusterSettings = services.clusterService().getClusterSettings();
3640
clusterSettings.addSettingsUpdateConsumer(FALLBACK_SETTING, licenseService::setSyntheticSourceFallback);
41+
clusterSettings.addSettingsUpdateConsumer(
42+
CLUSTER_LOGSDB_ENABLED,
43+
logsdbIndexModeSettingsProvider::updateClusterIndexModeLogsdbEnabled
44+
);
3745
// Nothing to share here:
3846
return super.createComponents(services);
3947
}
@@ -43,11 +51,11 @@ public Collection<IndexSettingProvider> getAdditionalIndexSettingProviders(Index
4351
if (DiscoveryNode.isStateless(settings)) {
4452
return List.of();
4553
}
46-
return List.of(new SyntheticSourceIndexSettingsProvider(licenseService));
54+
return List.of(new SyntheticSourceIndexSettingsProvider(licenseService), logsdbIndexModeSettingsProvider);
4755
}
4856

4957
@Override
5058
public List<Setting<?>> getSettings() {
51-
return List.of(FALLBACK_SETTING);
59+
return List.of(FALLBACK_SETTING, CLUSTER_LOGSDB_ENABLED);
5260
}
5361
}

0 commit comments

Comments
 (0)