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

[Rollup] Validate timezones based on rules not string comparision #36237

Merged
merged 26 commits into from
Apr 17, 2019
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9037c4a
[Rollup] Compare timezones based on rules not string comparision
polyfractal Dec 4, 2018
cc6563e
Fix timestamps in test
polyfractal Dec 4, 2018
4867d99
Use ZoneId
polyfractal Dec 6, 2018
1ef04f0
Merge remote-tracking branch 'origin/master' into rollup_obsolete_tz
polyfractal Dec 7, 2018
da7ebe3
Fix test
polyfractal Dec 10, 2018
21a38f5
Merge remote-tracking branch 'origin/master' into rollup_obsolete_tz
polyfractal Dec 10, 2018
aadf68b
Deprecation warnings when using obsolete timezones
polyfractal Dec 11, 2018
38ca541
Merge remote-tracking branch 'origin/master' into rollup_obsolete_tz
polyfractal Dec 11, 2018
ef0f695
Switch DateHistoConfig over to ZoneId
polyfractal Dec 18, 2018
d41dda4
Merge remote-tracking branch 'origin/master' into rollup_obsolete_tz
polyfractal Dec 18, 2018
d049fea
Test fix: searching the wrong index
polyfractal Dec 18, 2018
e9f42ef
checkstyle
polyfractal Dec 18, 2018
1f7802f
ML needs to use zones instead of strings too
polyfractal Dec 18, 2018
5a2cac4
Revert "Switch DateHistoConfig over to ZoneId"
polyfractal Jan 9, 2019
72a1bed
Fix rule matching
polyfractal Jan 10, 2019
94abbeb
Add test for TZ validation in action
polyfractal Jan 10, 2019
d573aef
Merge remote-tracking branch 'origin/master' into rollup_obsolete_tz
polyfractal Jan 10, 2019
feba7e5
Yml test version updates
polyfractal Jan 11, 2019
9f4aada
Merge remote-tracking branch 'origin/master' into rollup_obsolete_tz
polyfractal Feb 5, 2019
de22b2f
Remove last traces of Joda
polyfractal Feb 5, 2019
b88091b
Do not set timezone on rollup request histo
polyfractal Feb 7, 2019
d80e035
Merge remote-tracking branch 'origin/master' into rollup_obsolete_tz
polyfractal Apr 8, 2019
83bf9bf
Merge remote-tracking branch 'origin/master' into rollup_obsolete_tz
polyfractal Apr 15, 2019
fbda167
checkstyle
polyfractal Apr 15, 2019
8822afd
Fix tests, make more realistic
polyfractal Apr 15, 2019
a9f2911
Remove unnecessary changes
polyfractal Apr 15, 2019
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
6 changes: 3 additions & 3 deletions docs/reference/rollup/apis/get-job.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Which will yield the following response:
"interval" : "1h",
"delay": "7d",
"field": "timestamp",
"time_zone": "UTC"
"time_zone": "Z"
},
"terms" : {
"fields" : [
Expand Down Expand Up @@ -192,7 +192,7 @@ Which will yield the following response:
"interval" : "1h",
"delay": "7d",
"field": "timestamp",
"time_zone": "UTC"
"time_zone": "Z"
},
"terms" : {
"fields" : [
Expand Down Expand Up @@ -247,7 +247,7 @@ Which will yield the following response:
"interval" : "1h",
"delay": "7d",
"field": "timestamp",
"time_zone": "UTC"
"time_zone": "Z"
},
"terms" : {
"fields" : [
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/rollup/apis/rollup-caps.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ Which will yield the following response:
"timestamp" : [
{
"agg" : "date_histogram",
"time_zone" : "UTC",
"time_zone" : "Z",
"interval" : "1h",
"delay": "7d"
}
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/rollup/apis/rollup-index-caps.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ This will yield the following response:
"timestamp" : [
{
"agg" : "date_histogram",
"time_zone" : "UTC",
"time_zone" : "Z",
"interval" : "1h",
"delay": "7d"
}
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/rollup/apis/rollup-job-config.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ The `date_histogram` group has several parameters:

`time_zone`::
Defines what time_zone the rollup documents are stored as. Unlike raw data, which can shift timezones on the fly, rolled documents have
to be stored with a specific timezone. By default, rollup documents are stored in `UTC`, but this can be changed with the `time_zone`
to be stored with a specific timezone. By default, rollup documents are stored in `UTC` (`"Z"`), but this can be changed with the `time_zone`
parameter.

.Calendar vs Fixed time intervals
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/rollup/rollup-search-limitations.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -131,5 +131,5 @@ thrown. We expect the list of support queries to grow over time as more are imp
=== Timezones

Rollup documents are stored in the timezone of the `date_histogram` group configuration in the job. If no timezone is specified, the default
is to rollup timestamps in `UTC`.
is to rollup timestamps in `UTC` (`"Z"`).

121 changes: 121 additions & 0 deletions server/src/main/java/org/elasticsearch/common/time/DateUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,127 @@ public static DateTimeZone zoneIdToDateTimeZone(ZoneId zoneId) {
DEPRECATED_SHORT_TZ_IDS = tzs.keySet();
}

// Map of deprecated timezones and their recommended new counterpart
public static final Map<String, String> DEPRECATED_LONG_TIMEZONES;
static {
Map<String, String> tzs = new HashMap<>();
tzs.put("Africa/Asmera","Africa/Nairobi");
tzs.put("Africa/Timbuktu","Africa/Abidjan");
tzs.put("America/Argentina/ComodRivadavia","America/Argentina/Catamarca");
tzs.put("America/Atka","America/Adak");
tzs.put("America/Buenos_Aires","America/Argentina/Buenos_Aires");
tzs.put("America/Catamarca","America/Argentina/Catamarca");
tzs.put("America/Coral_Harbour","America/Atikokan");
tzs.put("America/Cordoba","America/Argentina/Cordoba");
tzs.put("America/Ensenada","America/Tijuana");
tzs.put("America/Fort_Wayne","America/Indiana/Indianapolis");
tzs.put("America/Indianapolis","America/Indiana/Indianapolis");
tzs.put("America/Jujuy","America/Argentina/Jujuy");
tzs.put("America/Knox_IN","America/Indiana/Knox");
tzs.put("America/Louisville","America/Kentucky/Louisville");
tzs.put("America/Mendoza","America/Argentina/Mendoza");
tzs.put("America/Montreal","America/Toronto");
tzs.put("America/Porto_Acre","America/Rio_Branco");
tzs.put("America/Rosario","America/Argentina/Cordoba");
tzs.put("America/Santa_Isabel","America/Tijuana");
tzs.put("America/Shiprock","America/Denver");
tzs.put("America/Virgin","America/Port_of_Spain");
tzs.put("Antarctica/South_Pole","Pacific/Auckland");
tzs.put("Asia/Ashkhabad","Asia/Ashgabat");
tzs.put("Asia/Calcutta","Asia/Kolkata");
tzs.put("Asia/Chongqing","Asia/Shanghai");
tzs.put("Asia/Chungking","Asia/Shanghai");
tzs.put("Asia/Dacca","Asia/Dhaka");
tzs.put("Asia/Harbin","Asia/Shanghai");
tzs.put("Asia/Kashgar","Asia/Urumqi");
tzs.put("Asia/Katmandu","Asia/Kathmandu");
tzs.put("Asia/Macao","Asia/Macau");
tzs.put("Asia/Rangoon","Asia/Yangon");
tzs.put("Asia/Saigon","Asia/Ho_Chi_Minh");
tzs.put("Asia/Tel_Aviv","Asia/Jerusalem");
tzs.put("Asia/Thimbu","Asia/Thimphu");
tzs.put("Asia/Ujung_Pandang","Asia/Makassar");
tzs.put("Asia/Ulan_Bator","Asia/Ulaanbaatar");
tzs.put("Atlantic/Faeroe","Atlantic/Faroe");
tzs.put("Atlantic/Jan_Mayen","Europe/Oslo");
tzs.put("Australia/ACT","Australia/Sydney");
tzs.put("Australia/Canberra","Australia/Sydney");
tzs.put("Australia/LHI","Australia/Lord_Howe");
tzs.put("Australia/NSW","Australia/Sydney");
tzs.put("Australia/North","Australia/Darwin");
tzs.put("Australia/Queensland","Australia/Brisbane");
tzs.put("Australia/South","Australia/Adelaide");
tzs.put("Australia/Tasmania","Australia/Hobart");
tzs.put("Australia/Victoria","Australia/Melbourne");
tzs.put("Australia/West","Australia/Perth");
tzs.put("Australia/Yancowinna","Australia/Broken_Hill");
tzs.put("Brazil/Acre","America/Rio_Branco");
tzs.put("Brazil/DeNoronha","America/Noronha");
tzs.put("Brazil/East","America/Sao_Paulo");
tzs.put("Brazil/West","America/Manaus");
tzs.put("Canada/Atlantic","America/Halifax");
tzs.put("Canada/Central","America/Winnipeg");
tzs.put("Canada/East-Saskatchewan","America/Regina");
tzs.put("Canada/Eastern","America/Toronto");
tzs.put("Canada/Mountain","America/Edmonton");
tzs.put("Canada/Newfoundland","America/St_Johns");
tzs.put("Canada/Pacific","America/Vancouver");
tzs.put("Canada/Yukon","America/Whitehorse");
tzs.put("Chile/Continental","America/Santiago");
tzs.put("Chile/EasterIsland","Pacific/Easter");
tzs.put("Cuba","America/Havana");
tzs.put("Egypt","Africa/Cairo");
tzs.put("Eire","Europe/Dublin");
tzs.put("Europe/Belfast","Europe/London");
tzs.put("Europe/Tiraspol","Europe/Chisinau");
tzs.put("GB","Europe/London");
tzs.put("GB-Eire","Europe/London");
tzs.put("Greenwich","Etc/GMT");
tzs.put("Hongkong","Asia/Hong_Kong");
tzs.put("Iceland","Atlantic/Reykjavik");
tzs.put("Iran","Asia/Tehran");
tzs.put("Israel","Asia/Jerusalem");
tzs.put("Jamaica","America/Jamaica");
tzs.put("Japan","Asia/Tokyo");
tzs.put("Kwajalein","Pacific/Kwajalein");
tzs.put("Libya","Africa/Tripoli");
tzs.put("Mexico/BajaNorte","America/Tijuana");
tzs.put("Mexico/BajaSur","America/Mazatlan");
tzs.put("Mexico/General","America/Mexico_City");
tzs.put("NZ","Pacific/Auckland");
tzs.put("NZ-CHAT","Pacific/Chatham");
tzs.put("Navajo","America/Denver");
tzs.put("PRC","Asia/Shanghai");
tzs.put("Pacific/Johnston","Pacific/Honolulu");
tzs.put("Pacific/Ponape","Pacific/Pohnpei");
tzs.put("Pacific/Samoa","Pacific/Pago_Pago");
tzs.put("Pacific/Truk","Pacific/Chuuk");
tzs.put("Pacific/Yap","Pacific/Chuuk");
tzs.put("Poland","Europe/Warsaw");
tzs.put("Portugal","Europe/Lisbon");
tzs.put("ROC","Asia/Taipei");
tzs.put("ROK","Asia/Seoul");
tzs.put("Singapore","Asia/Singapore");
tzs.put("Turkey","Europe/Istanbul");
tzs.put("UCT","Etc/UCT");
tzs.put("US/Alaska","America/Anchorage");
tzs.put("US/Aleutian","America/Adak");
tzs.put("US/Arizona","America/Phoenix");
tzs.put("US/Central","America/Chicago");
tzs.put("US/East-Indiana","America/Indiana/Indianapolis");
tzs.put("US/Eastern","America/New_York");
tzs.put("US/Hawaii","Pacific/Honolulu");
tzs.put("US/Indiana-Starke","America/Indiana/Knox");
tzs.put("US/Michigan","America/Detroit");
tzs.put("US/Mountain","America/Denver");
tzs.put("US/Pacific","America/Los_Angeles");
tzs.put("US/Samoa","Pacific/Pago_Pago");
tzs.put("Universal","Etc/UTC");
tzs.put("W-SU","Europe/Moscow");
tzs.put("Zulu","Etc/UTC");
DEPRECATED_LONG_TIMEZONES = Collections.unmodifiableMap(tzs);
}

public static ZoneId dateTimeZoneToZoneId(DateTimeZone timeZone) {
if (timeZone == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.core.rollup.job;

import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.fieldcaps.FieldCapabilities;
import org.elasticsearch.common.Nullable;
Expand All @@ -15,6 +16,7 @@
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.rounding.DateTimeUnit;
import org.elasticsearch.common.rounding.Rounding;
import org.elasticsearch.common.time.DateUtils;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
Expand All @@ -25,6 +27,8 @@
import org.joda.time.DateTimeZone;

import java.io.IOException;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Map;
import java.util.Objects;

Expand Down Expand Up @@ -53,7 +57,7 @@ public class DateHistogramGroupConfig implements Writeable, ToXContentObject {
private static final String FIELD = "field";
public static final String TIME_ZONE = "time_zone";
public static final String DELAY = "delay";
private static final String DEFAULT_TIMEZONE = "UTC";
public static final ZoneId DEFAULT_TIMEZONE = ZoneOffset.UTC;
private static final ConstructingObjectParser<DateHistogramGroupConfig, Void> PARSER;
static {
PARSER = new ConstructingObjectParser<>(NAME, a ->
Expand All @@ -67,7 +71,7 @@ public class DateHistogramGroupConfig implements Writeable, ToXContentObject {
private final String field;
private final DateHistogramInterval interval;
private final DateHistogramInterval delay;
private final String timeZone;
private final ZoneId timeZone;

/**
* Create a new {@link DateHistogramGroupConfig} using the given field and interval parameters.
Expand Down Expand Up @@ -103,10 +107,9 @@ public DateHistogramGroupConfig(final String field,
this.interval = interval;
this.field = field;
this.delay = delay;
this.timeZone = (timeZone != null && timeZone.isEmpty() == false) ? timeZone : DEFAULT_TIMEZONE;

// validate interval
createRounding(this.interval.toString(), this.timeZone);
// Convert to ZoneId, then validate roundings (which unfortunately requires converting to DateTimeZone)
this.timeZone = Strings.isNullOrEmpty(timeZone) ? DEFAULT_TIMEZONE : ZoneId.of(timeZone, ZoneId.SHORT_IDS);
createRounding(this.interval.toString(), DateUtils.zoneIdToDateTimeZone(this.timeZone));
if (delay != null) {
// and delay
TimeValue.parseTimeValue(this.delay.toString(), DELAY);
Expand All @@ -117,15 +120,23 @@ public DateHistogramGroupConfig(final String field,
interval = new DateHistogramInterval(in);
field = in.readString();
delay = in.readOptionalWriteable(DateHistogramInterval::new);
timeZone = in.readString();
// new ZoneId can deal with older DateTimeStrings, no need for version check
timeZone = ZoneId.of(in.readString(), ZoneId.SHORT_IDS);
}

@Override
public void writeTo(final StreamOutput out) throws IOException {
interval.writeTo(out);
out.writeString(field);
out.writeOptionalWriteable(delay);
out.writeString(timeZone);
// TODO change version after backport
if (out.getVersion().onOrAfter(Version.V_7_0_0)) {
polyfractal marked this conversation as resolved.
Show resolved Hide resolved
out.writeString(timeZone.toString());
} else {
// If we're on an older version, DateTime doesn't know how to
// deal with new ZoneId strings (E.g. "Z" instead of "UTC")
out.writeString(DateUtils.zoneIdToDateTimeZone(timeZone).toString());
}
}

@Override
Expand All @@ -137,7 +148,7 @@ public XContentBuilder toXContent(final XContentBuilder builder, final Params pa
if (delay != null) {
builder.field(DELAY, delay.toString());
}
builder.field(TIME_ZONE, timeZone);
builder.field(TIME_ZONE, timeZone.toString());
}
return builder.endObject();
}
Expand Down Expand Up @@ -167,14 +178,14 @@ public DateHistogramInterval getDelay() {
* Get the timezone to apply
*/
public String getTimeZone() {
return timeZone;
return timeZone.toString();
}

/**
* Create the rounding for this date histogram
*/
public Rounding createRounding() {
return createRounding(interval.toString(), timeZone);
return createRounding(interval.toString(), DateUtils.zoneIdToDateTimeZone(timeZone));
}

public void validateMappings(Map<String, Map<String, FieldCapabilities>> fieldCapsResponse,
Expand Down Expand Up @@ -211,12 +222,12 @@ public boolean equals(final Object other) {
return Objects.equals(interval, that.interval)
&& Objects.equals(field, that.field)
&& Objects.equals(delay, that.delay)
&& Objects.equals(timeZone, that.timeZone);
&& timeZone.getRules().equals(((DateHistogramGroupConfig) other).timeZone.getRules());
}

@Override
public int hashCode() {
return Objects.hash(interval, field, delay, timeZone);
return Objects.hash(interval, field, delay, timeZone.getRules());
}

@Override
Expand All @@ -228,24 +239,15 @@ public static DateHistogramGroupConfig fromXContent(final XContentParser parser)
return PARSER.parse(parser, null);
}

private static Rounding createRounding(final String expr, final String timeZone) {
private static Rounding createRounding(final String expr, final DateTimeZone timeZone) {
DateTimeUnit timeUnit = DateHistogramAggregationBuilder.DATE_FIELD_UNITS.get(expr);
final Rounding.Builder rounding;
if (timeUnit != null) {
rounding = new Rounding.Builder(timeUnit);
} else {
rounding = new Rounding.Builder(TimeValue.parseTimeValue(expr, "createRounding"));
}
rounding.timeZone(toDateTimeZone(timeZone));
rounding.timeZone(timeZone);
return rounding.build();
}

private static DateTimeZone toDateTimeZone(final String timezone) {
try {
return DateTimeZone.forOffsetHours(Integer.parseInt(timezone));
} catch (NumberFormatException e) {
return DateTimeZone.forID(timezone);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,13 @@ public static DateHistogramGroupConfig randomDateHistogramGroupConfig(final Rand
final String field = randomField(random);
final DateHistogramInterval interval = randomInterval();
final DateHistogramInterval delay = random.nextBoolean() ? randomInterval() : null;
final String timezone = random.nextBoolean() ? randomDateTimeZone().toString() : null;
// TODO extend this to full set of ZoneId's once we move away from DateTime
// can't do it now because some ZoneIds are not compatible with DateTime
final String timezone = random.nextBoolean()
? (random.nextBoolean()
? randomDateTimeZone().toString()
: "Z")
: null;
return new DateHistogramGroupConfig(field, interval, delay, timezone);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.core.rollup.job;

import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.fieldcaps.FieldCapabilities;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
Expand Down Expand Up @@ -148,6 +149,7 @@ public void testBwcSerialization() throws IOException {
final DateHistogramGroupConfig reference = ConfigTestHelpers.randomDateHistogramGroupConfig(random());

final BytesStreamOutput out = new BytesStreamOutput();
out.setVersion(Version.V_6_4_0);
reference.writeTo(out);

// previous way to deserialize a DateHistogramGroupConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import org.elasticsearch.xpack.core.rollup.job.DateHistogramGroupConfig;
import org.elasticsearch.xpack.ml.datafeed.extractor.DataExtractorFactory;

import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -120,7 +122,7 @@ private static boolean validInterval(long datafeedInterval, ParsedRollupCaps rol
if (rollupJobGroupConfig.hasDatehistogram() == false) {
return false;
}
if ("UTC".equalsIgnoreCase(rollupJobGroupConfig.getTimezone()) == false) {
if (ZoneId.of(rollupJobGroupConfig.getTimezone()).getRules().equals(ZoneOffset.UTC.getRules()) == false) {
polyfractal marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
try {
Expand Down
Loading