日志框架笔记
日志的概念
1、日志文件
日志文件是用于记录系统操作时间的文件集合,可分为事件日志和消息日志,具有处理历史数据、诊断问题的追踪以及理解系统的活动等重要作用。
在计算机中、日志文件是记录在操作系统或其他软件运行中发生的事件或在通信软件的不同用户之间的消息文件。记录是保持日志的行为。在最简单的情况下,消息被写入单个日志文件。
许多操作系统、软件框架和程序包括日志系统。广泛使用日志记录标准是在因特网工程任务组(IETE)RFC542中定义的syslog,syslog标准化子系统能够生成、过滤、记录和分析日志消息。
1.1 调试日志
软件开发中,我们通常需要去调试程序,做一些信息,状态的输出便于我们查询程序的运行状况。为了让我们能够更加灵活和方便地控制这些调试的信息,所以我们需要专业的日志技术。Java中寻找bug会需要重视。调试也就是debug可以在程序运行中暂停程序运行,可以查看程序在运行中的情况。日志主要是为了更方便地去重现问题。
1.2 系统日志
系统日志是记录系统中硬件、软件和系统问题的信息,同时还可以监视系统中发生的事件。用户可以通过它来检查错误发生的原因。或者寻找受到攻击的攻击者留下的痕迹。系统日志包括系统日志、应用系统日志和安全日志。
系统日志的价值
系统日志策略可以在故障刚刚发生时就向你发送警告信息,系统日志帮助你在最短的时间内发现问题。
系统日志是一种非常关键的组件,因为系统日志可以让你充分了解自己的环境
2. Java日志框架
问题:
- 控制日志输出的内容和格式
- 控制日志输出的位置
- 日志优化:异步日志,日志文件的归档和压缩
- 日志系统的维护
- 面向接口开发——日志的门面
2.1 为什么要用日志框架
因为软件系统发展到今天已经很复杂了,特别是服务器端软件,涉及到知识、内容,问题太多。在某些方面使用别人成熟的框架,就相当于让别人帮你完成一些基础工作,你只需要集中精力完成系统业务逻辑设计,而且框架一般是成熟的、稳健的,它可以处理系统很多细节问题,比如,事务处理,安全性,数据流控制等问题。还有框架一般经过很多人使用,所以结构很好,扩展性也很好,同时它是不断升级的,可以直接享受别人升级代码的好处。
2.2 现有的日志框架
JUI(java util logging)、logback、log4j、log4j2、JCL(Jakarta Commons Logging)、slf4j(Simple Logging Facade for java)
日志门面
JCL、slf4j
日志实现
JUL、logback、log4j、log4j2
3. JUL
XML配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<!-- 导入依赖-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<groupId>org.example</groupId>
<artifactId>untitled</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
自定义配置文件
#配置文件
#RootLogger 顶级父元素指定的默认处理器为FileHandler
handlers = java.util.logging.FileHandler
#RootLogger顶级父元素默认的日志级别为:ALL
.level = ALL
#自定义Logger使用
com.liuxingwu.handlers = java.util.logging.ConsoleHandler
com.liuxingwu.level = CONFIG
#关闭默认设置
com.liuxingwu.uerParentHandlers = false
#向文件输出handler对象
#指定输出的文件路径E:/log/java0.log
java.util.logging.FileHandler.pattern = E:/logs/java%u.log
#指定日志文件的内容大小
java.util.logging.FileHandler.limit = 50000
#指定日志文件的数量
java.util.logging.FileHandler.count = 1
#指定handler对象的日志消息格式对象
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
#指定义追加的方式添加日志内容
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
目录结构
package com.liuxingwu;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.*;
/**
* @author LiuXingWu
* @create 2021-02-15 11:42
*/
public class JULTest {
// 快速入门
@Test
public void testQuick() {
// 1. 获取日志记录器对象
Logger logger = Logger.getLogger("com.liuxingwu.JULTest");
// 2. 日志记录输出
logger.info("hello jul");
// 通用方法进行日志记录
logger.log(Level.INFO, "inf context");
// 通过占位符方式输出变量值
String name = "liuxingwu";
Integer age = 22;
logger.log(Level.INFO, "用户信息:{0}, {1}", new Object[] {name, age});
}
// 日志级别
@Test
public void testLevel() {
// 1. 获取日志记录器对象
Logger logger = Logger.getLogger("com.liuxingwu.JULTest");
// 2. 日志记录输出
logger.severe("severe");
logger.warning("warning");
logger.info("info"); // jul默认的日志级别是info,比info高的级别会输出,比info低的级别默认不输出
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}
// 自定义日志级别
@Test
public void testLogConfig() throws IOException {
// 1. 获取日志记录器对象
Logger logger = Logger.getLogger("com.liuxingwu.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);
// 场景FileHandle 文件输出
FileHandler fileHandler = new FileHandler("E:/logs/JULDemo.log"); // 默认将程序的日志放在E盘的log文件下
// 关联
fileHandler.setFormatter(simpleFormatter);
logger.addHandler(fileHandler);
// 2. 日志记录输出
logger.severe("severe");
logger.warning("warning");
logger.info("info"); // jul默认的日志级别是info,比info高的级别会输出,比info低的级别默认不输出
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}
// logger对象父子关系
@Test
public void testLogParent() {
Logger logger1 = Logger.getLogger("com.liuxingwu");
Logger logger2 = Logger.getLogger("com");
// 测试
System.out.println(logger1.getParent() == logger2);
// 所有日志记录器的顶级父元素LogManager$RootLogger, name == ""
System.out.println("logger2 parent:" + logger2.getParent() + ", name: " + logger2.getParent().getName());
// 设置logger2的日志级别
// 关闭系统默认配置
logger2.setUseParentHandlers(false);
// 自定义配置日志级别
// 创建ConsoleHandler 控制台日志处理器 控制台的输出
ConsoleHandler consoleHandler = new ConsoleHandler();
// 创建一个简单的格式
SimpleFormatter simpleFormatter = new SimpleFormatter();
// 进行关联
consoleHandler.setFormatter(simpleFormatter);
logger2.addHandler(consoleHandler);
// 配置日志的具体级别
logger2.setLevel(Level.ALL);
consoleHandler.setLevel(Level.ALL);
logger1.severe("severe");
logger1.warning("warning");
logger1.info("info"); // jul默认的日志级别是info,比info高的级别会输出,比info低的级别默认不输出
logger1.config("config");
logger1.fine("fine");
logger1.finer("finer");
logger1.finest("finest");
}
// 加载自定义配置文件
@Test
public void testLogProperties() throws IOException {
// 1. 读取配置文件,通过类加载器
InputStream ins = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
// 2. 创建LogManager
LogManager logManager = LogManager.getLogManager();
// 3. 通过LogManager加载配置文件
logManager.readConfiguration(ins);
// 创建日志记录
Logger logger = Logger.getLogger("com.liuxingwu");
logger.severe("severe");
logger.warning("warning");
logger.info("info");
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
Logger logger1 = Logger.getLogger("test");
logger1.severe("severe test");
logger1.warning("warning test");
logger1.info("info test");
logger1.config("config test");
logger1.fine("fine test");
logger1.finer("finer test");
logger1.finest("finest test");
}
}
4. log4j
xml配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>log4j_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 导入依赖-->
<dependencies>
<dependency>
<!-- log4j-->
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 设置编译版本为1.8-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
属性配置文件
#指定RootLogger顶级父元素默认配置信息
#指定日志级别为trace,使用的appender为console,file
#log4j.rootLogger = trace, console, file, rollingFile
log4j.rootLogger = trace, console
#自定义logger对象设置
#定义指定包下的日志配置信息
log4j.logger.com.liuxingwu = info, file
#顶级父元素的配置信息
log4j.logger.org.apache = error
#指定控制台日志输出的appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
#指定消息格式的layout
##1.简单格式输出
#log4j.appender.console.layout = org.apache.log4j.SimpleLayout
##2.html格式输出
#log4j.appender.console.layout = org.apache.log4j.HTMLLayout
##3.xml格式输出
#log4j.appender.console.layout = org.apache.log4j.xml.XMLLayout
#自定义格式输出
log4j.appender.console.layout = org.apache.log4j.PatternLayout
#指定消息格式的内容
log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
# %m 输出代码中的日志信息
# %p 输出优先级,如DEBUG、INFO等
# %n 换行符(windows平台的换行符为"
",UNIX为"
")
# %r 输出自应用启动到输出该log信息耗时的毫秒数
# %c 输出打印语句所属的类的全名
# %t 输出产生该日志的线程全名
# %d 输出服务器当前时间,默认为ISO8601,也可以指定格式,如%d{yyyy年MM月dd日 HH:mm:ss}
# %l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如Test.main{Test.java:10}
# %F 输出日志消息产生时所在的文件名称
# %L 输出代码中的行号
# %% 输出一个"%"符号
#日志文件输出的appender对象
log4j.appender.file = org.apache.log4j.FileAppender
#指定消息格式layout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
#指定消息格式的内容
log4j.appender.file.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
#指定日志文件保存路径
log4j.appender.file.file = E:/logs/log4j_demo.log
#指定日志文件的字符集
log4j.appender.file.encoding = UTF-8
#按照文件大小拆分的appender对象
log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender
#指定消息格式layout
log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout
#指定消息格式的内容
log4j.appender.rollingFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
#指定日志文件保存路径
log4j.appender.rollingFile.file = E:/logs/log4j_demo1.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
#指定消息格式layout
log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout
#指定消息格式的内容
log4j.appender.dailyFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
#指定日志文件保存路径
log4j.appender.dailyFile.file = E:/logs/log4j_demo2.log
#指定日志文件的字符集
log4j.appender.dailyFile.encoding = UTF-8
#指定日期拆分的规则
log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss
测试代码
package com.liuxingwu;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.helpers.LogLog;
import org.junit.Test;
import org.apache.log4j.Logger;
/**
* @author LiuXingWu
* @create 2021-02-15 16:55
*/
public class log4jTest {
// 快速入门
@Test
public void testQuick() {
// 初始化配置信息,暂不使用配置文件
BasicConfigurator.configure();
// 获取日志记录器
Logger logger = Logger.getLogger(log4jTest.class);
// 日志记录输出
logger.info("hello log4j");
// 日志级别
logger.fatal("fatal"); // 严重错误,一般会造成系统崩溃并终止运行
logger.error("error"); // 错误信息,不会影响系统运行
logger.warn("warn"); // 警告信息,可能会发生问题
logger.info("info"); // 运行信息, 数据连接, 网络连接,IO连接
logger.debug("debug"); // 调试信息,一般在开发中使用,记录程序变量参数传递信息等
logger.trace("trace"); // 追踪信息,记录程序所有的流程信息
}
// 配置文件输出
@Test
public void testLogProperties() {
// 开启log4j内置日志记录,显示详细记录
LogLog.setInternalDebugging(true);
// 获取日志记录器
Logger logger = Logger.getLogger(log4jTest.class);
// 日志记录输出
logger.info("hello log4j");
// for (int i = 0; i < 100; i++) {
// 日志级别
logger.fatal("fatal"); // 严重错误,一般会造成系统崩溃并终止运行
logger.error("error"); // 错误信息,不会影响系统运行
logger.warn("warn"); // 警告信息,可能会发生问题
logger.info("info"); // 运行信息, 数据连接, 网络连接,IO连接
logger.debug("debug"); // 调试信息,一般在开发中使用,记录程序变量参数传递信息等
logger.trace("trace"); // 追踪信息,记录程序所有的流程信息
// }
// 再创建一个日志记录器对象
Logger logger1 = Logger.getLogger(Logger.class);
// 日志级别
logger1.fatal("fatal logger1"); // 严重错误,一般会造成系统崩溃并终止运行
logger1.error("error logger1"); // 错误信息,不会影响系统运行
logger1.warn("warn logger1"); // 警告信息,可能会发生问题
logger1.info("info logger1"); // 运行信息, 数据连接, 网络连接,IO连接
logger1.debug("debug logger1"); // 调试信息,一般在开发中使用,记录程序变量参数传递信息等
logger1.trace("trace logger1"); // 追踪信息,记录程序所有的流程信息
}
}
5. JCL
xml配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>jcl_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- 导入JCL-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- 导入log4j依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- 导入测试集依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 设置编译版本为1.8-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
属性配置
#指定RootLogger顶级父元素默认配置信息
#指定日志级别为trace,使用的appender为console
log4j.rootLogger = trace, console
#指定控制台日志输出的appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
#自定义格式输出
log4j.appender.console.layout = org.apache.log4j.PatternLayout
#指定消息格式的内容
log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
测试代码
package com.liuxingwu;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
/**
* @author LiuXingWu
* @create 2021-02-15 19:32
*/
public class JCLTest {
@Test
public void testQuick() {
// 获取日志记录器
Log log = LogFactory.getLog(JCLTest.class);
// 日志记录的输出
log.info("hello jcl");
}
}