JDK Logging

package org.example;

import java.io.NotSerializableException;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import java.util.logging.Level;

public class Main {

    private static Logger LOGGER;

    static {
        LOGGER = Logger.getLogger(Main.class.getName());
    }

    public static void main(final String[] args) {

        LOGGER.info("an info msg");
        LOGGER.warning("a warning msg");
        LOGGER.severe("a severe msg");

        LOGGER.log(Level.INFO, "test1: a info msg", new NotSerializableException());
        LOGGER.log(Level.WARNING, "test1: a warning msg", new NotSerializableException());
        LOGGER.log(Level.SEVERE, "test1: a severe msg", new NotSerializableException());

    }

}

关键组件

JVM内logger的配置文件读取,管理,生成、获取等操作都依赖于它

LogManager$LoggerContext有private final Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();存logger

控制日志输出,JDK自带ConsoleHanlder把输出流重定向到System.err,调用Logger的方法进行输出时都会调用Handler的publish方法,每个logger可有多个handler

时间格式?线程名?i18n等

从高到低为OFF—>SEVERE—>WARNING—>INFO—>CONFIG—>FINE—>FINER—>FINEST—>ALL


常用Logger.getLogger();获得一个logger,然后用logger做日志输出

handler也有level

所有匿名logger都会把空的root logger作为parent

JDK默认logging配置 $JAVA_HOME/jre/lib/logging.properties

-Djava.util.logging.config.file指定配置文件

-Djava.util.logging.manager 指定自定义的 LogManager 实现类,默认java.util.logging.LogManager

LoggerManager初始化中会添加两个logger,名称为””的root logger,另一个是名称为global的全局logger,级别是INFO

useParentHandlers属性控制日志不进行往上层logger传递

Tomcat log

-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager

-Djava.util.logging.config.file=xx/conf/logging.properties

org.apache.catalina.startup.Bootstrap
-->private static final Log log = LogFactory.getLog(Bootstrap.class);
-->private static final LogFactory singleton = new LogFactory();
---->org.apache.juli.logging.LogFactory::getLog
------>org.apache.juli.logging.LogFactory::getInstance
-------->org.apache.juli.logging.DirectJDKLog::getInstance
---------->java.util.logging.Logger::getLogger(最终调用JDK中的日志器)
---------->java.util.logging.Logger::demandLogger
------------>java.util.logging.LogManager::getLogManager 得到这个全局日志管理器
------------>java.util.logging.LogManager::ensureLogManagerInitialized
------------>java.util.logging.LogManager::readPrimordialConfiguration
-------------->org.apache.juli.ClassLoaderLogManager::readConfiguration //读取配置

catalina、localhost、manager、admin、host-manager

从 7.0.54 开始,catalina.out 被替换为按日期分割的日志文件,格式为 catalina.YYYY-MM-DD.log

使用slf4j+logback

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
</dependency>
LogManager.getLogManager().reset();
SLF4JBridgeHandler.install();