java 日志系统学习
一、 日志系统
1.JUL(java util logging)日志封装
JUL、logback、log4j、log4j2
2.JCL (jakarta Commons Logging) 日志接口
slf4j、JCL
二、JUL 学习
JUL 全称 java util Logging 是java 原生的日志框架,使用时不需要引入第三方类库。
2.1 框架介绍
- Logger : 记录器,应用程序通过获取Logger对象,调用其API 来发布日志信息。Logger 通常是应用程序访问日志系统的入口程序。
- Appenders: 也被称为Handlers,每个Logger都会关联一组Handlers,Logger会将日志交给关联Handlers处理,由handlers负责将日志做记录。Handlers 在此是一个抽象,其具体的实现决定了日志记录的位置可以是控制台、文件、网络上的其他日志服务或者操作系统日志等。(内部调用了Layouts)
- Layouts: 也被称为Formatters,它负责对日志事件中的数据进行转换和格式化。Layouts决定数据在一条日志记录中的最终形式。
- Level:每条日志消息都有一个关联的日志级别。该级别粗略知道了日志消息的重要性和紧迫,我可以将Level 和Loggers,Appenders 做关联以便于我们过滤消息。
- Filters:过滤器,根据需要指定哪些信息会被记录,哪些信息会被放过。
2.2 JUL的快速入门
/** * 日志系统快速入门 */ @Test public void testJUL() throws Exception{ //获取日志记录器,每个日志记录器都有自己的唯一标识(一般为全限定类名) Logger logger = Logger.getLogger("com.LoggerLean.JULTest"); //日志输出 logger.info("hello jul"); /** * 通用方法进行日志记录 * Level 是内置的一个枚举类 */ logger.log(Level.INFO,"msg info"); /** * 通过占位符 方式输出变量 */ String name = "GuiJia"; Integer age = 22; logger.log(Level.INFO,"用户信息: {0},{1}",new Object[]{name,age}); }
控制台输出
四月 19, 2022 10:29:57 下午 com.LoggerLean.JULTest testJUL
資訊: hello jul
四月 19, 2022 10:29:57 下午 com.LoggerLean.JULTest testJUL
資訊: msg info
四月 19, 2022 10:29:57 下午 com.LoggerLean.JULTest testJUL
資訊: 用户信息: GuiJia,22
2.3 JUL的日志级别
OFF : 最高级别的日志信息 (MAX_VALUE)
SEVERE : 系统error错误日志信息(1000)
WARNING : 程序警告信息 (900)
INFO : 程序需要关注的重要信息(800)
CONFIG : CONFIG是静态配置消息的消息级别(700)
FINE\FINER\FINEST : FINE是提供跟踪信息的消息级别。所有FINE、FINER和FINEST都用于相对详细的跟踪。这三个级别的确切含义在子系统之间会有所不同,但一般来说,FINEST用于最详细的输出,FINER用于较不详细的输出,FINE用于最低容量(也是最重要的)消息。一般来说,FINE级别应该用于那些对特定子系统没有特别兴趣的开发人员感兴趣的信息。FINE消息可能包括次要(可恢复)故障等内容。表明潜在性能问题的问题也值得记录为FINE。(500)
ALL : 记录应该记录的所有信息(MIN_VALUE)
测试程序
@Test public void testLevel() throws Exception{ Logger logger = Logger.getLogger("com.LoggerLean.JULTest"); logger.severe("severe"); logger.warning("warning"); logger.info("info"); //jul 的默认级别为info logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
结果(控制台输出):
四月 20, 2022 10:39:21 上午 com.LoggerLean.JULTest testLevel 嚴重: severe 四月 20, 2022 10:39:21 上午 com.LoggerLean.JULTest testLevel 警告: warning 四月 20, 2022 10:39:21 上午 com.LoggerLean.JULTest testLevel 資訊: info
通过输出可以知道,默认的日志级别为info,高于或等于info级别的logger日志信息才能输出。
2.4 JUL 自定义日志级别
自定义日志级别则是通过代码来理解
@Test public void testLoggerConfig() throws Exception{ Logger logger = Logger.getLogger("com.LoggerLean.JULTest"); //关闭系统默认配置 logger.setUseParentHandlers(false); //自定义配置日志级别 //创建ConsoleHandler ConsoleHandler consoleHandler = new ConsoleHandler(); //创建简单格式转换对象 SimpleFormatter simpleFormatter = new SimpleFormatter(); //进行关联 consoleHandler.setFormatter(simpleFormatter); logger.addHandler(consoleHandler); //配置日志具体级别 logger.setLevel(Level.ALL); consoleHandler.setLevel(Level.ALL); logger.severe("severe"); logger.warning("warning"); logger.info("info"); //jul 的默认级别为info logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
输出(控制台):
四月 20, 2022 11:08:00 上午 com.LoggerLean.JULTest testLoggerConfig 嚴重: severe 四月 20, 2022 11:08:00 上午 com.LoggerLean.JULTest testLoggerConfig 警告: warning 四月 20, 2022 11:08:00 上午 com.LoggerLean.JULTest testLoggerConfig 資訊: info 四月 20, 2022 11:08:00 上午 com.LoggerLean.JULTest testLoggerConfig 組態: config 四月 20, 2022 11:08:00 上午 com.LoggerLean.JULTest testLoggerConfig 詳細: fine 四月 20, 2022 11:08:00 上午 com.LoggerLean.JULTest testLoggerConfig 較詳細: finer 四月 20, 2022 11:08:00 上午 com.LoggerLean.JULTest testLoggerConfig 最詳細: finest
添加FileHandler 将输出输出到文件中
@Test public void testLoggerConfig() throws Exception{ Logger logger = Logger.getLogger("com.LoggerLean.JULTest"); //关闭系统默认配置 logger.setUseParentHandlers(false); //自定义配置日志级别 //创建ConsoleHandler(控制台输出) ConsoleHandler consoleHandler = new ConsoleHandler(); //创建简单格式转换对象 SimpleFormatter simpleFormatter = new SimpleFormatter(); //进行关联 consoleHandler.setFormatter(simpleFormatter); logger.addHandler(consoleHandler); //配置日志具体级别 logger.setLevel(Level.ALL); consoleHandler.setLevel(Level.ALL); //创建FileHandler(文件输出) FileHandler fileHandler = new FileHandler("D:\\git\\File\\testSystem\\LoggerLearn\\jul_demo\\src\\main\\resources\\logs/jul.log"); //关联 fileHandler.setFormatter(simpleFormatter); logger.addHandler(fileHandler); logger.severe("severe"); logger.warning("warning"); logger.info("info"); //jul 的默认级别为info logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
教程中老师使用的为相对路径,但是我使用相对路径则会出现NoSuchFileExpection 的错误(暂未解决),故而使用全路径
之后控制台输出如上,文件输出:
四月 20, 2022 11:23:47 上午 com.LoggerLean.JULTest testLoggerConfig 嚴重: severe 四月 20, 2022 11:23:47 上午 com.LoggerLean.JULTest testLoggerConfig 警告: warning 四月 20, 2022 11:23:47 上午 com.LoggerLean.JULTest testLoggerConfig 資訊: info 四月 20, 2022 11:23:47 上午 com.LoggerLean.JULTest testLoggerConfig 組態: config 四月 20, 2022 11:23:47 上午 com.LoggerLean.JULTest testLoggerConfig 詳細: fine 四月 20, 2022 11:23:47 上午 com.LoggerLean.JULTest testLoggerConfig 較詳細: finer 四月 20, 2022 11:23:47 上午 com.LoggerLean.JULTest testLoggerConfig 最詳細: finest
2.5 Logger对象父子关系
Logger 的父子关系比较类似java 的包结构
例如:
Logger logger1 = Logger.getLogger("com.children"); Logger logger2 = Logger.getLogger("com");
其中logger1 就为logger2的子对象,logger1默认继承logger2
如果没有规定父级包,则默认继承根节点Logger :LogManager$RootLogger,name 为 " "
根节点默认有自己的Handler和Formatter, 故自定义时需要关闭默认的配置。如果不关闭则会默认继承父级包的Handler和Formatter。
2.6 JUL 配置文件入门
1.在resources中创建配置文件logging.properties
2.通过代码来将配置文件加载到LogManager中,因为启动日志记录器之前,LogManager会查看是否有配置文件存在,有则使用配置文件,不然就默认加载java.home.jre 下的配置文件。
3.代码演示
@Test public void testLogProperties() throws Exception{ //读取配置文件,通过类加载器 InputStream inputStream = JULTest.class.getClassLoader().getResourceAsStream("logging.properties"); //创建LogManager LogManager logManager = LogManager.getLogManager(); //通过LogManager 加载配置文件 logManager.readConfiguration(inputStream); //创建日志记录器 Logger logger = Logger.getLogger("com.LoggerLean.JULTest"); logger.severe("severe"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
配置文件配置
handlers = java.util.logging.ConsoleHandler .level = ALL java.util.logging.FileHandler.pattern = /logs/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter java.util.logging.ConsoleHandler.level = ALL java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
多个handler 时
handlers = java.util.logging.ConsoleHandler,java.util.logging.FileHandler
2.7 JUL配置文件的详细说明
# RootLogger 顶级父元素指定的默认处理器为:ConsoleHandler handlers = java.util.logging.ConsoleHandler # RootLogger 顶级父元素默认的日志级别为:ALL (需要全大写) .level = ALL #自定义Logger 使用 #其中com.LoggerLean.JULTest 为Logger 的name #name后面加上配置 com.LoggerLean.JULTest.handlers = java.util.logging.ConsoleHandler com.LoggerLean.JULTest.level = CONFIG #关闭默认配置 com.LoggerLean.JULTest.userParentHandlers = false #向日志文件输出的 handler 对象 #指定日志文件路径 /logs/java0.log %u 表示数字,路径尽可能全路径 java.util.logging.FileHandler.pattern = /logs/java%u.log #指定日志文件内容大小 java.util.logging.FileHandler.limit = 50000 #指定日志文件数量 java.util.logging.FileHandler.count = 1 #指定 handler 对象日志消息格式对象,现为xml,要为一般格式可以为SimpleFormatter java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter #指定以追加方式添加日志内容 java.util.logging.FileHandler.append = true #向控制台输出的 handler 对象 #指定 handler 对象的日志级别 java.util.logging.ConsoleHandler.level = ALL #指定 handler 对象的日志消息格式对象 java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter #指定 handler 对象的字符集 java.util.logging.ConsoleHandler.encoding = UTF-8 #指定日志消息格式 java.util.logging.SimpleFormatter.format = %4$s: %5$s [%1$tc]%n
2.8 JUL 执行原理和流程
- 初始化LogManager
- LogManager加载logging.properties 配置
- 添加Logger到LogManager
- 从单例LogManager获取Logger
- 设置级别Level,并指定日志记录LogRecord
- Filter 提供了日志级别之外更细粒度的控制
- Handler 是用来处理日志输出位置
- Formatter是用来格式化LogRecord的
三、Log4J 学习
Log4J 是Apache下的一款开源的日志框架,通过在项目中使用Log4J,我们可以控制日志信息输出到控制台、文件、甚至是数据库中。我们可以控制每一条日志的输出格式,通过定义日志的输出级别,可以更灵活的控制日志的输出过程。方便项目调试
3.1 Log4J 的快速入门案例
/** * 快速入门案例 * @throws Exception */ @Test public void testQuick()throws Exception{ //初始化配置信息,推荐使用配置文件 BasicConfigurator.configure();; //获取日志记录对象 Logger logger = Logger.getLogger(Log4JTest.class); //输出日志信息 logger.info("hello Log4j"); }
控制台输出信息:
0 [main] INFO com.log4j.Log4JTest - hello Log4j
3.2 Log4J 的日志级别
logger.fatal("fatal"); //严重错误,一般会造成系统崩溃并终止运行 logger.error("error"); //错误信息,不会影响系统运行 logger.warn("warn"); //警告信息,可能会发生问题 logger.info("info"); //运行信息,可以为数据连接、网络链接、IO操作等 logger.debug("debug"); //调试信息,一般在开发中使用,记录程序变量参数传递信息等 logger.trace("trace"); // 追踪信息,记录程序所有的流程信息
其中默认的日志级别为debug级。
3.3 Log4j 组件
Log4j 主要由Loggers(日志记录器)、Appenders(输出端)和Layout(日志格式化器)组成。其中Loggers控制日志的输出级别与日志是否输出;Appenders 指定日志的输出方式(输出到控制台、文件等);Layout 控制日志信息的输出格式。
3.3.1 Loggers
日志记录器,负责收集处理日志记录,更早期的Logger类的命名为Category,所以Logger类可以视为Category类的别名。
Loggers类的实例命名是类的全限定名,Logger的名字大小写敏感,其命名有继承机制。例如:name为 org.apache.commons 的logger会继承name为org.apache 的logger。
Log4J 中有一个特殊的logger叫做“root”,它是所有logger的根,也就意味着其他所有的logger都会直接或间接的继承自root。root logger 可以用Logger.getRootLogger()方法获取。
3.3.2 Appenders
Appenders 用来指定日志输出到哪个地方,可以同时指定日志的输出目的地。Log4J 常用的输出目的地有以下几种:
输出端类型 作用 ConsoleAppender 将日志输出到控制台 FileAppender 将日志输出到文件中 DailyRollingFileAppender 将日志输出到一个日志文件中,并且每天输出到一个新的文件 RollingFileAppender 将日志信息输出到一个日志文件,并指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时生成一个新的文件 JDBCAppender 把日志信息保存到数据库中
3.3.3 Layouts
布局其Layouts 用于控制日志输出内容的格式,让我们可以使用各种需要的格式输出日志。Log4j常用的Layouts:
格式化器类型 作用 HTMLLayout 格式化日志输出为HTML表格形式 SimpleLayout 简单的日志输出格式化,打印的日志格式为(info -message) PatternLayout 最强大的格式转化器,可以根据自定义格式输出日志,如果没有指定转换格式,就是用默认的格式 有了这三个组件,我们就可以通过配置文件初始化配置,而不需要通过代码来配置。
3.4 Log4j 配置文件介绍
通过LogManager 可以知道,Log4J 支持两种类型的配置文件,一种是properties ,另一种为 XML 类型的,文件命名分别为 log4j.properties 和 log4j.xml
3.4.1 配置文件的配置示例
log4j.rootLogger = trace,console log4j.appender.console = org.apache.log4j.ConsoleAppender log4j.appender.console.layout = org.apache.log4j.SimpleLayout
3.5 Log4j内置日志记录
通过
LogLog.setInternalDebugging(true)
来使得控制台显示Log4j 的日志信息,默认情况下为false。
3.6 Log4j 的layout配置文件
#指定RootLogger 顶级父级元素默认配置信息 #指定日志级别=trace ,使用的appender为 = console(一般为自己命名) log4j.rootLogger = trace,console #指定控制台日志输出的 appender log4j.appender.console = org.apache.log4j.ConsoleAppender #指定日志格式 layout 三种格式 log4j.appender.console.layout = org.apache.log4j.PatternLayout #当日志格式为PatternLayout 时 指定日志格式 log4j.appender.console.layout.conversionPattern = %r [%t] %p %c %x - %m%n
在log4j.properties 配置文件中,我们定义了日志输出级别和输出端,在输出端中分别配置日志的输出格式。
* log4j 采用类似 c 语言的 printf 函数的打印格式格式化日志信息,具体的占位符及其含义如下: %m 输出代码中指定的日志信息 %p 输出优先级,及 DEBUG、INFO 等 %n 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n") %r 输出自应用启动到输出该 log 信息耗费的毫秒数 %c 输出打印语句所属的类的全名 %t 输出产生该日志的线程全名 %d 输出服务器当前时间,默认为 ISO8601,也指定格式,如:%d{yyyy年MM月dd日 HH:mm:ss} %l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。 如:Test.main(Test.java:10) %F 输出日志消息产生时所在的文件名称 %L 输出代码中的行号 %% 输出一个'%'字符 *可以在% 与字符之间加上修饰符来控制最小宽度、最大宽度和文本的对其方式。如* %5c 输出category名称,最小宽度是5,category<5,默认的情况下右对齐 %-5c 输出category名称,最小宽度为5,category<5, '-'号指定左对齐,会有空格 %.5c 输出category名称,最大宽度为5,category>5,就会将左边多余的字符截掉,<5不会有空格 %20.30c category 名称<20补空格,并且右对齐,>30字符,就从左边较远超出的字符截掉
3.7 log4j FileAppender 配置
#多个appender log4j.rootLogger = trace,console,file #日志文件输出的appender 对象 log4j.appender.file = org.apache.log4j.FileAppender #指定消息格式 log4j.appender.file.layout = org.apache.log4j.PatternLayout #当日志格式为PatternLayout 时 指定日志格式 log4j.appender.file.layout.conversionPattern = %r [%t] %p %c %x - %m%n #自定日志文件保存路径 log4j.appender.file.file = /logs/log4j.log #指定日志文件的字符集 log4j.appender.file.encoding = UTF-8 #按照文件大小拆分的 appender 对象 #日志文件输出的 appender 对象 log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender #指定消息格式 log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout #当日志格式为PatternLayout 时 指定日志格式 log4j.appender.rollingFile.layout.conversionPattern = %r [%t] %p %c %x - %m%n #自定日志文件保存路径 log4j.appender.rollingFile.file = /logs/log4j.log #指定日志文件的字符集 log4j.appender.rollingFile.encoding = UTF-8 #指定日志文件内容的大小 log4j.appender.rollingFile.maxFileSize = 1MB #指定日志文件的数量 log4j.appender.rollingFile.maxBackupIndex = 10 #按照时间规则拆分的appender 对象 log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender #指定消息格式 log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout #当日志格式为PatternLayout 时 指定日志格式 log4j.appender.dailyFile.layout.conversionPattern = %r [%t] %p %c %x - %m%n #自定日志文件保存路径 log4j.appender.dailyFile.file = /logs/log4j.log #指定日志文件的字符集 log4j.appender.dailyFile.encoding = UTF-8 #指定日期拆分规则 log4j.appender.dailFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss
3.8 log4j 的JDBCAppender 配置
#mysql log4j.appender.logDB = org.apache.log4j.jdbc.JDBCAppender #指定消息格式 log4j.appender.logDB.layout = org.apache.log4j.PatternLayout #指定Driver log4j.appender.logDB.Driver = com.mysql.jdbc.Driver #指定URL log4j.appender.logDB.URL = jdbc:mysql://localhost:3306/test #指定用户名 log4j.appender.logDB.User=root #指定密码 log4j.appender.logDB.Password = root #指定Sql类型 log4j.appender.logDB.Sql=INSERT INTO log(project_name,create_date,level,category,file_name,line,all_category,message) values('itcast','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
3.9 log4j 自定义logger
#自定义logger 对象 log4j.logger.com.test = info,file
默认会替换父类的等级,复用父级的appender等级。