+ private final static String KEY_LOGGER = Logger.class.getName();
+ private final static String KEY_LEVEL = Level.class.getName();
+ private final static String KEY_MSG = String.class.getName();
+ private final static String KEY_THROWABLE = Throwable.class.getName();
+ private final static String KEY_INSTANT = Instant.class.getName();
+ private final static String KEY_CALL_LOCATION = StackTraceElement.class.getName();
+ private final static String KEY_THREAD = Thread.class.getName();
+
+ private class LogEntryPublisher extends SubmissionPublisher<Map<String, Serializable>> {
+
+ private LogEntryPublisher() {
+ super();
+ }
+
+ private void log(ThinLogger logger, Level level, ResourceBundle bundle, String msg, Instant instant,
+ Thread thread, Throwable thrown, StackTraceElement callLocation) {
+ assert level != null;
+ assert logger != null;
+ assert msg != null;
+ assert instant != null;
+ assert thread != null;
+
+ final long sequence = nextEntry.incrementAndGet();
+
+ Map<String, Serializable> logEntry = new LogEntryMap(sequence);
+
+ // same object as key class name
+ logEntry.put(KEY_LEVEL, level);
+ logEntry.put(KEY_MSG, msg);
+ logEntry.put(KEY_INSTANT, instant);
+ if (thrown != null)
+ logEntry.put(KEY_THROWABLE, thrown);
+ if (callLocation != null)
+ logEntry.put(KEY_CALL_LOCATION, callLocation);
+
+ // object is a string
+ logEntry.put(KEY_LOGGER, logger.getName());
+ logEntry.put(KEY_THREAD, thread.getName());
+
+ // should be unmodifiable for security reasons
+ if (synchronous) {
+ assert synchronousSubscriber != null;
+ synchronousSubscriber.onNext(logEntry);
+ } else {
+ if (!isClosed())
+ submit(Collections.unmodifiableMap(logEntry));
+ }
+ }
+
+ }
+
+ /**
+ * An internal optimisation for collections. It should not be referred to
+ * directly as a type.
+ */
+ // TODO optimise memory with a custom map implementation?
+ // but access may be slower
+ private static class LogEntryMap extends HashMap<String, Serializable> {
+ private static final long serialVersionUID = 7361434381922521356L;
+
+ private final long sequence;
+
+ private LogEntryMap(long sequence) {
+ // maximum 7 fields, so using default load factor 0.75
+ // an initial size of 10 should prevent rehashing (7 / 0.75 ~ 9.333)
+ // see HashMap class description for more details
+ super(10, 0.75f);
+ this.sequence = sequence;
+ }