HADOOP-18653. LogLevel servlet to determine log impl before using setLevel (#5456)
The log level can only be set on Log4J log implementations; probes are used to downgrade to a warning when other logging back ends are used Contributed by Viraj Jasani
This commit is contained in:
parent
09469bf47d
commit
aff840c59c
|
@ -34,6 +34,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.hadoop.classification.VisibleForTesting;
|
import org.apache.hadoop.classification.VisibleForTesting;
|
||||||
import org.apache.hadoop.thirdparty.com.google.common.base.Charsets;
|
import org.apache.hadoop.thirdparty.com.google.common.base.Charsets;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.apache.hadoop.HadoopIllegalArgumentException;
|
import org.apache.hadoop.HadoopIllegalArgumentException;
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.classification.InterfaceStability;
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
|
@ -44,6 +46,7 @@ import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
|
||||||
import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
|
import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
|
||||||
import org.apache.hadoop.security.ssl.SSLFactory;
|
import org.apache.hadoop.security.ssl.SSLFactory;
|
||||||
import org.apache.hadoop.util.GenericOptionsParser;
|
import org.apache.hadoop.util.GenericOptionsParser;
|
||||||
|
import org.apache.hadoop.util.GenericsUtil;
|
||||||
import org.apache.hadoop.util.ServletUtil;
|
import org.apache.hadoop.util.ServletUtil;
|
||||||
import org.apache.hadoop.util.Tool;
|
import org.apache.hadoop.util.Tool;
|
||||||
import org.apache.hadoop.util.ToolRunner;
|
import org.apache.hadoop.util.ToolRunner;
|
||||||
|
@ -338,14 +341,18 @@ public class LogLevel {
|
||||||
out.println(MARKER
|
out.println(MARKER
|
||||||
+ "Submitted Class Name: <b>" + logName + "</b><br />");
|
+ "Submitted Class Name: <b>" + logName + "</b><br />");
|
||||||
|
|
||||||
Logger log = Logger.getLogger(logName);
|
org.slf4j.Logger log = LoggerFactory.getLogger(logName);
|
||||||
out.println(MARKER
|
out.println(MARKER
|
||||||
+ "Log Class: <b>" + log.getClass().getName() +"</b><br />");
|
+ "Log Class: <b>" + log.getClass().getName() +"</b><br />");
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
out.println(MARKER + "Submitted Level: <b>" + level + "</b><br />");
|
out.println(MARKER + "Submitted Level: <b>" + level + "</b><br />");
|
||||||
}
|
}
|
||||||
|
|
||||||
process(log, level, out);
|
if (GenericsUtil.isLog4jLogger(logName)) {
|
||||||
|
process(Logger.getLogger(logName), level, out);
|
||||||
|
} else {
|
||||||
|
out.println("Sorry, setting log level is only supported for log4j loggers.<br />");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.println(FORMS);
|
out.println(FORMS);
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.hadoop.util;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.classification.InterfaceStability;
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
|
@ -33,6 +34,14 @@ import org.slf4j.LoggerFactory;
|
||||||
@InterfaceStability.Unstable
|
@InterfaceStability.Unstable
|
||||||
public class GenericsUtil {
|
public class GenericsUtil {
|
||||||
|
|
||||||
|
private static final String SLF4J_LOG4J_ADAPTER_CLASS = "org.slf4j.impl.Log4jLoggerAdapter";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to false only if log4j adapter class is not found in the classpath. Once set to false,
|
||||||
|
* the utility method should not bother re-loading class again.
|
||||||
|
*/
|
||||||
|
private static final AtomicBoolean IS_LOG4J_LOGGER = new AtomicBoolean(true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Class object (of type <code>Class<T></code>) of the
|
* Returns the Class object (of type <code>Class<T></code>) of the
|
||||||
* argument of type <code>T</code>.
|
* argument of type <code>T</code>.
|
||||||
|
@ -87,12 +96,27 @@ public class GenericsUtil {
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Logger log = LoggerFactory.getLogger(clazz);
|
return isLog4jLogger(clazz.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the log of the given logger is of Log4J implementation.
|
||||||
|
*
|
||||||
|
* @param logger the logger name, usually class name as string.
|
||||||
|
* @return true if the logger uses Log4J implementation.
|
||||||
|
*/
|
||||||
|
public static boolean isLog4jLogger(String logger) {
|
||||||
|
if (logger == null || !IS_LOG4J_LOGGER.get()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Logger log = LoggerFactory.getLogger(logger);
|
||||||
try {
|
try {
|
||||||
Class log4jClass = Class.forName("org.slf4j.impl.Log4jLoggerAdapter");
|
Class<?> log4jClass = Class.forName(SLF4J_LOG4J_ADAPTER_CLASS);
|
||||||
return log4jClass.isInstance(log);
|
return log4jClass.isInstance(log);
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
|
IS_LOG4J_LOGGER.set(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ public class TestGenericsUtil {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsLog4jLogger() throws Exception {
|
public void testIsLog4jLogger() throws Exception {
|
||||||
assertFalse("False if clazz is null", GenericsUtil.isLog4jLogger(null));
|
assertFalse("False if clazz is null", GenericsUtil.isLog4jLogger((Class<?>) null));
|
||||||
assertTrue("The implementation is Log4j",
|
assertTrue("The implementation is Log4j",
|
||||||
GenericsUtil.isLog4jLogger(TestGenericsUtil.class));
|
GenericsUtil.isLog4jLogger(TestGenericsUtil.class));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue