You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by mi...@apache.org on 2016/04/14 10:37:40 UTC

[3/6] logging-log4j2 git commit: LOG4J2-1334 initial version of reusable LogEvent + factory

LOG4J2-1334 initial version of reusable LogEvent + factory


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

Branch: refs/heads/LOG4J2-1365
Commit: 5f461a72203d5b729005db4690bfc4c9e2b4e64d
Parents: 0a06f8f
Author: rpopma <rp...@apache.org>
Authored: Thu Apr 14 01:49:55 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Thu Apr 14 01:49:55 2016 +0900

----------------------------------------------------------------------
 .../logging/log4j/core/impl/Log4jLogEvent.java  |  28 ++-
 .../log4j/core/impl/MutableLogEvent.java        | 200 +++++++++++++++++++
 .../core/impl/ReusableLogEventFactory.java      |  80 ++++++++
 3 files changed, 306 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5f461a72/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 3f8961a..2e017dd 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
@@ -396,7 +396,7 @@ public Log4jLogEvent(final String loggerName, final Marker marker, final String
         this.nanoTime = nanoTime;
     }
 
-    private static Map<String, String> createMap(final List<Property> properties) {
+    static Map<String, String> createMap(final List<Property> properties) {
         final Map<String, String> contextMap = ThreadContext.getImmutableContext();
         if (properties == null || properties.isEmpty()) {
             return contextMap; // may be ThreadContext.EMPTY_MAP but not null
@@ -766,7 +766,7 @@ public Log4jLogEvent(final String loggerName, final Marker marker, final String
     /**
      * Proxy pattern used to serialize the LogEvent.
      */
-    private static class LogEventProxy implements Serializable {
+    static class LogEventProxy implements Serializable {
 
         private static final long serialVersionUID = -8634075037355293699L;
         private final String loggerFQCN;
@@ -812,6 +812,30 @@ public Log4jLogEvent(final String loggerName, final Marker marker, final String
             this.nanoTime = event.nanoTime;
         }
 
+        public LogEventProxy(final MutableLogEvent event, final boolean includeLocation) {
+            this.loggerFQCN = event.getLoggerFqcn();
+            this.marker = event.getMarker();
+            this.level = event.getLevel();
+            this.loggerName = event.getLoggerName();
+
+            final Message msg = event.getMessage();
+            this.message = msg instanceof ReusableMessage
+                    ? memento((ReusableMessage) msg)
+                    : msg;
+            this.timeMillis = event.getTimeMillis();
+            this.thrown = event.getThrown();
+            this.thrownProxy = event.getThrownProxy();
+            this.contextMap = event.getContextMap();
+            this.contextStack = event.getContextStack();
+            this.source = includeLocation ? event.getSource() : null;
+            this.threadId = event.getThreadId();
+            this.threadName = event.getThreadName();
+            this.threadPriority = event.getThreadPriority();
+            this.isLocationRequired = includeLocation;
+            this.isEndOfBatch = event.isEndOfBatch();
+            this.nanoTime = event.getNanoTime();
+        }
+
         private Message memento(final ReusableMessage message) {
             return new SimpleMessage(message.getFormattedMessage());
         }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5f461a72/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
new file mode 100644
index 0000000..2e2626f
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
@@ -0,0 +1,200 @@
+package org.apache.logging.log4j.core.impl;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.message.Message;
+
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.util.Map;
+
+/**
+ * Mutable implementation of the {@code LogEvent} interface.
+ */
+public class MutableLogEvent implements LogEvent {
+    private String loggerFqcn;
+    private Marker marker;
+    private Level level;
+    private String loggerName;
+    private Message message;
+    private Throwable thrown;
+    private long timeMillis;
+    private Map<String, String> contextMap;
+    private ThreadContext.ContextStack contextStack;
+    private long threadId;
+    private String threadName;
+    private int threadPriority;
+    private boolean includeLocation;
+    private boolean endOfBatch = false;
+    private long nanoTime;
+    // private ThrowableProxy thrownProxy;
+    // private StackTraceElement source;
+
+    @Override
+    public String getLoggerFqcn() {
+        return loggerFqcn;
+    }
+
+    public void setLoggerFqcn(String loggerFqcn) {
+        this.loggerFqcn = loggerFqcn;
+    }
+
+    @Override
+    public Marker getMarker() {
+        return marker;
+    }
+
+    public void setMarker(Marker marker) {
+        this.marker = marker;
+    }
+
+    @Override
+    public Level getLevel() {
+        return level;
+    }
+
+    public void setLevel(Level level) {
+        this.level = level;
+    }
+
+    @Override
+    public String getLoggerName() {
+        return loggerName;
+    }
+
+    public void setLoggerName(String loggerName) {
+        this.loggerName = loggerName;
+    }
+
+    @Override
+    public Message getMessage() {
+        return message;
+    }
+
+    public void setMessage(Message message) {
+        this.message = message;
+    }
+
+    @Override
+    public Throwable getThrown() {
+        return thrown;
+    }
+
+    public void setThrown(Throwable thrown) {
+        this.thrown = thrown;
+    }
+
+    @Override
+    public long getTimeMillis() {
+        return timeMillis;
+    }
+
+    public void setTimeMillis(long timeMillis) {
+        this.timeMillis = timeMillis;
+    }
+
+    @Override
+    public ThrowableProxy getThrownProxy() {
+        if (thrown != null) {
+            return new ThrowableProxy(thrown);
+        }
+        return null;
+    }
+
+    @Override
+    public Map<String, String> getContextMap() {
+        return contextMap;
+    }
+
+    public void setContextMap(Map<String, String> contextMap) {
+        this.contextMap = contextMap;
+    }
+
+    @Override
+    public ThreadContext.ContextStack getContextStack() {
+        return contextStack;
+    }
+
+    public void setContextStack(ThreadContext.ContextStack contextStack) {
+        this.contextStack = contextStack;
+    }
+
+    @Override
+    public long getThreadId() {
+        return threadId;
+    }
+
+    public void setThreadId(long threadId) {
+        this.threadId = threadId;
+    }
+
+    @Override
+    public String getThreadName() {
+        return threadName;
+    }
+
+    public void setThreadName(String threadName) {
+        this.threadName = threadName;
+    }
+
+    @Override
+    public int getThreadPriority() {
+        return threadPriority;
+    }
+
+    public void setThreadPriority(int threadPriority) {
+        this.threadPriority = threadPriority;
+    }
+
+    @Override
+    public StackTraceElement getSource() {
+        if (loggerFqcn == null || !includeLocation) {
+            return null;
+        }
+        return Log4jLogEvent.calcLocation(loggerFqcn);
+    }
+
+    @Override
+    public boolean isIncludeLocation() {
+        return includeLocation;
+    }
+
+    @Override
+    public void setIncludeLocation(boolean includeLocation) {
+        this.includeLocation = includeLocation;
+    }
+
+    @Override
+    public boolean isEndOfBatch() {
+        return endOfBatch;
+    }
+
+    @Override
+    public void setEndOfBatch(boolean endOfBatch) {
+        this.endOfBatch = endOfBatch;
+    }
+
+    @Override
+    public long getNanoTime() {
+        return nanoTime;
+    }
+
+    public void setNanoTime(long nanoTime) {
+        this.nanoTime = nanoTime;
+    }
+
+    /**
+     * Creates a LogEventProxy that can be serialized.
+     * @return a LogEventProxy.
+     */
+    protected Object writeReplace() {
+        getThrownProxy(); // ensure ThrowableProxy is initialized
+        return new Log4jLogEvent.LogEventProxy(this, this.includeLocation);
+    }
+
+    private void readObject(final ObjectInputStream stream) throws InvalidObjectException {
+        throw new InvalidObjectException("Proxy required");
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5f461a72/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java
new file mode 100644
index 0000000..190b27a
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ReusableLogEventFactory.java
@@ -0,0 +1,80 @@
+/*
+ * 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.impl;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Property;
+import org.apache.logging.log4j.core.util.Clock;
+import org.apache.logging.log4j.core.util.ClockFactory;
+import org.apache.logging.log4j.message.Message;
+
+import java.util.List;
+
+/**
+ * Garbage-free LogEventFactory that reuses a single mutable log event.
+ */
+public class ReusableLogEventFactory implements LogEventFactory {
+
+    private static ThreadLocal<MutableLogEvent> mutableLogEventThreadLocal = new ThreadLocal<>();
+    private static final Clock CLOCK = ClockFactory.getClock();
+    /**
+     * Creates a log event.
+     *
+     * @param loggerName The name of the Logger.
+     * @param marker An optional Marker.
+     * @param fqcn The fully qualified class name of the caller.
+     * @param level The event Level.
+     * @param data The Message.
+     * @param properties Properties to be added to the log event.
+     * @param t An optional Throwable.
+     * @return The LogEvent.
+     */
+    @Override
+    public LogEvent createEvent(final String loggerName, final Marker marker,
+                                final String fqcn, final Level level, final Message data,
+                                final List<Property> properties, final Throwable t) {
+        MutableLogEvent result = mutableLogEventThreadLocal.get();
+        if (result == null) {
+            result = new MutableLogEvent();
+            result.setThreadId(Thread.currentThread().getId());
+            result.setThreadName(Thread.currentThread().getName());
+            result.setThreadPriority(Thread.currentThread().getPriority());
+            mutableLogEventThreadLocal.set(result);
+        }
+
+        result.setLoggerName(loggerName);
+        result.setMarker(marker);
+        result.setLoggerFqcn(fqcn);
+        result.setLevel(level == null ? Level.OFF : level);
+        result.setMessage(data);
+        result.setThrown(t);
+        result.setContextMap(Log4jLogEvent.createMap(properties));
+        result.setContextStack(ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack());// mutable copy
+        result.setTimeMillis(CLOCK.currentTimeMillis());
+        result.setNanoTime(Log4jLogEvent.getNanoClock().nanoTime());
+
+        // TODO
+//        result.setEndOfBatch();
+//        result.setIncludeLocation();
+//        result.setSource();
+        //return new Log4jLogEvent(loggerName, marker, fqcn, level, data, properties, t);
+        return result;
+    }
+}