You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zh...@apache.org on 2021/03/30 07:54:44 UTC
[hbase] branch master updated: HBASE-25696 Need to initialize
SLF4JBridgeHandler in jul-to-slf4j for redirecting jul to slf4j (#3093)
This is an automated email from the ASF dual-hosted git repository.
zhangduo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/master by this push:
new 0242489 HBASE-25696 Need to initialize SLF4JBridgeHandler in jul-to-slf4j for redirecting jul to slf4j (#3093)
0242489 is described below
commit 024248994fc5d2d78e8b91a65e412a33e8042430
Author: Duo Zhang <zh...@apache.org>
AuthorDate: Tue Mar 30 15:54:18 2021 +0800
HBASE-25696 Need to initialize SLF4JBridgeHandler in jul-to-slf4j for redirecting jul to slf4j (#3093)
Signed-off-by: Michael Stack <st...@apache.org>
---
bin/hbase | 2 +
bin/hbase.cmd | 3 +
.../apache/hadoop/hbase/logging/TestJul2Slf4j.java | 96 ++++++++++++++++++++++
hbase-logging/pom.xml | 2 +-
.../hbase/logging/JulToSlf4jInitializer.java | 42 ++++++++++
hbase-logging/src/test/resources/log4j2.xml | 1 +
pom.xml | 1 +
7 files changed, 146 insertions(+), 1 deletion(-)
diff --git a/bin/hbase b/bin/hbase
index 601e2c1..ef1ff3d 100755
--- a/bin/hbase
+++ b/bin/hbase
@@ -311,6 +311,8 @@ for f in "${HBASE_HOME}"/lib/client-facing-thirdparty/*.jar; do
CLASSPATH="${CLASSPATH}:${f}"
fi
done
+# redirect java.util.logging to slf4j
+HBASE_OPTS="$HBASE_OPTS -Djava.util.logging.config.class=org.apache.hadoop.hbase.logging.JulToSlf4jInitializer"
# default log directory & file
if [ "$HBASE_LOG_DIR" = "" ]; then
diff --git a/bin/hbase.cmd b/bin/hbase.cmd
index 1fd39d2..342c043 100644
--- a/bin/hbase.cmd
+++ b/bin/hbase.cmd
@@ -326,6 +326,9 @@ set HBASE_OPTS=%HBASE_OPTS% -Dhbase.home.dir="%HBASE_HOME%"
set HBASE_OPTS=%HBASE_OPTS% -Dhbase.id.str="%HBASE_IDENT_STRING%"
set HBASE_OPTS=%HBASE_OPTS% -XX:OnOutOfMemoryError="taskkill /F /PID %p"
+@rem redirect java.util.logging to slf4j
+set HBASE_OPTS=%HBASE_OPTS% -Djava.util.logging.config.class="org.apache.hadoop.hbase.logging.JulToSlf4jInitializer"
+
if not defined HBASE_ROOT_LOGGER (
set HBASE_ROOT_LOGGER=INFO,console
)
diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/logging/TestJul2Slf4j.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/logging/TestJul2Slf4j.java
new file mode 100644
index 0000000..30409ee
--- /dev/null
+++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/logging/TestJul2Slf4j.java
@@ -0,0 +1,96 @@
+/**
+ * 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.hadoop.hbase.logging;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.hadoop.hbase.HBaseClassTestRule;
+import org.apache.hadoop.hbase.testclassification.MiscTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * This should be in the hbase-logging module but the {@link HBaseClassTestRule} is in hbase-common
+ * so we can only put the class in hbase-common module for now...
+ */
+@Category({ MiscTests.class, SmallTests.class })
+public class TestJul2Slf4j {
+
+ @ClassRule
+ public static final HBaseClassTestRule CLASS_RULE =
+ HBaseClassTestRule.forClass(TestJul2Slf4j.class);
+
+ static {
+ System.setProperty("java.util.logging.config.class", JulToSlf4jInitializer.class.getName());
+ }
+
+ private String loggerName = getClass().getName();
+
+ private org.apache.logging.log4j.core.Appender mockAppender;
+
+ @Before
+ public void setUp() {
+ mockAppender = mock(org.apache.logging.log4j.core.Appender.class);
+ when(mockAppender.getName()).thenReturn("mockAppender");
+ when(mockAppender.isStarted()).thenReturn(true);
+ ((org.apache.logging.log4j.core.Logger) org.apache.logging.log4j.LogManager
+ .getLogger(loggerName)).addAppender(mockAppender);
+ }
+
+ @After
+ public void tearDown() {
+ ((org.apache.logging.log4j.core.Logger) org.apache.logging.log4j.LogManager
+ .getLogger(loggerName)).removeAppender(mockAppender);
+ }
+
+ @Test
+ public void test() throws IOException {
+ AtomicReference<org.apache.logging.log4j.Level> level = new AtomicReference<>();
+ AtomicReference<String> msg = new AtomicReference<String>();
+ doAnswer(new Answer<Void>() {
+
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ org.apache.logging.log4j.core.LogEvent logEvent =
+ invocation.getArgument(0, org.apache.logging.log4j.core.LogEvent.class);
+ level.set(logEvent.getLevel());
+ msg.set(logEvent.getMessage().getFormattedMessage());
+ return null;
+ }
+ }).when(mockAppender).append(any(org.apache.logging.log4j.core.LogEvent.class));
+ java.util.logging.Logger logger = java.util.logging.Logger.getLogger(loggerName);
+ logger.info(loggerName);
+ verify(mockAppender, times(1)).append(any(org.apache.logging.log4j.core.LogEvent.class));
+ assertEquals(org.apache.logging.log4j.Level.INFO, level.get());
+ assertEquals(loggerName, msg.get());
+ }
+}
diff --git a/hbase-logging/pom.xml b/hbase-logging/pom.xml
index c1409b3..8be692c 100644
--- a/hbase-logging/pom.xml
+++ b/hbase-logging/pom.xml
@@ -86,7 +86,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
- <scope>test</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
diff --git a/hbase-logging/src/main/java/org/apache/hadoop/hbase/logging/JulToSlf4jInitializer.java b/hbase-logging/src/main/java/org/apache/hadoop/hbase/logging/JulToSlf4jInitializer.java
new file mode 100644
index 0000000..e7b5fdd
--- /dev/null
+++ b/hbase-logging/src/main/java/org/apache/hadoop/hbase/logging/JulToSlf4jInitializer.java
@@ -0,0 +1,42 @@
+/**
+ * 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.hadoop.hbase.logging;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.logging.LogManager;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.slf4j.bridge.SLF4JBridgeHandler;
+
+/**
+ * Setup {@link SLF4JBridgeHandler}.
+ * <p/>
+ * Set the system property {@code java.util.logging.config.class} to this class to initialize the
+ * direction for java.util.logging to slf4j.
+ */
+@InterfaceAudience.Private
+public class JulToSlf4jInitializer {
+
+ private static final String PROPERTIES = "handlers=" + SLF4JBridgeHandler.class.getName();
+
+ public JulToSlf4jInitializer() throws IOException {
+ LogManager.getLogManager()
+ .readConfiguration(new ByteArrayInputStream(PROPERTIES.getBytes(StandardCharsets.UTF_8)));
+ }
+}
diff --git a/hbase-logging/src/test/resources/log4j2.xml b/hbase-logging/src/test/resources/log4j2.xml
index 643fae6..f75f13e 100644
--- a/hbase-logging/src/test/resources/log4j2.xml
+++ b/hbase-logging/src/test/resources/log4j2.xml
@@ -41,5 +41,6 @@
<!-- For testing where we want to capture the log message of these special loggers -->
<Logger name="org.apache.hadoop.hbase.ipc.FailedServers" level="debug" />
<Logger name="org.apache.hadoop.hbase.regionserver.RSRpcServices" level="debug" />
+ <Logger name="org.apache.hadoop.hbase.logging.TestJul2Slf4j" level="debug" />
</Loggers>
</Configuration>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 0f5c6fb..aeb8bd4 100755
--- a/pom.xml
+++ b/pom.xml
@@ -775,6 +775,7 @@
<systemPropertyVariables>
<test.build.classes>${test.build.classes}</test.build.classes>
<java.io.tmpdir>${test.tmp.dir}</java.io.tmpdir>
+ <java.util.logging.config.class>org.apache.hadoop.hbase.logging.JulToSlf4jInitializer</java.util.logging.config.class>
</systemPropertyVariables>
<excludes>
<!-- users can add -D option to skip particular test classes