sofa-common-tools is a common dependency of SOFAStack middleware, it provides:
Separate log space for application and middleware
SOFA thread
The audience of this library is middleware and SDK developer.
Note: Since version 1.2.0, sofa-common-tools don’t support JDK 1.6 anymore.
Background
In daily developing, Java logging usually consists of choosing a log facade (e.g., JCL and SLF4j) and log implementation (e.g., Log4j2 and logback).
Say you are developing an application that uses a JAR which utilizes log4j2 for logging.
In such scenario, you cannot choose log implementation other than log4j2 (log implementation conflicts if you choose Logback).
Some solutions available:
The jar uses log facade instead log implementation but application developers still have to provide log configuration
The jar initialize loggers and appenders programmatically (This works well in Multi-ClassLoader environment where middleware/SDK developers handle many repeated work)
Application resort to same log implementation as the JAR and provide also log configuration
None of the above solutions is perfect, sofa-common-tools provides a Midas touch: middleware/SDK developers print logs using only facade and hand the right to select whichever log implementation to application developer.
At the mean time, middleware/SDK developers provide log configurations per log implementation.
sofa-common-tools detects automatically the log implementation and initializes appenders and loggers for middleware/SDK.
To differentiate SDKs/middlewares, each jar has its own log context and log space identifiable via SpaceID in sofa-common-tools.
Some notes:
sofa-common-tools only supports SLF4j facade currently
Quick Start
Say you are developing an OCR SDK for downstream to integrate. First, you choose com.alipay.sdk.ocr as your log space.
Second, define a logger factory to retrieve all the loggers you need:
import org.slf4j.Logger;
import com.alipay.sofa.common.log.LoggerSpaceManager;
public class AlipayOcrLoggerFactory {
private static final String OCR_LOGGER_SPACE = "com.alipay.sdk.ocr";
public static Logger getLogger(String name) {
if (name == null || name.isEmpty()) {
return null;
}
return LoggerSpaceManager.getLoggerBySpace(name, OCR_LOGGER_SPACE);
}
public static Logger getLogger(Class<?> klass) {
if (klass == null) {
return null;
}
return getLogger(klass.getCanonicalName());
}
}
Third, create log configuration for your log space in classpath (space name com.alipay.sdk.ocr maps to com/alipay/sdk/ocr/log/ ), for example
$ cd com/alipay/sdk/ocr/log && tree
.
├── log4j
│ └── log-conf.xml
├── log4j2
│ └── log-conf.xml
└── logback
└── log-conf.xml
The directory name is quite self-evident. If application choose a log implementation you don’t configure, error will be thrown.
A sample configuration for logback logback/log-conf.xml:
public class Main {
public static void main(String[] args) {
Logger ocrLogger = AlipayOcrLoggerFactory.getLogger("com.alipay.foo");
ocrLogger.info("hello world");
}
}
In console, the following log will be printed:
17:42:41.083 [main] INFO com.alipay.foo - hello world
Configuration
The configuration of corresponding logging implementation can be parameterized, that is to say, placeholders are allowed in XML file.
By default, sofa-common-tools provides following parameters with sensible default values:
Parameter
Default value
logging.path
${user.home}
file.encoding
UTF-8
logging.level.{spaceName}
INFO
logging.path.{spaceName}
${logging.path}
Application is able to override the value through JVM options, e.g., -Dlogging.path=/home/admin.
Customized Parameter
Middlewares/SDKs can defined customized parameters for xml placeholders as well.
Those parameters must be initialized before using:
import org.slf4j.Logger;
import com.alipay.sofa.common.log.LoggerSpaceManager;import java.util.HashMap;
public class AlipayOcrLoggerFactory {
private static final String OCR_LOGGER_SPACE = "com.alipay.sdk.ocr";
static {
// Note: this step is important, as in Ark environment your SDK may be used in module dependency
// and will be initialized multiple times.
if (!MultiAppLoggerSpaceManager.isSpaceInitialized(OCR_LOGGER_SPACE)) {
Map spaceIdProperties = new HashMap<String, String>();
// Initialize your parameters here
MultiAppLoggerSpaceManager.init(OCR_LOGGER_SPACE, spaceIdProperties);
}
}
public static Logger getLogger(String name) {
if (name == null || name.isEmpty()) {
return null;
}
return LoggerSpaceManager.getLoggerBySpace(name, OCR_LOGGER_SPACE);
}
public static Logger getLogger(Class<?> klass) {
if (klass == null) {
return null;
}
return getLogger(klass.getCanonicalName());
}
}
Debugging
The logging ability can be disabled totally through sofa.middleware.log.disable JVM option (Of course for middleware/SDK jar using sofa-common-tools).
Debugging with specific log implementation, lock-down of other log implementation, e.g., -Dlogback.middleware.log.disable=true disables logback. All supported switch:
log4j.middleware.log.disable
log4j2.middleware.log.disable
logback.middleware.log.disable
Miscellaneous
sofa.middleware.log.disable, defaults to false
logback.middleware.log.disable, defaults to false
log4j2.middleware.log.disable, defaults to false
log4j.middleware.log.disable, defaults to false
LogLog
sofa-common-tools uses internally System.out for logging, logging level can be set via JVM option sofa.middleware.log.internal.level.
Console logging
Global configuration
Switch sofa.middleware.log.console toggles console logging for all middleware/SDK, defaults to false
sofa-common-tools
sofa-common-toolsis a common dependency of SOFAStack middleware, it provides:The audience of this library is middleware and SDK developer.
Note: Since version 1.2.0, sofa-common-tools don’t support JDK 1.6 anymore.
Background
In daily developing, Java logging usually consists of choosing a log facade (e.g., JCL and SLF4j) and log implementation (e.g., Log4j2 and logback). Say you are developing an application that uses a JAR which utilizes log4j2 for logging. In such scenario, you cannot choose log implementation other than log4j2 (log implementation conflicts if you choose Logback). Some solutions available:
None of the above solutions is perfect,
sofa-common-toolsprovides a Midas touch: middleware/SDK developers print logs using only facade and hand the right to select whichever log implementation to application developer. At the mean time, middleware/SDK developers provide log configurations per log implementation.sofa-common-toolsdetects automatically the log implementation and initializes appenders and loggers for middleware/SDK. To differentiate SDKs/middlewares, each jar has its own log context and log space identifiable viaSpaceIDinsofa-common-tools.Some notes:
sofa-common-toolsonly supports SLF4j facade currentlyQuick Start
Say you are developing an OCR SDK for downstream to integrate. First, you choose
com.alipay.sdk.ocras your log space. Second, define a logger factory to retrieve all the loggers you need:Third, create log configuration for your log space in classpath (space name
com.alipay.sdk.ocrmaps tocom/alipay/sdk/ocr/log/), for exampleThe directory name is quite self-evident. If application choose a log implementation you don’t configure, error will be thrown.
A sample configuration for logback
logback/log-conf.xml:Lastly, just logging
In console, the following log will be printed:
Configuration
The configuration of corresponding logging implementation can be parameterized, that is to say, placeholders are allowed in XML file. By default,
sofa-common-toolsprovides following parameters with sensible default values:Application is able to override the value through JVM options, e.g.,
-Dlogging.path=/home/admin.Customized Parameter
Middlewares/SDKs can defined customized parameters for xml placeholders as well. Those parameters must be initialized before using:
Debugging
sofa.middleware.log.disableJVM option (Of course for middleware/SDK jar usingsofa-common-tools).-Dlogback.middleware.log.disable=truedisables logback. All supported switch:Miscellaneous
falsefalsefalsefalseLogLog
sofa-common-toolsuses internallySystem.outfor logging, logging level can be set via JVM optionsofa.middleware.log.internal.level.Console logging
sofa.middleware.log.consoletoggles console logging for all middleware/SDK, defaults tofalsesofa.middleware.log.console.levelconfigures log level globallysofa.middleware.log.${spaceid}.consoletoggles console logging for corresponding middleware/SDK, defaults tofalsesofa.middleware.log.{space id}.console.levelconfigures log level correspondingly, which overrides global log levelLogging pattern
sofa.middleware.log.console.logback.patterndefaults to%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%nsofa.middleware.log.console.log4j2.patterndefaults to%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %X{PID} --- [%15.15t] %-40.40logger{39} : %m%nConsole logging options can be passed through JVM option or Spring Boot
properties.Compiling
Maven 3.2.5+, JDK Version 1.6+
LICENSE
Apache 2.0
Contribution
Contribution Guide