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> <dependency>
<groupId>commons-logging</groupId> <groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId> <artifactId>commons-logging</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>log4j</groupId> <groupId>log4j</groupId>
<artifactId>log4j</artifactId> <artifactId>log4j</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>

View File

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

View File

@ -70,4 +70,14 @@ public interface LoggerAdapter {
* @param file logging file * @param file logging file
*/ */
void setFile(File 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, FailsafeLogger> LOGGERS = new ConcurrentHashMap<>();
private static final ConcurrentMap<String, FailsafeErrorTypeAwareLogger> ERROR_TYPE_AWARE_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 // search common-used logging frameworks
static { static {
String logger = System.getProperty("dubbo.application.logger", ""); String logger = System.getProperty("dubbo.application.logger", "");
switch (logger) { switch (logger) {
case "slf4j": case Slf4jLoggerAdapter.NAME:
setLoggerAdapter(new Slf4jLoggerAdapter()); setLoggerAdapter(new Slf4jLoggerAdapter());
break; break;
case "jcl": case JclLoggerAdapter.NAME:
setLoggerAdapter(new JclLoggerAdapter()); setLoggerAdapter(new JclLoggerAdapter());
break; break;
case "log4j": case Log4jLoggerAdapter.NAME:
setLoggerAdapter(new Log4jLoggerAdapter()); setLoggerAdapter(new Log4jLoggerAdapter());
break; break;
case "jdk": case JdkLoggerAdapter.NAME:
setLoggerAdapter(new JdkLoggerAdapter()); setLoggerAdapter(new JdkLoggerAdapter());
break; break;
case "log4j2": case Log4j2LoggerAdapter.NAME:
setLoggerAdapter(new Log4j2LoggerAdapter()); setLoggerAdapter(new Log4j2LoggerAdapter());
break; break;
default: default:
@ -70,15 +70,44 @@ public class LoggerFactory {
JclLoggerAdapter.class, JclLoggerAdapter.class,
JdkLoggerAdapter.class JdkLoggerAdapter.class
); );
boolean found = false;
// try to use the first available adapter
for (Class<? extends LoggerAdapter> clazz : candidates) { for (Class<? extends LoggerAdapter> clazz : candidates) {
try { 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); loggerAdapter.getLogger(LoggerFactory.class);
setLoggerAdapter(loggerAdapter); setLoggerAdapter(loggerAdapter);
found = true;
break; break;
} catch (Throwable ignored) { } 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) { public static void setLoggerAdapter(LoggerAdapter loggerAdapter) {
if (loggerAdapter != null) { if (loggerAdapter != null) {
if (loggerAdapter == LOGGER_ADAPTER) { if (loggerAdapter == LoggerFactory.loggerAdapter) {
return; return;
} }
loggerAdapter.getLogger(LoggerFactory.class.getName()); loggerAdapter.getLogger(LoggerFactory.class.getName());
LoggerFactory.LOGGER_ADAPTER = loggerAdapter; LoggerFactory.loggerAdapter = loggerAdapter;
for (Map.Entry<String, FailsafeLogger> entry : LOGGERS.entrySet()) { 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 * @return logger
*/ */
public static Logger getLogger(Class<?> key) { 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 * @return logger provider
*/ */
public static Logger getLogger(String key) { 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 * @return error type aware logger
*/ */
public static ErrorTypeAwareLogger getErrorTypeAwareLogger(Class<?> key) { 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 * @return error type aware logger
*/ */
public static ErrorTypeAwareLogger getErrorTypeAwareLogger(String key) { 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 * @return logging level
*/ */
public static Level getLevel() { public static Level getLevel() {
return LOGGER_ADAPTER.getLevel(); return loggerAdapter.getLevel();
} }
/** /**
@ -164,7 +193,7 @@ public class LoggerFactory {
* @param level logging level * @param level logging level
*/ */
public static void setLevel(Level 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 * @return current logging file
*/ */
public static File getFile() { public static File getFile() {
return LOGGER_ADAPTER.getFile(); return loggerAdapter.getFile();
} }
/** /**
@ -191,10 +220,11 @@ public class LoggerFactory {
List<String> result = new LinkedList<>(); List<String> result = new LinkedList<>();
for (Map.Entry<Class<? extends LoggerAdapter>, String> entry : candidates.entrySet()) { for (Map.Entry<Class<? extends LoggerAdapter>, String> entry : candidates.entrySet()) {
try { try {
LoggerAdapter loggerAdapter = entry.getKey().newInstance(); LoggerAdapter loggerAdapter = entry.getKey().getConstructor().newInstance();
loggerAdapter.getLogger(LoggerFactory.class); loggerAdapter.getLogger(LoggerFactory.class);
result.add(entry.getValue()); result.add(entry.getValue());
} catch (Throwable ignored) { } catch (Exception ignored) {
// ignored
} }
} }
return result; return result;
@ -213,9 +243,9 @@ public class LoggerFactory {
candidates.put(JclLoggerAdapter.class, "jcl"); candidates.put(JclLoggerAdapter.class, "jcl");
candidates.put(JdkLoggerAdapter.class, "jdk"); candidates.put(JdkLoggerAdapter.class, "jdk");
String name = candidates.get(LOGGER_ADAPTER.getClass()); String name = candidates.get(loggerAdapter.getClass());
if (name == null) { if (name == null) {
name = LOGGER_ADAPTER.getClass().getSimpleName(); name = loggerAdapter.getClass().getSimpleName();
} }
return name; return name;
} }

View File

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

View File

@ -29,19 +29,23 @@ import java.util.logging.LogManager;
public class JdkLoggerAdapter implements LoggerAdapter { public class JdkLoggerAdapter implements LoggerAdapter {
public static final String NAME = "jdk";
private static final String GLOBAL_LOGGER_NAME = "global"; private static final String GLOBAL_LOGGER_NAME = "global";
private File file; private File file;
private boolean propertiesLoaded = false;
public JdkLoggerAdapter() { public JdkLoggerAdapter() {
try { try {
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("logging.properties"); InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("logging.properties");
if (in != null) { if (in != null) {
LogManager.getLogManager().readConfiguration(in); LogManager.getLogManager().readConfiguration(in);
propertiesLoaded = true;
} else { } else {
System.err.println("No such logging.properties in classpath for jdk logging config!"); 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()); System.err.println("Failed to load logging.properties in classpath for jdk logging config, cause: " + t.getMessage());
} }
try { 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 @Override
public void setFile(File file) { 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 class Log4jLoggerAdapter implements LoggerAdapter {
public static final String NAME = "log4j";
private File file; private File file;
@SuppressWarnings("unchecked") @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 @Override
public void setFile(File file) { 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; import java.io.File;
public class Log4j2LoggerAdapter implements LoggerAdapter { public class Log4j2LoggerAdapter implements LoggerAdapter {
public static final String NAME = "log4j2";
private Level level; private Level level;
public Log4j2LoggerAdapter() { public Log4j2LoggerAdapter() {
} }
private static org.apache.logging.log4j.Level toLog4j2Level(Level level) { private static org.apache.logging.log4j.Level toLog4j2Level(Level level) {
@ -103,5 +103,11 @@ public class Log4j2LoggerAdapter implements LoggerAdapter {
@Override @Override
public void setFile(File file) { 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.Level;
import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerAdapter; import org.apache.dubbo.common.logger.LoggerAdapter;
import org.apache.dubbo.common.utils.ClassUtils;
import java.io.File; import java.io.File;
public class Slf4jLoggerAdapter implements LoggerAdapter { public class Slf4jLoggerAdapter implements LoggerAdapter {
public static final String NAME = "slf4j";
private Level level; private Level level;
private File file; private File file;
@ -57,4 +58,14 @@ public class Slf4jLoggerAdapter implements LoggerAdapter {
this.file = file; 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> <groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId> <artifactId>spring-context</artifactId>
</dependency> </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> </dependencies>
</project> </project>