[LOG4J2-1299] Add pattern converter for thread id and priority in
PatternLayout.

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/585beba1
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/585beba1
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/585beba1

Branch: refs/heads/master
Commit: 585beba1eeebe0ba771ce0e4364954861e1db154
Parents: 1bd8a51
Author: ggregory <[email protected]>
Authored: Tue Mar 1 10:43:21 2016 -0800
Committer: ggregory <[email protected]>
Committed: Tue Mar 1 10:43:21 2016 -0800

----------------------------------------------------------------------
 .../logging/log4j/core/AbstractLogEvent.java    | 10 ++
 .../org/apache/logging/log4j/core/LogEvent.java | 16 +++-
 .../db/jpa/AbstractLogEventWrapperEntity.java   | 20 ++++
 .../appender/db/jpa/BasicLogEventEntity.java    | 22 +++++
 .../logging/log4j/core/async/AsyncLogger.java   | 15 +--
 .../log4j/core/async/RingBufferLogEvent.java    | 28 +++++-
 .../async/RingBufferLogEventTranslator.java     | 28 +++---
 .../core/async/ThreadNameCachingStrategy.java   | 35 ++++++-
 .../logging/log4j/core/impl/Log4jLogEvent.java  | 96 +++++++++++++++-----
 .../log4j/core/jackson/LogEventMixIn.java       | 10 ++
 .../log4j/core/layout/CsvLogEventLayout.java    |  2 +
 .../core/pattern/ThreadIdPatternConverter.java  | 61 +++++++++++++
 .../pattern/ThreadNamePatternConverter.java     | 59 ++++++++++++
 .../core/pattern/ThreadPatternConverter.java    | 59 ------------
 .../pattern/ThreadPriorityPatternConverter.java | 61 +++++++++++++
 .../apache/logging/log4j/core/LogEventTest.java |  2 +
 .../core/appender/db/jpa/JpaH2AppenderTest.java |  2 +-
 .../db/jpa/JpaHyperSqlAppenderTest.java         |  2 +-
 .../core/appender/db/jpa/TestBaseEntity.java    | 12 +++
 .../core/async/RingBufferLogEventTest.java      | 10 +-
 .../log4j/core/impl/Log4jLogEventTest.java      |  3 +-
 .../log4j/core/net/server/ThreadIdFilter.java   | 40 ++++++++
 .../core/net/server/ThreadPriorityFilter.java   | 40 ++++++++
 .../log4j/core/pattern/PatternParserTest.java   | 37 +++++++-
 .../pattern/ThreadIdPatternConverterTest.java   | 39 ++++++++
 .../pattern/ThreadNamePatternConverterTest.java |  2 +-
 .../ThreadPriorityPatternConverterTest.java     | 39 ++++++++
 .../log4j/flume/appender/FlumeEvent.java        | 18 ++++
 .../nosql/appender/NoSqlDatabaseManager.java    |  2 +
 .../appender/NoSqlDatabaseManagerTest.java      |  6 ++
 src/changes/changes.xml                         |  3 +
 src/site/xdoc/manual/layouts.xml.vm             | 28 +++++-
 32 files changed, 689 insertions(+), 118 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java
index cd1b4e9..489a156 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java
@@ -78,11 +78,21 @@ public abstract class AbstractLogEvent implements LogEvent {
     }
 
     @Override
+    public long getThreadId() {
+        return 0;
+    }
+
+    @Override
     public String getThreadName() {
         return null;
     }
 
     @Override
+    public int getThreadPriority() {
+        return 0;
+    }
+
+    @Override
     public Throwable getThrown() {
         return null;
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
index e89f6e5..422a2d1 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
@@ -106,7 +106,7 @@ public interface LogEvent extends Serializable {
     StackTraceElement getSource();
 
     /**
-     * Gets thread name.
+     * Gets the thread name.
      *
      * @return thread name, may be null.
      * TODO guess this could go into a thread context object too. (RG) Why?
@@ -114,6 +114,20 @@ public interface LogEvent extends Serializable {
     String getThreadName();
 
     /**
+     * Gets the thread ID.
+     *
+     * @return thread ID.
+     */
+    long getThreadId();
+
+    /**
+     * Gets the thread priority.
+     *
+     * @return thread priority.
+     */
+    int getThreadPriority();
+
+    /**
      * Gets throwable associated with logging request.
      *
      * <p>Convenience method for {@code ThrowableProxy.getThrowable();}</p>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
index ae256ef..edddfb4 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
@@ -159,6 +159,16 @@ public abstract class AbstractLogEventWrapperEntity 
implements LogEvent {
     /**
      * A no-op mutator to satisfy JPA requirements, as this entity is 
write-only.
      *
+     * @param threadId Ignored.
+     */
+    @SuppressWarnings("unused")
+    public void setThreadId(final long threadId) {
+        // this entity is write-only
+    }
+
+    /**
+     * A no-op mutator to satisfy JPA requirements, as this entity is 
write-only.
+     *
      * @param threadName Ignored.
      */
     @SuppressWarnings("unused")
@@ -169,6 +179,16 @@ public abstract class AbstractLogEventWrapperEntity 
implements LogEvent {
     /**
      * A no-op mutator to satisfy JPA requirements, as this entity is 
write-only.
      *
+     * @param threadPriority Ignored.
+     */
+    @SuppressWarnings("unused")
+    public void setThreadPriority(final int threadPriority) {
+        // this entity is write-only
+    }
+
+    /**
+     * A no-op mutator to satisfy JPA requirements, as this entity is 
write-only.
+     *
      * @param nanoTime Ignored.
      */
     @SuppressWarnings("unused")

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java
index a732e53..8fc49dc 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java
@@ -147,6 +147,28 @@ public abstract class BasicLogEventEntity extends 
AbstractLogEventWrapperEntity
     }
 
     /**
+     * Gets the thread ID. Annotated with {@code @Basic}.
+     *
+     * @return the thread ID.
+     */
+    @Override
+    @Basic
+    public long getThreadId() {
+        return this.getWrappedEvent().getThreadId();
+    }
+
+    /**
+     * Gets the thread name. Annotated with {@code @Basic}.
+     *
+     * @return the thread name.
+     */
+    @Override
+    @Basic
+    public int getThreadPriority() {
+        return this.getWrappedEvent().getThreadPriority();
+    }
+
+    /**
      * Gets the thread name. Annotated with {@code @Basic}.
      *
      * @return the thread name.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
index dbee74f..d7ffb3c 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
@@ -245,14 +245,15 @@ public class AsyncLogger extends Logger implements 
EventTranslatorVararg<RingBuf
                 // needs shallow copy to be fast (LOG4J2-154)
                 ThreadContext.getImmutableStack(), //
 
+                THREAD_NAME_CACHING_STRATEGY.getThreadId(), //
+
                 // Thread.currentThread().getName(), //
-                THREAD_NAME_CACHING_STRATEGY.getThreadName(), //
+                THREAD_NAME_CACHING_STRATEGY.getThreadName(),
 
+                THREAD_NAME_CACHING_STRATEGY.getThreadPriority(), //
                 // location (expensive to calculate)
-                calcLocationIfRequested(fqcn),
-
-                eventTimeMillis(message), //
-                nanoClock.nanoTime() //
+                calcLocationIfRequested(fqcn)
+, eventTimeMillis(message), nanoClock.nanoTime() //
                 );
     }
 
@@ -315,10 +316,12 @@ public class AsyncLogger extends Logger implements 
EventTranslatorVararg<RingBuf
         // needs shallow copy to be fast (LOG4J2-154)
         final ContextStack contextStack = ThreadContext.getImmutableStack();
 
+        final Long threadId = THREAD_NAME_CACHING_STRATEGY.getThreadId();
         final String threadName = THREAD_NAME_CACHING_STRATEGY.getThreadName();
+        final Integer threadPriority = 
THREAD_NAME_CACHING_STRATEGY.getThreadPriority();
 
         event.setValues(asyncLogger, asyncLogger.getName(), marker, fqcn, 
level, message, thrown, contextMap,
-                contextStack, threadName, location, eventTimeMillis(message), 
nanoClock.nanoTime());
+                contextStack, threadId, threadName, threadPriority, location, 
eventTimeMillis(message), nanoClock.nanoTime());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
index 010b877..37c7be0 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
@@ -119,7 +119,9 @@ public class RingBufferLogEvent implements LogEvent {
     private ThrowableProxy thrownProxy;
     private Map<String, String> contextMap;
     private ContextStack contextStack;
+    private long threadId;
     private String threadName;
+    private int threadPriority;
     private StackTraceElement location;
     private long currentTimeMillis;
     private boolean endOfBatch;
@@ -128,8 +130,8 @@ public class RingBufferLogEvent implements LogEvent {
 
     public void setValues(final AsyncLogger anAsyncLogger, final String 
aLoggerName, final Marker aMarker,
             final String theFqcn, final Level aLevel, final Message msg, final 
Throwable aThrowable,
-            final Map<String, String> aMap, final ContextStack aContextStack, 
final String aThreadName,
-            final StackTraceElement aLocation, final long aCurrentTimeMillis, 
final long aNanoTime) {
+            final Map<String, String> aMap, final ContextStack aContextStack, 
long threadId,
+            final String threadName, int threadPriority, final 
StackTraceElement aLocation, final long aCurrentTimeMillis, final long 
aNanoTime) {
         this.asyncLogger = anAsyncLogger;
         this.loggerName = aLoggerName;
         this.marker = aMarker;
@@ -150,7 +152,9 @@ public class RingBufferLogEvent implements LogEvent {
         this.thrownProxy = null;
         this.contextMap = aMap;
         this.contextStack = aContextStack;
-        this.threadName = aThreadName;
+        this.threadId = threadId;
+        this.threadName = threadName;
+        this.threadPriority = threadPriority;
         this.location = aLocation;
         this.currentTimeMillis = aCurrentTimeMillis;
         this.nanoTime = aNanoTime;
@@ -259,11 +263,21 @@ public class RingBufferLogEvent implements LogEvent {
     }
 
     @Override
+    public long getThreadId() {
+        return threadId;
+    }
+
+    @Override
     public String getThreadName() {
         return threadName;
     }
 
     @Override
+    public int getThreadPriority() {
+        return threadPriority;
+    }
+
+    @Override
     public StackTraceElement getSource() {
         return location;
     }
@@ -319,10 +333,11 @@ public class RingBufferLogEvent implements LogEvent {
                 null, // t
                 null, // map
                 null, // contextStack
-                null, // threadName
+                0, // threadName
                 null, // location
                 0, // currentTimeMillis
-                0 // nanoTime
+                null, 
+                0, 0 // nanoTime
         );
     }
 
@@ -357,9 +372,12 @@ public class RingBufferLogEvent implements LogEvent {
                 .setMessage(getMessage()) // ensure non-null
                 .setNanoTime(nanoTime) //
                 .setSource(location) //
+                .setThreadId(threadId) //
                 .setThreadName(threadName) //
+                .setThreadPriority(threadPriority) //
                 .setThrown(getThrown()) // may deserialize from thrownProxy
                 .setThrownProxy(thrownProxy) // avoid unnecessarily creating 
thrownProxy
                 .setTimeMillis(currentTimeMillis);
     }
+
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
index 519ffb9..37a4825 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
@@ -43,7 +43,9 @@ public class RingBufferLogEventTranslator implements
     private Throwable thrown;
     private Map<String, String> contextMap;
     private ContextStack contextStack;
+    private long threadId;
     private String threadName;
+    private int threadPriority;
     private StackTraceElement location;
     private long currentTimeMillis;
     private long nanoTime;
@@ -51,9 +53,8 @@ public class RingBufferLogEventTranslator implements
     // @Override
     @Override
     public void translateTo(final RingBufferLogEvent event, final long 
sequence) {
-        event.setValues(asyncLogger, loggerName, marker, fqcn, level, message,
-                thrown, contextMap, contextStack, threadName, location,
-                currentTimeMillis, nanoTime);
+        event.setValues(asyncLogger, loggerName, marker, fqcn, level, message, 
thrown, contextMap, contextStack,
+                threadId, threadName, threadPriority, location, 
currentTimeMillis, nanoTime);
         clear();
     }
 
@@ -71,17 +72,18 @@ public class RingBufferLogEventTranslator implements
                 null, // t
                 null, // map
                 null, // contextStack
-                null, // threadName
+                0, // threadName
                 null, // location
                 0, // currentTimeMillis
-                0 // nanoTime
+                null, 
+                0, 0 // nanoTime
         );
     }
 
     public void setValues(final AsyncLogger anAsyncLogger, final String 
aLoggerName, final Marker aMarker,
             final String theFqcn, final Level aLevel, final Message msg, final 
Throwable aThrowable,
-            final Map<String, String> aMap, final ContextStack aContextStack, 
final String aThreadName,
-            final StackTraceElement aLocation, final long aCurrentTimeMillis, 
final long aNanoTime) {
+            final Map<String, String> aMap, final ContextStack aContextStack, 
long threadId,
+            final String threadName, int threadPriority, final 
StackTraceElement aLocation, final long aCurrentTimeMillis, final long 
aNanoTime) {
         this.asyncLogger = anAsyncLogger;
         this.loggerName = aLoggerName;
         this.marker = aMarker;
@@ -91,7 +93,9 @@ public class RingBufferLogEventTranslator implements
         this.thrown = aThrowable;
         this.contextMap = aMap;
         this.contextStack = aContextStack;
-        this.threadName = aThreadName;
+        this.threadId = threadId;
+        this.threadName = threadName;
+        this.threadPriority = threadPriority;
         this.location = aLocation;
         this.currentTimeMillis = aCurrentTimeMillis;
         this.nanoTime = aNanoTime;
@@ -108,11 +112,13 @@ public class RingBufferLogEventTranslator implements
         this.thrown = aThrowable;
     }
 
-    public void setValuesPart2(final Map<String, String> aMap, final 
ContextStack aContextStack, final String aThreadName,
-            final StackTraceElement aLocation, final long aCurrentTimeMillis, 
final long aNanoTime) {
+    public void setValuesPart2(final Map<String, String> aMap, final 
ContextStack aContextStack, long threadId,
+            final String threadName, int threadPriority, final 
StackTraceElement aLocation, final long aCurrentTimeMillis, final long 
aNanoTime) {
         this.contextMap = aMap;
         this.contextStack = aContextStack;
-        this.threadName = aThreadName;
+        this.threadId = threadId;
+        this.threadName = threadName;
+        this.threadPriority = threadPriority;
         this.location = aLocation;
         this.currentTimeMillis = aCurrentTimeMillis;
         this.nanoTime = aNanoTime;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/async/ThreadNameCachingStrategy.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/ThreadNameCachingStrategy.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/ThreadNameCachingStrategy.java
index 69fb55b..0de95a8 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/ThreadNameCachingStrategy.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/ThreadNameCachingStrategy.java
@@ -26,6 +26,16 @@ import org.apache.logging.log4j.util.PropertiesUtil;
 enum ThreadNameCachingStrategy { // LOG4J2-467
     CACHED {
         @Override
+        public long getThreadId() {
+            Long result = THREADLOCAL_ID.get();
+            if (result == null) {
+                result = Thread.currentThread().getId();
+                THREADLOCAL_ID.set(result);
+            }
+            return result;
+        }
+
+        @Override
         public String getThreadName() {
             String result = THREADLOCAL_NAME.get();
             if (result == null) {
@@ -34,19 +44,42 @@ enum ThreadNameCachingStrategy { // LOG4J2-467
             }
             return result;
         }
+
+        @Override
+        public int getThreadPriority() {
+            Integer result = THREADLOCAL_PRIORITY.get();
+            if (result == null) {
+                result = Thread.currentThread().getPriority();
+                THREADLOCAL_PRIORITY.set(result);
+            }
+            return result;
+        }
     },
     UNCACHED {
         @Override
+        public long getThreadId() {
+            return Thread.currentThread().getId();
+        }
+
+        @Override
         public String getThreadName() {
             return Thread.currentThread().getName();
         }
+
+        @Override
+        public int getThreadPriority() {
+            return Thread.currentThread().getPriority();
+        }
     };
     
     private static final StatusLogger LOGGER = StatusLogger.getLogger();
+    private static final ThreadLocal<Long> THREADLOCAL_ID = new 
ThreadLocal<>();
     private static final ThreadLocal<String> THREADLOCAL_NAME = new 
ThreadLocal<>();
+    private static final ThreadLocal<Integer> THREADLOCAL_PRIORITY = new 
ThreadLocal<>();
     
-    
+    abstract long getThreadId();
     abstract String getThreadName();
+    abstract int getThreadPriority();
 
     static ThreadNameCachingStrategy create() {
         final String name = 
PropertiesUtil.getProperties().getStringProperty("AsyncLogger.ThreadNameStrategy",

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
index 4fe1b38..d8ff470 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
@@ -47,7 +47,7 @@ import org.apache.logging.log4j.util.Strings;
  */
 public class Log4jLogEvent implements LogEvent {
 
-    private static final long serialVersionUID = -1351367343806656055L;
+    private static final long serialVersionUID = -8393305700508709443L;
     private static final Clock CLOCK = ClockFactory.getClock();
     private static volatile NanoClock nanoClock = new DummyNanoClock();
     private final String loggerFqcn;
@@ -60,7 +60,9 @@ public class Log4jLogEvent implements LogEvent {
     private ThrowableProxy thrownProxy;
     private final Map<String, String> contextMap;
     private final ThreadContext.ContextStack contextStack;
+    private long threadId;
     private String threadName;
+    private int threadPriority;
     private StackTraceElement source;
     private boolean includeLocation;
     private boolean endOfBatch = false;
@@ -80,7 +82,9 @@ public class Log4jLogEvent implements LogEvent {
         private ThrowableProxy thrownProxy;
         private Map<String, String> contextMap = 
ThreadContext.getImmutableContext();
         private ThreadContext.ContextStack contextStack = 
ThreadContext.getImmutableStack();
-        private String threadName = null;
+        private long threadId;
+        private String threadName;
+        private int threadPriority;
         private StackTraceElement source;
         private boolean includeLocation;
         private boolean endOfBatch = false;
@@ -114,11 +118,15 @@ public class Log4jLogEvent implements LogEvent {
                 Log4jLogEvent evt = (Log4jLogEvent) other;
                 this.thrownProxy = evt.thrownProxy;
                 this.source = evt.source;
+                this.threadId = evt.threadId;
                 this.threadName = evt.threadName;
+                this.threadPriority = evt.threadPriority;
             } else {
                 this.thrownProxy = other.getThrownProxy();
                 this.source = other.getSource();
+                this.threadId = other.getThreadId();
                 this.threadName = other.getThreadName();
+                this.threadPriority = other.getThreadPriority();
             }
         }
 
@@ -172,11 +180,21 @@ public class Log4jLogEvent implements LogEvent {
             return this;
         }
 
+        public Builder setThreadId(long threadId) {
+            this.threadId = threadId;
+            return this;
+        }
+
         public Builder setThreadName(String threadName) {
             this.threadName = threadName;
             return this;
         }
 
+        public Builder setThreadPriority(int threadPriority) {
+            this.threadPriority = threadPriority;
+            return this;
+        }
+
         public Builder setSource(StackTraceElement source) {
             this.source = source;
             return this;
@@ -206,7 +224,7 @@ public class Log4jLogEvent implements LogEvent {
         @Override
         public Log4jLogEvent build() {
             final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, 
loggerFqcn, level, message, thrown,
-                    thrownProxy, contextMap, contextStack, threadName, source, 
timeMillis, nanoTime);
+                    thrownProxy, contextMap, contextStack, threadId, 
threadName, threadPriority, source, timeMillis, nanoTime);
             result.setIncludeLocation(includeLocation);
             result.setEndOfBatch(endOfBatch);
             return result;
@@ -222,8 +240,8 @@ public class Log4jLogEvent implements LogEvent {
     }
 
     public Log4jLogEvent() {
-        this(Strings.EMPTY, null, Strings.EMPTY, null, null, (Throwable) null, 
null, null, null, null, null,
-                CLOCK.currentTimeMillis(), nanoClock.nanoTime());
+        this(Strings.EMPTY, null, Strings.EMPTY, null, null, (Throwable) null, 
null, null, null, 0, null,
+                0, null, CLOCK.currentTimeMillis(), nanoClock.nanoTime());
     }
 
     /**
@@ -232,8 +250,8 @@ public class Log4jLogEvent implements LogEvent {
     */
    @Deprecated
    public Log4jLogEvent(final long timestamp) {
-       this(Strings.EMPTY, null, Strings.EMPTY, null, null, (Throwable) null, 
null, null, null, null, null,
-               timestamp, nanoClock.nanoTime());
+       this(Strings.EMPTY, null, Strings.EMPTY, null, null, (Throwable) null, 
null, null, null, 0, null,
+               0, null, timestamp, nanoClock.nanoTime());
    }
 
    /**
@@ -268,13 +286,13 @@ public class Log4jLogEvent implements LogEvent {
        this(loggerName, marker, loggerFQCN, level, message, t, null,
            createMap(properties),
            ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack(), 
// mutable copy
-           null, // thread name
+           0, // thread name
            null, // stack trace element
-           // LOG4J2-628 use log4j.Clock for timestamps
+           0,
+           null, // LOG4J2-628 use log4j.Clock for timestamps
            // LOG4J2-744 unless TimestampMessage already has one
            message instanceof TimestampMessage ? ((TimestampMessage) 
message).getTimestamp() :
-               CLOCK.currentTimeMillis(),
-           nanoClock.nanoTime());
+               CLOCK.currentTimeMillis(), nanoClock.nanoTime());
    }
 
    /**
@@ -297,8 +315,8 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
                         final Message message, final Throwable t, final 
Map<String, String> mdc,
                         final ThreadContext.ContextStack ndc, final String 
threadName,
                         final StackTraceElement location, final long 
timestampMillis) {
-       this(loggerName, marker, loggerFQCN, level, message, t, null, mdc, ndc, 
threadName,
-               location, timestampMillis, nanoClock.nanoTime());
+       this(loggerName, marker, loggerFQCN, level, message, t, null, mdc, ndc, 
0,
+               threadName, 0, location, timestampMillis, nanoClock.nanoTime());
    }
 
    /**
@@ -326,7 +344,7 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
                                             final String threadName, final 
StackTraceElement location,
                                             final long timestamp) {
         final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, 
loggerFQCN, level, message, thrown,
-                thrownProxy, mdc, ndc, threadName, location, timestamp, 
nanoClock.nanoTime());
+                thrownProxy, mdc, ndc, 0, threadName, 0, location, timestamp, 
nanoClock.nanoTime());
         return result;
     }
 
@@ -341,7 +359,9 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
      * @param thrownProxy A ThrowableProxy or null.
      * @param contextMap The mapped diagnostic context.
      * @param contextStack the nested diagnostic context.
+     * @param threadId the thread ID
      * @param threadName The name of the thread.
+     * @param threadPriority the thread priority
      * @param source The locations of the caller.
      * @param timestampMillis The timestamp of the event.
      * @param nanoTime The value of the running Java Virtual Machine's 
high-resolution time source when the event was
@@ -349,8 +369,9 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
      */
     private Log4jLogEvent(final String loggerName, final Marker marker, final 
String loggerFQCN, final Level level,
             final Message message, final Throwable thrown, final 
ThrowableProxy thrownProxy,
-            final Map<String, String> contextMap, final 
ThreadContext.ContextStack contextStack,
-            final String threadName, final StackTraceElement source, final 
long timestampMillis, final long nanoTime) {
+            final Map<String, String> contextMap, final 
ThreadContext.ContextStack contextStack, long threadId,
+            final String threadName, int threadPriority, final 
StackTraceElement source, final long timestampMillis,
+            final long nanoTime) {
         this.loggerName = loggerName;
         this.marker = marker;
         this.loggerFqcn = loggerFQCN;
@@ -363,7 +384,9 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
         this.timeMillis = message instanceof TimestampMessage
                 ? ((TimestampMessage) message).getTimestamp()
                 : timestampMillis;
+        this.threadId = threadId;
         this.threadName = threadName;
+        this.threadPriority = threadPriority;
         this.source = source;
         if (message != null && message instanceof LoggerNameAwareMessage) {
             ((LoggerNameAwareMessage) message).setLoggerName(loggerName);
@@ -442,6 +465,14 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
         return message;
     }
 
+    @Override
+    public long getThreadId() {
+        if (threadId == 0) {
+            threadId = Thread.currentThread().getId();
+        }
+        return threadId;
+    }
+
     /**
      * Returns the name of the Thread on which the event was generated.
      * @return The name of the Thread.
@@ -454,6 +485,14 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
         return threadName;
     }
 
+    @Override
+    public int getThreadPriority() {
+        if (threadPriority == 0) {
+            threadPriority = Thread.currentThread().getPriority();
+        }
+        return threadPriority;
+    }
+
     /**
      * Returns the time in milliseconds from the epoch when the event occurred.
      * @return The time the event occurred.
@@ -605,8 +644,8 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
             final LogEventProxy proxy = (LogEventProxy) event;
             final Log4jLogEvent result = new Log4jLogEvent(proxy.loggerName, 
proxy.marker,
                     proxy.loggerFQCN, proxy.level, proxy.message,
-                    proxy.thrown, proxy.thrownProxy, proxy.contextMap, 
proxy.contextStack, proxy.threadName,
-                    proxy.source, proxy.timeMillis, proxy.nanoTime);
+                    proxy.thrown, proxy.thrownProxy, proxy.contextMap, 
proxy.contextStack, proxy.threadId,
+                    proxy.threadName, proxy.threadPriority, proxy.source, 
proxy.timeMillis, proxy.nanoTime);
             result.setEndOfBatch(proxy.isEndOfBatch);
             result.setIncludeLocation(proxy.isLocationRequired);
             return result;
@@ -675,9 +714,15 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
         if (contextStack != null ? !contextStack.equals(that.contextStack) : 
that.contextStack != null) {
             return false;
         }
+        if (threadId != that.threadId) {
+            return false;
+        }
         if (threadName != null ? !threadName.equals(that.threadName) : 
that.threadName != null) {
             return false;
         }
+        if (threadPriority != that.threadPriority) {
+            return false;
+        }
         if (thrown != null ? !thrown.equals(that.thrown) : that.thrown != 
null) {
             return false;
         }
@@ -702,7 +747,9 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
         result = 31 * result + (thrownProxy != null ? thrownProxy.hashCode() : 
0);
         result = 31 * result + (contextMap != null ? contextMap.hashCode() : 
0);
         result = 31 * result + (contextStack != null ? contextStack.hashCode() 
: 0);
+        result = 31 * result + (int) (threadId ^ (threadId >>> 32));
         result = 31 * result + (threadName != null ? threadName.hashCode() : 
0);
+        result = 31 * result + (threadPriority ^ (threadPriority >>> 32));
         result = 31 * result + (source != null ? source.hashCode() : 0);
         result = 31 * result + (includeLocation ? 1 : 0);
         result = 31 * result + (endOfBatch ? 1 : 0);
@@ -715,7 +762,7 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
      */
     private static class LogEventProxy implements Serializable {
 
-        private static final long serialVersionUID = -7139032940312647146L;
+        private static final long serialVersionUID = -8634075037355293699L;
         private final String loggerFQCN;
         private final Marker marker;
         private final Level level;
@@ -726,11 +773,15 @@ public Log4jLogEvent(final String loggerName, final 
Marker marker, final String
         private final ThrowableProxy thrownProxy;
         private final Map<String, String> contextMap;
         private final ThreadContext.ContextStack contextStack;
+        /** @since 2.6 */
+        private final long threadId;
         private final String threadName;
+        /** @since 2.6 */
+        private final int threadPriority;
         private final StackTraceElement source;
         private final boolean isLocationRequired;
         private final boolean isEndOfBatch;
-        /** @since Log4J 2.4 */
+        /** @since 2.4 */
         private final transient long nanoTime;
 
         public LogEventProxy(final Log4jLogEvent event, final boolean 
includeLocation) {
@@ -745,7 +796,9 @@ public Log4jLogEvent(final String loggerName, final Marker 
marker, final String
             this.contextMap = event.contextMap;
             this.contextStack = event.contextStack;
             this.source = includeLocation ? event.getSource() : null;
+            this.threadId = event.getThreadId();
             this.threadName = event.getThreadName();
+            this.threadPriority = event.getThreadPriority();
             this.isLocationRequired = includeLocation;
             this.isEndOfBatch = event.endOfBatch;
             this.nanoTime = event.nanoTime;
@@ -757,10 +810,11 @@ public Log4jLogEvent(final String loggerName, final 
Marker marker, final String
          */
         protected Object readResolve() {
             final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, 
loggerFQCN, level, message, thrown,
-                    thrownProxy, contextMap, contextStack, threadName, source, 
timeMillis, nanoTime);
+                    thrownProxy, contextMap, contextStack, threadId, 
threadName, threadPriority, source, timeMillis, nanoTime);
             result.setEndOfBatch(isEndOfBatch);
             result.setIncludeLocation(isLocationRequired);
             return result;
         }
     }
+
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventMixIn.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventMixIn.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventMixIn.java
index a926499..ab9cd19 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventMixIn.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventMixIn.java
@@ -92,10 +92,20 @@ abstract class LogEventMixIn implements LogEvent {
     public abstract StackTraceElement getSource();
 
     @Override
+    @JsonProperty("threadId")
+    @JacksonXmlProperty(isAttribute = true, localName = "threadId")
+    public abstract long getThreadId();
+
+    @Override
     @JsonProperty("thread")
     @JacksonXmlProperty(isAttribute = true, localName = "thread")
     public abstract String getThreadName();
 
+    @Override
+    @JsonProperty("threadPriority")
+    @JacksonXmlProperty(isAttribute = true, localName = "threadPriority")
+    public abstract int getThreadPriority();
+
     @JsonIgnore
     @Override
     public abstract Throwable getThrown();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java
index 1a3d6ad..ef69f0f 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java
@@ -85,7 +85,9 @@ public class CsvLogEventLayout extends AbstractCsvLayout {
             printer.print(event.getNanoTime());
             printer.print(event.getTimeMillis());
             printer.print(event.getLevel());
+            printer.print(event.getThreadId());
             printer.print(event.getThreadName());
+            printer.print(event.getThreadPriority());
             printer.print(event.getMessage().getFormattedMessage());
             printer.print(event.getLoggerFqcn());
             printer.print(event.getLoggerName());

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadIdPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadIdPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadIdPatternConverter.java
new file mode 100644
index 0000000..844d47d
--- /dev/null
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadIdPatternConverter.java
@@ -0,0 +1,61 @@
+/*
+ * 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.logging.log4j.core.pattern;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+
+/**
+ * Formats the event thread ID.
+ * 
+ * @since 2.6
+ */
+@Plugin(name = "ThreadIdPatternConverter", category = 
PatternConverter.CATEGORY)
+@ConverterKeys({ "tid", "threadId" })
+public final class ThreadIdPatternConverter extends LogEventPatternConverter {
+    /**
+     * Singleton.
+     */
+    private static final ThreadIdPatternConverter INSTANCE =
+        new ThreadIdPatternConverter();
+
+    /**
+     * Private constructor.
+     */
+    private ThreadIdPatternConverter() {
+        super("ThreadId", "threadId");
+    }
+
+    /**
+     * Obtains an instance of ThreadPatternConverter.
+     *
+     * @param options options, currently ignored, may be null.
+     * @return instance of ThreadPatternConverter.
+     */
+    public static ThreadIdPatternConverter newInstance(
+        final String[] options) {
+        return INSTANCE;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final StringBuilder toAppendTo) {
+        toAppendTo.append(event.getThreadId());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadNamePatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadNamePatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadNamePatternConverter.java
new file mode 100644
index 0000000..37c0861
--- /dev/null
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadNamePatternConverter.java
@@ -0,0 +1,59 @@
+/*
+ * 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.logging.log4j.core.pattern;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+
+/**
+ * Formats the event thread name.
+ */
+@Plugin(name = "ThreadPatternConverter", category = PatternConverter.CATEGORY)
+@ConverterKeys({ "t", "thread", "threadName" })
+public final class ThreadNamePatternConverter extends LogEventPatternConverter 
{
+    /**
+     * Singleton.
+     */
+    private static final ThreadNamePatternConverter INSTANCE =
+        new ThreadNamePatternConverter();
+
+    /**
+     * Private constructor.
+     */
+    private ThreadNamePatternConverter() {
+        super("Thread", "thread");
+    }
+
+    /**
+     * Obtains an instance of ThreadPatternConverter.
+     *
+     * @param options options, currently ignored, may be null.
+     * @return instance of ThreadPatternConverter.
+     */
+    public static ThreadNamePatternConverter newInstance(
+        final String[] options) {
+        return INSTANCE;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final StringBuilder toAppendTo) {
+        toAppendTo.append(event.getThreadName());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadPatternConverter.java
deleted file mode 100644
index 8817bbc..0000000
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadPatternConverter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.logging.log4j.core.pattern;
-
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.config.plugins.Plugin;
-
-/**
- * Formats the event thread name.
- */
-@Plugin(name = "ThreadPatternConverter", category = PatternConverter.CATEGORY)
-@ConverterKeys({ "t", "thread", "threadName" })
-public final class ThreadPatternConverter extends LogEventPatternConverter {
-    /**
-     * Singleton.
-     */
-    private static final ThreadPatternConverter INSTANCE =
-        new ThreadPatternConverter();
-
-    /**
-     * Private constructor.
-     */
-    private ThreadPatternConverter() {
-        super("Thread", "thread");
-    }
-
-    /**
-     * Obtains an instance of ThreadPatternConverter.
-     *
-     * @param options options, currently ignored, may be null.
-     * @return instance of ThreadPatternConverter.
-     */
-    public static ThreadPatternConverter newInstance(
-        final String[] options) {
-        return INSTANCE;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void format(final LogEvent event, final StringBuilder toAppendTo) {
-        toAppendTo.append(event.getThreadName());
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadPriorityPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadPriorityPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadPriorityPatternConverter.java
new file mode 100644
index 0000000..31ae15d
--- /dev/null
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThreadPriorityPatternConverter.java
@@ -0,0 +1,61 @@
+/*
+ * 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.logging.log4j.core.pattern;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+
+/**
+ * Formats the event thread priority.
+ * 
+ * @since 2.6
+ */
+@Plugin(name = "ThreadPriorityPatternConverter", category = 
PatternConverter.CATEGORY)
+@ConverterKeys({ "tp", "threadPriority" })
+public final class ThreadPriorityPatternConverter extends 
LogEventPatternConverter {
+    /**
+     * Singleton.
+     */
+    private static final ThreadPriorityPatternConverter INSTANCE =
+        new ThreadPriorityPatternConverter();
+
+    /**
+     * Private constructor.
+     */
+    private ThreadPriorityPatternConverter() {
+        super("ThreadPriority", "threadPriority");
+    }
+
+    /**
+     * Obtains an instance of ThreadPatternConverter.
+     *
+     * @param options options, currently ignored, may be null.
+     * @return instance of ThreadPatternConverter.
+     */
+    public static ThreadPriorityPatternConverter newInstance(
+        final String[] options) {
+        return INSTANCE;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final StringBuilder toAppendTo) {
+        toAppendTo.append(event.getThreadPriority());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/LogEventTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/LogEventTest.java 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/LogEventTest.java
index fc53583..722c5a1 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/LogEventTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/LogEventTest.java
@@ -105,7 +105,9 @@ public class LogEventTest {
                 .setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
                 .setLevel(Level.INFO) //
                 .setMessage(new SimpleMessage("Hello, world!")) //
+                .setThreadId(1) // this must be initialized or the test fails
                 .setThreadName("this must be initialized or the test fails") //
+                .setThreadPriority(2) // this must be initialized or the test 
fails
                 .setNanoTime(0) //
                 .build();
         final LogEvent event2 = new Log4jLogEvent.Builder(event1).build();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaH2AppenderTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaH2AppenderTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaH2AppenderTest.java
index c4b9ae7..638fbe4 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaH2AppenderTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaH2AppenderTest.java
@@ -47,7 +47,7 @@ public class JpaH2AppenderTest extends 
AbstractJpaAppenderTest {
                 "id INTEGER IDENTITY, timemillis BIGINT, nanoTime BIGINT, 
level NVARCHAR(10), loggerName NVARCHAR(255), " +
                 "message NVARCHAR(1024), thrown NVARCHAR(1048576), 
contextMapJson NVARCHAR(1048576)," +
                 "loggerFQCN NVARCHAR(1024), contextStack NVARCHAR(1048576), 
marker NVARCHAR(255), source NVARCHAR(2048)," +
-                "threadName NVARCHAR(255)" +
+                "threadId BIGINT, threadName NVARCHAR(255), threadPriority 
INTEGER" +
                 " )");
         statement.close();
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaHyperSqlAppenderTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaHyperSqlAppenderTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaHyperSqlAppenderTest.java
index 7ef8a24..a5379c3 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaHyperSqlAppenderTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaHyperSqlAppenderTest.java
@@ -51,7 +51,7 @@ public class JpaHyperSqlAppenderTest extends 
AbstractJpaAppenderTest {
                 "id INTEGER IDENTITY, timemillis BIGINT, nanoTime BIGINT, 
level VARCHAR(10), loggerName VARCHAR(255), " +
                 "message VARCHAR(1024), thrown VARCHAR(1048576), 
contextMapJson VARCHAR(1048576)," +
                 "loggerFQCN VARCHAR(1024), contextStack VARCHAR(1048576), 
marker VARCHAR(255), source VARCHAR(2048)," +
-                "threadName VARCHAR(255)" +
+                "threadId BIGINT, threadName NVARCHAR(255), threadPriority 
INTEGER" +
                 " )");
         statement.close();
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBaseEntity.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBaseEntity.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBaseEntity.java
index e70cdb9..02ef9ab 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBaseEntity.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBaseEntity.java
@@ -112,12 +112,24 @@ public class TestBaseEntity extends 
AbstractLogEventWrapperEntity {
 
     @Override
     @Transient
+    public long getThreadId() {
+        return this.getWrappedEvent().getThreadId();
+    }
+
+    @Override
+    @Transient
     public String getThreadName() {
         return this.getWrappedEvent().getThreadName();
     }
 
     @Override
     @Transient
+    public int getThreadPriority() {
+        return this.getWrappedEvent().getThreadPriority();
+    }
+
+    @Override
+    @Transient
     public long getTimeMillis() {
         return this.getWrappedEvent().getTimeMillis();
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
index 2da7b11..ec3a874 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
@@ -60,7 +60,7 @@ public class RingBufferLogEventTest {
         final long currentTimeMillis = 0;
         final long nanoTime = 1;
         evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
-                contextStack, threadName, location, currentTimeMillis, 
nanoTime);
+                contextStack, -1, threadName, -1, location, currentTimeMillis, 
nanoTime);
         assertEquals(Level.OFF, evt.getLevel());
     }
 
@@ -80,7 +80,7 @@ public class RingBufferLogEventTest {
         final long currentTimeMillis = 0;
         final long nanoTime = 1;
         evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
-                contextStack, threadName, location, currentTimeMillis, 
nanoTime);
+                contextStack, -1, threadName, -1, location, currentTimeMillis, 
nanoTime);
         assertNotNull(evt.getMessage());
     }
 
@@ -100,7 +100,7 @@ public class RingBufferLogEventTest {
         final long currentTimeMillis = 123;
         final long nanoTime = 1;
         evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
-                contextStack, threadName, location, currentTimeMillis, 
nanoTime);
+                contextStack, -1, threadName, -1, location, currentTimeMillis, 
nanoTime);
         assertEquals(123, evt.getTimeMillis());
     }
 
@@ -120,7 +120,7 @@ public class RingBufferLogEventTest {
         final long currentTimeMillis = 12345;
         final long nanoTime = 1;
         evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
-                contextStack, threadName, location, currentTimeMillis, 
nanoTime);
+                contextStack, -1, threadName, -1, location, currentTimeMillis, 
nanoTime);
         
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         final ObjectOutputStream out = new ObjectOutputStream(baos);
@@ -159,7 +159,7 @@ public class RingBufferLogEventTest {
         final long currentTimeMillis = 12345;
         final long nanoTime = 1;
         evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
-                contextStack, threadName, location, currentTimeMillis, 
nanoTime);
+                contextStack, -1, threadName, -1, location, currentTimeMillis, 
nanoTime);
         
         final LogEvent actual = evt.createMemento();
         assertEquals(evt.getLoggerName(), actual.getLoggerName());

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/Log4jLogEventTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/Log4jLogEventTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/Log4jLogEventTest.java
index e029a53..0a7df37 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/Log4jLogEventTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/Log4jLogEventTest.java
@@ -174,7 +174,8 @@ public class Log4jLogEventTest {
         // System.out.println("final String base64 = \"" + 
base64Str.replaceAll("\r\n", "\\\\r\\\\n\" +\r\n\"") +
         // "\";");
         
-         final String base64 = 
"rO0ABXNyAD5vcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnQkTG9nRXZlbnRQcm94eZztD11w2ioWAgANWgAMaXNFbmRPZkJhdGNoWgASaXNMb2NhdGlvblJlcXVpcmVkSgAKdGltZU1pbGxpc0wACmNvbnRleHRNYXB0AA9MamF2YS91dGlsL01hcDtMAAxjb250ZXh0U3RhY2t0ADVMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL1RocmVhZENvbnRleHQkQ29udGV4dFN0YWNrO0wABWxldmVsdAAgTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9MZXZlbDtMAApsb2dnZXJGUUNOdAASTGphdmEvbGFuZy9TdHJpbmc7TAAKbG9nZ2VyTmFtZXEAfgAETAAGbWFya2VydAAhTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9NYXJrZXI7TAAHbWVzc2FnZXQAKkxvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovbWVzc2FnZS9NZXNzYWdlO0wABnNvdXJjZXQAHUxqYXZhL2xhbmcvU3RhY2tUcmFjZUVsZW1lbnQ7TAAKdGhyZWFkTmFtZXEAfgAETAALdGhyb3duUHJveHl0ADNMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL2NvcmUvaW1wbC9UaHJvd2FibGVQcm94eTt4cAAAAAAAAEmWAtJzcgAeamF2YS51dGlsLkNvbGxlY3Rpb25zJEVtcHR5TWFwWTYUhVrc59ACAAB4cHNyAD5vcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouVGhyZWFkQ29udGV4dCRFbXB0eVRocmVhZENvbnRleHRTdGFjawAAAAAAAAABAgAAeHBzcgAeb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLkxld
 
mVsAAAAAAAYIBoCAANJAAhpbnRMZXZlbEwABG5hbWVxAH4ABEwADXN0YW5kYXJkTGV2ZWx0ACxMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL3NwaS9TdGFuZGFyZExldmVsO3hwAAABkHQABElORk9+cgAqb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLnNwaS5TdGFuZGFyZExldmVsAAAAAAAAAAASAAB4cgAOamF2YS5sYW5nLkVudW0AAAAAAAAAABIAAHhwdAAESU5GT3QAAHQACXNvbWUudGVzdHBzcgAub3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLm1lc3NhZ2UuU2ltcGxlTWVzc2FnZYt0TTBgt6KoAgABTAAHbWVzc2FnZXEAfgAEeHB0AANhYmNwdAAEbWFpbnNyADFvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLlRocm93YWJsZVByb3h52cww1Zp7rPoCAAdJABJjb21tb25FbGVtZW50Q291bnRMAApjYXVzZVByb3h5cQB+AAhbABJleHRlbmRlZFN0YWNrVHJhY2V0AD9bTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvRXh0ZW5kZWRTdGFja1RyYWNlRWxlbWVudDtMABBsb2NhbGl6ZWRNZXNzYWdlcQB+AARMAAdtZXNzYWdlcQB+AARMAARuYW1lcQB+AARbABFzdXBwcmVzc2VkUHJveGllc3QANFtMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL2NvcmUvaW1wbC9UaHJvd2FibGVQcm94eTt4cAAAAABwdXIAP1tMb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5FeHRlbmRlZFN0YWNrVHJhY2VFbGVtZW50O8rPiCOlx8+8AgAAeHAAAAAac3IAPG9yZy5hcGFjaGUubG9nZ2luZy5sb2
 
c0ai5jb3JlLmltcGwuRXh0ZW5kZWRTdGFja1RyYWNlRWxlbWVudOHez7rGtpAHAgACTAAOZXh0cmFDbGFzc0luZm90ADZMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL2NvcmUvaW1wbC9FeHRlbmRlZENsYXNzSW5mbztMABFzdGFja1RyYWNlRWxlbWVudHEAfgAHeHBzcgA0b3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5FeHRlbmRlZENsYXNzSW5mbwAAAAAAAAABAgADWgAFZXhhY3RMAAhsb2NhdGlvbnEAfgAETAAHdmVyc2lvbnEAfgAEeHABdAANdGVzdC1jbGFzc2VzL3QAAT9zcgAbamF2YS5sYW5nLlN0YWNrVHJhY2VFbGVtZW50YQnFmiY23YUCAARJAApsaW5lTnVtYmVyTAAOZGVjbGFyaW5nQ2xhc3NxAH4ABEwACGZpbGVOYW1lcQB+AARMAAptZXRob2ROYW1lcQB+AAR4cAAAAJh0ADRvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnRUZXN0dAAWTG9nNGpMb2dFdmVudFRlc3QuamF2YXQAKnRlc3RKYXZhSW9TZXJpYWxpemFibGVXaXRoVW5rbm93blRocm93YWJsZXNxAH4AInNxAH4AJQBxAH4AKHQACDEuNy4wXzU1c3EAfgAp/////nQAJHN1bi5yZWZsZWN0Lk5hdGl2ZU1ldGhvZEFjY2Vzc29ySW1wbHB0AAdpbnZva2Uwc3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACn/////cQB+ADJwdAAGaW52b2tlc3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACn/////dAAoc3VuLnJlZmxlY3QuRGVsZWdhdGluZ01ldGhvZEFjY2Vzc29ySW1wbHBxAH4AN3NxAH4AInN
 
xAH4AJQBxAH4AKHEAfgAwc3EAfgAp/////3QAGGphdmEubGFuZy5yZWZsZWN0Lk1ldGhvZHBxAH4AN3NxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAL3QAKW9yZy5qdW5pdC5ydW5uZXJzLm1vZGVsLkZyYW1ld29ya01ldGhvZCQxdAAURnJhbWV3b3JrTWV0aG9kLmphdmF0ABFydW5SZWZsZWN0aXZlQ2FsbHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAADHQAM29yZy5qdW5pdC5pbnRlcm5hbC5ydW5uZXJzLm1vZGVsLlJlZmxlY3RpdmVDYWxsYWJsZXQAF1JlZmxlY3RpdmVDYWxsYWJsZS5qYXZhdAADcnVuc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTEuamFycQB+AChzcQB+ACkAAAAsdAAnb3JnLmp1bml0LnJ1bm5lcnMubW9kZWwuRnJhbWV3b3JrTWV0aG9kcQB+AEV0ABFpbnZva2VFeHBsb3NpdmVseXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAEXQAMm9yZy5qdW5pdC5pbnRlcm5hbC5ydW5uZXJzLnN0YXRlbWVudHMuSW52b2tlTWV0aG9kdAARSW52b2tlTWV0aG9kLmphdmF0AAhldmFsdWF0ZXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAABD3QAHm9yZy5qdW5pdC5ydW5uZXJzLlBhcmVudFJ1bm5lcnQAEVBhcmVudFJ1bm5lci5qYXZhdAAHcnVuTGVhZnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAARnQAKG9yZy5qdW5pdC5ydW5uZXJzLkJsb2NrSlVuaXQ0
 
Q2xhc3NSdW5uZXJ0ABtCbG9ja0pVbml0NENsYXNzUnVubmVyLmphdmF0AAhydW5DaGlsZHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAMnEAfgBmcQB+AGdxAH4AaHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAA7nQAIG9yZy5qdW5pdC5ydW5uZXJzLlBhcmVudFJ1bm5lciQzcQB+AGBxAH4ATXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAP3QAIG9yZy5qdW5pdC5ydW5uZXJzLlBhcmVudFJ1bm5lciQxcQB+AGB0AAhzY2hlZHVsZXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAA7HEAfgBfcQB+AGB0AAtydW5DaGlsZHJlbnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAANXEAfgBfcQB+AGB0AAphY2Nlc3MkMDAwc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTEuamFycQB+AChzcQB+ACkAAADldAAgb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVyJDJxAH4AYHEAfgBac3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTEuamFycQB+AChzcQB+ACkAAAAadAAwb3JnLmp1bml0LmludGVybmFsLnJ1bm5lcnMuc3RhdGVtZW50cy5SdW5CZWZvcmVzdAAPUnVuQmVmb3Jlcy5qYXZhcQB+AFpzcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMS5qYXJxAH4AKHNxAH4AKQAAABt0AC9vcmcuanVuaXQuaW50ZXJuYWwucnVubmVycy5zdGF0ZW1lbnRzLlJ1bkFmdGVyc3QADlJ1bkFmd
 
GVycy5qYXZhcQB+AFpzcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMS5qYXJxAH4AKHNxAH4AKQAAATVxAH4AX3EAfgBgcQB+AE1zcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAAAMnQAOm9yZy5lY2xpcHNlLmpkdC5pbnRlcm5hbC5qdW5pdDQucnVubmVyLkpVbml0NFRlc3RSZWZlcmVuY2V0ABhKVW5pdDRUZXN0UmVmZXJlbmNlLmphdmFxAH4ATXNxAH4AInNxAH4AJQF0AAQuY3AvcQB+AChzcQB+ACkAAAAmdAAzb3JnLmVjbGlwc2UuamR0LmludGVybmFsLmp1bml0LnJ1bm5lci5UZXN0RXhlY3V0aW9udAASVGVzdEV4ZWN1dGlvbi5qYXZhcQB+AE1zcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAAB03QANm9yZy5lY2xpcHNlLmpkdC5pbnRlcm5hbC5qdW5pdC5ydW5uZXIuUmVtb3RlVGVzdFJ1bm5lcnQAFVJlbW90ZVRlc3RSdW5uZXIuamF2YXQACHJ1blRlc3Rzc3EAfgAic3EAfgAlAXQABC5jcC9xAH4AKHNxAH4AKQAAAqtxAH4Ap3EAfgCocQB+AKlzcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAABhnEAfgCncQB+AKhxAH4ATXNxAH4AInNxAH4AJQF0AAQuY3AvcQB+AChzcQB+ACkAAADFcQB+AKdxAH4AqHQABG1haW50ABZPTUcgSSd2ZSBiZWVuIGRlbGV0ZWQhcQB+ALd0AEVvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnRUZXN0JERlbGV0ZWRFeGNlcHRpb251cgA0W0xvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLlRocm93YWJsZV
 Byb3h5O/rtAeCFous5AgAAeHAAAAAA";
+        final String base64_v_2_5 = 
"rO0ABXNyAD5vcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnQkTG9nRXZlbnRQcm94eZztD11w2ioWAgANWgAMaXNFbmRPZkJhdGNoWgASaXNMb2NhdGlvblJlcXVpcmVkSgAKdGltZU1pbGxpc0wACmNvbnRleHRNYXB0AA9MamF2YS91dGlsL01hcDtMAAxjb250ZXh0U3RhY2t0ADVMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL1RocmVhZENvbnRleHQkQ29udGV4dFN0YWNrO0wABWxldmVsdAAgTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9MZXZlbDtMAApsb2dnZXJGUUNOdAASTGphdmEvbGFuZy9TdHJpbmc7TAAKbG9nZ2VyTmFtZXEAfgAETAAGbWFya2VydAAhTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9NYXJrZXI7TAAHbWVzc2FnZXQAKkxvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovbWVzc2FnZS9NZXNzYWdlO0wABnNvdXJjZXQAHUxqYXZhL2xhbmcvU3RhY2tUcmFjZUVsZW1lbnQ7TAAKdGhyZWFkTmFtZXEAfgAETAALdGhyb3duUHJveHl0ADNMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL2NvcmUvaW1wbC9UaHJvd2FibGVQcm94eTt4cAAAAAAAAEmWAtJzcgAeamF2YS51dGlsLkNvbGxlY3Rpb25zJEVtcHR5TWFwWTYUhVrc59ACAAB4cHNyAD5vcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouVGhyZWFkQ29udGV4dCRFbXB0eVRocmVhZENvbnRleHRTdGFjawAAAAAAAAABAgAAeHBzcgAeb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRq
 
LkxldmVsAAAAAAAYIBoCAANJAAhpbnRMZXZlbEwABG5hbWVxAH4ABEwADXN0YW5kYXJkTGV2ZWx0ACxMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL3NwaS9TdGFuZGFyZExldmVsO3hwAAABkHQABElORk9+cgAqb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLnNwaS5TdGFuZGFyZExldmVsAAAAAAAAAAASAAB4cgAOamF2YS5sYW5nLkVudW0AAAAAAAAAABIAAHhwdAAESU5GT3QAAHQACXNvbWUudGVzdHBzcgAub3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLm1lc3NhZ2UuU2ltcGxlTWVzc2FnZYt0TTBgt6KoAgABTAAHbWVzc2FnZXEAfgAEeHB0AANhYmNwdAAEbWFpbnNyADFvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLlRocm93YWJsZVByb3h52cww1Zp7rPoCAAdJABJjb21tb25FbGVtZW50Q291bnRMAApjYXVzZVByb3h5cQB+AAhbABJleHRlbmRlZFN0YWNrVHJhY2V0AD9bTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvRXh0ZW5kZWRTdGFja1RyYWNlRWxlbWVudDtMABBsb2NhbGl6ZWRNZXNzYWdlcQB+AARMAAdtZXNzYWdlcQB+AARMAARuYW1lcQB+AARbABFzdXBwcmVzc2VkUHJveGllc3QANFtMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL2NvcmUvaW1wbC9UaHJvd2FibGVQcm94eTt4cAAAAABwdXIAP1tMb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5FeHRlbmRlZFN0YWNrVHJhY2VFbGVtZW50O8rPiCOlx8+8AgAAeHAAAAAac3IAPG9yZy5hcGFjaGUubG9nZ2luZ
 
y5sb2c0ai5jb3JlLmltcGwuRXh0ZW5kZWRTdGFja1RyYWNlRWxlbWVudOHez7rGtpAHAgACTAAOZXh0cmFDbGFzc0luZm90ADZMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL2NvcmUvaW1wbC9FeHRlbmRlZENsYXNzSW5mbztMABFzdGFja1RyYWNlRWxlbWVudHEAfgAHeHBzcgA0b3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5FeHRlbmRlZENsYXNzSW5mbwAAAAAAAAABAgADWgAFZXhhY3RMAAhsb2NhdGlvbnEAfgAETAAHdmVyc2lvbnEAfgAEeHABdAANdGVzdC1jbGFzc2VzL3QAAT9zcgAbamF2YS5sYW5nLlN0YWNrVHJhY2VFbGVtZW50YQnFmiY23YUCAARJAApsaW5lTnVtYmVyTAAOZGVjbGFyaW5nQ2xhc3NxAH4ABEwACGZpbGVOYW1lcQB+AARMAAptZXRob2ROYW1lcQB+AAR4cAAAAJh0ADRvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnRUZXN0dAAWTG9nNGpMb2dFdmVudFRlc3QuamF2YXQAKnRlc3RKYXZhSW9TZXJpYWxpemFibGVXaXRoVW5rbm93blRocm93YWJsZXNxAH4AInNxAH4AJQBxAH4AKHQACDEuNy4wXzU1c3EAfgAp/////nQAJHN1bi5yZWZsZWN0Lk5hdGl2ZU1ldGhvZEFjY2Vzc29ySW1wbHB0AAdpbnZva2Uwc3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACn/////cQB+ADJwdAAGaW52b2tlc3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACn/////dAAoc3VuLnJlZmxlY3QuRGVsZWdhdGluZ01ldGhvZEFjY2Vzc29ySW1wbHBxAH4AN3NxAH
 
4AInNxAH4AJQBxAH4AKHEAfgAwc3EAfgAp/////3QAGGphdmEubGFuZy5yZWZsZWN0Lk1ldGhvZHBxAH4AN3NxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAL3QAKW9yZy5qdW5pdC5ydW5uZXJzLm1vZGVsLkZyYW1ld29ya01ldGhvZCQxdAAURnJhbWV3b3JrTWV0aG9kLmphdmF0ABFydW5SZWZsZWN0aXZlQ2FsbHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAADHQAM29yZy5qdW5pdC5pbnRlcm5hbC5ydW5uZXJzLm1vZGVsLlJlZmxlY3RpdmVDYWxsYWJsZXQAF1JlZmxlY3RpdmVDYWxsYWJsZS5qYXZhdAADcnVuc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTEuamFycQB+AChzcQB+ACkAAAAsdAAnb3JnLmp1bml0LnJ1bm5lcnMubW9kZWwuRnJhbWV3b3JrTWV0aG9kcQB+AEV0ABFpbnZva2VFeHBsb3NpdmVseXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAEXQAMm9yZy5qdW5pdC5pbnRlcm5hbC5ydW5uZXJzLnN0YXRlbWVudHMuSW52b2tlTWV0aG9kdAARSW52b2tlTWV0aG9kLmphdmF0AAhldmFsdWF0ZXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAABD3QAHm9yZy5qdW5pdC5ydW5uZXJzLlBhcmVudFJ1bm5lcnQAEVBhcmVudFJ1bm5lci5qYXZhdAAHcnVuTGVhZnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAARnQAKG9yZy5qdW5pdC5ydW5uZXJzLkJsb2NrSlV
 
uaXQ0Q2xhc3NSdW5uZXJ0ABtCbG9ja0pVbml0NENsYXNzUnVubmVyLmphdmF0AAhydW5DaGlsZHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAMnEAfgBmcQB+AGdxAH4AaHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAA7nQAIG9yZy5qdW5pdC5ydW5uZXJzLlBhcmVudFJ1bm5lciQzcQB+AGBxAH4ATXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAP3QAIG9yZy5qdW5pdC5ydW5uZXJzLlBhcmVudFJ1bm5lciQxcQB+AGB0AAhzY2hlZHVsZXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAA7HEAfgBfcQB+AGB0AAtydW5DaGlsZHJlbnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAANXEAfgBfcQB+AGB0AAphY2Nlc3MkMDAwc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTEuamFycQB+AChzcQB+ACkAAADldAAgb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVyJDJxAH4AYHEAfgBac3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTEuamFycQB+AChzcQB+ACkAAAAadAAwb3JnLmp1bml0LmludGVybmFsLnJ1bm5lcnMuc3RhdGVtZW50cy5SdW5CZWZvcmVzdAAPUnVuQmVmb3Jlcy5qYXZhcQB+AFpzcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMS5qYXJxAH4AKHNxAH4AKQAAABt0AC9vcmcuanVuaXQuaW50ZXJuYWwucnVubmVycy5zdGF0ZW1lbnRzLlJ1bkFmdGVyc3QADlJ1
 
bkFmdGVycy5qYXZhcQB+AFpzcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMS5qYXJxAH4AKHNxAH4AKQAAATVxAH4AX3EAfgBgcQB+AE1zcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAAAMnQAOm9yZy5lY2xpcHNlLmpkdC5pbnRlcm5hbC5qdW5pdDQucnVubmVyLkpVbml0NFRlc3RSZWZlcmVuY2V0ABhKVW5pdDRUZXN0UmVmZXJlbmNlLmphdmFxAH4ATXNxAH4AInNxAH4AJQF0AAQuY3AvcQB+AChzcQB+ACkAAAAmdAAzb3JnLmVjbGlwc2UuamR0LmludGVybmFsLmp1bml0LnJ1bm5lci5UZXN0RXhlY3V0aW9udAASVGVzdEV4ZWN1dGlvbi5qYXZhcQB+AE1zcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAAB03QANm9yZy5lY2xpcHNlLmpkdC5pbnRlcm5hbC5qdW5pdC5ydW5uZXIuUmVtb3RlVGVzdFJ1bm5lcnQAFVJlbW90ZVRlc3RSdW5uZXIuamF2YXQACHJ1blRlc3Rzc3EAfgAic3EAfgAlAXQABC5jcC9xAH4AKHNxAH4AKQAAAqtxAH4Ap3EAfgCocQB+AKlzcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAABhnEAfgCncQB+AKhxAH4ATXNxAH4AInNxAH4AJQF0AAQuY3AvcQB+AChzcQB+ACkAAADFcQB+AKdxAH4AqHQABG1haW50ABZPTUcgSSd2ZSBiZWVuIGRlbGV0ZWQhcQB+ALd0AEVvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnRUZXN0JERlbGV0ZWRFeGNlcHRpb251cgA0W0xvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLlRocm93Y
 WJsZVByb3h5O/rtAeCFous5AgAAeHAAAAAA";
+        final String base64 = 
"rO0ABXNyAD5vcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnQkTG9nRXZlbnRQcm94eYgtmn+yXsP9AgAPWgAMaXNFbmRPZkJhdGNoWgASaXNMb2NhdGlvblJlcXVpcmVkSgAIdGhyZWFkSWRJAA50aHJlYWRQcmlvcml0eUoACnRpbWVNaWxsaXNMAApjb250ZXh0TWFwdAAPTGphdmEvdXRpbC9NYXA7TAAMY29udGV4dFN0YWNrdAA1TG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9UaHJlYWRDb250ZXh0JENvbnRleHRTdGFjaztMAAVsZXZlbHQAIExvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovTGV2ZWw7TAAKbG9nZ2VyRlFDTnQAEkxqYXZhL2xhbmcvU3RyaW5nO0wACmxvZ2dlck5hbWVxAH4ABEwABm1hcmtlcnQAIUxvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovTWFya2VyO0wAB21lc3NhZ2V0ACpMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL21lc3NhZ2UvTWVzc2FnZTtMAAZzb3VyY2V0AB1MamF2YS9sYW5nL1N0YWNrVHJhY2VFbGVtZW50O0wACnRocmVhZE5hbWVxAH4ABEwAC3Rocm93blByb3h5dAAzTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvVGhyb3dhYmxlUHJveHk7eHAAAAAAAAAAAAABAAAABQAAAABJlgLSc3IAHmphdmEudXRpbC5Db2xsZWN0aW9ucyRFbXB0eU1hcFk2FIVa3OfQAgAAeHBzcgA+b3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLlRocmVhZENvbnRleHQkRW1wdHlUaHJlYWRDb250ZXh0U3RhY2sAAAAAAA
 
AAAQIAAHhwc3IAHm9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5MZXZlbAAAAAAAGCAaAgADSQAIaW50TGV2ZWxMAARuYW1lcQB+AARMAA1zdGFuZGFyZExldmVsdAAsTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9zcGkvU3RhbmRhcmRMZXZlbDt4cAAAAZB0AARJTkZPfnIAKm9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5zcGkuU3RhbmRhcmRMZXZlbAAAAAAAAAAAEgAAeHIADmphdmEubGFuZy5FbnVtAAAAAAAAAAASAAB4cHQABElORk90AAB0AAlzb21lLnRlc3Rwc3IALm9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5tZXNzYWdlLlNpbXBsZU1lc3NhZ2WLdE0wYLeiqAIAAUwAB21lc3NhZ2VxAH4ABHhwdAADYWJjcHQABG1haW5zcgAxb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5UaHJvd2FibGVQcm94ednMMNWae6z6AgAHSQASY29tbW9uRWxlbWVudENvdW50TAAKY2F1c2VQcm94eXEAfgAIWwASZXh0ZW5kZWRTdGFja1RyYWNldAA/W0xvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovY29yZS9pbXBsL0V4dGVuZGVkU3RhY2tUcmFjZUVsZW1lbnQ7TAAQbG9jYWxpemVkTWVzc2FnZXEAfgAETAAHbWVzc2FnZXEAfgAETAAEbmFtZXEAfgAEWwARc3VwcHJlc3NlZFByb3hpZXN0ADRbTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvVGhyb3dhYmxlUHJveHk7eHAAAAAAcHVyAD9bTG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuRXh0ZW5kZWRTdGFja1RyYWNlRWxlbWVudDvKz4g
 
jpcfPvAIAAHhwAAAAGnNyADxvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkV4dGVuZGVkU3RhY2tUcmFjZUVsZW1lbnTh3s+6xraQBwIAAkwADmV4dHJhQ2xhc3NJbmZvdAA2TG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvRXh0ZW5kZWRDbGFzc0luZm87TAARc3RhY2tUcmFjZUVsZW1lbnRxAH4AB3hwc3IANG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuRXh0ZW5kZWRDbGFzc0luZm8AAAAAAAAAAQIAA1oABWV4YWN0TAAIbG9jYXRpb25xAH4ABEwAB3ZlcnNpb25xAH4ABHhwAXQADXRlc3QtY2xhc3Nlcy90AAE/c3IAG2phdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudGEJxZomNt2FAgAESQAKbGluZU51bWJlckwADmRlY2xhcmluZ0NsYXNzcQB+AARMAAhmaWxlTmFtZXEAfgAETAAKbWV0aG9kTmFtZXEAfgAEeHAAAACqdAA0b3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5Mb2c0akxvZ0V2ZW50VGVzdHQAFkxvZzRqTG9nRXZlbnRUZXN0LmphdmF0ACp0ZXN0SmF2YUlvU2VyaWFsaXphYmxlV2l0aFVua25vd25UaHJvd2FibGVzcQB+ACJzcQB+ACUAcQB+ACh0AAgxLjcuMF83OXNxAH4AKf////50ACRzdW4ucmVmbGVjdC5OYXRpdmVNZXRob2RBY2Nlc3NvckltcGx0AB1OYXRpdmVNZXRob2RBY2Nlc3NvckltcGwuamF2YXQAB2ludm9rZTBzcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKQAAADlxAH4AMnEAfgAzdAAGaW52b2tlc3EAfgAic3EAfgAlAHEA
 
fgAocQB+ADBzcQB+ACkAAAArdAAoc3VuLnJlZmxlY3QuRGVsZWdhdGluZ01ldGhvZEFjY2Vzc29ySW1wbHQAIURlbGVnYXRpbmdNZXRob2RBY2Nlc3NvckltcGwuamF2YXEAfgA4c3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACkAAAJedAAYamF2YS5sYW5nLnJlZmxlY3QuTWV0aG9kdAALTWV0aG9kLmphdmFxAH4AOHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnQABDQuMTJzcQB+ACkAAAAydAApb3JnLmp1bml0LnJ1bm5lcnMubW9kZWwuRnJhbWV3b3JrTWV0aG9kJDF0ABRGcmFtZXdvcmtNZXRob2QuamF2YXQAEXJ1blJlZmxlY3RpdmVDYWxsc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAAMdAAzb3JnLmp1bml0LmludGVybmFsLnJ1bm5lcnMubW9kZWwuUmVmbGVjdGl2ZUNhbGxhYmxldAAXUmVmbGVjdGl2ZUNhbGxhYmxlLmphdmF0AANydW5zcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMi5qYXJxAH4ARnNxAH4AKQAAAC90ACdvcmcuanVuaXQucnVubmVycy5tb2RlbC5GcmFtZXdvcmtNZXRob2RxAH4ASXQAEWludm9rZUV4cGxvc2l2ZWx5c3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAARdAAyb3JnLmp1bml0LmludGVybmFsLnJ1bm5lcnMuc3RhdGVtZW50cy5JbnZva2VNZXRob2R0ABFJbnZva2VNZXRob2QuamF2YXQACGV2YWx1YXRlc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAFFdAAeb3JnLmp1bml0LnJ1b
 
m5lcnMuUGFyZW50UnVubmVydAARUGFyZW50UnVubmVyLmphdmF0AAdydW5MZWFmc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAABOdAAob3JnLmp1bml0LnJ1bm5lcnMuQmxvY2tKVW5pdDRDbGFzc1J1bm5lcnQAG0Jsb2NrSlVuaXQ0Q2xhc3NSdW5uZXIuamF2YXQACHJ1bkNoaWxkc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAA5cQB+AGpxAH4Aa3EAfgBsc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAEidAAgb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVyJDNxAH4AZHEAfgBRc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAABHdAAgb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVyJDFxAH4AZHQACHNjaGVkdWxlc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAEgcQB+AGNxAH4AZHQAC3J1bkNoaWxkcmVuc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAA6cQB+AGNxAH4AZHQACmFjY2VzcyQwMDBzcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMi5qYXJxAH4ARnNxAH4AKQAAAQx0ACBvcmcuanVuaXQucnVubmVycy5QYXJlbnRSdW5uZXIkMnEAfgBkcQB+AF5zcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMi5qYXJxAH4ARnNxAH4AKQAAABp0ADBvcmcuanVuaXQuaW50ZXJuYWwucnVubmVycy5zdGF0ZW1lbnRzLlJ1bkJlZm9yZXN0AA
 
9SdW5CZWZvcmVzLmphdmFxAH4AXnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnEAfgBGc3EAfgApAAAAG3QAL29yZy5qdW5pdC5pbnRlcm5hbC5ydW5uZXJzLnN0YXRlbWVudHMuUnVuQWZ0ZXJzdAAOUnVuQWZ0ZXJzLmphdmFxAH4AXnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnEAfgBGc3EAfgApAAABa3EAfgBjcQB+AGRxAH4AUXNxAH4AInNxAH4AJQF0AAQuY3AvcQB+AChzcQB+ACkAAABWdAA6b3JnLmVjbGlwc2UuamR0LmludGVybmFsLmp1bml0NC5ydW5uZXIuSlVuaXQ0VGVzdFJlZmVyZW5jZXQAGEpVbml0NFRlc3RSZWZlcmVuY2UuamF2YXEAfgBRc3EAfgAic3EAfgAlAXQABC5jcC9xAH4AKHNxAH4AKQAAACZ0ADNvcmcuZWNsaXBzZS5qZHQuaW50ZXJuYWwuanVuaXQucnVubmVyLlRlc3RFeGVjdXRpb250ABJUZXN0RXhlY3V0aW9uLmphdmFxAH4AUXNxAH4AInNxAH4AJQF0AAQuY3AvcQB+AChzcQB+ACkAAAHLdAA2b3JnLmVjbGlwc2UuamR0LmludGVybmFsLmp1bml0LnJ1bm5lci5SZW1vdGVUZXN0UnVubmVydAAVUmVtb3RlVGVzdFJ1bm5lci5qYXZhdAAIcnVuVGVzdHNzcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAACo3EAfgCrcQB+AKxxAH4ArXNxAH4AInNxAH4AJQF0AAQuY3AvcQB+AChzcQB+ACkAAAF+cQB+AKtxAH4ArHEAfgBRc3EAfgAic3EAfgAlAXQABC5jcC9xAH4AKHNxAH4AKQAAAMBxAH4Aq3EAfgCsdAAEbWFpbnQAFk9NRyBJJ3ZlIGJlZW4gZGVsZXRlZCFxAH4
 
Au3QARW9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuTG9nNGpMb2dFdmVudFRlc3QkRGVsZXRlZEV4Y2VwdGlvbnVyADRbTG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuVGhyb3dhYmxlUHJveHk7+u0B4IWi6zkCAAB4cAAAAAA=";
 
         final byte[] binaryDecoded = 
DatatypeConverter.parseBase64Binary(base64);
         final Log4jLogEvent evt2 = deserialize(binaryDecoded);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadIdFilter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadIdFilter.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadIdFilter.java
new file mode 100644
index 0000000..d00edb2
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadIdFilter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.logging.log4j.core.net.server;
+
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.filter.AbstractFilter;
+
+/**
+ * TODO Should use thread ID cache?
+ * @since 2.6
+ */
+public class ThreadIdFilter extends AbstractFilter {
+
+    private static final long serialVersionUID = 1L;
+
+    public ThreadIdFilter(final Result onMatch, final Result onMismatch) {
+        super(onMatch, onMismatch);
+    }
+
+    @Override
+    public Filter.Result filter(final LogEvent event) {
+        return event.getThreadId() == Thread.currentThread().getId() ? onMatch 
: onMismatch;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadPriorityFilter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadPriorityFilter.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadPriorityFilter.java
new file mode 100644
index 0000000..7c9c734
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadPriorityFilter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.logging.log4j.core.net.server;
+
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.filter.AbstractFilter;
+
+/**
+ * TODO Should use thread priority cache?
+ * @since 2.6
+ */
+public class ThreadPriorityFilter extends AbstractFilter {
+
+    private static final long serialVersionUID = 1L;
+
+    public ThreadPriorityFilter(final Result onMatch, final Result onMismatch) 
{
+        super(onMatch, onMismatch);
+    }
+
+    @Override
+    public Filter.Result filter(final LogEvent event) {
+        return event.getThreadPriority() == 
Thread.currentThread().getPriority() ? onMatch : onMismatch;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
index b01f2bc..2545f88 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
@@ -253,11 +253,44 @@ public class PatternParserTest {
         testThreadNamePattern("%threadName");
     }
 
+    @Test
+    public void testThreadIdFullPattern() {
+        testThreadIdPattern("%threadId");
+    }
+
+    @Test
+    public void testThreadIdShortPattern() {
+        testThreadIdPattern("%tid");
+    }
+
+    @Test
+    public void testThreadPriorityShortPattern() {
+        testThreadPriorityPattern("%tp");
+    }
+
+    @Test
+    public void testThreadPriorityFullPattern() {
+        testThreadPriorityPattern("%threadPriority");
+    }
+
+    private void testThreadIdPattern(final String pattern) {
+        testFirstConverter(pattern, ThreadIdPatternConverter.class);
+    }
+
     private void testThreadNamePattern(final String pattern) {
+        testFirstConverter(pattern, ThreadNamePatternConverter.class);
+    }
+
+    private void testThreadPriorityPattern(final String pattern) {
+        testFirstConverter(pattern, ThreadPriorityPatternConverter.class);
+    }
+
+    private void testFirstConverter(final String pattern, Class<?> checkClass) 
{
         final List<PatternFormatter> formatters = parser.parse(pattern);
         assertNotNull(formatters);
-        assertEquals(1, formatters.size());
-        assertTrue(formatters.get(0).getConverter() instanceof 
ThreadPatternConverter);
+        final String msg = formatters.toString();
+        assertEquals(msg, 1, formatters.size());
+        assertTrue(msg, 
checkClass.isInstance(formatters.get(0).getConverter()));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadIdPatternConverterTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadIdPatternConverterTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadIdPatternConverterTest.java
new file mode 100644
index 0000000..b608df8
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadIdPatternConverterTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.logging.log4j.core.pattern;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class ThreadIdPatternConverterTest {
+
+    @Test
+    public void testConverterAppendsLogEventNanoTimeToStringBuilder() {
+        final LogEvent event = Log4jLogEvent.newBuilder() //
+                .setThreadId(1).build();
+        final StringBuilder sb = new StringBuilder();
+        final ThreadIdPatternConverter converter = 
ThreadIdPatternConverter.newInstance(null);
+        converter.format(event, sb);
+        assertEquals("1", sb.toString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadNamePatternConverterTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadNamePatternConverterTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadNamePatternConverterTest.java
index 6b5dfc6..1ae94d2 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadNamePatternConverterTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadNamePatternConverterTest.java
@@ -32,7 +32,7 @@ public class ThreadNamePatternConverterTest {
         final LogEvent event = Log4jLogEvent.newBuilder() //
                 .setThreadName("Hello-1").build();
         final StringBuilder sb = new StringBuilder();
-        final ThreadPatternConverter converter = 
ThreadPatternConverter.newInstance(null);
+        final ThreadNamePatternConverter converter = 
ThreadNamePatternConverter.newInstance(null);
         converter.format(event, sb);
         assertEquals("Hello-1", sb.toString());
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/585beba1/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadPriorityPatternConverterTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadPriorityPatternConverterTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadPriorityPatternConverterTest.java
new file mode 100644
index 0000000..37db555
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThreadPriorityPatternConverterTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.logging.log4j.core.pattern;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class ThreadPriorityPatternConverterTest {
+
+    @Test
+    public void testConverterAppendsLogEventNanoTimeToStringBuilder() {
+        final LogEvent event = Log4jLogEvent.newBuilder() //
+                .setThreadPriority(1).build();
+        final StringBuilder sb = new StringBuilder();
+        final ThreadPriorityPatternConverter converter = 
ThreadPriorityPatternConverter.newInstance(null);
+        converter.format(event, sb);
+        assertEquals("1", sb.toString());
+    }
+}

Reply via email to