logback、log4j混用,指定log未输出问题排查
问题描述:
某个SDK(有一定历史的祖传代码)中自定义了一个logger,并且在应用初始化时调用log4j为该logger配置了Appender、Layout,filePath,logName命名为logA.log。而使用了这个SDK的应用,正好在需要查看这个log时,发现logA.log是存在的,但是文件内容却为空。
结论:翻了一下源码,结合当前使用这个SDK的应用的日志配置,得出结论:
1) SDK中自定义的那个logger的声明,使用的日志框架为common-logging+log4j,虽然通过代码指定了使用log4j为其配置Appender、filePath,但是该应用采用的日志框架为slf4j+logback,SDK中的所有log在运行时其实是使用的logback,以logback配置为输出标准。所以,自然不会输出到log4j指定的file中。
2)在SDK中指定某个日志的具体实现,并配置日志名称、输出路径,理解这种做法的初衷,但是,该log的level、appender、filepath最好是由用户自己按需配置。
场景还原:
抽象出代码如下,sdk-a中指定logName=“log4jLog”,并通过log4j进行配置,本意是想把Log4jTest中的日志单独打印到一个文件中。
package com.sdk.a;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;import java.io.File;
import java.util.Enumeration;
import java.util.Properties;public class Log4jInit {private static final Log logger = LogFactory.getLog(Log4jInit.class);static private volatile boolean initOK = false;public static final String LOG_NAME = "log4jLog";static private Properties defaultProperties = new Properties();static {defaultProperties.put("log4j.logger.log4jLog", "info, D");defaultProperties.put("log4j.additivity.log4jLog", "false");defaultProperties.put("log4j.appender.D", "org.apache.log4j.DailyRollingFileAppender");defaultProperties.put("log4j.appender.D.DatePattern", "'.'yyyy-MM-dd");defaultProperties.put("log4j.appender.D.File", "log4j_data.log");defaultProperties.put("log4j.appender.D.layout", "org.apache.log4j.PatternLayout");defaultProperties.put("log4j.appender.D.layout.ConversionPattern","%d{MM-dd HH:mm:ss} - %m%n");defaultProperties.put("log4j.appender.D.Append", "true");}public static void initLog() {if (initOK) {return;}ClassLoader cl = Thread.currentThread().getContextClassLoader();Thread.currentThread().setContextClassLoader(Log4jInit.class.getClassLoader());try {PropertyConfigurator.configure(defaultProperties);FileAppender bizFileAppender = new FileAppender();bizFileAppender.setFile("/app/weblogic/logs/log-demo/log4j.log");setFileAppender(bizFileAppender, LOG_NAME);initOK = true;}finally {Thread.currentThread().setContextClassLoader(cl);}}private static void setFileAppender(FileAppender bizFileAppender, String logName) {FileAppender fileAppender = getFileAppender(Logger.getLogger(logName));String bizLogDir = new File(bizFileAppender.getFile()).getParent();File newLogFile = new File(bizLogDir, fileAppender.getFile());fileAppender.setFile(newLogFile.getAbsolutePath());fileAppender.activateOptions();logger.info(logName + ",appender-path:" + newLogFile.getAbsolutePath());}
}import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;public class Log4jTest {static {Log4jInit.initLog();}//LOG_NAME在Log4jInit.initLog()中配置private static final Log log4j = LogFactory.getLog(Log4jInit.LOG_NAME);public void printLog() {log4j.info("log4j.info");}
}
应用使用sdk-a,如果想要特殊处理Logger("log4jLog"),可以自定义file、appender。
${LOG_DIR}/other.log ${LOG_BAK_DIR}/other.%d{yyyy-MM-dd}.log ${LOG_MAX_HISTORY} ${LOG_TOTAL_SIZE_CAP} %d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%thread] %logger{50}\(%file:%line\) - %msg%n
启动应用,打印sdk-a的Logger(log4jLog),查看日志,可以看出:
1)确实输出了sdk-a中定义的/app/weblogic/logs/log-demo/log4j.log,并且内容为空。
2)Logger(log4jLog)由应用配置的logback,输出到了otherAppender定义的file中。
package com.ls.demo.log.logdemo;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.sdk.a.Log4jTest;@SpringBootApplication
public class LogDemoApplication {public static void main(String[] args) {SpringApplication.run(LogDemoApplication.class, args);//使用sdk-aLog4jTest log4jTest = new Log4jTest();log4jTest.printLog();Logger logger = LoggerFactory.getLogger(LogDemoApplication.class);logger.info("logback.info");}
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
