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

@@ -1863,12 +1855,7 @@ For AccessEvents, the available providers and their configuration properties (de

Event timestamp

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