You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/08/07 23:11:16 UTC
svn commit: r1511497 -
/tomcat/trunk/java/org/apache/juli/OneLineFormatter.java
Author: markt
Date: Wed Aug 7 21:11:15 2013
New Revision: 1511497
URL: http://svn.apache.org/r1511497
Log:
Improve the one line formatter so it outputs the correct thread ID even when using the async log writer.
Modified:
tomcat/trunk/java/org/apache/juli/OneLineFormatter.java
Modified: tomcat/trunk/java/org/apache/juli/OneLineFormatter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/juli/OneLineFormatter.java?rev=1511497&r1=1511496&r2=1511497&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/juli/OneLineFormatter.java (original)
+++ tomcat/trunk/java/org/apache/juli/OneLineFormatter.java Wed Aug 7 21:11:15 2013
@@ -19,6 +19,12 @@ package org.apache.juli;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
@@ -34,6 +40,27 @@ public class OneLineFormatter extends Fo
private static final String LINE_SEP = System.getProperty("line.separator");
private static final String ST_SEP = LINE_SEP + " ";
+ private static final String UNKONWN_THREAD_NAME = "Unknown thread with ID ";
+ private static final Object threadMxBeanLock = new Object();
+ private static volatile ThreadMXBean threadMxBean = null;
+ private static final int THREAD_NAME_CACHE_SIZE = 10000;
+ private static ThreadLocal<LinkedHashMap<Integer,String>> threadNameCache =
+ new ThreadLocal<LinkedHashMap<Integer,String>>() {
+
+ @Override
+ protected LinkedHashMap<Integer,String> initialValue() {
+ return new LinkedHashMap<Integer,String>() {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected boolean removeEldestEntry(
+ Entry<Integer, String> eldest) {
+ return (size() > THREAD_NAME_CACHE_SIZE);
+ }
+ };
+ }
+ };
/* Timestamp format */
private static final String timeFormat = "dd-MMM-yyyy HH:mm:ss";
@@ -79,7 +106,13 @@ public class OneLineFormatter extends Fo
// Thread
sb.append(' ');
sb.append('[');
- sb.append(Thread.currentThread().getName());
+ if (Thread.currentThread() instanceof AsyncFileHandler.LoggerThread) {
+ // If using the async handler can't get the thread name from the
+ // current thread.
+ sb.append(getThreadName(record.getThreadID()));
+ } else {
+ sb.append(Thread.currentThread().getName());
+ }
sb.append(']');
// Source
@@ -122,4 +155,47 @@ public class OneLineFormatter extends Fo
}
buf.append(frac);
}
+
+
+ /**
+ * LogRecord has threadID but no thread name.
+ * LogRecord uses an int for thread ID but thread IDs are longs.
+ * If the real thread ID > (Integer.MAXVALUE / 2) LogRecord uses it's own
+ * ID in an effort to avoid clashes due to overflow.
+ * <p>
+ * Words fail me to describe what I think of the design decision to use an
+ * int in LogRecord for a long value and the resulting mess that follows.
+ */
+ private static String getThreadName(int logRecordThreadId) {
+ Map<Integer,String> cache = threadNameCache.get();
+ String result = null;
+
+ if (logRecordThreadId > (Integer.MAX_VALUE / 2)) {
+ result = cache.get(Integer.valueOf(logRecordThreadId));
+ }
+
+ if (result != null) {
+ return result;
+ }
+
+ if (logRecordThreadId > Integer.MAX_VALUE / 2) {
+ result = UNKONWN_THREAD_NAME + logRecordThreadId;
+ } else {
+ // Double checked locking OK as threadMxBean is volatile
+ if (threadMxBean == null) {
+ synchronized (threadMxBeanLock) {
+ if (threadMxBean == null) {
+ threadMxBean = ManagementFactory.getThreadMXBean();
+ }
+ }
+ }
+ ThreadInfo threadInfo =
+ threadMxBean.getThreadInfo(logRecordThreadId);
+ result = threadInfo.getThreadName();
+ }
+
+ cache.put(Integer.valueOf(logRecordThreadId), result);
+
+ return result;
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org