Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d9eb350
Move `InstantFormatter` to `log4j-core`
vy Oct 18, 2024
1cf4ac9
Update `com.github.jnr:jnr-ffi` to version `2.2.17` (#3082)
asf-rm Oct 14, 2024
062b945
Correct example property syntax for PatternMatch under ScriptPatternS…
martin-dorey-hv Oct 16, 2024
dfe0ada
Fixes property names in release notes (#3089)
ppkarwasz Oct 16, 2024
9ef736f
Remove JANSI dependency in `2.x` (#3070)
ppkarwasz Oct 16, 2024
c45f456
Update `co.elastic.clients:elasticsearch-java` to version `8.15.3` (#…
asf-rm Oct 18, 2024
b3a6fcc
Rewrite `InstantPatternDynamicFormatter`
vy Oct 25, 2024
f255f0b
Merge remote-tracking branch 'origin/2.x' into feature/2.x/cached-ins…
vy Oct 25, 2024
3e39405
Fix Javadoc
vy Oct 25, 2024
8d3ba30
More Javadoc fixes
vy Oct 25, 2024
80a7c27
Fix Spotless failures
vy Oct 25, 2024
4f431d6
Add #2943 to the changelog
vy Oct 25, 2024
2f74ffc
Fix Java 8 errors
vy Oct 25, 2024
ff4f688
Remove redundant `DatePatternConverter.Formatter`
vy Oct 25, 2024
9e7f4ce
Merge remote-tracking branch 'origin/2.x' into feature/2.x/cached-ins…
vy Oct 27, 2024
12ec63a
Decrease the visibility of `InstantPatternDynamicFormatter`
vy Oct 27, 2024
8281082
Remove deprecated `TimeFormatBenchmark`
vy Oct 27, 2024
4d3b5db
Merge remote-tracking branch 'origin/2.x' into feature/2.x/cached-ins…
vy Oct 28, 2024
1f84806
Export `o.a.l.l.c.util.internal.instant` package
vy Oct 28, 2024
612adf8
Add `@ExportTo` for the `o.a.l.l.c.util.internal.instant` package
vy Oct 29, 2024
9c64a39
Improve docs
vy Oct 29, 2024
cce4fa9
Fix `site` failure
vy Oct 29, 2024
33218ce
Fix date pattern in `log4j-rolling-size-with-time.xml`
vy Oct 29, 2024
523251d
Merge remote-tracking branch 'origin/2.x' into feature/2.x/cached-ins…
vy Oct 29, 2024
02f7bee
Document potential optimization directions
vy Oct 30, 2024
4bf4232
Merge remote-tracking branch 'origin/2.x' into feature/2.x/cached-ins…
vy Oct 31, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import static org.apache.logging.log4j.core.util.internal.instant.InstantPatternDynamicFormatter.sequencePattern;
import static org.assertj.core.api.Assertions.assertThat;

import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
Expand All @@ -38,7 +37,6 @@
import org.apache.logging.log4j.core.util.internal.instant.InstantPatternDynamicFormatter.PatternSequence;
import org.apache.logging.log4j.core.util.internal.instant.InstantPatternDynamicFormatter.StaticPatternSequence;
import org.apache.logging.log4j.util.Constants;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
Expand Down Expand Up @@ -379,27 +377,48 @@ private static String formatInstant(
return buffer.toString();
}

@Test
void f() {
final String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS";
final Locale LOCALE = Locale.US;
final TimeZone TIME_ZONE = TimeZone.getTimeZone("UTC");
final InstantPatternFormatter formatter = InstantPatternFormatter.newBuilder()
.setPattern(pattern)
.setLocale(LOCALE)
.setTimeZone(TIME_ZONE)
.setCachingEnabled(false)
.build();
final StringBuilder buffer = new StringBuilder();
final MutableInstant mutableInstant = new MutableInstant();

final Instant instant1 = Instant.now();
mutableInstant.initFromEpochSecond(instant1.getEpochSecond(), instant1.getNano());
formatter.formatTo(buffer, mutableInstant);

buffer.setLength(0);
final Instant instant2 = instant1.plusMillis(1);
mutableInstant.initFromEpochSecond(instant2.getEpochSecond(), instant2.getNano());
formatter.formatTo(buffer, mutableInstant);
@ParameterizedTest
@MethodSource("formatterInputs")
void verify_manually_computed_sub_minute_precision_values(
final String ignoredPattern,
final Locale ignoredLocale,
final TimeZone timeZone,
final MutableInstant instant) {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"HH:mm:ss.S-SS-SSS-SSSS-SSSSS-SSSSSS-SSSSSSS-SSSSSSSS-SSSSSSSSS|n")
.withZone(timeZone.toZoneId());
final String formatterOutput = formatter.format(instant);
final int offsetMillis = timeZone.getOffset(instant.getEpochMillisecond());
final long adjustedEpochSeconds = (instant.getEpochMillisecond() + offsetMillis) / 1000;
// 86400 seconds per day, 3600 seconds per hour
final int local_H = (int) ((adjustedEpochSeconds % 86400L) / 3600L);
final int local_m = (int) ((adjustedEpochSeconds / 60) % 60);
final int local_s = (int) (adjustedEpochSeconds % 60);
final int local_S = instant.getNanoOfSecond() / 100000000;
final int local_SS = instant.getNanoOfSecond() / 10000000;
final int local_SSS = instant.getNanoOfSecond() / 1000000;
final int local_SSSS = instant.getNanoOfSecond() / 100000;
final int local_SSSSS = instant.getNanoOfSecond() / 10000;
final int local_SSSSSS = instant.getNanoOfSecond() / 1000;
final int local_SSSSSSS = instant.getNanoOfSecond() / 100;
final int local_SSSSSSSS = instant.getNanoOfSecond() / 10;
final int local_SSSSSSSSS = instant.getNanoOfSecond();
final int local_n = instant.getNanoOfSecond();
final String output = String.format(
"%02d:%02d:%02d.%d-%d-%d-%d-%d-%d-%d-%d-%d|%d",
local_H,
local_m,
local_s,
local_S,
local_SS,
local_SSS,
local_SSSS,
local_SSSSS,
local_SSSSSS,
local_SSSSSSS,
local_SSSSSSSS,
local_SSSSSSSSS,
local_n);
assertThat(output).isEqualTo(formatterOutput);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,30 @@
* <li>Precompute and cache the output for parts that are of precision lower than or equal to {@value InstantPatternDynamicFormatter#PRECISION_THRESHOLD} (i.e., {@code yyyy-MM-dd'T'HH:mm:} and {@code X}) and cache it</li>
* <li>Upon a formatting request, combine the cached outputs with the dynamic parts (i.e., {@code ss.SSS})</li>
* </ol>
* <h2>Implementation note</h2>
* <p>
* Formatting can actually even be made faster and garbage-free by manually formatting sub-minute precision directives as follows:
* </p>
* <pre>{@code
* int offsetMillis = timeZone.getOffset(mutableInstant.getEpochMillisecond());
* long adjustedEpochSeconds = (instant.getEpochMillisecond() + offsetMillis) / 1000;
* int local_s = (int) (adjustedEpochSeconds % 60);
* int local_S = instant.getNanoOfSecond() / 100000000;
* int local_SS = instant.getNanoOfSecond() / 10000000;
* int local_SSS = instant.getNanoOfSecond() / 1000000;
* int local_SSSS = instant.getNanoOfSecond() / 100000;
* int local_SSSSS = instant.getNanoOfSecond() / 10000;
* int local_SSSSSS = instant.getNanoOfSecond() / 1000;
* int local_SSSSSSS = instant.getNanoOfSecond() / 100;
* int local_SSSSSSSS = instant.getNanoOfSecond() / 10;
* int local_SSSSSSSSS = instant.getNanoOfSecond();
* int local_n = instant.getNanoOfSecond();
* }</pre>
* <p>
* Though this will require more hardcoded formatting and a change in the sequence merging strategies.
* Hence, this optimization is intentionally shelved off due to involved complexity.
* See {@code verify_manually_computed_sub_minute_precision_values()} in {@code InstantPatternDynamicFormatterTest} for a demonstration of this optimization.
* </p>
*
* @since 2.25.0
*/
Expand Down