You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ck...@apache.org on 2022/01/14 23:49:10 UTC

[logging-log4j2] branch master updated: LOG4J2-3282 Support source class & method in to-jul (#698)

This is an automated email from the ASF dual-hosted git repository.

ckozak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/master by this push:
     new 35ecbc3  LOG4J2-3282 Support source class & method in to-jul (#698)
35ecbc3 is described below

commit 35ecbc36192f02477e4c7f2324c9656f36cba775
Author: Michael Vorburger ⛑️ <vo...@apache.org>
AuthorDate: Sat Jan 15 00:39:54 2022 +0100

    LOG4J2-3282 Support source class & method in to-jul (#698)
---
 .../org/apache/logging/log4j/tojul/JULLogger.java  |  7 +--
 .../logging/log4j/tojul/LazyLog4jLogRecord.java    | 70 ++++++++++++++++++++++
 .../org/apache/logging/log4j/tojul/LoggerTest.java | 27 ++++++++-
 3 files changed, 96 insertions(+), 8 deletions(-)

diff --git a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULLogger.java b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULLogger.java
index 52c5299..5f27ae3 100644
--- a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULLogger.java
+++ b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULLogger.java
@@ -18,7 +18,6 @@ package org.apache.logging.log4j.tojul;
 
 import static java.util.Objects.requireNonNull;
 
-import java.util.logging.LogRecord;
 import java.util.logging.Logger;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
@@ -60,15 +59,11 @@ final class JULLogger extends AbstractLogger {
         if (!logger.isLoggable(julLevel)) {
             return;
         }
-        LogRecord record = new LogRecord(julLevel, message.getFormattedMessage()); // NOT getFormat()
+        LazyLog4jLogRecord record = new LazyLog4jLogRecord(fqcn, julLevel, message.getFormattedMessage()); // NOT getFormat()
         // NOT record.setParameters(message.getParameters()); BECAUSE getFormattedMessage() NOT getFormat()
         record.setLoggerName(getName());
         record.setThrown(t == null ? message.getThrowable() : t);
-        // Source class/method is not supported (yet)
-        record.setSourceClassName(null);
-        record.setSourceMethodName(null);
         logger.log(record);
-        // fqcn is un-used
     }
 
     // Convert Level in Log4j scale to JUL scale.
diff --git a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/LazyLog4jLogRecord.java b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/LazyLog4jLogRecord.java
new file mode 100644
index 0000000..f7bce8f
--- /dev/null
+++ b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/LazyLog4jLogRecord.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.tojul;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import org.apache.logging.log4j.util.StackLocatorUtil;
+
+/**
+ * Extension of {@link java.util.logging.LogRecord} with lazy get source related methods based on Log4j's {@link StackLocatorUtil#calcLocation(String)}.
+ */
+final class LazyLog4jLogRecord extends LogRecord {
+
+    private static final long serialVersionUID = 6798134264543826471L;
+
+    // parent class LogRecord already has a needToInferCaller but it's private
+    private transient boolean inferCaller = true;
+
+    private final String fqcn;
+
+    LazyLog4jLogRecord(String fqcn, Level level, String msg) {
+        super(level, msg);
+        this.fqcn = fqcn;
+    }
+
+    @Override
+    public String getSourceClassName() {
+        if (inferCaller) {
+            inferCaller();
+        }
+        return super.getSourceClassName();
+    }
+
+    @Override
+    public String getSourceMethodName() {
+        if (inferCaller) {
+            inferCaller();
+        }
+        return super.getSourceMethodName();
+    }
+
+    private void inferCaller() {
+        StackTraceElement location = null;
+        if (fqcn != null) {
+            location = StackLocatorUtil.calcLocation(fqcn);
+        }
+        if (location != null) {
+            setSourceClassName(location.getClassName());
+            setSourceMethodName(location.getMethodName());
+        } else {
+            setSourceClassName(null);
+            setSourceMethodName(null);
+        }
+        inferCaller = false;
+    }
+}
\ No newline at end of file
diff --git a/log4j-to-jul/src/test/java/org/apache/logging/log4j/tojul/LoggerTest.java b/log4j-to-jul/src/test/java/org/apache/logging/log4j/tojul/LoggerTest.java
index c418376..aabc338 100644
--- a/log4j-to-jul/src/test/java/org/apache/logging/log4j/tojul/LoggerTest.java
+++ b/log4j-to-jul/src/test/java/org/apache/logging/log4j/tojul/LoggerTest.java
@@ -81,8 +81,8 @@ public class LoggerTest {
         assertThat(log1.getMessage()).isEqualTo("hello, world");
         assertThat(log1.getParameters()).isNull();
         assertThat(log1.getThrown()).isNull();
-        assertThat(log1.getSourceClassName()).isNull();
-        assertThat(log1.getSourceMethodName()).isNull();
+        assertThat(log1.getSourceClassName()).isEqualTo(getClass().getName());
+        assertThat(log1.getSourceMethodName()).isEqualTo("infoAtInfo");
     }
 
     @Test public void infoAtInfoWithParameters() {
@@ -201,4 +201,27 @@ public class LoggerTest {
             super(name, value);
         }
     }
+
+    /**
+     * Test that the {@link LogRecord#getSourceClassName()}, which we already tested above in infoAtInfo()
+     * also works as expected if the logging happened in a class that we have called (indirect), not in the test method itself.
+     */
+    @Test public void indirectSource() {
+        java.util.logging.Logger.getLogger(Another.class.getName()).setLevel(Level.INFO);
+        new Another(handler);
+        List<LogRecord> logs = handler.getStoredLogRecords();
+        assertThat(logs).hasSize(1);
+        LogRecord log1 = logs.get(0);
+        assertThat(log1.getSourceClassName()).isEqualTo(Another.class.getName());
+        assertThat(log1.getSourceMethodName()).isEqualTo("<init>");
+    }
+
+    static class Another {
+        org.apache.logging.log4j.Logger anotherLog4jLogger = LogManager.getLogger(getClass());
+        java.util.logging.Logger anotherJULLogger = java.util.logging.Logger.getLogger(getClass().getName());
+        Another(TestLogHandler handler) {
+            anotherJULLogger.addHandler(handler);
+            anotherLog4jLogger.info("hello, another world");
+        }
+    }
 }