背景
调试 Tomcat 源码过程中,控制台日志打印的都是 INFO 级别的日志,于是就想修改下日志级别,打印 Digester 类的 DEBUG 级别的日志,便于观察 Digester 类解析 server.xml 的流程,顺便跟踪了一下 Tomcat 使用日志的流程,整理如下。
使用方法
Java提供了原生态的日志工具包 java.util.logging,功能虽然没有 log4j 强大,但是够用了,我想这也是 Tomcat 使用原生日志的原因吧。Java 默认的日志配置文件路径是 Java 安装路径下的 \jre\lib\logging.properties。
使用过程中可以设置系统变量来改变路径,使用方法很简单,示例如下
public class MyClass {
public static void main(String[] args) {
System.setProperty("java.util.logging.config.file",
"D:\\A2017Study\\TomcateStudy\\catalina-home\\conf\\logging.properties");
Logger log = Logger.getLogger("Javasoft");
log.info("aaa");
}
}
复制代码
logging包结构图
从类图上,不难看出,这里使用了工厂模式、单例模式、观察者模式(即监听器)。
LogManager 类负责生成 Logger 实例,区分用户 Logger 和系统 Logger,默认新建的 Logger其 isSystemLog 标识为false,存储在 userContext 中。
LoggerContext 维护了一个 HashTable,保存创建的Logger对象。
调用时序图
分析上述示例的 main 方法,得到整个调用的时序图如下:
logging.properties 文件的作用就是定义 Logger 的 Handler 和 level,这个文件是在 LogManager 的构造方法中调用的,源码如下:
public static LogManager getLogManager() {
if (manager != null) {
manager.readPrimordialConfiguration();
}
return manager;
}
public void readConfiguration() throws IOException, SecurityException {
checkPermission();
String cname = System.getProperty("java.util.logging.config.class");
if (cname != null) {
try {
Class clz = ClassLoader.getSystemClassLoader().loadClass(cname);
clz.newInstance();
return;
}
String fname = System.getProperty("java.util.logging.config.file");
if (fname == null) {
fname = System.getProperty("java.home");
if (fname == null) {
throw new Error("Can't find java.home ??");
}
File f = new File(fname, "lib");
f = new File(f, "logging.properties");
fname = f.getCanonicalPath();
}
……
}
复制代码
readConfiguration() 值得关注的是两个配置(其他代码省略了,只保留重要代码)。
LogManager 类通过它们来控制配置文件的初始化,类注释如下:
In addition, the LogManager uses two optional system properties that
allow more control over reading the initial configuration:
"java.util.logging.config.class"
"java.util.logging.config.file"
所以我们可以通过 -Djava.util.logging.config.file 配置这两个变量来控制最终的配置文件,如果指定了class类,我们就需要在自定义类的构造函数中完成配置文件的初始化过程,当然直接指定file配置显得更简单一些。
主要关注的是日志的 level 和 handler 属性,文章开头的问题,通过修改 Java 安装目录下默认的 logging.properties 文件,修改全局控制台的日志等级为java.util.logging.ConsoleHandler.level=FINE,就能打印出 Tomcat 启动过程中的所有日志了。