Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a setting controlling the activation of the logs index mode in logs@settings #109025

Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
ac4bd1a
feature: enable logs index mode for logs behind feature flag
salvatore-campagna May 24, 2024
bcf8d75
feature: introduce a feature flag and a setting controlling 'logs' in…
salvatore-campagna May 24, 2024
c9adc0c
fix: mode mode
salvatore-campagna May 24, 2024
9a05971
fix: remove unused code
salvatore-campagna May 24, 2024
c5997b0
Merge branch 'main' into feature/108762-feature-flag-logs-settings
salvatore-campagna Jun 6, 2024
db785c3
fix: use a FeatureFlag to determine the default setting value
salvatore-campagna Jun 6, 2024
fd8000f
fix: missing json file extension
salvatore-campagna Jun 6, 2024
f2b4aed
fix: unable to replace immutable map entry
salvatore-campagna Jun 6, 2024
8f45572
test: include a java rest test for index mode with logs
salvatore-campagna Jun 7, 2024
93916bc
fix: error if replacing component template failes
salvatore-campagna Jun 7, 2024
04ced4d
fix: rename class to match naming conventions
salvatore-campagna Jun 7, 2024
ded8123
gradlew: add missing stack plugin dependency
salvatore-campagna Jun 7, 2024
6ef65cd
fix: include username and password for authentication
salvatore-campagna Jun 7, 2024
131610e
fix: user and pass not required
salvatore-campagna Jun 7, 2024
23147db
Update docs/changelog/109025.yaml
salvatore-campagna Jun 7, 2024
fa81d81
nit: remove unnecessary code
salvatore-campagna Jun 7, 2024
35601b8
fix: disable security and use default distro
salvatore-campagna Jun 7, 2024
f5bcb0f
fix: component template map and cluster modules
salvatore-campagna Jun 7, 2024
7852b7a
fix: license header
salvatore-campagna Jun 7, 2024
ba39898
fix: create another static map
salvatore-campagna Jun 7, 2024
40b0806
nit: rename map
salvatore-campagna Jun 7, 2024
f72f861
fix: do not agte usage of logs index.mode with the setting
salvatore-campagna Jun 7, 2024
bf0669f
fix: rename and move logsdb index mode setting
salvatore-campagna Jun 7, 2024
31066c5
nit: rename variable
salvatore-campagna Jun 7, 2024
fb283a6
fix: unused import
salvatore-campagna Jun 7, 2024
93c8b12
fix: trial license and no security
salvatore-campagna Jun 8, 2024
f32ad99
fix: remove ingest-common module
salvatore-campagna Jun 9, 2024
0f0df55
Merge branch 'main' into feature/108762-feature-flag-logs-settings
salvatore-campagna Jun 9, 2024
d72e632
fix: remove unused modules
salvatore-campagna Jun 10, 2024
465adc2
fix: use logs@custom to override mappings
salvatore-campagna Jun 10, 2024
8c0e747
fix: check no logs index mode in release build
salvatore-campagna Jun 10, 2024
86919b2
Merge branch 'main' into feature/108762-feature-flag-logs-settings
salvatore-campagna Jun 10, 2024
754b85f
fix: include hostname in logs mappings
salvatore-campagna Jun 10, 2024
7c43f5a
fix: rely on hotname and timestamp from logs@mappings
salvatore-campagna Jun 10, 2024
1b3828c
fix: use 'host.name' instead of 'hostname'
salvatore-campagna Jun 10, 2024
268ddb8
fix: use host.name in logs@mappings
salvatore-campagna Jun 10, 2024
7de0e84
Merge branch 'main' into feature/108762-feature-flag-logs-settings
salvatore-campagna Jun 10, 2024
bd31042
fix: add data-streams to test classpath
salvatore-campagna Jun 10, 2024
305ec41
fix: missing wildcard xpack module
salvatore-campagna Jun 10, 2024
b0be5b4
fix: use 'host.name' instead of 'hostname'
salvatore-campagna Jun 10, 2024
06d4ff7
checkstyle: line too long
salvatore-campagna Jun 10, 2024
d3b7cc8
checkstyle: line too long
salvatore-campagna Jun 10, 2024
5b797fc
test: disable test waiting for ignore_malformed support
salvatore-campagna Jun 11, 2024
a9b7a24
fix: synthetic source reconstruction artifacts
salvatore-campagna Jun 11, 2024
b9b28ad
nit: typo
salvatore-campagna Jun 11, 2024
d06c6be
fix: move logsdb java rest test to data-streams module are remove fea…
salvatore-campagna Jun 12, 2024
ebebe73
fix: license headers
salvatore-campagna Jun 12, 2024
2e72371
fix: remove unnecessary modules after moving tests to data-streams
salvatore-campagna Jun 12, 2024
1f21f76
fix: missing test files
salvatore-campagna Jun 12, 2024
399eee2
fix: remove test
salvatore-campagna Jun 12, 2024
c884c00
fix: no need for logs@custom
salvatore-campagna Jun 12, 2024
c1a2286
fix: rename test methods
salvatore-campagna Jun 12, 2024
448a0a5
Merge branch 'main' into feature/108762-feature-flag-logs-settings
salvatore-campagna Jun 12, 2024
813de46
fix: hostname to host.name
salvatore-campagna Jun 12, 2024
d009021
changelog: update summary
salvatore-campagna Jun 12, 2024
96760bd
fix: test alternate host mappings
salvatore-campagna Jun 13, 2024
0ba9e89
fix: use strict mapping
salvatore-campagna Jun 13, 2024
f3e1090
checkstyle: line too long
salvatore-campagna Jun 13, 2024
7ce8af0
fix: volatile to final
salvatore-campagna Jun 17, 2024
77b9a84
Merge branch 'main' into feature/108762-feature-flag-logs-settings
salvatore-campagna Jun 17, 2024
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
7 changes: 7 additions & 0 deletions docs/changelog/109025.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pr: 109025
summary: Introduce a feature flag and a setting controlling the activation of the
`logs` index mode
area: Logs
type: feature
issues:
- 108762
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class LogsDataStreamIT extends ESSingleNodeTestCase {
"@timestamp" : {
"type": "date"
},
"hostname": {
"host.name": {
"type": "keyword"
},
"pid": {
Expand All @@ -86,7 +86,7 @@ public class LogsDataStreamIT extends ESSingleNodeTestCase {
"@timestamp" : {
"type": "date"
},
"hostname": {
"host.name": {
"type": "keyword",
"time_series_dimension": "true"
},
Expand All @@ -110,7 +110,7 @@ public class LogsDataStreamIT extends ESSingleNodeTestCase {
private static final String LOG_DOC_TEMPLATE = """
{
"@timestamp": "%s",
"hostname": "%s",
"host.name": "%s",
"pid": "%d",
"method": "%s",
"message": "%s",
Expand All @@ -121,7 +121,7 @@ public class LogsDataStreamIT extends ESSingleNodeTestCase {
private static final String TIME_SERIES_DOC_TEMPLATE = """
{
"@timestamp": "%s",
"hostname": "%s",
"host.name": "%s",
"pid": "%d",
"method": "%s",
"ip_address": "%s",
Expand Down Expand Up @@ -207,7 +207,7 @@ public void testIndexModeLogsAndTimeSeriesSwitching() throws IOException, Execut
final String dataStreamName = generateDataStreamName("custom");
final List<String> indexPatterns = List.of("custom-*-*");
final Map<String, String> logsSettings = Map.of("index.mode", "logs");
final Map<String, String> timeSeriesSettings = Map.of("index.mode", "time_series", "index.routing_path", "hostname");
final Map<String, String> timeSeriesSettings = Map.of("index.mode", "time_series", "index.routing_path", "host.name");

putComposableIndexTemplate(client(), "custom-composable-template", LOGS_OR_STANDARD_MAPPING, logsSettings, indexPatterns);
createDataStream(client(), dataStreamName);
Expand All @@ -224,7 +224,7 @@ public void testIndexModeLogsAndTimeSeriesSwitching() throws IOException, Execut
assertDataStreamBackingIndicesModes(dataStreamName, List.of(IndexMode.LOGS, IndexMode.TIME_SERIES, IndexMode.LOGS));
}

public void testInvalidIndexModeTimeSeriesSwitchWithoutROutingPath() throws IOException, ExecutionException, InterruptedException {
public void testInvalidIndexModeTimeSeriesSwitchWithoutRoutingPath() throws IOException, ExecutionException, InterruptedException {
final String dataStreamName = generateDataStreamName("custom");
final List<String> indexPatterns = List.of("custom-*-*");
final Map<String, String> logsSettings = Map.of("index.mode", "logs");
Expand All @@ -250,7 +250,7 @@ public void testInvalidIndexModeTimeSeriesSwitchWithoutDimensions() throws IOExc
final String dataStreamName = generateDataStreamName("custom");
final List<String> indexPatterns = List.of("custom-*-*");
final Map<String, String> logsSettings = Map.of("index.mode", "logs");
final Map<String, String> timeSeriesSettings = Map.of("index.mode", "time_series", "index.routing_path", "hostname");
final Map<String, String> timeSeriesSettings = Map.of("index.mode", "time_series", "index.routing_path", "host.name");

putComposableIndexTemplate(client(), "custom-composable-template", LOGS_OR_STANDARD_MAPPING, logsSettings, indexPatterns);
createDataStream(client(), dataStreamName);
Expand All @@ -269,8 +269,9 @@ public void testInvalidIndexModeTimeSeriesSwitchWithoutDimensions() throws IOExc
assertThat(
exception.getCause().getCause().getMessage(),
Matchers.equalTo(
"All fields that match routing_path must be configured with [time_series_dimension: true] or flattened fields with "
+ "a list of dimensions in [time_series_dimensions] and without the [script] parameter. [hostname] was not a dimension."
"All fields that match routing_path must be configured with [time_series_dimension: true] or flattened fields "
+ "with a list of dimensions in [time_series_dimensions] and without the [script] parameter. [host.name] was not a "
+ "dimension."
)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private static void waitForLogs(RestClient client) throws Exception {
"@timestamp" : {
"type": "date"
},
"hostname": {
"host.name": {
"type": "keyword"
},
"pid": {
Expand Down Expand Up @@ -116,7 +116,7 @@ private static void waitForLogs(RestClient client) throws Exception {
"@timestamp" : {
"type": "date"
},
"hostname": {
"host.name": {
"type": "keyword",
"time_series_dimension": "true"
},
Expand All @@ -138,7 +138,7 @@ private static void waitForLogs(RestClient client) throws Exception {
private static final String DOC_TEMPLATE = """
{
"@timestamp": "%s",
"hostname": "%s",
"host.name": "%s",
"pid": "%d",
"method": "%s",
"message": "%s",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.datastreams.logsdb;

import org.elasticsearch.client.RestClient;
import org.elasticsearch.index.IndexMode;
import org.elasticsearch.test.cluster.ElasticsearchCluster;
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.ClassRule;

import java.io.IOException;

import static org.hamcrest.Matchers.equalTo;

public class LogsIndexModeDisabledRestTestIT extends LogsIndexModeRestTestIT {

@ClassRule()
public static ElasticsearchCluster cluster = ElasticsearchCluster.local()
.distribution(DistributionType.DEFAULT)
.module("constant-keyword")
.module("data-streams")
.module("mapper-extras")
.module("x-pack-aggregate-metric")
.module("x-pack-stack")
.setting("xpack.security.enabled", "false")
.setting("xpack.license.self_generated.type", "trial")
.build();

@Override
protected String getTestRestCluster() {
return cluster.getHttpAddresses();
}

@Before
public void setup() throws Exception {
client = client();
waitForLogs(client);
}

private RestClient client;

public void testLogsSettingsIndexModeDisabled() throws IOException {
assertOK(createDataStream(client, "logs-custom-dev"));
final String indexMode = (String) getSetting(client, getDataStreamBackingIndex(client, "logs-custom-dev", 0), "index.mode");
assertThat(indexMode, Matchers.not(equalTo(IndexMode.LOGS.getName())));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.datastreams.logsdb;

import org.elasticsearch.client.RestClient;
import org.elasticsearch.index.IndexMode;
import org.elasticsearch.test.cluster.ElasticsearchCluster;
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.ClassRule;

import java.io.IOException;

import static org.hamcrest.Matchers.equalTo;

public class LogsIndexModeEnabledRestTestIT extends LogsIndexModeRestTestIT {

@ClassRule()
public static ElasticsearchCluster cluster = ElasticsearchCluster.local()
.distribution(DistributionType.DEFAULT)
.module("constant-keyword")
.module("data-streams")
.module("mapper-extras")
.module("x-pack-aggregate-metric")
.module("x-pack-stack")
.setting("xpack.security.enabled", "false")
.setting("xpack.license.self_generated.type", "trial")
.setting("cluster.logsdb.enabled", "true")
.build();

@Override
protected String getTestRestCluster() {
return cluster.getHttpAddresses();
}

@Before
public void setup() throws Exception {
client = client();
waitForLogs(client);
}

private RestClient client;

private static final String MAPPINGS = """
{
"template": {
"mappings": {
"properties": {
"method": {
"type": "keyword"
},
"message": {
"type": "text"
}
}
}
}
}""";

private static String BULK_INDEX_REQUEST = """
{ "create": {}}
{ "@timestamp": "2023-01-01T05:11:00Z", "host.name": "foo", "method" : "PUT", "message": "foo put message" }
{ "create": {}}
{ "@timestamp": "2023-01-01T05:12:00Z", "host.name": "bar", "method" : "POST", "message": "bar post message" }
{ "create": {}}
{ "@timestamp": "2023-01-01T05:12:00Z", "host.name": "baz", "method" : "PUT", "message": "baz put message" }
{ "create": {}}
{ "@timestamp": "2023-01-01T05:13:00Z", "host.name": "baz", "method" : "PUT", "message": "baz put message" }
""";

public void testCreateDataStream() throws IOException {
assertOK(putComponentTemplate(client, "logs@custom", MAPPINGS));
assertOK(createDataStream(client, "logs-custom-dev"));
final String indexMode = (String) getSetting(client, getDataStreamBackingIndex(client, "logs-custom-dev", 0), "index.mode");
assertThat(indexMode, equalTo(IndexMode.LOGS.getName()));
}

public void testBulkIndexing() throws IOException {
assertOK(putComponentTemplate(client, "logs@custom", MAPPINGS));
assertOK(createDataStream(client, "logs-custom-dev"));
assertOK(bulkIndex(client, "logs-custom-dev", () -> BULK_INDEX_REQUEST));
}

public void testRolloverDataStream() throws IOException {
assertOK(putComponentTemplate(client, "logs@custom", MAPPINGS));
assertOK(createDataStream(client, "logs-custom-dev"));
final String firstBackingIndex = getDataStreamBackingIndex(client, "logs-custom-dev", 0);
assertOK(rolloverDataStream(client, "logs-custom-dev"));
final String secondBackingIndex = getDataStreamBackingIndex(client, "logs-custom-dev", 1);
assertThat(firstBackingIndex, Matchers.not(equalTo(secondBackingIndex)));
assertThat(getDataStreamBackingIndices(client, "logs-custom-dev").size(), equalTo(2));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.datastreams.logsdb;

import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.test.rest.ESRestTestCase;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public abstract class LogsIndexModeRestTestIT extends ESRestTestCase {
protected static void waitForLogs(RestClient client) throws Exception {
assertBusy(() -> {
try {
final Request request = new Request("GET", "_index_template/logs");
assertOK(client.performRequest(request));
} catch (ResponseException e) {
fail(e.getMessage());
}
});
}

protected static Response putComponentTemplate(final RestClient client, final String templateName, final String mappings)
throws IOException {
final Request request = new Request("PUT", "/_component_template/" + templateName);
request.setJsonEntity(mappings);
return client.performRequest(request);
}

protected static Response createDataStream(final RestClient client, final String dataStreamName) throws IOException {
return client.performRequest(new Request("PUT", "_data_stream/" + dataStreamName));
}

protected static Response rolloverDataStream(final RestClient client, final String dataStreamName) throws IOException {
return client.performRequest(new Request("POST", "/" + dataStreamName + "/_rollover"));
}

@SuppressWarnings("unchecked")
protected static String getDataStreamBackingIndex(final RestClient client, final String dataStreamName, int backingIndex)
throws IOException {
final Request request = new Request("GET", "_data_stream/" + dataStreamName);
final List<Object> dataStreams = (List<Object>) entityAsMap(client.performRequest(request)).get("data_streams");
final Map<String, Object> dataStream = (Map<String, Object>) dataStreams.get(0);
final List<Map<String, String>> backingIndices = (List<Map<String, String>>) dataStream.get("indices");
return backingIndices.get(backingIndex).get("index_name");
}

@SuppressWarnings("unchecked")
protected static List<String> getDataStreamBackingIndices(final RestClient client, final String dataStreamName) throws IOException {
final Request request = new Request("GET", "_data_stream/" + dataStreamName);
final List<Object> dataStreams = (List<Object>) entityAsMap(client.performRequest(request)).get("data_streams");
final Map<String, Object> dataStream = (Map<String, Object>) dataStreams.get(0);
final List<Map<String, String>> backingIndices = (List<Map<String, String>>) dataStream.get("indices");
return backingIndices.stream().map(map -> map.get("indices")).collect(Collectors.toList());
}

@SuppressWarnings("unchecked")
protected static Object getSetting(final RestClient client, final String indexName, final String setting) throws IOException {
final Request request = new Request("GET", "/" + indexName + "/_settings?flat_settings=true&include_defaults=true");
final Map<String, Object> settings = ((Map<String, Map<String, Object>>) entityAsMap(client.performRequest(request)).get(indexName))
.get("settings");

return settings.get(setting);
}

protected static Response bulkIndex(final RestClient client, final String dataStreamName, final Supplier<String> bulkSupplier)
throws IOException {
var bulkRequest = new Request("POST", "/" + dataStreamName + "/_bulk");
bulkRequest.setJsonEntity(bulkSupplier.get());
bulkRequest.addParameter("refresh", "true");
return client().performRequest(bulkRequest);
}
}
Loading