HBASE-25696 Need to initialize SLF4JBridgeHandler in jul-to-slf4j for redirecting jul to slf4j (#3093)

Signed-off-by: Michael Stack <stack@apache.org>
This commit is contained in:
Duo Zhang 2021-03-30 15:54:18 +08:00 committed by GitHub
parent 46f7d9dd4b
commit 024248994f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 146 additions and 1 deletions

View File

@ -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

View File

@ -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
)

View File

@ -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());
}
}

View File

@ -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>

View File

@ -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)));
}
}

View File

@ -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>

View File

@ -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