From 9d52f3763ef118b62685cf02df94729635b74c5c Mon Sep 17 00:00:00 2001 From: Abigael-JT <130055999+Abigael-JT@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:51:21 +0200 Subject: [PATCH 1/3] improved error message for incorrect timestamp format --- .../teragrep/pth10/ast/DefaultTimeFormat.java | 2 +- .../pth10/ast/time/InstantTimestamp.java | 16 ++++++++++++++-- .../com/teragrep/pth10/EarliestLatestTest.java | 5 ++++- .../com/teragrep/pth10/relativeTimeTest.java | 6 +++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java b/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java index c307078d5..5a3d90f46 100644 --- a/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java +++ b/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java @@ -97,7 +97,7 @@ public Date parse(String time) { catch (ParseException ignored) { } } - throw new RuntimeException("TimeQualifier conversion error: <" + time + "> can't be parsed."); + throw new RuntimeException("Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats <>)"); } private Date parseDate(String time, String timeFormat) throws ParseException { diff --git a/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java b/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java index 2464aba9a..b8858c606 100644 --- a/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java +++ b/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java @@ -49,6 +49,8 @@ import com.teragrep.pth10.ast.DefaultTimeFormat; import com.teragrep.pth10.ast.TextString; import com.teragrep.pth10.ast.UnquotedText; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.sql.Timestamp; import java.text.ParseException; @@ -57,6 +59,7 @@ public final class InstantTimestamp implements DPLTimestamp { + private static final Logger LOGGER = LoggerFactory.getLogger(EpochTimestamp.class); private final String value; private final String timeformat; @@ -72,6 +75,7 @@ public Instant instant() { rv = relativeTimestamp.calculate(new Timestamp(System.currentTimeMillis())); } catch (NumberFormatException ne) { + LOGGER.debug("Could not parse relative timestamp, trying default formats"); rv = instantFromString(value, timeformat); } @@ -80,11 +84,19 @@ public Instant instant() { // Uses defaultTimeFormat if timeformat is null and DPLTimeFormat if timeformat isn't null (which means that the // timeformat= option was used). - private Instant instantFromString(final String value, final String timeFormatString) { + private Instant instantFromString(final String value, final String timeFormatString, final NumberFormatException cause) { final String unquotedValue = new UnquotedText(new TextString(value)).read(); // erase the possible outer quotes final Instant timevalue; if (timeFormatString == null || timeFormatString.isEmpty()) { - timevalue = new DefaultTimeFormat().parse(unquotedValue).toInstant(); + try { + timevalue = new DefaultTimeFormat().parse(unquotedValue).toInstant(); + } + catch (final RuntimeException ex) { + throw new RuntimeException( + "Error parsing <" + unquotedValue + ">. " + ex.getMessage() + ". " + cause.getMessage() + ".", + cause + ); + } } else { // TODO: should be included in DPLTimeFormat diff --git a/src/test/java/com/teragrep/pth10/EarliestLatestTest.java b/src/test/java/com/teragrep/pth10/EarliestLatestTest.java index 2eb530dd1..d82a677dc 100644 --- a/src/test/java/com/teragrep/pth10/EarliestLatestTest.java +++ b/src/test/java/com/teragrep/pth10/EarliestLatestTest.java @@ -358,7 +358,10 @@ public void defaultFormatInvalidInputTest() { // MM/dd/yyyy:HH:mm:ss 2013-07-15 .performThrowingDPLTest(RuntimeException.class, query, this.testFile, res -> { }); Assertions - .assertEquals("TimeQualifier conversion error: <31/31/2014:00:00:00> can't be parsed.", sqe.getMessage()); + .assertEquals( + "Error parsing <31/31/2014:00:00:00>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats , , ). Unknown relative time modifier string [31/31/2014:00:00:00].", + sqe.getMessage() + ); } @Test diff --git a/src/test/java/com/teragrep/pth10/relativeTimeTest.java b/src/test/java/com/teragrep/pth10/relativeTimeTest.java index 81ed57857..fb5499880 100644 --- a/src/test/java/com/teragrep/pth10/relativeTimeTest.java +++ b/src/test/java/com/teragrep/pth10/relativeTimeTest.java @@ -336,7 +336,7 @@ public void parseTimestampLatestRelativeTestWithPlus() { ) public void parseTimestampLatestRelativeTestWithoutSign() { String q = "index=cinnamon latest=3h "; - String expected = "TimeQualifier conversion error: <3h> can't be parsed."; + String expected = "Error parsing <3h>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats , , ). Unknown relative time modifier string [3h]."; RuntimeException exception = this.streamingTestUtil .performThrowingDPLTest(RuntimeException.class, q, this.testFile, res -> { @@ -422,7 +422,7 @@ public void parseTimestampEarliestRelativeSnapToDayLatestNow() { String expectedLatestString = String.valueOf(expectedLatest).substring(0, 7); // don't check last 2 numbers as the query takes some time and the "now" is different String regex = "^.*_time >= from_unixtime\\(" + expectedEarliest + ".*_time < from_unixtime\\(" + expectedLatestString + ".*$"; - ; + String result = this.streamingTestUtil.getCtx().getSparkQuery(); Assertions.assertTrue(result.matches(regex)); }); @@ -437,7 +437,7 @@ public void parseTimestampEarliestRelativeSnapToDayLatestNow() { public void parseTimestampRelativeInvalidSnapToTimeUnitTest() { // pth10 ticket #66 query: 'index=... sourcetype=... earliest=@-5h latest=@-3h' String query = "index=cinnamon earliest=\"@-5h\" latest=\"@-3h\""; - String expected = "TimeQualifier conversion error: <@-5h> can't be parsed."; + String expected = "Error parsing <@-5h>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats , , ). Unknown relative time modifier string [@-5h]."; RuntimeException exception = this.streamingTestUtil .performThrowingDPLTest(RuntimeException.class, query, this.testFile, res -> { From 656502f6df182c2766c826277145e1a8df7365aa Mon Sep 17 00:00:00 2001 From: Abigael-JT <130055999+Abigael-JT@users.noreply.github.com> Date: Mon, 17 Mar 2025 10:31:25 +0200 Subject: [PATCH 2/3] Rebased and update after PR #454 merge --- .../java/com/teragrep/pth10/ast/DefaultTimeFormat.java | 6 +++++- .../com/teragrep/pth10/ast/time/InstantTimestamp.java | 10 +++++++--- .../java/com/teragrep/pth10/DefaultTimeFormatTest.java | 5 ++++- .../java/com/teragrep/pth10/EarliestLatestTest.java | 2 +- src/test/java/com/teragrep/pth10/relativeTimeTest.java | 4 ++-- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java b/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java index 5a3d90f46..e830adb6e 100644 --- a/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java +++ b/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java @@ -47,6 +47,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Date; /** @@ -97,7 +98,10 @@ public Date parse(String time) { catch (ParseException ignored) { } } - throw new RuntimeException("Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats <>)"); + throw new RuntimeException( + "Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats: " + + Arrays.toString(formats) + ")" + ); } private Date parseDate(String time, String timeFormat) throws ParseException { diff --git a/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java b/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java index b8858c606..a01d2c5bf 100644 --- a/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java +++ b/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java @@ -59,7 +59,7 @@ public final class InstantTimestamp implements DPLTimestamp { - private static final Logger LOGGER = LoggerFactory.getLogger(EpochTimestamp.class); + private static final Logger LOGGER = LoggerFactory.getLogger(InstantTimestamp.class); private final String value; private final String timeformat; @@ -76,7 +76,7 @@ public Instant instant() { } catch (NumberFormatException ne) { LOGGER.debug("Could not parse relative timestamp, trying default formats"); - rv = instantFromString(value, timeformat); + rv = instantFromString(value, timeformat, ne); } return rv; @@ -84,7 +84,11 @@ public Instant instant() { // Uses defaultTimeFormat if timeformat is null and DPLTimeFormat if timeformat isn't null (which means that the // timeformat= option was used). - private Instant instantFromString(final String value, final String timeFormatString, final NumberFormatException cause) { + private Instant instantFromString( + final String value, + final String timeFormatString, + final NumberFormatException cause + ) { final String unquotedValue = new UnquotedText(new TextString(value)).read(); // erase the possible outer quotes final Instant timevalue; if (timeFormatString == null || timeFormatString.isEmpty()) { diff --git a/src/test/java/com/teragrep/pth10/DefaultTimeFormatTest.java b/src/test/java/com/teragrep/pth10/DefaultTimeFormatTest.java index 4f2163650..f6d9dcbae 100644 --- a/src/test/java/com/teragrep/pth10/DefaultTimeFormatTest.java +++ b/src/test/java/com/teragrep/pth10/DefaultTimeFormatTest.java @@ -123,6 +123,9 @@ void invalidTimeformat() { .assertThrows(RuntimeException.class, () -> new DefaultTimeFormat().getEpoch(time)); Assertions - .assertEquals("TimeQualifier conversion error: <12/34/2020:10:25:40> can't be parsed.", rte.getMessage()); + .assertEquals( + "Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats: [MM/dd/yyyy:HH:mm:ss, yyyy-MM-dd'T'HH:mm:ss.SSSXXX, yyyy-MM-dd'T'HH:mm:ss.SSS, yyyy-MM-dd'T'HH:mm:ssXXX, yyyy-MM-dd'T'HH:mm:ss])", + rte.getMessage() + ); } } diff --git a/src/test/java/com/teragrep/pth10/EarliestLatestTest.java b/src/test/java/com/teragrep/pth10/EarliestLatestTest.java index d82a677dc..9e2ee513f 100644 --- a/src/test/java/com/teragrep/pth10/EarliestLatestTest.java +++ b/src/test/java/com/teragrep/pth10/EarliestLatestTest.java @@ -359,7 +359,7 @@ public void defaultFormatInvalidInputTest() { // MM/dd/yyyy:HH:mm:ss 2013-07-15 }); Assertions .assertEquals( - "Error parsing <31/31/2014:00:00:00>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats , , ). Unknown relative time modifier string [31/31/2014:00:00:00].", + "Error parsing <31/31/2014:00:00:00>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats: [MM/dd/yyyy:HH:mm:ss, yyyy-MM-dd'T'HH:mm:ss.SSSXXX, yyyy-MM-dd'T'HH:mm:ss.SSS, yyyy-MM-dd'T'HH:mm:ssXXX, yyyy-MM-dd'T'HH:mm:ss]). Unknown relative time modifier string [31/31/2014:00:00:00].", sqe.getMessage() ); } diff --git a/src/test/java/com/teragrep/pth10/relativeTimeTest.java b/src/test/java/com/teragrep/pth10/relativeTimeTest.java index fb5499880..e88d5c3e9 100644 --- a/src/test/java/com/teragrep/pth10/relativeTimeTest.java +++ b/src/test/java/com/teragrep/pth10/relativeTimeTest.java @@ -336,7 +336,7 @@ public void parseTimestampLatestRelativeTestWithPlus() { ) public void parseTimestampLatestRelativeTestWithoutSign() { String q = "index=cinnamon latest=3h "; - String expected = "Error parsing <3h>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats , , ). Unknown relative time modifier string [3h]."; + String expected = "Error parsing <3h>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats: [MM/dd/yyyy:HH:mm:ss, yyyy-MM-dd'T'HH:mm:ss.SSSXXX, yyyy-MM-dd'T'HH:mm:ss.SSS, yyyy-MM-dd'T'HH:mm:ssXXX, yyyy-MM-dd'T'HH:mm:ss]). Unknown relative time modifier string [3h]."; RuntimeException exception = this.streamingTestUtil .performThrowingDPLTest(RuntimeException.class, q, this.testFile, res -> { @@ -437,7 +437,7 @@ public void parseTimestampEarliestRelativeSnapToDayLatestNow() { public void parseTimestampRelativeInvalidSnapToTimeUnitTest() { // pth10 ticket #66 query: 'index=... sourcetype=... earliest=@-5h latest=@-3h' String query = "index=cinnamon earliest=\"@-5h\" latest=\"@-3h\""; - String expected = "Error parsing <@-5h>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats , , ). Unknown relative time modifier string [@-5h]."; + String expected = "Error parsing <@-5h>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats: [MM/dd/yyyy:HH:mm:ss, yyyy-MM-dd'T'HH:mm:ss.SSSXXX, yyyy-MM-dd'T'HH:mm:ss.SSS, yyyy-MM-dd'T'HH:mm:ssXXX, yyyy-MM-dd'T'HH:mm:ss]). Unknown relative time modifier string [@-5h]."; RuntimeException exception = this.streamingTestUtil .performThrowingDPLTest(RuntimeException.class, query, this.testFile, res -> { From 61ed2d45c12718c98506ade60cb72930f38d2fad Mon Sep 17 00:00:00 2001 From: Abigael-JT <130055999+Abigael-JT@users.noreply.github.com> Date: Fri, 11 Apr 2025 16:02:23 +0300 Subject: [PATCH 3/3] throw DateTimeException instead of RuntimeException and added it to method signature --- src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java | 5 +++-- .../java/com/teragrep/pth10/ast/time/InstantTimestamp.java | 5 +++-- src/test/java/com/teragrep/pth10/EarliestLatestTest.java | 5 +++-- src/test/java/com/teragrep/pth10/relativeTimeTest.java | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java b/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java index e830adb6e..e00e92bd7 100644 --- a/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java +++ b/src/main/java/com/teragrep/pth10/ast/DefaultTimeFormat.java @@ -47,6 +47,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.DateTimeException; import java.util.Arrays; import java.util.Date; @@ -89,7 +90,7 @@ public long getEpoch(String time) { * @param time The human-readable time * @return Date parsed from the given string */ - public Date parse(String time) { + public Date parse(String time) throws DateTimeException { // Try parsing all provided time formats in order for (final String format : formats) { try { @@ -98,7 +99,7 @@ public Date parse(String time) { catch (ParseException ignored) { } } - throw new RuntimeException( + throw new DateTimeException( "Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats: " + Arrays.toString(formats) + ")" ); diff --git a/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java b/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java index a01d2c5bf..098835196 100644 --- a/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java +++ b/src/main/java/com/teragrep/pth10/ast/time/InstantTimestamp.java @@ -54,6 +54,7 @@ import java.sql.Timestamp; import java.text.ParseException; +import java.time.DateTimeException; import java.time.Instant; import java.util.Objects; @@ -95,8 +96,8 @@ private Instant instantFromString( try { timevalue = new DefaultTimeFormat().parse(unquotedValue).toInstant(); } - catch (final RuntimeException ex) { - throw new RuntimeException( + catch (final DateTimeException ex) { + throw new DateTimeException( "Error parsing <" + unquotedValue + ">. " + ex.getMessage() + ". " + cause.getMessage() + ".", cause ); diff --git a/src/test/java/com/teragrep/pth10/EarliestLatestTest.java b/src/test/java/com/teragrep/pth10/EarliestLatestTest.java index 9e2ee513f..4c8c1e581 100644 --- a/src/test/java/com/teragrep/pth10/EarliestLatestTest.java +++ b/src/test/java/com/teragrep/pth10/EarliestLatestTest.java @@ -60,6 +60,7 @@ import org.slf4j.LoggerFactory; import java.sql.Timestamp; +import java.time.DateTimeException; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; @@ -354,8 +355,8 @@ public void defaultFormatTest() { // MM/dd/yyyy:HH:mm:ss 2013-07-15 10:01:50 ) public void defaultFormatInvalidInputTest() { // MM/dd/yyyy:HH:mm:ss 2013-07-15 10:01:50 String query = "(index=strawberry OR index=seagull) AND earliest=31/31/2014:00:00:00"; - RuntimeException sqe = this.streamingTestUtil - .performThrowingDPLTest(RuntimeException.class, query, this.testFile, res -> { + DateTimeException sqe = this.streamingTestUtil + .performThrowingDPLTest(DateTimeException.class, query, this.testFile, res -> { }); Assertions .assertEquals( diff --git a/src/test/java/com/teragrep/pth10/relativeTimeTest.java b/src/test/java/com/teragrep/pth10/relativeTimeTest.java index e88d5c3e9..f0b25d247 100644 --- a/src/test/java/com/teragrep/pth10/relativeTimeTest.java +++ b/src/test/java/com/teragrep/pth10/relativeTimeTest.java @@ -338,8 +338,8 @@ public void parseTimestampLatestRelativeTestWithoutSign() { String q = "index=cinnamon latest=3h "; String expected = "Error parsing <3h>. Check that the timestamp or the relative time value is in the correct format (Supported timestamp formats: [MM/dd/yyyy:HH:mm:ss, yyyy-MM-dd'T'HH:mm:ss.SSSXXX, yyyy-MM-dd'T'HH:mm:ss.SSS, yyyy-MM-dd'T'HH:mm:ssXXX, yyyy-MM-dd'T'HH:mm:ss]). Unknown relative time modifier string [3h]."; - RuntimeException exception = this.streamingTestUtil - .performThrowingDPLTest(RuntimeException.class, q, this.testFile, res -> { + DateTimeException exception = this.streamingTestUtil + .performThrowingDPLTest(DateTimeException.class, q, this.testFile, res -> { }); Assertions.assertEquals(expected, exception.getMessage());