|
@@ -57,6 +57,8 @@ import org.elasticsearch.common.settings.Settings;
|
|
|
import org.elasticsearch.common.xcontent.ObjectPath;
|
|
|
import org.elasticsearch.common.xcontent.XContentType;
|
|
|
import org.elasticsearch.index.IndexNotFoundException;
|
|
|
+import org.elasticsearch.index.mapper.DateFieldMapper;
|
|
|
+import org.elasticsearch.index.mapper.MapperParsingException;
|
|
|
import org.elasticsearch.rest.RestStatus;
|
|
|
import org.elasticsearch.test.ESIntegTestCase;
|
|
|
import org.junit.After;
|
|
@@ -66,8 +68,9 @@ import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Comparator;
|
|
|
import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
+import java.util.Locale;
|
|
|
import java.util.Optional;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
import static org.elasticsearch.indices.IndicesOptionsIntegrationIT._flush;
|
|
|
import static org.elasticsearch.indices.IndicesOptionsIntegrationIT.clearCache;
|
|
@@ -144,9 +147,9 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
assertThat(ObjectPath.eval("properties.@timestamp1.type", mappings), is("date"));
|
|
|
|
|
|
int numDocsBar = randomIntBetween(2, 16);
|
|
|
- indexDocs("metrics-bar", numDocsBar);
|
|
|
+ indexDocs("metrics-bar", "@timestamp2", numDocsBar);
|
|
|
int numDocsFoo = randomIntBetween(2, 16);
|
|
|
- indexDocs("metrics-foo", numDocsFoo);
|
|
|
+ indexDocs("metrics-foo", "@timestamp1", numDocsFoo);
|
|
|
|
|
|
verifyDocs("metrics-bar", numDocsBar, 1, 1);
|
|
|
verifyDocs("metrics-foo", numDocsFoo, 1, 1);
|
|
@@ -174,9 +177,9 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
assertThat(ObjectPath.eval("properties.@timestamp2.type", mappings), is("date"));
|
|
|
|
|
|
int numDocsBar2 = randomIntBetween(2, 16);
|
|
|
- indexDocs("metrics-bar", numDocsBar2);
|
|
|
+ indexDocs("metrics-bar", "@timestamp2", numDocsBar2);
|
|
|
int numDocsFoo2 = randomIntBetween(2, 16);
|
|
|
- indexDocs("metrics-foo", numDocsFoo2);
|
|
|
+ indexDocs("metrics-foo", "@timestamp1", numDocsFoo2);
|
|
|
|
|
|
verifyDocs("metrics-bar", numDocsBar + numDocsBar2, 1, 2);
|
|
|
verifyDocs("metrics-foo", numDocsFoo + numDocsFoo2, 1, 2);
|
|
@@ -208,7 +211,7 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
|
|
|
{
|
|
|
BulkRequest bulkRequest = new BulkRequest()
|
|
|
- .add(new IndexRequest(dataStreamName).source("{}", XContentType.JSON));
|
|
|
+ .add(new IndexRequest(dataStreamName).source("{\"@timestamp1\": \"2020-12-12\"}", XContentType.JSON));
|
|
|
expectFailure(dataStreamName, () -> client().bulk(bulkRequest).actionGet());
|
|
|
}
|
|
|
{
|
|
@@ -218,11 +221,12 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
}
|
|
|
{
|
|
|
BulkRequest bulkRequest = new BulkRequest()
|
|
|
- .add(new UpdateRequest(dataStreamName, "_id").doc("{}", XContentType.JSON));
|
|
|
+ .add(new UpdateRequest(dataStreamName, "_id").doc("{\"@timestamp1\": \"2020-12-12\"}", XContentType.JSON));
|
|
|
expectFailure(dataStreamName, () -> client().bulk(bulkRequest).actionGet());
|
|
|
}
|
|
|
{
|
|
|
- IndexRequest indexRequest = new IndexRequest(dataStreamName).source("{}", XContentType.JSON);
|
|
|
+ IndexRequest indexRequest = new IndexRequest(dataStreamName)
|
|
|
+ .source("{\"@timestamp1\": \"2020-12-12\"}", XContentType.JSON);
|
|
|
expectFailure(dataStreamName, () -> client().index(indexRequest).actionGet());
|
|
|
}
|
|
|
{
|
|
@@ -235,14 +239,15 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
expectFailure(dataStreamName, () -> client().delete(deleteRequest).actionGet());
|
|
|
}
|
|
|
{
|
|
|
- IndexRequest indexRequest = new IndexRequest(dataStreamName).source("{}", XContentType.JSON)
|
|
|
+ IndexRequest indexRequest = new IndexRequest(dataStreamName)
|
|
|
+ .source("{\"@timestamp1\": \"2020-12-12\"}", XContentType.JSON)
|
|
|
.opType(DocWriteRequest.OpType.CREATE);
|
|
|
IndexResponse indexResponse = client().index(indexRequest).actionGet();
|
|
|
assertThat(indexResponse.getIndex(), equalTo(DataStream.getDefaultBackingIndexName(dataStreamName, 1)));
|
|
|
}
|
|
|
{
|
|
|
BulkRequest bulkRequest = new BulkRequest()
|
|
|
- .add(new IndexRequest(dataStreamName).source("{}", XContentType.JSON)
|
|
|
+ .add(new IndexRequest(dataStreamName).source("{\"@timestamp1\": \"2020-12-12\"}", XContentType.JSON)
|
|
|
.opType(DocWriteRequest.OpType.CREATE));
|
|
|
BulkResponse bulkItemResponses = client().bulk(bulkRequest).actionGet();
|
|
|
assertThat(bulkItemResponses.getItems()[0].getIndex(), equalTo(DataStream.getDefaultBackingIndexName(dataStreamName, 1)));
|
|
@@ -279,7 +284,7 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
client().execute(PutComposableIndexTemplateAction.INSTANCE, request).actionGet();
|
|
|
|
|
|
int numDocs = randomIntBetween(2, 16);
|
|
|
- indexDocs(dataStreamName, numDocs);
|
|
|
+ indexDocs(dataStreamName, "@timestamp", numDocs);
|
|
|
verifyDocs(dataStreamName, numDocs, 1, 1);
|
|
|
|
|
|
String backingIndex = DataStream.getDefaultBackingIndexName(dataStreamName, 1);
|
|
@@ -310,7 +315,7 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
getIndexResponse.mappings().get(backingIndex).getSourceAsMap()), equalTo("keyword"));
|
|
|
|
|
|
int numDocs2 = randomIntBetween(2, 16);
|
|
|
- indexDocs(dataStreamName, numDocs2);
|
|
|
+ indexDocs(dataStreamName, "@timestamp", numDocs2);
|
|
|
verifyDocs(dataStreamName, numDocs + numDocs2, 1, 2);
|
|
|
|
|
|
DeleteDataStreamAction.Request deleteDataStreamRequest = new DeleteDataStreamAction.Request(dataStreamName);
|
|
@@ -373,7 +378,7 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
client().admin().indices().createDataStream(request).actionGet();
|
|
|
|
|
|
verifyResolvability(dataStreamName, client().prepareIndex(dataStreamName)
|
|
|
- .setSource("{}", XContentType.JSON)
|
|
|
+ .setSource("{\"ts\": \"2020-12-12\"}", XContentType.JSON)
|
|
|
.setOpType(DocWriteRequest.OpType.CREATE),
|
|
|
false);
|
|
|
verifyResolvability(dataStreamName, refreshBuilder(dataStreamName), false);
|
|
@@ -406,7 +411,7 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
request = new CreateDataStreamAction.Request("logs-barbaz");
|
|
|
client().admin().indices().createDataStream(request).actionGet();
|
|
|
verifyResolvability("logs-barbaz", client().prepareIndex("logs-barbaz")
|
|
|
- .setSource("{}", XContentType.JSON)
|
|
|
+ .setSource("{\"ts\": \"2020-12-12\"}", XContentType.JSON)
|
|
|
.setOpType(DocWriteRequest.OpType.CREATE),
|
|
|
false);
|
|
|
|
|
@@ -496,7 +501,8 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
putComposableIndexTemplate("id1", "@timestamp", List.of("logs-foo*"));
|
|
|
|
|
|
// Index doc that triggers creation of a data stream
|
|
|
- IndexRequest indexRequest = new IndexRequest("logs-foobar").source("{}", XContentType.JSON).opType("create");
|
|
|
+ IndexRequest indexRequest =
|
|
|
+ new IndexRequest("logs-foobar").source("{\"@timestamp\": \"2020-12-12\"}", XContentType.JSON).opType("create");
|
|
|
IndexResponse indexResponse = client().index(indexRequest).actionGet();
|
|
|
assertThat(indexResponse.getIndex(), equalTo(DataStream.getDefaultBackingIndexName("logs-foobar", 1)));
|
|
|
assertBackingIndex(DataStream.getDefaultBackingIndexName("logs-foobar", 1), "properties.@timestamp");
|
|
@@ -508,7 +514,7 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
assertBackingIndex(DataStream.getDefaultBackingIndexName("logs-foobar", 2), "properties.@timestamp");
|
|
|
|
|
|
// Index another doc into a data stream
|
|
|
- indexRequest = new IndexRequest("logs-foobar").source("{}", XContentType.JSON).opType("create");
|
|
|
+ indexRequest = new IndexRequest("logs-foobar").source("{\"@timestamp\": \"2020-12-12\"}", XContentType.JSON).opType("create");
|
|
|
indexResponse = client().index(indexRequest).actionGet();
|
|
|
assertThat(indexResponse.getIndex(), equalTo(DataStream.getDefaultBackingIndexName("logs-foobar", 2)));
|
|
|
|
|
@@ -523,7 +529,7 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
assertBackingIndex(DataStream.getDefaultBackingIndexName("logs-foobar", 3), "properties.@timestamp");
|
|
|
|
|
|
// Index another doc into a data stream
|
|
|
- indexRequest = new IndexRequest("logs-foobar").source("{}", XContentType.JSON).opType("create");
|
|
|
+ indexRequest = new IndexRequest("logs-foobar").source("{\"@timestamp\": \"2020-12-12\"}", XContentType.JSON).opType("create");
|
|
|
indexResponse = client().index(indexRequest).actionGet();
|
|
|
assertThat(indexResponse.getIndex(), equalTo(DataStream.getDefaultBackingIndexName("logs-foobar", 3)));
|
|
|
|
|
@@ -575,8 +581,7 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
" \"format\": \"yyyy-MM\",\n" +
|
|
|
" \"meta\": {\n" +
|
|
|
" \"x\": \"y\"\n" +
|
|
|
- " },\n" +
|
|
|
- " \"store\": true\n" +
|
|
|
+ " }\n" +
|
|
|
" }\n" +
|
|
|
" }\n" +
|
|
|
" }";
|
|
@@ -589,7 +594,7 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
assertThat(getDataStreamResponse.getDataStreams().size(), equalTo(1));
|
|
|
assertThat(getDataStreamResponse.getDataStreams().get(0).getName(), equalTo("logs-foobar"));
|
|
|
assertThat(getDataStreamResponse.getDataStreams().get(0).getTimeStampField().getName(), equalTo("@timestamp"));
|
|
|
- Map<?, ?> expectedTimestampMapping = Map.of("type", "date", "format", "yyyy-MM", "meta", Map.of("x", "y"), "store", true);
|
|
|
+ Map<?, ?> expectedTimestampMapping = Map.of("type", "date", "format", "yyyy-MM", "meta", Map.of("x", "y"));
|
|
|
assertThat(getDataStreamResponse.getDataStreams().get(0).getTimeStampField().getFieldMapping(), equalTo(expectedTimestampMapping));
|
|
|
assertBackingIndex(DataStream.getDefaultBackingIndexName("logs-foobar", 1), "properties.@timestamp", expectedTimestampMapping);
|
|
|
|
|
@@ -617,13 +622,15 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
assertThat(rolloverResponse.getNewIndex(), equalTo(backingIndex2));
|
|
|
assertTrue(rolloverResponse.isRolledOver());
|
|
|
|
|
|
- Map<?, ?> expectedMapping = Map.of("properties", Map.of("@timestamp", Map.of("type", "date")));
|
|
|
+ Map<?, ?> expectedMapping =
|
|
|
+ Map.of("properties", Map.of("@timestamp", Map.of("type", "date")), "_timestamp", Map.of("path", "@timestamp"));
|
|
|
GetMappingsResponse getMappingsResponse = getMapping("logs-foobar").get();
|
|
|
assertThat(getMappingsResponse.getMappings().size(), equalTo(2));
|
|
|
assertThat(getMappingsResponse.getMappings().get(backingIndex1).getSourceAsMap(), equalTo(expectedMapping));
|
|
|
assertThat(getMappingsResponse.getMappings().get(backingIndex2).getSourceAsMap(), equalTo(expectedMapping));
|
|
|
|
|
|
- expectedMapping = Map.of("properties", Map.of("@timestamp", Map.of("type", "date"), "my_field", Map.of("type", "keyword")));
|
|
|
+ expectedMapping = Map.of("properties", Map.of("@timestamp", Map.of("type", "date"), "my_field", Map.of("type", "keyword")),
|
|
|
+ "_timestamp", Map.of("path", "@timestamp"));
|
|
|
putMapping("{\"properties\":{\"my_field\":{\"type\":\"keyword\"}}}", "logs-foobar").get();
|
|
|
// The mappings of all backing indices should be updated:
|
|
|
getMappingsResponse = getMapping("logs-foobar").get();
|
|
@@ -662,7 +669,8 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
|
|
|
// Index doc that triggers creation of a data stream
|
|
|
String dataStream = "logs-foobar";
|
|
|
- IndexRequest indexRequest = new IndexRequest(dataStream).source("{}", XContentType.JSON).opType(DocWriteRequest.OpType.CREATE);
|
|
|
+ IndexRequest indexRequest = new IndexRequest(dataStream).source("{\"@timestamp\": \"2020-12-12\"}", XContentType.JSON)
|
|
|
+ .opType(DocWriteRequest.OpType.CREATE);
|
|
|
IndexResponse indexResponse = client().index(indexRequest).actionGet();
|
|
|
assertThat(indexResponse.getIndex(), equalTo(DataStream.getDefaultBackingIndexName(dataStream, 1)));
|
|
|
|
|
@@ -696,7 +704,8 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
putComposableIndexTemplate("id1", "@timestamp", List.of("logs-foo*"));
|
|
|
|
|
|
// Index doc that triggers creation of a data stream
|
|
|
- IndexRequest indexRequest = new IndexRequest("logs-foobar").source("{}", XContentType.JSON).opType(DocWriteRequest.OpType.CREATE);
|
|
|
+ IndexRequest indexRequest = new IndexRequest("logs-foobar").source("{\"@timestamp\": \"2020-12-12\"}", XContentType.JSON)
|
|
|
+ .opType(DocWriteRequest.OpType.CREATE);
|
|
|
IndexResponse indexResponse = client().index(indexRequest).actionGet();
|
|
|
assertThat(indexResponse.getIndex(), equalTo(DataStream.getDefaultBackingIndexName("logs-foobar", 1)));
|
|
|
|
|
@@ -721,6 +730,33 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
assertThat(ObjectPath.eval(timestampFieldPathInMapping, mappings), is(expectedMapping));
|
|
|
}
|
|
|
|
|
|
+ public void testNoTimestampInDocument() throws Exception {
|
|
|
+ putComposableIndexTemplate("id", "@timestamp", List.of("logs-foobar*"));
|
|
|
+ String dataStreamName = "logs-foobar";
|
|
|
+ CreateDataStreamAction.Request createDataStreamRequest = new CreateDataStreamAction.Request(dataStreamName);
|
|
|
+ client().admin().indices().createDataStream(createDataStreamRequest).get();
|
|
|
+
|
|
|
+ IndexRequest indexRequest = new IndexRequest(dataStreamName)
|
|
|
+ .opType("create")
|
|
|
+ .source("{}", XContentType.JSON);
|
|
|
+ Exception e = expectThrows(MapperParsingException.class, () -> client().index(indexRequest).actionGet());
|
|
|
+ assertThat(e.getCause().getMessage(), equalTo("data stream timestamp field [@timestamp] is missing"));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testMultipleTimestampValuesInDocument() throws Exception {
|
|
|
+ putComposableIndexTemplate("id", "@timestamp", List.of("logs-foobar*"));
|
|
|
+ String dataStreamName = "logs-foobar";
|
|
|
+ CreateDataStreamAction.Request createDataStreamRequest = new CreateDataStreamAction.Request(dataStreamName);
|
|
|
+ client().admin().indices().createDataStream(createDataStreamRequest).get();
|
|
|
+
|
|
|
+ IndexRequest indexRequest = new IndexRequest(dataStreamName)
|
|
|
+ .opType("create")
|
|
|
+ .source("{\"@timestamp\": [\"2020-12-12\",\"2022-12-12\"]}", XContentType.JSON);
|
|
|
+ Exception e = expectThrows(MapperParsingException.class, () -> client().index(indexRequest).actionGet());
|
|
|
+ assertThat(e.getCause().getMessage(),
|
|
|
+ equalTo("data stream timestamp field [@timestamp] encountered multiple values"));
|
|
|
+ }
|
|
|
+
|
|
|
private static void verifyResolvability(String dataStream, ActionRequestBuilder requestBuilder, boolean fail) {
|
|
|
verifyResolvability(dataStream, requestBuilder, fail, 0);
|
|
|
}
|
|
@@ -755,12 +791,13 @@ public class DataStreamIT extends ESIntegTestCase {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static void indexDocs(String dataStream, int numDocs) {
|
|
|
+ private static void indexDocs(String dataStream, String timestampField, int numDocs) {
|
|
|
BulkRequest bulkRequest = new BulkRequest();
|
|
|
for (int i = 0; i < numDocs; i++) {
|
|
|
+ String value = DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.formatMillis(System.currentTimeMillis());
|
|
|
bulkRequest.add(new IndexRequest(dataStream)
|
|
|
.opType(DocWriteRequest.OpType.CREATE)
|
|
|
- .source("{}", XContentType.JSON));
|
|
|
+ .source(String.format(Locale.ROOT, "{\"%s\":\"%s\"}", timestampField, value), XContentType.JSON));
|
|
|
}
|
|
|
BulkResponse bulkResponse = client().bulk(bulkRequest).actionGet();
|
|
|
assertThat(bulkResponse.getItems().length, equalTo(numDocs));
|