Enhance logger adapter to use a configured logger (#10952)

This commit is contained in:
Albumen Kevin 2022-11-26 10:39:34 +08:00 committed by GitHub
parent 10082d3fa1
commit 247eeb39a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 135 additions and 30 deletions

View File

@ -40,10 +40,12 @@
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>

View File

@ -30,7 +30,7 @@ public class FastJson2Impl extends AbstractJSONImpl {
try {
Class<?> aClass = ClassUtils.forName("com.alibaba.fastjson2.JSON");
return aClass != null;
} catch (Throwable t) {
} catch (Exception t) {
return false;
}
}

View File

@ -70,4 +70,14 @@ public interface LoggerAdapter {
* @param file logging file
*/
void setFile(File file);
/**
* Return is the current logger has been configured.
* Used to check if logger is available to use.
*
* @return true if the current logger has been configured
*/
default boolean isConfigured() {
return true;
}
}

View File

@ -41,25 +41,25 @@ public class LoggerFactory {
private static final ConcurrentMap<String, FailsafeLogger> LOGGERS = new ConcurrentHashMap<>();
private static final ConcurrentMap<String, FailsafeErrorTypeAwareLogger> ERROR_TYPE_AWARE_LOGGERS = new ConcurrentHashMap<>();
private static volatile LoggerAdapter LOGGER_ADAPTER;
private static volatile LoggerAdapter loggerAdapter;
// search common-used logging frameworks
static {
String logger = System.getProperty("dubbo.application.logger", "");
switch (logger) {
case "slf4j":
case Slf4jLoggerAdapter.NAME:
setLoggerAdapter(new Slf4jLoggerAdapter());
break;
case "jcl":
case JclLoggerAdapter.NAME:
setLoggerAdapter(new JclLoggerAdapter());
break;
case "log4j":
case Log4jLoggerAdapter.NAME:
setLoggerAdapter(new Log4jLoggerAdapter());
break;
case "jdk":
case JdkLoggerAdapter.NAME:
setLoggerAdapter(new JdkLoggerAdapter());
break;
case "log4j2":
case Log4j2LoggerAdapter.NAME:
setLoggerAdapter(new Log4j2LoggerAdapter());
break;
default:
@ -70,15 +70,44 @@ public class LoggerFactory {
JclLoggerAdapter.class,
JdkLoggerAdapter.class
);
boolean found = false;
// try to use the first available adapter
for (Class<? extends LoggerAdapter> clazz : candidates) {
try {
LoggerAdapter loggerAdapter = clazz.newInstance();
LoggerAdapter loggerAdapter = clazz.getConstructor().newInstance();
loggerAdapter.getLogger(LoggerFactory.class);
if (loggerAdapter.isConfigured()) {
setLoggerAdapter(loggerAdapter);
found = true;
break;
}
} catch (Exception | LinkageError ignored) {
// ignore
}
}
if (found) {
break;
}
System.err.println("Dubbo: Unable to find a proper configured logger to log out.");
for (Class<? extends LoggerAdapter> clazz : candidates) {
try {
LoggerAdapter loggerAdapter = clazz.getConstructor().newInstance();
loggerAdapter.getLogger(LoggerFactory.class);
setLoggerAdapter(loggerAdapter);
found = true;
break;
} catch (Throwable ignored) {
// ignore
}
}
if (found) {
System.err.println("Dubbo: Using default logger: " + loggerAdapter.getClass().getName() + ". " +
"If you cannot see any log, please configure -Ddubbo.application.logger property to your preferred logging framework.");
} else {
System.err.println("Dubbo: Unable to find any available logger adapter to log out. Dubbo logs will be ignored. " +
"Please configure -Ddubbo.application.logger property and add corresponding logging library to classpath.");
}
}
}
@ -98,13 +127,13 @@ public class LoggerFactory {
*/
public static void setLoggerAdapter(LoggerAdapter loggerAdapter) {
if (loggerAdapter != null) {
if (loggerAdapter == LOGGER_ADAPTER) {
if (loggerAdapter == LoggerFactory.loggerAdapter) {
return;
}
loggerAdapter.getLogger(LoggerFactory.class.getName());
LoggerFactory.LOGGER_ADAPTER = loggerAdapter;
LoggerFactory.loggerAdapter = loggerAdapter;
for (Map.Entry<String, FailsafeLogger> entry : LOGGERS.entrySet()) {
entry.getValue().setLogger(LOGGER_ADAPTER.getLogger(entry.getKey()));
entry.getValue().setLogger(LoggerFactory.loggerAdapter.getLogger(entry.getKey()));
}
}
}
@ -116,7 +145,7 @@ public class LoggerFactory {
* @return logger
*/
public static Logger getLogger(Class<?> key) {
return LOGGERS.computeIfAbsent(key.getName(), name -> new FailsafeLogger(LOGGER_ADAPTER.getLogger(name)));
return LOGGERS.computeIfAbsent(key.getName(), name -> new FailsafeLogger(loggerAdapter.getLogger(name)));
}
/**
@ -126,7 +155,7 @@ public class LoggerFactory {
* @return logger provider
*/
public static Logger getLogger(String key) {
return LOGGERS.computeIfAbsent(key, k -> new FailsafeLogger(LOGGER_ADAPTER.getLogger(k)));
return LOGGERS.computeIfAbsent(key, k -> new FailsafeLogger(loggerAdapter.getLogger(k)));
}
/**
@ -136,7 +165,7 @@ public class LoggerFactory {
* @return error type aware logger
*/
public static ErrorTypeAwareLogger getErrorTypeAwareLogger(Class<?> key) {
return ERROR_TYPE_AWARE_LOGGERS.computeIfAbsent(key.getName(), name -> new FailsafeErrorTypeAwareLogger(LOGGER_ADAPTER.getLogger(name)));
return ERROR_TYPE_AWARE_LOGGERS.computeIfAbsent(key.getName(), name -> new FailsafeErrorTypeAwareLogger(loggerAdapter.getLogger(name)));
}
/**
@ -146,7 +175,7 @@ public class LoggerFactory {
* @return error type aware logger
*/
public static ErrorTypeAwareLogger getErrorTypeAwareLogger(String key) {
return ERROR_TYPE_AWARE_LOGGERS.computeIfAbsent(key, k -> new FailsafeErrorTypeAwareLogger(LOGGER_ADAPTER.getLogger(k)));
return ERROR_TYPE_AWARE_LOGGERS.computeIfAbsent(key, k -> new FailsafeErrorTypeAwareLogger(loggerAdapter.getLogger(k)));
}
/**
@ -155,7 +184,7 @@ public class LoggerFactory {
* @return logging level
*/
public static Level getLevel() {
return LOGGER_ADAPTER.getLevel();
return loggerAdapter.getLevel();
}
/**
@ -164,7 +193,7 @@ public class LoggerFactory {
* @param level logging level
*/
public static void setLevel(Level level) {
LOGGER_ADAPTER.setLevel(level);
loggerAdapter.setLevel(level);
}
/**
@ -173,7 +202,7 @@ public class LoggerFactory {
* @return current logging file
*/
public static File getFile() {
return LOGGER_ADAPTER.getFile();
return loggerAdapter.getFile();
}
/**
@ -191,10 +220,11 @@ public class LoggerFactory {
List<String> result = new LinkedList<>();
for (Map.Entry<Class<? extends LoggerAdapter>, String> entry : candidates.entrySet()) {
try {
LoggerAdapter loggerAdapter = entry.getKey().newInstance();
LoggerAdapter loggerAdapter = entry.getKey().getConstructor().newInstance();
loggerAdapter.getLogger(LoggerFactory.class);
result.add(entry.getValue());
} catch (Throwable ignored) {
} catch (Exception ignored) {
// ignored
}
}
return result;
@ -213,9 +243,9 @@ public class LoggerFactory {
candidates.put(JclLoggerAdapter.class, "jcl");
candidates.put(JdkLoggerAdapter.class, "jdk");
String name = candidates.get(LOGGER_ADAPTER.getClass());
String name = candidates.get(loggerAdapter.getClass());
if (name == null) {
name = LOGGER_ADAPTER.getClass().getSimpleName();
name = loggerAdapter.getClass().getSimpleName();
}
return name;
}

View File

@ -25,7 +25,7 @@ import org.apache.commons.logging.LogFactory;
import java.io.File;
public class JclLoggerAdapter implements LoggerAdapter {
public static final String NAME = "jcl";
private Level level;
private File file;

View File

@ -29,19 +29,23 @@ import java.util.logging.LogManager;
public class JdkLoggerAdapter implements LoggerAdapter {
public static final String NAME = "jdk";
private static final String GLOBAL_LOGGER_NAME = "global";
private File file;
private boolean propertiesLoaded = false;
public JdkLoggerAdapter() {
try {
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("logging.properties");
if (in != null) {
LogManager.getLogManager().readConfiguration(in);
propertiesLoaded = true;
} else {
System.err.println("No such logging.properties in classpath for jdk logging config!");
}
} catch (Throwable t) {
} catch (Exception t) {
System.err.println("Failed to load logging.properties in classpath for jdk logging config, cause: " + t.getMessage());
}
try {
@ -56,7 +60,8 @@ public class JdkLoggerAdapter implements LoggerAdapter {
}
}
}
} catch (Throwable t) {
} catch (Exception ignored) {
// ignore
}
}
@ -133,7 +138,11 @@ public class JdkLoggerAdapter implements LoggerAdapter {
@Override
public void setFile(File file) {
// ignore
}
@Override
public boolean isConfigured() {
return propertiesLoaded;
}
}

View File

@ -29,6 +29,7 @@ import java.util.Enumeration;
public class Log4jLoggerAdapter implements LoggerAdapter {
public static final String NAME = "log4j";
private File file;
@SuppressWarnings("unchecked")
@ -49,7 +50,8 @@ public class Log4jLoggerAdapter implements LoggerAdapter {
}
}
}
} catch (Throwable t) {
} catch (Exception t) {
// ignore
}
}
@ -126,7 +128,32 @@ public class Log4jLoggerAdapter implements LoggerAdapter {
@Override
public void setFile(File file) {
// ignore
}
@Override
public boolean isConfigured() {
boolean hasAppender = false;
try {
org.apache.log4j.Logger logger = LogManager.getRootLogger();
if (logger != null) {
Enumeration<Appender> appenders = logger.getAllAppenders();
if (appenders != null) {
while (appenders.hasMoreElements()) {
hasAppender = true;
Appender appender = appenders.nextElement();
if (appender instanceof FileAppender) {
FileAppender fileAppender = (FileAppender) appender;
String filename = fileAppender.getFile();
file = new File(filename);
break;
}
}
}
}
} catch (Exception t) {
// ignore
}
return hasAppender;
}
}

View File

@ -25,11 +25,11 @@ import org.apache.logging.log4j.LogManager;
import java.io.File;
public class Log4j2LoggerAdapter implements LoggerAdapter {
public static final String NAME = "log4j2";
private Level level;
public Log4j2LoggerAdapter() {
}
private static org.apache.logging.log4j.Level toLog4j2Level(Level level) {
@ -103,5 +103,11 @@ public class Log4j2LoggerAdapter implements LoggerAdapter {
@Override
public void setFile(File file) {
// ignore
}
@Override
public boolean isConfigured() {
return true;
}
}

View File

@ -19,11 +19,12 @@ package org.apache.dubbo.common.logger.slf4j;
import org.apache.dubbo.common.logger.Level;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerAdapter;
import org.apache.dubbo.common.utils.ClassUtils;
import java.io.File;
public class Slf4jLoggerAdapter implements LoggerAdapter {
public static final String NAME = "slf4j";
private Level level;
private File file;
@ -57,4 +58,14 @@ public class Slf4jLoggerAdapter implements LoggerAdapter {
this.file = file;
}
@Override
public boolean isConfigured() {
try {
ClassUtils.forName("org.slf4j.impl.StaticLoggerBinder");
return true;
} catch (ClassNotFoundException ignore) {
// ignore
}
return false;
}
}

View File

@ -39,5 +39,15 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>