From 247eeb39a5eedae2b9f37d1ed032da3497672e6f Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Sat, 26 Nov 2022 10:39:34 +0800 Subject: [PATCH] Enhance logger adapter to use a configured logger (#10952) --- dubbo-common/pom.xml | 2 + .../dubbo/common/json/impl/FastJson2Impl.java | 2 +- .../dubbo/common/logger/LoggerAdapter.java | 10 +++ .../dubbo/common/logger/LoggerFactory.java | 72 +++++++++++++------ .../common/logger/jcl/JclLoggerAdapter.java | 2 +- .../common/logger/jdk/JdkLoggerAdapter.java | 15 +++- .../logger/log4j/Log4jLoggerAdapter.java | 31 +++++++- .../logger/log4j2/Log4j2LoggerAdapter.java | 8 ++- .../logger/slf4j/Slf4jLoggerAdapter.java | 13 +++- .../dubbo-container-spring/pom.xml | 10 +++ 10 files changed, 135 insertions(+), 30 deletions(-) diff --git a/dubbo-common/pom.xml b/dubbo-common/pom.xml index a122539922..d8c60c7f74 100644 --- a/dubbo-common/pom.xml +++ b/dubbo-common/pom.xml @@ -40,10 +40,12 @@ commons-logging commons-logging + provided log4j log4j + provided org.apache.logging.log4j diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java index 24147dc32a..cabf75d004 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java @@ -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; } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java index fc644e5ad4..6c668592d3 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java @@ -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; + } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerFactory.java index 91c0e60020..56b2ddb74c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerFactory.java @@ -41,25 +41,25 @@ public class LoggerFactory { private static final ConcurrentMap LOGGERS = new ConcurrentHashMap<>(); private static final ConcurrentMap 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 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 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 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 result = new LinkedList<>(); for (Map.Entry, 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; } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLoggerAdapter.java index 959a5136df..1751c602e9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jcl/JclLoggerAdapter.java @@ -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; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jdk/JdkLoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jdk/JdkLoggerAdapter.java index 19041304b1..43f32b1728 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jdk/JdkLoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/jdk/JdkLoggerAdapter.java @@ -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; + } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j/Log4jLoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j/Log4jLoggerAdapter.java index 5febaf2501..fad4605fa5 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j/Log4jLoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j/Log4jLoggerAdapter.java @@ -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 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; + } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j2/Log4j2LoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j2/Log4j2LoggerAdapter.java index 76f29dd73e..0a74a63739 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j2/Log4j2LoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/log4j2/Log4j2LoggerAdapter.java @@ -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; } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerAdapter.java index c28c8d8ef0..1f56242dda 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/slf4j/Slf4jLoggerAdapter.java @@ -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; + } } diff --git a/dubbo-container/dubbo-container-spring/pom.xml b/dubbo-container/dubbo-container-spring/pom.xml index ea11ebfe63..880f041e32 100644 --- a/dubbo-container/dubbo-container-spring/pom.xml +++ b/dubbo-container/dubbo-container-spring/pom.xml @@ -39,5 +39,15 @@ org.springframework spring-context + + org.slf4j + slf4j-api + test + + + log4j + log4j + test +