Skip to content

Commit 68d79cb

Browse files
committed
HBASE-25696 Need to initialize SLF4JBridgeHandler in jul-to-slf4j for redirecting jul to slf4j
1 parent 6a8998b commit 68d79cb

6 files changed

Lines changed: 140 additions & 1 deletion

File tree

bin/hbase

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ for f in "${HBASE_HOME}"/lib/client-facing-thirdparty/*.jar; do
311311
CLASSPATH="${CLASSPATH}:${f}"
312312
fi
313313
done
314+
# redirect java.util.logging to slf4j
315+
HBASE_OPTS="$HBASE_OPTS -Djava.util.logging.config.class=org.apache.hadoop.hbase.logging.JulToSlf4jInitializer"
314316

315317
# default log directory & file
316318
if [ "$HBASE_LOG_DIR" = "" ]; then

bin/hbase.cmd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ set HBASE_OPTS=%HBASE_OPTS% -Dhbase.home.dir="%HBASE_HOME%"
326326
set HBASE_OPTS=%HBASE_OPTS% -Dhbase.id.str="%HBASE_IDENT_STRING%"
327327
set HBASE_OPTS=%HBASE_OPTS% -XX:OnOutOfMemoryError="taskkill /F /PID %p"
328328

329+
@rem redirect java.util.logging to slf4j
330+
set HBASE_OPTS=%HBASE_OPTS% -Djava.util.logging.config.class="org.apache.hadoop.hbase.logging.JulToSlf4jInitializer"
331+
329332
if not defined HBASE_ROOT_LOGGER (
330333
set HBASE_ROOT_LOGGER=INFO,console
331334
)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.hadoop.hbase.logging;
19+
20+
import static org.junit.Assert.assertEquals;
21+
import static org.mockito.ArgumentMatchers.any;
22+
import static org.mockito.Mockito.doAnswer;
23+
import static org.mockito.Mockito.mock;
24+
import static org.mockito.Mockito.times;
25+
import static org.mockito.Mockito.verify;
26+
import static org.mockito.Mockito.when;
27+
28+
import java.io.IOException;
29+
import java.util.concurrent.atomic.AtomicReference;
30+
import org.apache.hadoop.hbase.HBaseClassTestRule;
31+
import org.apache.hadoop.hbase.testclassification.MiscTests;
32+
import org.apache.hadoop.hbase.testclassification.SmallTests;
33+
import org.junit.After;
34+
import org.junit.Before;
35+
import org.junit.Test;
36+
import org.junit.experimental.categories.Category;
37+
import org.mockito.invocation.InvocationOnMock;
38+
import org.mockito.stubbing.Answer;
39+
40+
/**
41+
* This should be in the hbase-logging module but the {@link HBaseClassTestRule} is in hbase-common
42+
* so we can only put the class in hbase-common module for now...
43+
*/
44+
@Category({ MiscTests.class, SmallTests.class })
45+
public class TestJul2Slf4j {
46+
47+
static {
48+
System.setProperty("java.util.logging.config.class", JulToSlf4jInitializer.class.getName());
49+
}
50+
51+
private String loggerName = getClass().getName();
52+
53+
private org.apache.logging.log4j.core.Appender mockAppender;
54+
55+
@Before
56+
public void setUp() {
57+
mockAppender = mock(org.apache.logging.log4j.core.Appender.class);
58+
when(mockAppender.getName()).thenReturn("mockAppender");
59+
when(mockAppender.isStarted()).thenReturn(true);
60+
((org.apache.logging.log4j.core.Logger) org.apache.logging.log4j.LogManager
61+
.getLogger(loggerName)).addAppender(mockAppender);
62+
}
63+
64+
@After
65+
public void tearDown() {
66+
((org.apache.logging.log4j.core.Logger) org.apache.logging.log4j.LogManager
67+
.getLogger(loggerName)).removeAppender(mockAppender);
68+
}
69+
70+
@Test
71+
public void test() throws IOException {
72+
AtomicReference<org.apache.logging.log4j.Level> level = new AtomicReference<>();
73+
AtomicReference<String> msg = new AtomicReference<String>();
74+
doAnswer(new Answer<Void>() {
75+
76+
@Override
77+
public Void answer(InvocationOnMock invocation) throws Throwable {
78+
org.apache.logging.log4j.core.LogEvent logEvent =
79+
invocation.getArgument(0, org.apache.logging.log4j.core.LogEvent.class);
80+
level.set(logEvent.getLevel());
81+
msg.set(logEvent.getMessage().getFormattedMessage());
82+
return null;
83+
}
84+
}).when(mockAppender).append(any(org.apache.logging.log4j.core.LogEvent.class));
85+
java.util.logging.Logger logger = java.util.logging.Logger.getLogger(loggerName);
86+
logger.info(loggerName);
87+
verify(mockAppender, times(1)).append(any(org.apache.logging.log4j.core.LogEvent.class));
88+
assertEquals(org.apache.logging.log4j.Level.INFO, level.get());
89+
assertEquals(loggerName, msg.get());
90+
}
91+
}

hbase-logging/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
<dependency>
8787
<groupId>org.slf4j</groupId>
8888
<artifactId>jul-to-slf4j</artifactId>
89-
<scope>test</scope>
89+
<scope>provided</scope>
9090
</dependency>
9191
<dependency>
9292
<groupId>org.apache.logging.log4j</groupId>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.hadoop.hbase.logging;
19+
20+
import java.io.ByteArrayInputStream;
21+
import java.io.IOException;
22+
import java.nio.charset.StandardCharsets;
23+
import java.util.logging.LogManager;
24+
import org.apache.yetus.audience.InterfaceAudience;
25+
import org.slf4j.bridge.SLF4JBridgeHandler;
26+
27+
/**
28+
* Setup {@link SLF4JBridgeHandler}.
29+
* <p/>
30+
* Set the system property {@code java.util.logging.config.class} to this class to initialize the
31+
* direction for java.util.logging to slf4j.
32+
*/
33+
@InterfaceAudience.Private
34+
public class JulToSlf4jInitializer {
35+
36+
private static final String PROPERTIES = "handlers=" + SLF4JBridgeHandler.class.getName();
37+
38+
public JulToSlf4jInitializer() throws IOException {
39+
LogManager.getLogManager()
40+
.readConfiguration(new ByteArrayInputStream(PROPERTIES.getBytes(StandardCharsets.UTF_8)));
41+
}
42+
}

hbase-logging/src/test/resources/log4j2.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,6 @@
4141
<!-- For testing where we want to capture the log message of these special loggers -->
4242
<Logger name="org.apache.hadoop.hbase.ipc.FailedServers" level="debug" />
4343
<Logger name="org.apache.hadoop.hbase.regionserver.RSRpcServices" level="debug" />
44+
<Logger name="org.apache.hadoop.hbase.logging.TestJul2Slf4j" level="debug" />
4445
</Loggers>
4546
</Configuration>

0 commit comments

Comments
 (0)