标签:不同的 multi tsp pac empty 依赖 ops new 配置
bolt的日志文件默认位于{user.home}/logs/bolt目录下
文件名 | 说明 |
---|---|
common-default.log | 普通日志 |
common-error.log | 错误级别日志 |
connection-event.log | 连接相关的日志 |
remoting-rpc.log | rpc协议相关的日志 |
bolt只依赖SLF4j门面框架,可以支持三种类型的日志实现:log4j, log4j2, 和 logback。运行时根据具体项目引入的日志框架,实现日志的自适应打印。
日志隔离的功能是工具包sofa-common-tools实现的。
日志的入口类是BoltLoggerFactory
private static final Logger logger = BoltLoggerFactory.getLogger("CommonDefault");
获取名称为CommonDefault的日志,这个名称是在日志配置文件中配置的。
<AsyncLogger name="CommonDefault" level="${LOG_LEVEL}" additivity="false">
<appender-ref ref="CommonDefaultAppender"/>
<appender-ref ref="ERROR-APPENDER"/>
</AsyncLogger>
public static Logger getLogger(String name) {
if (name == null || name.isEmpty()) {
return null;
}
return LoggerSpaceManager.getLoggerBySpace(name, BOLT_LOG_SPACE);
}
spaceName参数BOLT_LOG_SPACE的值是com.alipay.remoting,表示的是日志空间的名称。
不同的space使用不同的配置文件。例如space名称为com.alipay.remoting时,bolt会尝试从classpath下的com.alipay.remoting.log目录下寻找配置文件。resouces下有三种日志框架的配置文件,如图
com.alipay.sofa.common.log.LoggerSpaceManager#getLoggerBySpace
public static Logger getLoggerBySpace(String name, String spaceName) {
return getLoggerBySpace(name, new SpaceId(spaceName),
Collections.<String, String> emptyMap());
}
public static Logger getLoggerBySpace(String name, SpaceId spaceId,
Map<String, String> properties) {
//init first
init(spaceId, properties);
return MultiAppLoggerSpaceManager.getLoggerBySpace(name, spaceId);
}
MultiAppLoggerSpaceManager中实现了自适应逻辑
public static Logger getLoggerBySpace(String name, SpaceId spaceId, ClassLoader spaceClassloader) {
//创建日志工厂类
AbstractLoggerSpaceFactory abstractLoggerSpaceFactory = getILoggerFactoryBySpaceName(
spaceId, spaceClassloader);
return abstractLoggerSpaceFactory.getLogger(name);
}
创建日志工厂方法已经返回的是具体的日志工厂实现类(由构造器LoggerSpaceFactoryBuilder的实现类构建)
从工厂类中获取日志对象Logger并返回
创建日志工厂
private static AbstractLoggerSpaceFactory createILoggerFactory(SpaceId spaceId,
ClassLoader spaceClassloader) {
if (System.getProperty(SOFA_MIDDLEWARE_LOG_DISABLE_PROP_KEY) != null
&& Boolean.TRUE.toString().equalsIgnoreCase(
System.getProperty(SOFA_MIDDLEWARE_LOG_DISABLE_PROP_KEY))) {
ReportUtil.reportWarn("Sofa-Middleware-Log is disabled! -D"
+ SOFA_MIDDLEWARE_LOG_DISABLE_PROP_KEY + "=true");
return NOP_LOGGER_FACTORY;
}
// 设置日志的配置文件
LogEnvUtils.processGlobalSystemLogProperties();
try {
if (LogEnvUtils.isLogbackUsable(spaceClassloader)) {
String isLogbackDisable = System
.getProperty(LOGBACK_MIDDLEWARE_LOG_DISABLE_PROP_KEY);
if (isLogbackDisable != null
&& Boolean.TRUE.toString().equalsIgnoreCase(isLogbackDisable)) {
ReportUtil.reportWarn("Logback-Sofa-Middleware-Log is disabled! -D"
+ LOGBACK_MIDDLEWARE_LOG_DISABLE_PROP_KEY + "=true");
} else {
ReportUtil.report("Actual binding is of type [ " + spaceId.toString()
+ " Logback ]");
LoggerSpaceFactoryBuilder loggerSpaceFactory4LogbackBuilder = new LoggerSpaceFactory4LogbackBuilder(
spacesMap.get(spaceId));
return loggerSpaceFactory4LogbackBuilder.build(spaceId.getSpaceName(),
spaceClassloader);
}
}
if (LogEnvUtils.isLog4j2Usable(spaceClassloader)) {
String isLog4j2Disable = System.getProperty(LOG4J2_MIDDLEWARE_LOG_DISABLE_PROP_KEY);
if (isLog4j2Disable != null
&& Boolean.TRUE.toString().equalsIgnoreCase(isLog4j2Disable)) {
ReportUtil.reportWarn("Log4j2-Sofa-Middleware-Log is disabled! -D"
+ LOG4J2_MIDDLEWARE_LOG_DISABLE_PROP_KEY + "=true");
} else {
ReportUtil.report("Actual binding is of type [ " + spaceId.toString()
+ " Log4j2 ]");
LoggerSpaceFactoryBuilder loggerSpaceFactory4Log4j2Builder = new LoggerSpaceFactory4Log4j2Builder(
spacesMap.get(spaceId));
return loggerSpaceFactory4Log4j2Builder.build(spaceId.getSpaceName(),
spaceClassloader);
}
}
if (LogEnvUtils.isLog4jUsable(spaceClassloader)) {
String isLog4jDisable = System.getProperty(LOG4J_MIDDLEWARE_LOG_DISABLE_PROP_KEY);
if (isLog4jDisable != null
&& Boolean.TRUE.toString().equalsIgnoreCase(isLog4jDisable)) {
ReportUtil.reportWarn("Log4j-Sofa-Middleware-Log is disabled! -D"
+ LOG4J_MIDDLEWARE_LOG_DISABLE_PROP_KEY + "=true");
} else {
ReportUtil.report("Actual binding is of type [ " + spaceId.toString()
+ " Log4j ]");
LoggerSpaceFactoryBuilder loggerSpaceFactory4Log4jBuilder = new LoggerSpaceFactory4Log4jBuilder(
spacesMap.get(spaceId));
return loggerSpaceFactory4Log4jBuilder.build(spaceId.getSpaceName(),
spaceClassloader);
}
}
if (LogEnvUtils.isCommonsLoggingUsable(spaceClassloader)) {
//此种情形:commons-logging 桥接到 log4j 实现,默认日志实现仍然是 log4j
String isLog4jDisable = System
.getProperty(LOG4J_COMMONS_LOGGING_MIDDLEWARE_LOG_DISABLE_PROP_KEY);
if (isLog4jDisable != null
&& Boolean.TRUE.toString().equalsIgnoreCase(isLog4jDisable)) {
ReportUtil
.reportWarn("Log4j-Sofa-Middleware-Log(But adapter commons-logging to slf4j) is disabled! -D"
+ LOG4J_COMMONS_LOGGING_MIDDLEWARE_LOG_DISABLE_PROP_KEY
+ "=true");
} else {
ReportUtil.report("Actual binding is of type [ " + spaceId.toString()
+ " Log4j (Adapter commons-logging to slf4j)]");
LoggerSpaceFactoryBuilder loggerSpaceFactory4Log4jBuilder = new LoggerSpaceFactory4CommonsLoggingBuilder(
spacesMap.get(spaceId));
return loggerSpaceFactory4Log4jBuilder.build(spaceId.getSpaceName(),
spaceClassloader);
}
}
ReportUtil.reportWarn("No log util is usable, Default app logger will be used.");
} catch (Throwable e) {
ReportUtil.reportError("Build ILoggerFactory error! Default app logger will be used.",
e);
}
return NOP_LOGGER_FACTORY;
}
LogEnvUtils用来判断是否存在相应的类包,例如判断类路径下是否存在log4j2的jar包
public static boolean isLog4j2Usable(ClassLoader spaceClassloader) {
AssertUtil.notNull(spaceClassloader);
try {
return (spaceClassloader.loadClass("org.apache.logging.slf4j.Log4jLoggerFactory") != null);
} catch (ClassNotFoundException e) {
return false;
}
}
如果存在多个日志jar包,代码中可以看出优先级为
按顺序一旦找到某一日志jar包,就调用相应构造器的build方法进行构建。
创建Log4j2工厂
@Override
public AbstractLoggerSpaceFactory build(String spaceName, ClassLoader spaceClassloader) {
AssertUtil.hasText(spaceName);
AssertUtil.notNull(spaceClassloader);
//load config file
URL configFileUrl = getSpaceLogConfigFileURL(spaceClassloader, spaceName);
// set default logging.level
specifySpaceLogConfigProperites(spaceName);
return doBuild(spaceName, spaceClassloader, configFileUrl);
}
加载配置文件
private URL getSpaceLogConfigFileURL(ClassLoader spaceClassloader, String spaceName) {
String suffix = LogEnvUtils.getLogConfEnvSuffix(spaceName);
//TODO avoid this pattern "log-conf.xml.console"
String logConfigLocation = spaceName.replace('.', '/') + "/" + LOG_DIRECTORY + "/"
+ getLoggingToolName() + "/" + LOG_XML_CONFIG_FILE_NAME + suffix;
URL configFileUrl = spaceClassloader.getResource(logConfigLocation);
//recommend this pattern "log-conf-console.xml"
if (configFileUrl == null && suffix != null && !suffix.isEmpty()) {
//try again with another env profile file pattern;
logConfigLocation = spaceName.replace('.', '/')
+ "/"
+ LOG_DIRECTORY
+ "/"
+ getLoggingToolName()
+ "/"
+ String.format(LOG_XML_CONFIG_FILE_ENV_PATTERN,
suffix.substring(1));
configFileUrl = spaceClassloader.getResource(logConfigLocation);
}
AssertUtil.state(configFileUrl != null, this + " build error: No " + getLoggingToolName()
+ " config file (" + configFileUrl + ") found!");
return configFileUrl;
}
日志文件名后缀
// 指定特定spaceName的环境配置,值格式: spaceName1:dev&spaceName2:test&spaceName3:product
String LOG_ENV_SUFFIX = "log.env.suffix";
日志配置文件路径
参数 | 值 |
---|---|
suffix | 未配置,空字符串 |
LOG_DIRECTORY | log |
getLoggingToolName() | logback log4j2 log4j |
LOG_XML_CONFIG_FILE_NAME | log-conf.xml |
日志配置文件可能的地址是
设置默认日志级别
private void specifySpaceLogConfigProperites(String spaceName) {
//如果system.properties 与 properites 都含有某分配置,那么以 system.properties 为准,同时WARN警告,properties中重复定义会被抛弃;
Iterator<Map.Entry<Object, Object>> iterator = spaceInfo.properties().entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Object, Object> entry = iterator.next();
if (System.getProperties().containsKey(entry.getKey())) {
iterator.remove();
logger.warn(
"Props key {} is also already existed in System.getProps ({}:{}),so use it!",
entry.getKey(), entry.getKey(), System.getProperty((String) entry.getKey()));
}
}
/**
* == 1.space's logger path
*/
String loggingPathKey = LOG_PATH_PREFIX + spaceName;
if (System.getProperty(loggingPathKey) == null && System.getProperty(LOG_PATH) != null
&& spaceInfo.properties().getProperty(loggingPathKey) == null) {
spaceInfo.properties().setProperty(loggingPathKey, System.getProperty(LOG_PATH));
}
/**
* == 2.space's logger level
*/
String loggingLevelKey = LOG_LEVEL_PREFIX + spaceName;
if (System.getProperty(loggingLevelKey) == null
&& spaceInfo.properties().getProperty(loggingLevelKey) == null) {
spaceInfo.properties().setProperty(loggingLevelKey,
Constants.DEFAULT_MIDDLEWARE_SPACE_LOG_LEVEL);
}
}
构建
com.alipay.sofa.common.log.factory.LoggerSpaceFactory4Log4j2Builder#doBuild
@Override
public AbstractLoggerSpaceFactory doBuild(String spaceName, ClassLoader spaceClassloader,
URL url) {
try {
final LoggerContext context = new LoggerContext(spaceName, null, url.toURI());
Configuration config = null;
ConfigurationFactory configurationFactory = ConfigurationFactory.getInstance();
try {
//log4j-core 2.3 version
Class[] parameterTypes = new Class[3];
parameterTypes[0] = String.class;
parameterTypes[1] = URI.class;
parameterTypes[2] = ClassLoader.class;
Method getConfigurationMethod = configurationFactory.getClass().getMethod(
"getConfiguration", parameterTypes);
config = (Configuration) getConfigurationMethod.invoke(configurationFactory,
spaceName, url.toURI(), spaceClassloader);
} catch (NoSuchMethodException noSuchMethodException) {
//log4j-core 2.8 version
Class[] parameterTypes = new Class[4];
parameterTypes[0] = LoggerContext.class;
parameterTypes[1] = String.class;
parameterTypes[2] = URI.class;
parameterTypes[3] = ClassLoader.class;
Method getConfigurationMethod = configurationFactory.getClass().getMethod(
"getConfiguration", parameterTypes);
config = (Configuration) getConfigurationMethod.invoke(configurationFactory,
context, spaceName, url.toURI(), spaceClassloader);
}
if (config == null) {
throw new RuntimeException("No log4j2 configuration are found.");
}
for (Map.Entry entry : getProperties().entrySet()) {
//from Map<String,String>
config.getProperties().put((String) entry.getKey(), (String) entry.getValue());
}
for (Map.Entry entry : System.getProperties().entrySet()) {
//from Map<String,String>
config.getProperties().put((String) entry.getKey(), (String) entry.getValue());
}
context.start(config);
return new AbstractLoggerSpaceFactory(getLoggingToolName()) {
private ConcurrentMap<String, org.apache.logging.slf4j.Log4jLogger> loggerMap = new ConcurrentHashMap<String, org.apache.logging.slf4j.Log4jLogger>();
@Override
public Logger setLevel(String loggerName, AdapterLevel adapterLevel)
throws Exception {
org.apache.logging.slf4j.Log4jLogger log4jLoggerAdapter = (org.apache.logging.slf4j.Log4jLogger) this
.getLogger(loggerName);
final String key = Logger.ROOT_LOGGER_NAME.equals(loggerName) ? LogManager.ROOT_LOGGER_NAME
: loggerName;
org.apache.logging.log4j.core.Logger log4j2Logger = context.getLogger(key);
//level
org.apache.logging.log4j.Level log4j2Level = this.toLog4j2Level(adapterLevel);
log4j2Logger.setLevel(log4j2Level);
return log4jLoggerAdapter;
}
@Override
public org.slf4j.Logger getLogger(String name) {
final String key = Logger.ROOT_LOGGER_NAME.equals(name) ? LogManager.ROOT_LOGGER_NAME
: name;
org.apache.logging.log4j.core.Logger log4jLogger = context.getLogger(key);
Log4jLogger oldInst = this.loggerMap.get(key);
if (oldInst != null) {
return oldInst;
}
Log4jLogger newInst = new Log4jLogger(log4jLogger, key);
oldInst = this.loggerMap.putIfAbsent(key, newInst);
return oldInst == null ? newInst : oldInst;
}
private org.apache.logging.log4j.Level toLog4j2Level(AdapterLevel adapterLevel) {
if (adapterLevel == null) {
throw new IllegalStateException(
"AdapterLevel is NULL when adapter to log4j2.");
}
switch (adapterLevel) {
case TRACE:
return Level.TRACE;
case DEBUG:
return Level.DEBUG;
case INFO:
return Level.INFO;
case WARN:
return Level.WARN;
case ERROR:
return Level.ERROR;
default:
throw new IllegalStateException(adapterLevel
+ " is unknown when adapter to log4j2.");
}
}
};
} catch (Throwable e) {
throw new IllegalStateException("Log4j2 loggerSpaceFactory build error!", e);
}
}
调用ConfigurationFactory解析log4j2的配置文件,然后返回匿名类。匿名类的getLogger方法就是前面生成工厂类后获取Logger对象时调用的。
标签:不同的 multi tsp pac empty 依赖 ops new 配置
原文地址:https://www.cnblogs.com/huiyao/p/12436780.html