diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/tsdb/10_settings.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/tsdb/10_settings.yml index 4df1579cd4597..a1ac1f363d19b 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/tsdb/10_settings.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/tsdb/10_settings.yml @@ -230,3 +230,162 @@ set start_time and end_time without timeseries mode: index: time_series: end_time: 1632625782000 + +--- +check start_time and end_time with data_nano: + - skip: + version: " - 8.0.99" + reason: introduced in 8.1.0 + - do: + indices.create: + index: test_index + body: + settings: + index: + mode: time_series + routing_path: [metricset] + time_series: + start_time: 2021-09-26T03:09:42Z + end_time: 2021-09-26T03:09:52Z + mappings: + properties: + "@timestamp": + type: date_nanos + metricset: + type: keyword + time_series_dimension: true + + - do: + index: + refresh: true + index: test_index + body: { + "@timestamp": "2021-09-26T03:09:51.123456789Z", + "metricset": "pod" + } + + - do: + search: + index: test_index + body: + docvalue_fields: [ '@timestamp' ] + - match: { hits.total.value: 1 } + - match: { "hits.hits.0.fields.@timestamp": [ "2021-09-26T03:09:51.123456789Z" ] } + + - do: + catch: /time series index @timestamp value \[2010-09-26T03:09:52.123456789Z\] must be larger than 2021-09-26T03:09:42Z/ + index: + index: test_index + body: { + "@timestamp": "2010-09-26T03:09:52.123456789Z", + "metricset": "pod" + } + + - do: + catch: /time series index @timestamp value \[2031-09-26T03:09:52.123456789Z\] must be smaller than 2021-09-26T03:09:52Z/ + index: + index: test_index + body: { + "@timestamp": "2031-09-26T03:09:52.123456789Z", + "metricset": "pod" + } + +--- +check start_time boundary with data_nano: + - skip: + version: " - 8.0.99" + reason: introduced in 8.1.0 + - do: + indices.create: + index: test_index + body: + settings: + index: + mode: time_series + routing_path: [metricset] + time_series: + start_time: 2021-09-26T03:09:42Z + end_time: 2021-09-26T03:09:52Z + mappings: + properties: + "@timestamp": + type: date_nanos + metricset: + type: keyword + time_series_dimension: true + + - do: + index: + refresh: true + index: test_index + body: { + "@timestamp": "2021-09-26T03:09:42.123456789Z", + "metricset": "pod" + } + + - do: + search: + index: test_index + body: + docvalue_fields: [ '@timestamp' ] + - match: { hits.total.value: 1 } + - match: { "hits.hits.0.fields.@timestamp": [ "2021-09-26T03:09:42.123456789Z" ] } + + - do: + catch: /time series index @timestamp value \[2021-09-26T03:09:41.123456789Z\] must be larger than 2021-09-26T03:09:42Z/ + index: + index: test_index + body: { + "@timestamp": "2021-09-26T03:09:41.123456789Z", + "metricset": "pod" + } + +--- +check end_time boundary with data_nano: + - skip: + version: " - 8.0.99" + reason: introduced in 8.1.0 + - do: + indices.create: + index: test_index + body: + settings: + index: + mode: time_series + routing_path: [metricset] + time_series: + start_time: 2021-09-26T03:09:42Z + end_time: 2021-09-26T03:09:52Z + mappings: + properties: + "@timestamp": + type: date_nanos + metricset: + type: keyword + time_series_dimension: true + + - do: + index: + refresh: true + index: test_index + body: { + "@timestamp": "2021-09-26T03:09:51.123456789Z", + "metricset": "pod" + } + + - do: + search: + index: test_index + body: + docvalue_fields: [ '@timestamp' ] + - match: { hits.total.value: 1 } + - match: { "hits.hits.0.fields.@timestamp": [ "2021-09-26T03:09:51.123456789Z" ] } + + - do: + catch: /time series index @timestamp value \[2021-09-26T03:09:52.123456789Z\] must be smaller than 2021-09-26T03:09:52Z/ + index: + index: test_index + body: { + "@timestamp": "2021-09-26T03:09:52.123456789Z", + "metricset": "pod" + } diff --git a/server/src/main/java/org/elasticsearch/index/IndexSettings.java b/server/src/main/java/org/elasticsearch/index/IndexSettings.java index 23df096597588..8b56a9e3d292b 100644 --- a/server/src/main/java/org/elasticsearch/index/IndexSettings.java +++ b/server/src/main/java/org/elasticsearch/index/IndexSettings.java @@ -492,7 +492,7 @@ public static boolean isTimeSeriesModeEnabled() { */ public static final Setting TIME_SERIES_END_TIME = Setting.dateSetting( "index.time_series.end_time", - DateUtils.MAX_NANOSECOND_INSTANT, + Instant.ofEpochMilli(DateUtils.MAX_MILLIS_BEFORE_9999), new Setting.Validator<>() { @Override public void validate(Instant value) {} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/DataStreamTimestampFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/DataStreamTimestampFieldMapper.java index 5b7b0e5fe6273..9bbe0f2f41889 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/DataStreamTimestampFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/DataStreamTimestampFieldMapper.java @@ -14,12 +14,14 @@ import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.index.IndexMode; +import org.elasticsearch.index.mapper.DateFieldMapper.Resolution; import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.XContentType; import java.io.IOException; import java.io.UncheckedIOException; +import java.time.Instant; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -215,19 +217,35 @@ private void validateTimestamp(IndexableField field, DocumentParserContext conte return; } - long value = field.numericValue().longValue(); + long originValue = field.numericValue().longValue(); + long value = originValue; + + Resolution resolution; if (context.mappingLookup().getMapper(DEFAULT_PATH).typeName().equals(DateFieldMapper.DATE_NANOS_CONTENT_TYPE)) { + resolution = Resolution.NANOSECONDS; value /= NSEC_PER_MSEC; + } else { + resolution = Resolution.MILLISECONDS; } long startTime = context.indexSettings().getTimeSeriesStartTime(); if (value < startTime) { - throw new IllegalArgumentException("time series index @timestamp value [" + value + "] must be larger than " + startTime); + throw new IllegalArgumentException( + "time series index @timestamp value [" + + resolution.toInstant(originValue) + + "] must be larger than " + + Instant.ofEpochMilli(startTime) + ); } long endTime = context.indexSettings().getTimeSeriesEndTime(); if (value >= endTime) { - throw new IllegalArgumentException("time series index @timestamp value [" + value + "] must be smaller than " + endTime); + throw new IllegalArgumentException( + "time series index @timestamp value [" + + resolution.toInstant(originValue) + + "] must be smaller than " + + Instant.ofEpochMilli(endTime) + ); } }