From 55727779c04f3817ce1d504cc62dceccb60b11d1 Mon Sep 17 00:00:00 2001
From: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com>
Date: Wed, 11 Dec 2024 12:21:48 -0500
Subject: [PATCH 01/46] [ML] Fixing streaming tests locale issue (#118481)
* Fixing the string locale
* Missing a toUpper
---
muted-tests.yml | 3 ---
.../src/main/java/org/elasticsearch/test/ESTestCase.java | 1 +
.../org/elasticsearch/xpack/inference/InferenceCrudIT.java | 7 +++++--
.../mock/TestStreamingCompletionServiceExtension.java | 5 +++--
4 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/muted-tests.yml b/muted-tests.yml
index c0e3c217abce2..9416113770d5a 100644
--- a/muted-tests.yml
+++ b/muted-tests.yml
@@ -315,9 +315,6 @@ tests:
- class: org.elasticsearch.xpack.test.rest.XPackRestIT
method: test {p0=migrate/10_reindex/Test Reindex With Unsupported Mode}
issue: https://github.com/elastic/elasticsearch/issues/118273
-- class: org.elasticsearch.xpack.inference.InferenceCrudIT
- method: testUnifiedCompletionInference
- issue: https://github.com/elastic/elasticsearch/issues/118405
- class: org.elasticsearch.xpack.security.operator.OperatorPrivilegesIT
method: testEveryActionIsEitherOperatorOnlyOrNonOperator
issue: https://github.com/elastic/elasticsearch/issues/118220
diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
index 6612f0da0c43f..f678f4af22328 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
@@ -1210,6 +1210,7 @@ public static String randomAlphaOfLength(int codeUnits) {
/**
* Generate a random string containing only alphanumeric characters.
+ * The locale for the string is {@link Locale#ROOT}.
* @param length the length of the string to generate
* @return the generated string
*/
diff --git a/x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/InferenceCrudIT.java b/x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/InferenceCrudIT.java
index 90d4f3a8eb33b..fc593a6a8b0fa 100644
--- a/x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/InferenceCrudIT.java
+++ b/x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/InferenceCrudIT.java
@@ -24,6 +24,7 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -471,7 +472,7 @@ public void testSupportedStream() throws Exception {
var events = streamInferOnMockService(modelId, TaskType.COMPLETION, input);
var expectedResponses = Stream.concat(
- input.stream().map(String::toUpperCase).map(str -> "{\"completion\":[{\"delta\":\"" + str + "\"}]}"),
+ input.stream().map(s -> s.toUpperCase(Locale.ROOT)).map(str -> "{\"completion\":[{\"delta\":\"" + str + "\"}]}"),
Stream.of("[DONE]")
).iterator();
assertThat(events.size(), equalTo((input.size() + 1) * 2));
@@ -510,7 +511,9 @@ public void testUnifiedCompletionInference() throws Exception {
}
private static Iterator expectedResultsIterator(List input) {
- return Stream.concat(input.stream().map(String::toUpperCase).map(InferenceCrudIT::expectedResult), Stream.of("[DONE]")).iterator();
+ // The Locale needs to be ROOT to match what the test service is going to respond with
+ return Stream.concat(input.stream().map(s -> s.toUpperCase(Locale.ROOT)).map(InferenceCrudIT::expectedResult), Stream.of("[DONE]"))
+ .iterator();
}
private static String expectedResult(String input) {
diff --git a/x-pack/plugin/inference/qa/test-service-plugin/src/main/java/org/elasticsearch/xpack/inference/mock/TestStreamingCompletionServiceExtension.java b/x-pack/plugin/inference/qa/test-service-plugin/src/main/java/org/elasticsearch/xpack/inference/mock/TestStreamingCompletionServiceExtension.java
index f7a05a27354ef..80696a285fb26 100644
--- a/x-pack/plugin/inference/qa/test-service-plugin/src/main/java/org/elasticsearch/xpack/inference/mock/TestStreamingCompletionServiceExtension.java
+++ b/x-pack/plugin/inference/qa/test-service-plugin/src/main/java/org/elasticsearch/xpack/inference/mock/TestStreamingCompletionServiceExtension.java
@@ -43,6 +43,7 @@
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Flow;
@@ -142,7 +143,7 @@ public void unifiedCompletionInfer(
}
private StreamingChatCompletionResults makeResults(List input) {
- var responseIter = input.stream().map(String::toUpperCase).iterator();
+ var responseIter = input.stream().map(s -> s.toUpperCase(Locale.ROOT)).iterator();
return new StreamingChatCompletionResults(subscriber -> {
subscriber.onSubscribe(new Flow.Subscription() {
@Override
@@ -173,7 +174,7 @@ private ChunkedToXContent completionChunk(String delta) {
}
private StreamingUnifiedChatCompletionResults makeUnifiedResults(UnifiedCompletionRequest request) {
- var responseIter = request.messages().stream().map(message -> message.content().toString().toUpperCase()).iterator();
+ var responseIter = request.messages().stream().map(message -> message.content().toString().toUpperCase(Locale.ROOT)).iterator();
return new StreamingUnifiedChatCompletionResults(subscriber -> {
subscriber.onSubscribe(new Flow.Subscription() {
@Override
From a8a4a7bc2348460bfa79fabc820e7b0a88907af1 Mon Sep 17 00:00:00 2001
From: Patrick Doyle <810052+prdoyle@users.noreply.github.com>
Date: Wed, 11 Dec 2024 12:35:30 -0500
Subject: [PATCH 02/46] Fix testInvalidJSON (#118398)
* Fix testInvalidJSON
* CURSE YOU SPOTLESS
---
muted-tests.yml | 3 -
.../service/FileSettingsServiceTests.java | 69 +++++++++----------
2 files changed, 31 insertions(+), 41 deletions(-)
diff --git a/muted-tests.yml b/muted-tests.yml
index 9416113770d5a..c07363657b3ec 100644
--- a/muted-tests.yml
+++ b/muted-tests.yml
@@ -123,9 +123,6 @@ tests:
- class: org.elasticsearch.xpack.downsample.ILMDownsampleDisruptionIT
method: testILMDownsampleRollingRestart
issue: https://github.com/elastic/elasticsearch/issues/114233
-- class: org.elasticsearch.reservedstate.service.FileSettingsServiceTests
- method: testInvalidJSON
- issue: https://github.com/elastic/elasticsearch/issues/116521
- class: org.elasticsearch.reservedstate.service.RepositoriesFileSettingsIT
method: testSettingsApplied
issue: https://github.com/elastic/elasticsearch/issues/116694
diff --git a/server/src/test/java/org/elasticsearch/reservedstate/service/FileSettingsServiceTests.java b/server/src/test/java/org/elasticsearch/reservedstate/service/FileSettingsServiceTests.java
index ae60a21b6fc22..08d83e48b7152 100644
--- a/server/src/test/java/org/elasticsearch/reservedstate/service/FileSettingsServiceTests.java
+++ b/server/src/test/java/org/elasticsearch/reservedstate/service/FileSettingsServiceTests.java
@@ -74,8 +74,10 @@
import static org.hamcrest.Matchers.hasEntry;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -288,63 +290,54 @@ public void testProcessFileChanges() throws Exception {
verifyNoMoreInteractions(healthIndicatorService);
}
- @SuppressWarnings("unchecked")
public void testInvalidJSON() throws Exception {
- doAnswer((Answer) invocation -> {
- invocation.getArgument(1, XContentParser.class).map(); // Throw if JSON is invalid
- ((Consumer) invocation.getArgument(3)).accept(null);
- return null;
- }).when(controller).process(any(), any(XContentParser.class), any(), any());
-
- CyclicBarrier fileChangeBarrier = new CyclicBarrier(2);
- fileSettingsService.addFileChangedListener(() -> awaitOrBust(fileChangeBarrier));
+ // Chop off the functionality so we don't run too much of the actual cluster logic that we're not testing
+ doNothing().when(controller).updateErrorState(any());
+ doAnswer(
+ (Answer) invocation -> { throw new AssertionError("Parse error should happen before this process method is called"); }
+ ).when(controller).process(any(), any(ReservedStateChunk.class), any(), any());
+ // Don't really care about the initial state
Files.createDirectories(fileSettingsService.watchedFileDir());
- // contents of the JSON don't matter, we just need a file to exist
- writeTestFile(fileSettingsService.watchedFile(), "{}");
+ doNothing().when(fileSettingsService).processInitialFileMissing();
+ fileSettingsService.start();
+ fileSettingsService.clusterChanged(new ClusterChangedEvent("test", clusterService.state(), ClusterState.EMPTY_STATE));
+ // Now break the JSON and wait
+ CyclicBarrier fileChangeBarrier = new CyclicBarrier(2);
doAnswer((Answer>) invocation -> {
- boolean returnedNormally = false;
try {
- var result = invocation.callRealMethod();
- returnedNormally = true;
- return result;
- } catch (XContentParseException e) {
- // We're expecting a parse error. processFileChanges specifies that this is supposed to throw ExecutionException.
- throw new ExecutionException(e);
- } catch (Throwable e) {
- throw new AssertionError("Unexpected exception", e);
+ return invocation.callRealMethod();
} finally {
- if (returnedNormally == false) {
- // Because of the exception, listeners aren't notified, so we need to activate the barrier ourselves
- awaitOrBust(fileChangeBarrier);
- }
+ awaitOrBust(fileChangeBarrier);
}
}).when(fileSettingsService).processFileChanges();
-
- // Establish the initial valid JSON
- fileSettingsService.start();
- fileSettingsService.clusterChanged(new ClusterChangedEvent("test", clusterService.state(), ClusterState.EMPTY_STATE));
- awaitOrBust(fileChangeBarrier);
-
- // Now break the JSON
writeTestFile(fileSettingsService.watchedFile(), "test_invalid_JSON");
awaitOrBust(fileChangeBarrier);
- verify(fileSettingsService, times(1)).processFileOnServiceStart(); // The initial state
- verify(fileSettingsService, times(1)).processFileChanges(); // The changed state
verify(fileSettingsService, times(1)).onProcessFileChangesException(
- argThat(e -> e instanceof ExecutionException && e.getCause() instanceof XContentParseException)
+ argThat(e -> unwrapException(e) instanceof XContentParseException)
);
// Note: the name "processFileOnServiceStart" is a bit misleading because it is not
// referring to fileSettingsService.start(). Rather, it is referring to the initialization
// of the watcher thread itself, which occurs asynchronously when clusterChanged is first called.
- verify(healthIndicatorService, times(2)).changeOccurred();
- verify(healthIndicatorService, times(1)).successOccurred();
- verify(healthIndicatorService, times(1)).failureOccurred(argThat(s -> s.startsWith(IllegalArgumentException.class.getName())));
- verifyNoMoreInteractions(healthIndicatorService);
+ verify(healthIndicatorService).failureOccurred(contains(XContentParseException.class.getName()));
+ }
+
+ /**
+ * Looks for the ultimate cause of {@code e} by stripping off layers of bookkeeping exception wrappers.
+ */
+ private Throwable unwrapException(Throwable e) {
+ while (e != null) {
+ if (e instanceof ExecutionException || e instanceof IllegalStateException) {
+ e = e.getCause();
+ } else {
+ break;
+ }
+ }
+ return e;
}
private static void awaitOrBust(CyclicBarrier barrier) {
From ae9bb90fd1ac229af2d960ace5f5d69eb4c352bf Mon Sep 17 00:00:00 2001
From: Marci W <333176+marciw@users.noreply.github.com>
Date: Wed, 11 Dec 2024 13:24:24 -0500
Subject: [PATCH 03/46] Update and edit logsdb docs for logsdb / synthetic
source GA (#118303)
* Update licensing; fix screenshots; edit generally
* Small edit for clarity and style
* Update docs/reference/index-modules.asciidoc
Co-authored-by: Liam Thompson <32779855+leemthompo@users.noreply.github.com>
* Apply changes from review
Co-authored-by: Liam Thompson <32779855+leemthompo@users.noreply.github.com>
* Address review comments
* Match similar change from review
* More changes from review
* Apply suggestions from review
Co-authored-by: shainaraskas <58563081+shainaraskas@users.noreply.github.com>
* Apply suggestions from review
Co-authored-by: shainaraskas <58563081+shainaraskas@users.noreply.github.com>
* Update docs/reference/data-streams/logs.asciidoc
Co-authored-by: shainaraskas <58563081+shainaraskas@users.noreply.github.com>
* Apply suggestions from review
Co-authored-by: shainaraskas <58563081+shainaraskas@users.noreply.github.com>
* Apply suggestions from review
* Change to general subscription note
* Apply suggestions from review
Co-authored-by: Oleksandr Kolomiiets
* Apply suggestions from review
Co-authored-by: Oleksandr Kolomiiets
* Apply suggestions from review; additional edits
* Apply suggestions from review; clarity tweaks
* Restore previous paragraph structure and context
---------
Co-authored-by: Liam Thompson <32779855+leemthompo@users.noreply.github.com>
Co-authored-by: shainaraskas <58563081+shainaraskas@users.noreply.github.com>
Co-authored-by: Oleksandr Kolomiiets
---
docs/reference/data-streams/logs.asciidoc | 197 +++++++++---------
docs/reference/data-streams/tsds.asciidoc | 2 +-
.../management-data-stream-fields.png | Bin 0 -> 251799 bytes
.../index-mgmt/management-data-stream.png | Bin 751333 -> 0 bytes
.../index-mgmt/management-index-templates.png | Bin 130766 -> 203626 bytes
docs/reference/index-modules.asciidoc | 5 +-
docs/reference/indices/index-mgmt.asciidoc | 2 +-
.../indices/put-index-template.asciidoc | 6 +-
.../mapping/fields/synthetic-source.asciidoc | 11 +-
9 files changed, 112 insertions(+), 111 deletions(-)
create mode 100644 docs/reference/images/index-mgmt/management-data-stream-fields.png
delete mode 100644 docs/reference/images/index-mgmt/management-data-stream.png
diff --git a/docs/reference/data-streams/logs.asciidoc b/docs/reference/data-streams/logs.asciidoc
index 6bb98684544a3..3af5e09889a89 100644
--- a/docs/reference/data-streams/logs.asciidoc
+++ b/docs/reference/data-streams/logs.asciidoc
@@ -1,18 +1,20 @@
[[logs-data-stream]]
== Logs data stream
-preview::[Logs data streams and the logsdb index mode are in tech preview and may be changed or removed in the future. Don't use logs data streams or logsdb index mode in production.]
+IMPORTANT: The {es} `logsdb` index mode is generally available in Elastic Cloud Hosted
+and self-managed Elasticsearch as of version 8.17, and is enabled by default for
+logs in https://www.elastic.co/elasticsearch/serverless[{serverless-full}].
A logs data stream is a data stream type that stores log data more efficiently.
In benchmarks, log data stored in a logs data stream used ~2.5 times less disk space than a regular data
-stream. The exact impact will vary depending on your data set.
+stream. The exact impact varies by data set.
[discrete]
[[how-to-use-logsds]]
=== Create a logs data stream
-To create a logs data stream, set your index template `index.mode` to `logsdb`:
+To create a logs data stream, set your <> `index.mode` to `logsdb`:
[source,console]
----
@@ -31,10 +33,12 @@ PUT _index_template/my-index-template
// TEST
<1> The index mode setting.
-<2> The index template priority. By default, Elasticsearch ships with an index template with a `logs-*-*` pattern with a priority of 100. You need to define a priority higher than 100 to ensure that this index template gets selected over the default index template for the `logs-*-*` pattern. See the <> for more information.
+<2> The index template priority. By default, Elasticsearch ships with a `logs-*-*` index template with a priority of 100. To make sure your index template takes priority over the default `logs-*-*` template, set its `priority` to a number higher than 100. For more information, see <>.
After the index template is created, new indices that use the template will be configured as a logs data stream. You can start indexing data and <>.
+You can also set the index mode and adjust other template settings in <>.
+
////
[source,console]
----
@@ -46,154 +50,159 @@ DELETE _index_template/my-index-template
[[logsdb-default-settings]]
[discrete]
-[[logsdb-synthtic-source]]
+[[logsdb-synthetic-source]]
=== Synthetic source
-By default, `logsdb` mode uses <>, which omits storing the original `_source`
-field and synthesizes it from doc values or stored fields upon document retrieval. Synthetic source comes with a few
-restrictions which you can read more about in the <> section dedicated to it.
+If you have the required https://www.elastic.co/subscriptions[subscription], `logsdb` index mode uses <>, which omits storing the original `_source`
+field. Instead, the document source is synthesized from doc values or stored fields upon document retrieval.
-NOTE: When dealing with multi-value fields, the `index.mapping.synthetic_source_keep` setting controls how field values
-are preserved for <> reconstruction. In `logsdb`, the default value is `arrays`,
-which retains both duplicate values and the order of entries but not necessarily the exact structure when it comes to
-array elements or objects. Preserving duplicates and ordering could be critical for some log fields. This could be the
-case, for instance, for DNS A records, HTTP headers, or log entries that represent sequential or repeated events.
+If you don't have the required https://www.elastic.co/subscriptions[subscription], `logsdb` mode uses the original `_source` field.
-For more details on this setting and ways to refine or bypass it, check out <>.
+Before using synthetic source, make sure to review the <>.
+
+When working with multi-value fields, the `index.mapping.synthetic_source_keep` setting controls how field values
+are preserved for <> reconstruction. In `logsdb`, the default value is `arrays`,
+which retains both duplicate values and the order of entries. However, the exact structure of
+array elements and objects is not necessarily retained. Preserving duplicates and ordering can be critical for some
+log fields, such as DNS A records, HTTP headers, and log entries that represent sequential or repeated events.
[discrete]
[[logsdb-sort-settings]]
=== Index sort settings
-The following settings are applied by default when using the `logsdb` mode for index sorting:
+In `logsdb` index mode, the following sort settings are applied by default:
-* `index.sort.field`: `["host.name", "@timestamp"]`
- In `logsdb` mode, indices are sorted by `host.name` and `@timestamp` fields by default. For data streams, the
- `@timestamp` field is automatically injected if it is not present.
+`index.sort.field`: `["host.name", "@timestamp"]`::
+Indices are sorted by `host.name` and `@timestamp` by default. The `@timestamp` field is automatically injected if it is not present.
-* `index.sort.order`: `["desc", "desc"]`
- The default sort order for both fields is descending (`desc`), prioritizing the latest data.
+`index.sort.order`: `["desc", "desc"]`::
+Both `host.name` and `@timestamp` are sorted in descending (`desc`) order, prioritizing the latest data.
-* `index.sort.mode`: `["min", "min"]`
- The default sort mode is `min`, ensuring that indices are sorted by the minimum value of multi-value fields.
+`index.sort.mode`: `["min", "min"]`::
+The `min` mode sorts indices by the minimum value of multi-value fields.
-* `index.sort.missing`: `["_first", "_first"]`
- Missing values are sorted to appear first (`_first`) in `logsdb` index mode.
+`index.sort.missing`: `["_first", "_first"]`::
+Missing values are sorted to appear `_first`.
-`logsdb` index mode allows users to override the default sort settings. For instance, users can specify their own fields
-and order for sorting by modifying the `index.sort.field` and `index.sort.order`.
+You can override these default sort settings. For example, to sort on different fields
+and change the order, manually configure `index.sort.field` and `index.sort.order`. For more details, see
+<>.
-When using default sort settings, the `host.name` field is automatically injected into the mappings of the
-index as a `keyword` field to ensure that sorting can be applied. This guarantees that logs are efficiently sorted and
-retrieved based on the `host.name` and `@timestamp` fields.
+When using the default sort settings, the `host.name` field is automatically injected into the index mappings as a `keyword` field to ensure that sorting can be applied. This guarantees that logs are efficiently sorted and retrieved based on the `host.name` and `@timestamp` fields.
-NOTE: If `subobjects` is set to `true` (which is the default), the `host.name` field will be mapped as an object field
-named `host`, containing a `name` child field of type `keyword`. On the other hand, if `subobjects` is set to `false`,
-a single `host.name` field will be mapped as a `keyword` field.
+NOTE: If `subobjects` is set to `true` (default), the `host` field is mapped as an object field
+named `host` with a `name` child field of type `keyword`. If `subobjects` is set to `false`,
+a single `host.name` field is mapped as a `keyword` field.
-Once an index is created, the sort settings are immutable and cannot be modified. To apply different sort settings,
-a new index must be created with the desired configuration. For data streams, this can be achieved by means of an index
-rollover after updating relevant (component) templates.
+To apply different sort settings to an existing data stream, update the data stream's component templates, and then
+perform or wait for a <>.
-If the default sort settings are not suitable for your use case, consider modifying them. Keep in mind that sort
-settings can influence indexing throughput, query latency, and may affect compression efficiency due to the way data
-is organized after sorting. For more details, refer to our documentation on
-<>.
-
-NOTE: For <>, the `@timestamp` field is automatically injected if not already present.
-However, if custom sort settings are applied, the `@timestamp` field is injected into the mappings, but it is not
+NOTE: In `logsdb` mode, the `@timestamp` field is automatically injected if it's not already present. If you apply custom sort settings, the `@timestamp` field is injected into the mappings but is not
automatically added to the list of sort fields.
[discrete]
-[[logsdb-specialized-codecs]]
-=== Specialized codecs
+[[logsdb-host-name]]
+==== Existing data streams
-`logsdb` index mode uses the `best_compression` <> by default, which applies {wikipedia}/Zstd[ZSTD]
-compression to stored fields. Users are allowed to override it and switch to the `default` codec for faster compression
-at the expense of slightly larger storage footprint.
+If you're enabling `logsdb` index mode on a data stream that already exists, make sure to check mappings and sorting. The `logsdb` mode automatically maps `host.name` as a keyword if it's included in the sort settings. If a `host.name` field already exists but has a different type, mapping errors might occur, preventing `logsdb` mode from being fully applied.
-`logsdb` index mode also adopts specialized codecs for numeric doc values that are crafted to optimize storage usage.
-Users can rely on these specialized codecs being applied by default when using `logsdb` index mode.
+To avoid mapping conflicts, consider these options:
-Doc values encoding for numeric fields in `logsdb` follows a static sequence of codecs, applying each one in the
-following order: delta encoding, offset encoding, Greatest Common Divisor GCD encoding, and finally Frame Of Reference
-(FOR) encoding. The decision to apply each encoding is based on heuristics determined by the data distribution.
-For example, before applying delta encoding, the algorithm checks if the data is monotonically non-decreasing or
-non-increasing. If the data fits this pattern, delta encoding is applied; otherwise, the next encoding is considered.
+* **Adjust mappings:** Check your existing mappings to ensure that `host.name` is mapped as a keyword.
-The encoding is specific to each Lucene segment and is also re-applied at segment merging time. The merged Lucene segment
-may use a different encoding compared to the original Lucene segments, based on the characteristics of the merged data.
+* **Change sorting:** If needed, you can remove `host.name` from the sort settings and use a different set of fields. Sorting by `@timestamp` can be a good fallback.
+
+* **Switch to a different <>**: If resolving `host.name` mapping conflicts is not feasible, you can choose not to use `logsdb` mode.
+
+IMPORTANT: On existing data streams, `logsdb` mode is applied on <> (automatic or manual).
+
+[discrete]
+[[logsdb-specialized-codecs]]
+=== Specialized codecs
-The following methods are applied sequentially:
+By default, `logsdb` index mode uses the `best_compression` <>, which applies {wikipedia}/Zstd[ZSTD]
+compression to stored fields. You can switch to the `default` codec for faster compression with a slightly larger storage footprint.
+
+The `logsdb` index mode also automatically applies specialized codecs for numeric doc values, in order to optimize storage usage. Numeric fields are
+encoded using the following sequence of codecs:
* **Delta encoding**:
- a compression method that stores the difference between consecutive values instead of the actual values.
+ Stores the difference between consecutive values instead of the actual values.
* **Offset encoding**:
- a compression method that stores the difference from a base value rather than between consecutive values.
+ Stores the difference from a base value rather than between consecutive values.
* **Greatest Common Divisor (GCD) encoding**:
- a compression method that finds the greatest common divisor of a set of values and stores the differences
- as multiples of the GCD.
+ Finds the greatest common divisor of a set of values and stores the differences as multiples of the GCD.
* **Frame Of Reference (FOR) encoding**:
- a compression method that determines the smallest number of bits required to encode a block of values and uses
+ Determines the smallest number of bits required to encode a block of values and uses
bit-packing to fit such values into larger 64-bit blocks.
+Each encoding is evaluated according to heuristics determined by the data distribution.
+For example, the algorithm checks whether the data is monotonically non-decreasing or
+non-increasing. If so, delta encoding is applied; otherwise, the process
+continues with the next encoding method (offset).
+
+Encoding is specific to each Lucene segment and is reapplied when segments are merged. The merged Lucene segment
+might use a different encoding than the original segments, depending on the characteristics of the merged data.
+
For keyword fields, **Run Length Encoding (RLE)** is applied to the ordinals, which represent positions in the Lucene
segment-level keyword dictionary. This compression is used when multiple consecutive documents share the same keyword.
[discrete]
[[logsdb-ignored-settings]]
-=== `ignore_malformed`, `ignore_above`, `ignore_dynamic_beyond_limit`
+=== `ignore` settings
+
+The `logsdb` index mode uses the following `ignore` settings. You can override these settings as needed.
+
+[discrete]
+[[logsdb-ignore-malformed]]
+==== `ignore_malformed`
-By default, `logsdb` index mode sets `ignore_malformed` to `true`. This setting allows documents with malformed fields
-to be indexed without causing indexing failures, ensuring that log data ingestion continues smoothly even when some
-fields contain invalid or improperly formatted data.
+By default, `logsdb` index mode sets `ignore_malformed` to `true`. With this setting, documents with malformed fields
+can be indexed without causing ingestion failures.
-Users can override this setting by setting `index.mapping.ignore_malformed` to `false`. However, this is not recommended
-as it might result in documents with malformed fields being rejected and not indexed at all.
+[discrete]
+[[logs-db-ignore-above]]
+==== `ignore_above`
In `logsdb` index mode, the `index.mapping.ignore_above` setting is applied by default at the index level to ensure
-efficient storage and indexing of large keyword fields.The index-level default for `ignore_above` is set to 8191
-**characters**. If using UTF-8 encoding, this results in a limit of 32764 bytes, depending on character encoding.
-The mapping-level `ignore_above` setting still takes precedence. If a specific field has an `ignore_above` value
-defined in its mapping, that value will override the index-level `index.mapping.ignore_above` value. This default
-behavior helps to optimize indexing performance by preventing excessively large string values from being indexed, while
-still allowing users to customize the limit, overriding it at the mapping level or changing the index level default
-setting.
+efficient storage and indexing of large keyword fields.The index-level default for `ignore_above` is 8191
+_characters._ Using UTF-8 encoding, this results in a limit of 32764 bytes, depending on character encoding.
+
+The mapping-level `ignore_above` setting takes precedence. If a specific field has an `ignore_above` value
+defined in its mapping, that value overrides the index-level `index.mapping.ignore_above` value. This default
+behavior helps to optimize indexing performance by preventing excessively large string values from being indexed.
+
+If you need to customize the limit, you can override it at the mapping level or change the index level default.
+
+[discrete]
+[[logs-db-ignore-limit]]
+==== `ignore_dynamic_beyond_limit`
In `logsdb` index mode, the setting `index.mapping.total_fields.ignore_dynamic_beyond_limit` is set to `true` by
-default. This allows dynamically mapped fields to be added on top of statically defined fields without causing document
-rejection, even after the total number of fields exceeds the limit defined by `index.mapping.total_fields.limit`. The
-`index.mapping.total_fields.limit` setting specifies the maximum number of fields an index can have (static, dynamic
-and runtime). When the limit is reached, new dynamically mapped fields will be ignored instead of failing the document
-indexing, ensuring continued log ingestion without errors.
+default. This setting allows dynamically mapped fields to be added on top of statically defined fields, even when the total number of fields exceeds the `index.mapping.total_fields.limit`. Instead of triggering an index failure, additional dynamically mapped fields are ignored so that ingestion can continue.
-NOTE: When automatically injected, `host.name` and `@timestamp` contribute to the limit of mapped fields. When
-`host.name` is mapped with `subobjects: true` it consists of two fields. When `host.name` is mapped with
-`subobjects: false` it only consists of one field.
+NOTE: When automatically injected, `host.name` and `@timestamp` count toward the limit of mapped fields. If `host.name` is mapped with `subobjects: true`, it has two fields. When mapped with `subobjects: false`, `host.name` has only one field.
[discrete]
[[logsdb-nodocvalue-fields]]
-=== Fields without doc values
+=== Fields without `doc_values`
-When `logsdb` index mode uses synthetic `_source`, and `doc_values` are disabled for a field in the mapping,
-Elasticsearch may set the `store` setting to `true` for that field as a last resort option to ensure that the field's
-data is still available for reconstructing the document’s source when retrieving it via
+When the `logsdb` index mode uses synthetic `_source` and `doc_values` are disabled for a field in the mapping,
+{es} might set the `store` setting to `true` for that field. This ensures that the field's
+data remains accessible for reconstructing the document's source when using
<>.
-For example, this happens with text fields when `store` is `false` and there is no suitable multi-field available to
-reconstruct the original value in <>.
-
-This automatic adjustment allows synthetic source to work correctly, even when doc values are not enabled for certain
-fields.
+For example, this adjustment occurs with text fields when `store` is `false` and no suitable multi-field is available for
+reconstructing the original value.
[discrete]
[[logsdb-settings-summary]]
-=== LogsDB settings summary
+=== Settings reference
-The following is a summary of key settings that apply when using `logsdb` index mode in Elasticsearch:
+The `logsdb` index mode uses the following settings:
* **`index.mode`**: `"logsdb"`
diff --git a/docs/reference/data-streams/tsds.asciidoc b/docs/reference/data-streams/tsds.asciidoc
index d0d6d4a455c63..1e1d56e5b4d93 100644
--- a/docs/reference/data-streams/tsds.asciidoc
+++ b/docs/reference/data-streams/tsds.asciidoc
@@ -17,7 +17,7 @@ metrics data. Only use a TSDS if you typically add metrics data to {es} in near
real-time and `@timestamp` order.
A TSDS is only intended for metrics data. For other timestamped data, such as
-logs or traces, use a regular data stream.
+logs or traces, use a <> or regular data stream.
[discrete]
[[differences-from-regular-data-stream]]
diff --git a/docs/reference/images/index-mgmt/management-data-stream-fields.png b/docs/reference/images/index-mgmt/management-data-stream-fields.png
new file mode 100644
index 0000000000000000000000000000000000000000..605d49b80ab1fbaf0bc65706fc740f236bf929ac
GIT binary patch
literal 251799
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