From 65d00730c3515cfedd2a15500ab534023c149dd8 Mon Sep 17 00:00:00 2001
From: Phil Clay
Date: Sat, 23 Nov 2019 11:41:47 -0800
Subject: [PATCH] Fixes #364 Switch FastDateFormat to DateTimeFormatter
Remove dependency on apache commons-lang3 (since FastDateFormat was the only thing being used).
Switch default timestamp format to DateTimeFormatter.ISO_OFFSET_DATE_TIME
Added the ability to specify DateTimeFormatter constant names as patterns.
This change is NOT fully backwards compatible, since:
* the default timestamp pattern changed to DateTimeFormatter.ISO_OFFSET_DATE_TIME
* the pattern strings supported by DateTimeFormatter are not exactly the same as those supported by FastDateFormat
---
README.md | 45 +++----
pom.xml | 12 +-
...FailureSummaryLoggingAppenderListener.java | 6 +-
.../FormattedTimestampJsonProvider.java | 61 ++++++---
...entFormattedTimestampJsonProviderTest.java | 123 ++++++++++++++++++
.../encoder/LogstashAccessEncoderTest.java | 11 +-
.../logback/encoder/LogstashEncoderTest.java | 26 ++--
7 files changed, 206 insertions(+), 78 deletions(-)
create mode 100644 src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventFormattedTimestampJsonProviderTest.java
diff --git a/README.md b/README.md
index 4e3183f0..60e179ad 100644
--- a/README.md
+++ b/README.md
@@ -1271,19 +1271,11 @@ The value can be written as a number (instead of a string) like this:
## Customizing Timestamp
-By default, timestamps are written as string values in the format `yyyy-MM-dd'T'HH:mm:ss.SSSZZ` (e.g. `2018-04-28T22:23:59.164-07:00`), in the default TimeZone of the host Java platform.
+By default, timestamps are written as string values in the format specified by
+[`DateTimeFormatter.ISO_OFFSET_DATE_TIME`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/format/DateTimeFormatter.html#ISO_OFFSET_DATE_TIME)
+(e.g. `2019-11-03T10:15:30.123+01:00`), in the default TimeZone of the host Java platform.
-You can change the timezone like this:
-
-```xml
-
- UTC
-
-```
-
-The value of the `timeZone` element can be any string accepted by java's `TimeZone.getTimeZone(String id)` method.
-
-You can change the pattern used like this:
+You can change the pattern like this:
```xml
@@ -1291,19 +1283,24 @@ You can change the pattern used like this:
```
-Use these timestamp pattern values to output the timestamp as a unix timestamp (number of milliseconds since unix epoch).
+The value of the `timestampPattern` can be any of the following:
-* `[UNIX_TIMESTAMP_AS_NUMBER]` - write the timestamp value as a numeric unix timestamp
-* `[UNIX_TIMESTAMP_AS_STRING]` - write the timestamp value as a string verion of the numeric unix timestamp
+* `[UNIX_TIMESTAMP_AS_NUMBER]` - timestamp written as a JSON number value of the milliseconds since unix epoch
+* `[UNIX_TIMESTAMP_AS_STRING]` - timestamp written as a JSON string value of the milliseconds since unix epoch
+* `[` _`constant`_ `]` - (e.g. `[ISO_OFFSET_DATE_TIME]`) timestamp written using the given `DateTimeFormatter` constant
+* any other value - (e.g. `yyyy-MM-dd'T'HH:mm:ss.SSS`) timestamp written using a `DateTimeFormatter` created from the given pattern
-For example:
+
+You can change the timezone like this:
```xml
- [UNIX_TIMESTAMP_AS_NUMBER]
+ UTC
```
+The value of the `timeZone` element can be any string accepted by java's `TimeZone.getTimeZone(String id)` method.
+
## Customizing JSON Factory and Generator
@@ -1607,12 +1604,7 @@ For LoggingEvents, the available providers and their configuration properties (d
Event timestamp
- fieldName - Output field name (@timestamp)
- - pattern - Output format (yyyy-MM-dd'T'HH:mm:ss.SSSZZ)
-
- - If set to [UNIX_TIMESTAMP_AS_NUMBER], then the timestamp will be written as a numeric unix timestamp value
- - If set to [UNIX_TIMESTAMP_AS_STRING], then the timestamp will be written as a string unix timestamp value
-
-
+ - pattern - Output format ([ISO_OFFSET_DATE_TIME]) See above for possible values.
- timeZone - Timezone (local timezone)
|
@@ -1863,12 +1855,7 @@ For AccessEvents, the available providers and their configuration properties (de
Event timestamp
- fieldName - Output field name (@timestamp)
- - pattern - Output format (yyyy-MM-dd'T'HH:mm:ss.SSSZZ)
-
- - If set to [UNIX_TIMESTAMP_AS_NUMBER], then the timestamp will be written as a numeric unix timestamp value
- - If set to [UNIX_TIMESTAMP_AS_STRING], then the timestamp will be written as a string unix timestamp value
-
-
+ - pattern - Output format ([ISO_OFFSET_DATE_TIME]) See above for possible values.
- timeZone - Timezone (local timezone)
|
diff --git a/pom.xml b/pom.xml
index a753cd08..2707c6dc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,6 @@
3.4.2
- 3.9
4.12
@@ -173,11 +172,6 @@
-->
true
-
- org.apache.commons
- commons-lang3
- ${commons-lang3.version}
-
com.lmax
disruptor
@@ -336,7 +330,7 @@
ch.qos.logback.classic
- !org.apache.commons.*,!com.lmax.disruptor.*,!ch.qos.logback.classic.*,!ch.qos.logback.core.*,!org.slf4j.*,*
+ !com.lmax.disruptor.*,!ch.qos.logback.classic.*,!ch.qos.logback.core.*,!org.slf4j.*,*
@@ -406,10 +400,6 @@
-
- org.apache.commons.lang3
- ${project.groupId}.encoder.org.apache.commons.lang3
-
com.lmax.disruptor
${project.groupId}.encoder.com.lmax.disruptor
diff --git a/src/main/java/net/logstash/logback/appender/listener/FailureSummaryLoggingAppenderListener.java b/src/main/java/net/logstash/logback/appender/listener/FailureSummaryLoggingAppenderListener.java
index a509385f..22318f87 100644
--- a/src/main/java/net/logstash/logback/appender/listener/FailureSummaryLoggingAppenderListener.java
+++ b/src/main/java/net/logstash/logback/appender/listener/FailureSummaryLoggingAppenderListener.java
@@ -14,11 +14,13 @@
package net.logstash.logback.appender.listener;
import java.time.Duration;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
import java.util.Objects;
+import java.util.TimeZone;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import net.logstash.logback.argument.StructuredArguments;
-import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,7 +54,7 @@ protected void handleFailureSummary(FailureSummary failureSummary, CallbackType
logger.warn("{} {} failures since {} for {}.",
StructuredArguments.value("failEventCount", failureSummary.getConsecutiveFailures()),
StructuredArguments.value("failType", callbackType.name().toLowerCase()),
- StructuredArguments.value("failStartTime", DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(failureSummary.getFirstFailureTime())),
+ StructuredArguments.value("failStartTime", DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(TimeZone.getDefault().toZoneId()).format(Instant.ofEpochMilli(failureSummary.getFirstFailureTime()))),
StructuredArguments.value("failDuration", Duration.ofMillis(System.currentTimeMillis() - failureSummary.getFirstFailureTime()).toString()),
failureSummary.getMostRecentFailure());
}
diff --git a/src/main/java/net/logstash/logback/composite/FormattedTimestampJsonProvider.java b/src/main/java/net/logstash/logback/composite/FormattedTimestampJsonProvider.java
index a370775d..fde60ca5 100644
--- a/src/main/java/net/logstash/logback/composite/FormattedTimestampJsonProvider.java
+++ b/src/main/java/net/logstash/logback/composite/FormattedTimestampJsonProvider.java
@@ -14,20 +14,21 @@
package net.logstash.logback.composite;
import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
import java.util.TimeZone;
-import net.logstash.logback.fieldnames.LogstashCommonFieldNames;
-
-import org.apache.commons.lang3.time.FastDateFormat;
-
import ch.qos.logback.core.spi.DeferredProcessingAware;
+import net.logstash.logback.fieldnames.LogstashCommonFieldNames;
import com.fasterxml.jackson.core.JsonGenerator;
/**
* Writes the timestamp field as either:
*
- * - A string value formatted by a {@link FastDateFormat} pattern
+ * - A string value formatted by a {@link DateTimeFormatter} pattern
* - A string value representing the number of milliseconds since unix epoch (designated by specifying the pattern value as {@value #UNIX_TIMESTAMP_AS_STRING})
* - A number value of the milliseconds since unix epoch (designated by specifying the pattern value as {@value #UNIX_TIMESTAMP_AS_NUMBER})
*
@@ -48,14 +49,20 @@ public abstract class FormattedTimestampJsonProviderPossible values:
+ *
+ *
+ * - {@value #UNIX_TIMESTAMP_AS_NUMBER} - timestamp written as a JSON number value of the milliseconds since unix epoch
+ * - {@value #UNIX_TIMESTAMP_AS_STRING} - timestamp written as a JSON string value of the milliseconds since unix epoch
+ * [constant]
- timestamp written using the {@link DateTimeFormatter} constant specified by constant
(e.g. {@code [ISO_OFFSET_DATE_TIME]})
+ * - any other value - timestamp written by a {@link DateTimeFormatter} created from the pattern string specified
+ *
*/
private String pattern = DEFAULT_PATTERN;
@@ -68,12 +75,12 @@ public abstract class FormattedTimestampJsonProvider