This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/7.0.x by this push:
new 20cd6b7 BZ 64190 Add 'proper' ms support to OneLineFormatter.
20cd6b7 is described below
commit 20cd6b7712c738a45ef841eb8b6bb975ed11b8c2
Author: Mark Thomas <[email protected]>
AuthorDate: Tue Mar 3 14:36:08 2020 +0000
BZ 64190 Add 'proper' ms support to OneLineFormatter.
S SS or SSS can now be used (once) anywhere in the format String.
Format strings without S SS or SSS are now ~30% faster
The current default (effectively "dd-MMM-yyyy HH:mm:ss.SSS") is within
less than 1% of the old implementation.
Using S SS or SSS anywhere but the very end doubles the time taken to
generate the timestamp.
---
java/org/apache/juli/OneLineFormatter.java | 77 +++++++++++++++++++---
.../TestOneLineFormatterMillisPerformance.java | 70 ++++++++++++++++++++
webapps/docs/changelog.xml | 5 ++
3 files changed, 142 insertions(+), 10 deletions(-)
diff --git a/java/org/apache/juli/OneLineFormatter.java
b/java/org/apache/juli/OneLineFormatter.java
index ee97d11..3daf126 100644
--- a/java/org/apache/juli/OneLineFormatter.java
+++ b/java/org/apache/juli/OneLineFormatter.java
@@ -52,7 +52,7 @@ public class OneLineFormatter extends Formatter {
};
/* Timestamp format */
- private static final String DEFAULT_TIME_FORMAT = "dd-MMM-yyyy HH:mm:ss";
+ private static final String DEFAULT_TIME_FORMAT = "dd-MMM-yyyy
HH:mm:ss.SSS";
/**
* The size of our global date format cache
@@ -69,6 +69,8 @@ public class OneLineFormatter extends Formatter {
*/
private ThreadLocal<DateFormatCache> localDateCache;
+ private volatile MillisHandling millisHandling = MillisHandling.APPEND;
+
public OneLineFormatter() {
String timeFormat = LogManager.getLogManager().getProperty(
@@ -87,12 +89,31 @@ public class OneLineFormatter extends Formatter {
* {@link java.text.SimpleDateFormat} syntax
*/
public void setTimeFormat(final String timeFormat) {
+ final String cachedTimeFormat;
+
+ if (timeFormat.endsWith(".SSS")) {
+ cachedTimeFormat = timeFormat.substring(0, timeFormat.length() -
4);
+ millisHandling = MillisHandling.APPEND;
+ } else if (timeFormat.contains("SSS")) {
+ millisHandling = MillisHandling.REPLACE_SSS;
+ cachedTimeFormat = timeFormat;
+ } else if (timeFormat.contains("SS")) {
+ millisHandling = MillisHandling.REPLACE_SS;
+ cachedTimeFormat = timeFormat;
+ } else if (timeFormat.contains("S")) {
+ millisHandling = MillisHandling.REPLACE_S;
+ cachedTimeFormat = timeFormat;
+ } else {
+ millisHandling = MillisHandling.NONE;
+ cachedTimeFormat = timeFormat;
+ }
+
final DateFormatCache globalDateCache =
- new DateFormatCache(globalCacheSize, timeFormat, null);
+ new DateFormatCache(globalCacheSize, cachedTimeFormat, null);
localDateCache = new ThreadLocal<DateFormatCache>() {
@Override
protected DateFormatCache initialValue() {
- return new DateFormatCache(localCacheSize, timeFormat,
globalDateCache);
+ return new DateFormatCache(localCacheSize, cachedTimeFormat,
globalDateCache);
}
};
}
@@ -157,18 +178,45 @@ public class OneLineFormatter extends Formatter {
}
protected void addTimestamp(StringBuilder buf, long timestamp) {
- buf.append(localDateCache.get().getFormat(timestamp));
- long frac = timestamp % 1000;
- buf.append('.');
- if (frac < 100) {
- if (frac < 10) {
+ String cachedTimeStamp = localDateCache.get().getFormat(timestamp);
+ if (millisHandling == MillisHandling.NONE) {
+ buf.append(cachedTimeStamp);
+ } else if (millisHandling == MillisHandling.APPEND) {
+ buf.append(cachedTimeStamp);
+ long frac = timestamp % 1000;
+ buf.append('.');
+ if (frac < 100) {
+ if (frac < 10) {
+ buf.append('0');
+ buf.append('0');
+ } else {
+ buf.append('0');
+ }
+ }
+ buf.append(frac);
+ } else {
+ // Some version of replace
+ long frac = timestamp % 1000;
+ // Formatted string may vary in length so the insert point may vary
+ int insertStart = cachedTimeStamp.indexOf('#');
+ buf.append(cachedTimeStamp.subSequence(0, insertStart));
+ if (frac < 100 && millisHandling == MillisHandling.REPLACE_SSS) {
buf.append('0');
+ if (frac < 10) {
+ buf.append('0');
+ }
+ } else if (frac < 10 && millisHandling ==
MillisHandling.REPLACE_SS) {
buf.append('0');
+ }
+ buf.append(frac);
+ if (millisHandling == MillisHandling.REPLACE_SSS) {
+ buf.append(cachedTimeStamp.substring(insertStart + 3));
+ } else if (millisHandling == MillisHandling.REPLACE_SS) {
+ buf.append(cachedTimeStamp.substring(insertStart + 2));
} else {
- buf.append('0');
+ buf.append(cachedTimeStamp.substring(insertStart + 1));
}
}
- buf.append(frac);
}
@@ -251,4 +299,13 @@ public class OneLineFormatter extends Formatter {
super.println(x);
}
}
+
+
+ private static enum MillisHandling {
+ NONE,
+ APPEND,
+ REPLACE_S,
+ REPLACE_SS,
+ REPLACE_SSS,
+ }
}
diff --git a/test/org/apache/juli/TestOneLineFormatterMillisPerformance.java
b/test/org/apache/juli/TestOneLineFormatterMillisPerformance.java
new file mode 100644
index 0000000..b7c0cab
--- /dev/null
+++ b/test/org/apache/juli/TestOneLineFormatterMillisPerformance.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+
+@RunWith(Parameterized.class)
+public class TestOneLineFormatterMillisPerformance {
+
+ @Parameterized.Parameters(name = "{index}: format[{0}]")
+ public static Collection<Object[]> parameters() {
+
+ List<Object[]> parameterSets = new ArrayList<>();
+
+ parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SSS" });
+ parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SS" });
+ parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.S" });
+ parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss" });
+ parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss XXX" });
+ parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SSSXXX" });
+ parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SSXXX" });
+ parameterSets.add(new String[] { "dd-MMM-yyyy HH:mm:ss.SXXX" });
+ parameterSets.add(new String[] { "SSS dd-MMM-yyyy HH:mm:ss" });
+ parameterSets.add(new String[] { "SS dd-MMM-yyyy HH:mm:ss" });
+ parameterSets.add(new String[] { "S dd-MMM-yyyy HH:mm:ss" });
+
+ return parameterSets;
+ }
+
+
+ @Parameter(0)
+ public String timestampFormat;
+
+ @Test
+ public void testMillisHandling() {
+ OneLineFormatter olf = new OneLineFormatter();
+ olf.setTimeFormat(timestampFormat);
+
+ long timeStamp = System.currentTimeMillis();
+ StringBuilder buf = new StringBuilder(64);
+
+ long start = System.nanoTime();
+ for (int i = 0; i < 10000000; i++) {
+ buf.setLength(0);
+ olf.addTimestamp(buf, timeStamp);
+ }
+ System.out.println("Format: [" + timestampFormat + "], Output: [" +
buf + "], Duration: [" + (System.nanoTime() - start) + "] ns");
+ }
+}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 1deb684..f616f20 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -126,6 +126,11 @@
Expand the coverage of the Korean translations provided with Apache
Tomcat. Contributions provided by B. Cansmile Cha. (markt)
</add>
+ <add>
+ <bug>64190</bug>: Add support for specifing milliseconds (using
+ <code>S</code>, <code>SS</code> or <code>SSS</code>) in the timestamp
+ used by JULI's <code>OneLineFormatter</code>. (markt)
+ </add>
</changelog>
</subsection>
</section>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]