一 概述
JUL是java原生的日志框架,在java
二 介绍
- loggers: 记录器,调用Logger对象的API来发布日志,为日志系统的入口程序。
- Appenders:或者称为Handlers,每个Logger会关联一组Handlers。Logger将日志信息交给关联的Handlers处理,有Handlers负责日志记录。其具体实现决定日志输出位置是控制台、文件、网络或者其他日志系统等。
- Layouts:称为Formatters,负责对日志数据进行转换和格式化。
- Level:日志级别。
- Filters:过滤器,根据需要过滤哪些信息会被记录,哪些会被丢弃。
三 简单使用
@Test
public void test01(){
// 获取日志记录器对象
Logger logger = Logger.getLogger(JULTest.class.getName());
// 一般日志输出
logger.info("jul test01");
// 一般日志输出
logger.log(Level.INFO,"jul info test01");
// 警告日志输出
logger.log(Level.WARNING,"jul warning test01");
// 占位符方式日志输出
logger.log(Level.INFO,"put:{0},out:{1}",new String[]{"小白","小花"});
}
四 日志级别
级别枚举 | 描述 |
---|---|
OFF | 关闭日志 |
SEVERE | 严重错误信息 |
WARNING | 警告信息 |
INFO | 一般信息 |
CONFIG | 配置信息 |
FINE | 详细信息 |
FINER | 较详细信息 |
FINEST | 非常详细信息 |
ALL | 开启所有级别的日志信息 |
1 默认的日志级别
测试代码:
@Test
public void test02(){
// 获取日志记录器对象
Logger logger = Logger.getLogger(JULTest.class.getName());
// 日志记录输出
logger.severe("severe");
logger.warning("warning");
logger.info("info"); // 默认日志输出级别
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}
执行结果:
九月 29, 2020 1:39:20 下午 com.salulu.logger.test.JULTest testLogLevel
严重: severe
九月 29, 2020 1:39:20 下午 com.salulu.logger.test.JULTest testLogLevel
警告: warning
九月 29, 2020 1:39:20 下午 com.salulu.logger.test.JULTest testLogLevel
信息: info
可以看到默认的输出级别为info级别
2 自定义日志级别
代码示例中,配置了输出到控制台和输出到文件中。
同时设置了日志输出级别为非常详细
@Test
public void test03()throws Exception{
// 获取日志记录器对象
Logger logger = Logger.getLogger(JULTest.class.getName());
logger.setUseParentHandlers(false);// 关闭系统默认配置
// 自定义配置日志级别
// 配置控制台输出
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setFormatter(new SimpleFormatter());
logger.addHandler(consoleHandler);
logger.setLevel(Level.ALL);// 配置日志具体级别
consoleHandler.setLevel(Level.ALL);
// 配置文件输出
FileHandler fileHandler = new FileHandler("/Users/liujian/IdeaProjects/sensetime/template-parent/logger-jul/out/test03.log");
fileHandler.setFormatter(new SimpleFormatter());// 关联简单格式转换对象
logger.addHandler(fileHandler);
// 2.日志记录输出
logger.severe("severe");
logger.warning("warning");
logger.info("info");
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}
日志输出结果:
九月 29, 2020 1:45:50 下午 com.salulu.logger.test.JULTest test03
严重: severe
九月 29, 2020 1:45:50 下午 com.salulu.logger.test.JULTest test03
警告: warning
九月 29, 2020 1:45:50 下午 com.salulu.logger.test.JULTest test03
信息: info
九月 29, 2020 1:45:50 下午 com.salulu.logger.test.JULTest test03
配置: config
九月 29, 2020 1:45:50 下午 com.salulu.logger.test.JULTest test03
详细: fine
九月 29, 2020 1:45:50 下午 com.salulu.logger.test.JULTest test03
较详细: finer
九月 29, 2020 1:45:50 下午 com.salulu.logger.test.JULTest test03
非常详细: finest
五 日志配置文件
1 默认的配置文件
1,首先读取配置类,如果有配置则使用配置类的信息。
2,如果没有配置类,则读取配置文件。
3,如果没有配置文件,则读取java_home的路径下lib文件里的logging.properties配置文件
源码如下:
java.util.logging.LogManager#readConfiguration()
public void readConfiguration() throws IOException, SecurityException {
checkPermission();
// 如果指定了配置类,则加载并使用它。
String cname = System.getProperty("java.util.logging.config.class");
if (cname != null) {
try {
// Instantiate the named class. It is its constructor's
// responsibility to initialize the logging configuration, by
// calling readConfiguration(InputStream) with a suitable stream.
try {
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
clz.newInstance();
return;
} catch (ClassNotFoundException ex) {
Class<?> clz = Thread.currentThread().getContextClassLoader().loadClass(cname);
clz.newInstance();
return;
}
} catch (Exception ex) {
System.err.println("Logging configuration class \"" + cname + "\" failed");
System.err.println("" + ex);
// keep going and useful config file.
}
}
// 如果没有配置类,则读取配置文件。
String fname = System.getProperty("java.util.logging.config.file");
// 如果没有配置文件,则读取java_home的路径
// 在java_home路径下有个lib文件夹,lib文件夹下有个logging.properties文件
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");
// 我自己电脑的配置就读取到如下路径:
// /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/logging.properties
fname = f.getCanonicalPath();
}
try (final InputStream in = new FileInputStream(fname)) {
final BufferedInputStream bin = new BufferedInputStream(in);
readConfiguration(bin);
}
}
读取到jdk自带的配置文件内容如下(注释省略):
# 默认的处理器对象
handlers= java.util.logging.ConsoleHandler
# 默认的日志级别
.level= INFO
# 文件输出路径:%h指的是当前用户目录,%u指日志按照数字增长
java.util.logging.FileHandler.pattern = %h/java%u.log
# 当个日志文件最大存储多少条
java.util.logging.FileHandler.limit = 50000
# 当前日志的数量,如果改为10,则%u就为0到9,总共10个日志文件
java.util.logging.FileHandler.count = 1
# 日志格式
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# 控制台日志级别为INFO
java.util.logging.ConsoleHandler.level = INFO
# 默认的简单格式转换对象
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
com.xyz.foo.level = SEVERE
2 自定义配置文件
- 配置
# 指定日志输出到多个地方(使用逗号隔开)
handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler
# 默认的日志级别
.level= ALL
# 文件输出路径:%h指的是当前用户目录,%u指日志按照数字增长
java.util.logging.FileHandler.pattern = /Users/liujian/IdeaProjects/sensetime/template-parent/logger-jul/out/salulu-test%u.log
# 当个日志文件最大存储多少条
java.util.logging.FileHandler.limit = 50000
# 当前日志的数量,如果改为10,则%u就为0到9,总共10个日志文件
java.util.logging.FileHandler.count = 1
# 日志格式
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
# 指定以追加方式添加日志内容
java.util.logging.FileHandler.append = true
# 指定控制台日志级别为ALL
java.util.logging.ConsoleHandler.level = ALL
# 默认的简单格式转换对象
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# 指定 handler 对象的字符集
java.util.logging.ConsoleHandler.encoding = UTF-8
com.xyz.foo.level = ALL
- 测试使用
@Test
public void test06() throws IOException {
// 读取配置文件,通过类加载器
InputStream ins = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
// 创建LogManager
LogManager logManager = LogManager.getLogManager();
// 通过LogManager加载配置文件
logManager.readConfiguration(ins);
Logger logger = Logger.getLogger(JULTest.class.getName());
logger.severe("severe");
logger.warning("warning");
logger.info("info");
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}