logback框架和日志分离管理
一、日志框架
1. 什么是日志框架?
日志框架 是一种软件组件,负责记录应用程序在运行时生成的日志信息。日志信息通常包括错误、警告、调试信息和其他重要的运行状态,帮助开发者和运维人员监控和调试应用。
2. 日志框架的作用
- 记录运行信息:捕获程序执行中的重要事件和状态信息,便于追踪问题和性能瓶颈。
- 故障排查:当应用发生错误时,日志记录提供了上下文信息,有助于快速定位和解决问题。
- 性能监控:记录性能指标,帮助分析系统的运行效率。
- 审计和合规:某些应用需要记录操作历史以满足安全审计和合规要求。
- 可追溯性:通过日志,用户可以追溯到具体的操作和系统状态。
3. 常见的日志框架
3.1. Log4j
最早的 Java 日志框架之一,提供了强大的日志记录功能。
支持多种输出目标(控制台、文件、数据库等),灵活的配置方式,但在性能上相对较低。
目前有 Log4j 1 和 Log4j 2,后者在性能和功能上进行了显著改进。
3.2. Logback
由 Log4j 的创始人开发,是 SLF4J 的原生实现,性能优越(比log4j强)。
支持异步日志记录、自动重载配置文件、灵活的输出格式等。
3.3. java.util.logging (JUL)
Java 官方自带的日志框架,简单易用,但功能和灵活性相对较弱。
默认与 JDK 一起提供,不需要额外依赖,但通常被其他日志框架替代。
java.util.logging 适合小型项目和快速集成,但在复杂应用中可能无法满足需求。
3.4. SLF4J(日志门面)(Simple Logging Facade for Java)
SLF4J 是一个日志门面,提供了统一的日志 API,允许开发者在不同的日志框架之间切换。可以与多种日志框架(如 Logback、Log4j)兼容使用,提供简洁的 API,易于使用。将依赖从具体日志框架转移到统一接口,简化了依赖管理。不处理日志,只是一层抽象,实际的日志处理依赖于其他框架。
4.常见的日志级别
- TRACE:最细粒度的信息,通常用于追踪问题。
- DEBUG:调试信息,通常在开发和测试时使用。
- INFO:正常运行的信息。
- WARN:警告信息,表示可能出现的问题。
- ERROR:错误信息,表示发生了错误。
- FATAL:严重错误,表示应用程序无法继续运行。
5.讲讲logback
Logback 主要由三个核心模块构成:
logback-core:核心模块,提供基本的日志记录功能。
logback-classic:经典模块,提供 SLF4J(Simple Logging Facade for Java)实现,支持多种日志级别和输出格式。
logback-access:用于 Servlet 环境中的访问日志记录。
5.1. logback-core
logback-core 是 Logback 的基础模块,提供了日志记录的核心功能和通用的 API。它包含了 Logback 的一些基本组件,比如 Appender、Layout 和 Filter。它定义了基本的日志记录行为。提供了其他模块(如 logback-classic 和 logback-access)所需的共享功能。
一般情况下,不需要直接与 logback-core 进行交互,因为它是 Logback 其他模块的基础。
5.2. logback-classic
logback-classic 是 Logback 的经典模块,它实现了 SLF4J的接口。这个模块是最常用的,通常用于大多数 Java 应用程序。
提供对 SLF4J API 的实现,支持多种日志级别(如 TRACE、DEBUG、INFO、WARN、ERROR、FATAL)。
允许配置日志输出到不同的目标(控制台、文件等)。
支持日志格式化和过滤器。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyApp {
private static final Logger logger = LoggerFactory.getLogger(MyApp.class);
public static void main(String[] args) {
logger.info("应用程序启动");
try {
int result = 10 / 0;
} catch (Exception e) {
logger.error("发生错误:{}", e.getMessage());
}
logger.info("应用程序结束");
}
5.3. logback-access
logback-access 是 Logback 的一个扩展模块,专门用于 Servlet 环境中的访问日志记录。它允许你记录 HTTP 请求和响应的相关信息。
提供一个 Servlet 过滤器,可以捕获和记录请求信息。
允许配置请求和响应日志的输出格式。
public class LoginServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(LoginServlet.class);
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
// 假设的用户验证逻辑
boolean isAuthenticated = authenticateUser(username, password);
if (isAuthenticated) {
logger.info("用户 {} 登录成功", username);
response.getWriter().write("登录成功");
} else {
logger.warn("用户 {} 登录失败,密码错误", username);
response.getWriter().write("登录失败");
}
}
private boolean authenticateUser(String username, String password) {
return "admin".equals(username) && "password".equals(password);
}
5.4.学到此处的疑惑?
上述在http交互中,好像直接使用logback classic也可以,为什么还多此一举多个logback access?或者说logback access优越在哪里?
举个例子作比较:
1.假设我们在处理用户登录时,使用 Logback Classic 记录日志:
public class LoginServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(LoginServlet.class);
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
boolean isAuthenticated = authenticateUser(username, password);
if (!isAuthenticated) {
// 手动记录登录失败的信息
logger.warn("登录失败,用户名: {}, 请求方法: {}, 请求路径: {}",
username, request.getMethod(), request.getRequestURI()); ---注意这里
response.getWriter().write("登录失败");
} else {
response.getWriter().write("登录成功");
}
}
private boolean authenticateUser(String username, String password) {
return "admin".equals(username) && "password".equals(password);
}
}
输出结果:
2024-10-21 10:00:00 WARN [http-nio-8080-exec-1] LoginServlet [LoginServlet.java:25]
登录失败,用户名: user, 请求方法: POST, 请求路径: /login
2.在同样的登录失败场景中,使用 Logback Access:
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
boolean isAuthenticated = authenticateUser(username, password);
if (!isAuthenticated) {
// 使用 Logback Access 自动记录 HTTP 请求信息
LogbackAccessFilter filter = new LogbackAccessFilter();
filter.logAccess(request, response, "登录失败,用户名: " + username); ---和上面比一下
response.getWriter().write("登录失败");
} else {
response.getWriter().write("登录成功");
}
}
private boolean authenticateUser(String username, String password) {
return "admin".equals(username) && "password".equals(password);
}
}
输出结果
2024-10-21 10:00:00 WARN [http-nio-8080-exec-1] AccessLogger [LogbackAccess.java:123]
请求方法: POST, 请求路径: /login, 用户名: user, 状态码: 401, 响应时间: 150ms
3.比较分析
输出内容:
Logback Classic:记录了用户名、请求方法和请求路径。这些信息帮助理解发生了什么,但缺乏对请求状态的详细描述。
Logback Access:自动记录请求方法、请求路径、状态码和响应时间等多种信息,使得分析请求情况更加全面。
代码简洁性:
Logback Classic:需要手动提取和记录请求相关的信息,代码较冗长且容易出错。
Logback Access:自动处理 HTTP 请求的记录,代码更简洁,专注于业务逻辑。
上下文信息:
Logback Classic:需要自己管理所有的请求上下文信息,容易遗漏关键信息。
Logback Access:全面捕获 HTTP 请求的上下文信息。
性能优化:
Logback Classic:未针对 HTTP 请求进行优化,记录过程相对较慢。
Logback Access:经过优化,专门为 HTTP 请求设计,可以更高效地记录访问信息。
6.举个完整示例
6.1. 项目结构 (登录为例)
my-login-app
│
├── src
│ ├── main
│ │ ├── java
│ │ │ ├── LoginServlet.java
│ │ │ └── MyApp.java
│ │ └── resources
│ │ └── logback.xml
│ └── webapp
│ └── index.html
└── pom.xml
6.2. Maven 依赖
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
6.3. Logback 配置文件
在 src/main/resources 目录下创建 logback.xml 文件,内容如下:
<configuration>
<!-- 配置 ConsoleAppender,用于输出日志到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} [%file:%line] - %msg%n</pattern>
</encoder>
</appender>
<!-- 配置 AccessAppender,用于处理 HTTP 访问日志 -->
<appender name="ACCESS" class="ch.qos.logback.access.Appender">
<encoder>
<pattern>%h %l %u %t "%r" %s %b %D</pattern> <!-- 自定义输出格式 -->
</encoder>
</appender>
<!-- 配置日志级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" /> <!-- 将控制台输出连接到根日志 -->
</root>
<logger name="ch.qos.logback.access" level="DEBUG">
<appender-ref ref="ACCESS" /> <!-- 将访问日志连接到特定日志级别 -->
</logger>
</configuration>
6.4.Logback 的 JDBCAppender
将日志输出到数据库中
1.先数据库建表:
CREATE TABLE logs (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp TIMESTAMP NOT NULL,
level VARCHAR(10) NOT NULL,
thread VARCHAR(50),
logger VARCHAR(100),
message TEXT
);
2.配置xml:
<configuration>
<!-- JDBC Appender -->
<appender name="JDBC" class="ch.qos.logback.classic.db.JDBCAppender">
<connectionSource>
<driverClass>com.mysql.cj.jdbc.Driver</driverClass>
<url>jdbc:mysql://localhost:3306/database</url>
<user>username</user>
<password>password</password>
</connectionSource>
<encoder>
<pattern>%date %level [%thread] %logger{10} %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="JDBC" /> <!-- 引用 JDBC Appender -->
</root>
</configuration>
3.数据存储结果:
id timestamp level thread logger message
1 2024-10-22 10:00:00 INFO main com.example.LoginServlet 用户 admin 登录成功
2 2024-10-22 10:01:00 WARN main com.example.LoginServlet 登录失败,用户名: user
3 2024-10-22 10:02:00 ERROR main com.example.LoginServlet 数据库连接失败
已经集成了与数据库操作,很方便
二、日志分离管理
1. 日志分类
将日志根据其性质和使用场景进行分类,常见的分类方式:
- 操作日志:
记录用户的登录和登出时间、IP 地址、操作行为(如数据查询、修改、删除等)。
例如,记录如下信息:
2024-10-22 10:00:00 INFO 用户 admin 登录成功, IP 地址: 192.168.1.1
2024-10-22 10:05:00 INFO 用户 admin 修改了文件 config.xml
- 安全日志:
记录安全相关事件,如访问控制失败、入侵检测、恶意软件检测等
2024-10-22 10:15:00 WARN 用户 user 尝试登录失败, 原因: 密码错误
2024-10-22 10:20:00 WARN 检测到异常登录活动: 用户 admin 从异常 IP 地址 203.0.113.45 登录
- 审计日志:
记录对敏感数据的访问、修改、删除操作
2024-10-22 10:30:00 INFO 用户 admin 访问敏感文件 sensitive_data.txt
2024-10-22 10:35:00 INFO 用户 admin 删除了用户账户 user123
- 系统日志:
记录系统启动、关闭、升级、故障和配置变更等事件。
2024-10-22 10:00:00 INFO 系统启动
2024-10-22 11:00:00 INFO 配置文件 config.yml 被修改
2.角色分离与权限管理
2.1. 角色理解
废除超级管理员,将权限分配。 三员对应三角色
1.系统管理员(配置):
主要负责系统的资源和运行进行配置、控制和管理,包括用户身份、系统资源配置、系统加载和启动、系统运行的异常处理、数据和设备的备份与恢复等。
2.安全管理员(授权):
主要对系统中的安全策略进行配置,包括安全参数的设置,主体、客体进行统一安全标记,对主体进行授权,配置可信验证策略等。
3.审计管理员(审计):
主要负责对审计记录进行分析,并根据分析结果进行处理,包括根据安全审计策略对审计记录进行存储、管理和查询等。
2.2.具体管理
1.系统管理员:
主要负责系统的日常运行维护工作。包括网络设备、安全保密产品、服务器和用户终端、操作系统数据库、涉密业务系统的安装、配置、升级、维护、运行管理;网络和系统的用户增加或删除;网络和系统的数据备份、运行日志审查和运行情况监控;应急条件下的安全恢复。
2.安全管理员:
主要负责系统的日常安全保密管理工作。包括网络和系统用户权限的授予与撤销,用户操作行为的安全设计,安全保密设备管理,系统安全事件的审计、分析和处理,应急条件下的安全恢复。
3.审计管理员:
主要负责对系统管理员和安全保密员的操作行为进行审计、分析和监督检查,及时发现违规行为并定期向系统安全保密管理机构汇报情况。
系统管理员、安全保密管理员和安全审计员不能以其他用户身份登陆系统,不能查看和修改任何业务数据库中的信息,不能删改日志内容。
同一设备或系统的系统管理员和安全审计员不能由同一人兼任,安全保密管理员和安全审计员不得由同一人兼任。
2.3. 日志中的三员管理
-
系统管理员:
负责日志管理系统的配置和维护,确保日志的准确性和完整性。管理员可以进行系统配置、日志存储路径设置和用户权限管理。
权限:
访问所有日志数据,包括操作日志、审计日志和安全事件日志。
配置日志记录参数和存储策略。 -
操作员:
负责日常操作和监控,检查系统日志以确保系统正常运行,及时发现异常并上报。
权限:
访问特定的操作日志和系统事件日志,但不能访问敏感数据或审计日志。
可以生成报告和查看操作历史。 -
审计员:
进行定期审计和检查,分析日志数据以识别潜在的安全问题。
权限:
访问所有日志数据,进行审计和分析。
不能进行日志修改或系统配置。
3.日志审计与监控
3.1.简单解释:
日志监控:主要关注实时跟踪系统的状态,及时捕获异常、错误或特定事件,以便快速响应。
日志分析:旨在深入挖掘日志数据,识别趋势、模式和潜在的安全问题,通常在后续阶段进行
3.2.ELK
ELK 是ElasticSearch开源生态中提供的一套完整日志收集、分析以及展示的解决方案,是三个产品的首字母缩写,分别是ElasticSearch、Logstash 和 Kibana。
- 1.ElasticSearch ,它是一个近实时(NRT)的分布式搜索和分析引擎,它可以用于全文搜索,结构化搜索以及分析。它是一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎,使用 Java 语言编写。
- 2.Logstash ,它是一个具有近实时(NRT)传输能力的数据收集、过滤、分析引擎,用来进行数据收集、解析、过滤,并最终将数据发送给ES。
- 3.Kibana ,它是一个为 ElasticSearch 提供分析和展示的可视化 Web 平台。它可以在 ElasticSearch 的索引中查找,交互数据,并生成各种维度表格、图形以及仪表盘。
比较复杂且长,可以算另一个领域来看,这里先不说
4.Linux的日志分离
4.1.Linux日志类型
1.【内核及系统日志】
2.【用户日志】
3.【程序日志】
分类 | 说明 |
---|---|
daemon | 后台进程相关的信息 |
kern | 内核产生的信息 |
lpr | 打印系统产生的信息 |
authpriv | 安全认证信息 |
cron | 定时计划任务相关的信息 |
邮件相关的信息 | |
syslog | 日志服务本身的信息 |
news | 新闻系统 |
local0~local7 | 8个系统保留的类,供其他程序使用或用户自定义 |
4.2.常见日志
Linux系统本身和大部分服务器程序的日志文件默认情况下都放置在目录“/var/log”中。一部分程序公用一个日志文件,一部分程序使用单个日志文件,而有些大型服务器程序由于日志文件不止一个,所以会在“/var/log”目录中建立相应的子目录来存放日志文件,这样既保证了日志文件目录的结构清晰,又可以快速地定位日志文件。有相当一部分日志文件只有root用户才有权限读取,这保证了相关日志信息的安全性。
日志路径 | 作用 |
---|---|
/var/log/cron | 记录了系统定时任务相关的日志 |
/var/log/cups/ | 记录打印信息的日志 |
/var/log/dmesg | 记录了系统在开机时内核自检的信息。也可以使用dmesg命令直接查看内核自建信息 |
/var/log/btmp | 记录错误登录的日志。这个文件是二进制文件,不能直接vi查看,而要使用lastb命令查看。 |
/var/log/lastlog | 记录系统中所有用户最后一次的登录时间的日志。这个文件也是二进制文件,不能直接vi,而要使用lastlog命令查看 |
/var/log/mailog | 记录邮件信息 |
/var/log/message | 记录系统重要信息的日志。这个日志文件中会记录Linux系统的绝大多数重要信息,如果系统出现问题时,首先要检查的就应该是这个日志文件。 |
/var/log/secure | 记录验证和授权方面的信息,只要涉及账户和密码的程序都会记录。比如说系统的登录,ssh的登陆,su切换用户,sudo授权,甚至添加用户和修改用户密码都会记录在这个日志文件中。 |
/var/log/wtmp | 永久记录所有用户的登录、注销信息,同时记录系统的启动、重启、关机事件。同样这个文件也是一个二进制文件,不能直接vi,而需要使用last命令来查看。 |
/var/run/utmp | 记录当前已经登录的用户的信息。这个文件会随着用户的登录和注销而不断变化,只记录当前登录用户的信息。同样这个文件不能直接vi,而要使用w,who,users等命令来查询。 |
4.3.日志级别
比普通的日志多几个级别:
编码 | 优先级 | 严重性 |
---|---|---|
7 | debug | 信息对开发人员调试应用程序有用,在操作过程中没用 |
6 | info | 正常的操作信息,可以收集报告,测量吞吐量等 |
5 | notice | 注意,正常但重要的事件 |
4 | warning | 警告,如果不采取措施,将会发生错误,例如文件系统已使用90% |
3 | err | 错误,阻止某个模块或程序的功能不能正常使用 |
2 | crit | 关键错误,已经影响到整个系统或软件不能正常工作 |
1 | alert | 警报,需要立即修改 |
0 | emerg | 紧急,内核崩溃等严重信息 |
4.4.日志轮换
把旧的日志删除,轮换新的日志内容
参数 | 参数说明 |
---|---|
daily | 日志的轮替周期是每天 |
weekly | 日志的轮替周期是每周 |
monthly | 日志的轮替周期是每月 |
rotate | 数字 |
compress | 日志轮替时,旧的日志进行压缩 |
create mode owner group | 建立新日志,同时指定新日志的权限与所有者和所属组。如create 0600 root utmp |
address | |
missingok | 如果日志不存在,则忽略该日志的警告信息 |
notifempty | 如果日志为空文件,则不进行日志轮替 |
minsize 大小 | 日志轮替的最小值。也就是日志一定要达到这个最小值才会轮替,否则就算时间达到也不轮替 |
size | 大小 |
dateext | 使用日期作为日志轮替文件的后缀。如secure-20241025 |
PS:logback也可以实现分离,但要单独对类在xml里面进行设置;目前我还在找解决办法