日志管理技术-ELK
日志管理
查看日志信息对于运维和开发人员来说是非常必要的,常见的查看日志情况如下:
- 当应用程序或服务出现故障时,查看日志可帮助快速定位问题,了解故障前后的系统状态
- 通过分析日志,可以监控应用程序性能,识别性能瓶颈或资源消耗异常
- 在开发和测试过程中,查看日志有助于开发人员调试代码、定位并修复bug,同时也是验证应用程序功能是否正常的重要依据
日志采集方式
在项目的logback.xml文件定义如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 定义日志文件的存放路径 -->
<property name="log.path" value="/home/ruoyi/logs" />
<!-- 定义日志输出的格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出日志的配置 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统信息日志文件的配置 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 基于时间的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件的命名模式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 保留日志的最大历史天数 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<!-- 过滤日志级别,只记录DEBUG级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统错误日志文件的配置 -->
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<!-- 过滤日志级别,只记录ERROR级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 用户访问日志文件的配置 -->
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 设置系统模块(com.ruoyi)的日志级别为INFO -->
<logger name="com.ruoyi" level="info" />
<!-- 设置Spring框架的日志级别为WARN -->
<logger name="org.springframework" level="warn" />
<!-- 根日志处理器的配置,默认级别为INFO,只输出到控制台 -->
<root level="info">
<appender-ref ref="console" />
</root>
<!-- 另一个根日志处理器的配置,用于同时输出系统信息和错误日志 -->
<!-- 注意:通常一个<configuration>中只应有一个<root>元素,这里的配置可能是为了展示目的而重复,实际使用时应合并 -->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
<!-- 设置用户操作日志的级别为INFO,并指定输出到用户访问日志文件 -->
<logger name="sys-user" level="info">
<appender-ref ref="sys-user"/>
</logger>
</configuration>
具体的生成的日志文件列表如下:

- 目前有三类文件,分别是sys-error.log、sys-info.log、sys-user.log文件
- 文件中不带日期记录的当天的日志
- sys-info.log记录的是系统日志,包含了运行日志和错误日志(较全)
- sys-error.log记录的是错误日志,排查错误一般看这个文件
- sys-user.log记录的是用户登录相关的日志数据
Linux命令查看日志
docker logs 命令
- 基本用法:
docker logs [OPTIONS] CONTAINER,其中CONTAINER是容器的名称或ID,OPTIONS是可选参数 -
实时查看日志:使用
-f或--follow参数,可以实时跟踪容器的日志输出。 -
例如,
docker logs -f mycontainer -
查看日志尾部内容:使用
--tail参数,可以仅显示日志的最后几行 -
例如,
docker logs --tail=100 mycontainer
进入容器内部查看(不推荐)
如果容器的日志被写入到文件系统中,可以通过docker exec命令进入容器内部查看日志文件。
- 进入容器:
docker exec -it mycontainer /bin/bash(或/bin/sh,取决于容器内的shell) - 查看日志的所有内容:
(cat | more | less) sys-info.2024-08-01.log - 实时监控日志的变化
- 实时监控日志变化:
tail -f sys-info.log - 实时监控日志尾部100行日志:
tail -n 100 f sys-info.log(常用) - 实时监控日志头部100行日志:
head -n 100 f sys-info.log - 按照关键字找日志的信息(常用)
- 查询日志文件中包含error的日志:
cat -n sys-info.log | grep 'error' - 日志太多,分页查询日志:
cat -n sys-info.log | grep 'error' | more
ELK日志管理
什么是ELK
ELK是一个开源的日志管理平台,由三个核心组件组成:Elasticsearch、Logstash 和 Kibana。这三个组件共同协作,提供了一个从日志收集、处理、存储到分析、可视化的完整解决方案
- Elasticsearch:这是一个基于Lucene的搜索引擎,用于存储和搜索日志数据。它提供了强大的全文搜索功能,支持复杂的查询和聚合操作,并且能够处理大规模的日志数据
- Logstash:这是一个日志收集和处理工具
- 将其转换为Elasticsearch可以理解的格式。Logstash还提供了丰富的过滤功能,可以对日志数据进行清洗、转换和增强
- Kibana:这是一个Web界面,用于可视化Elasticsearch中的日志数据。它提供了直观的图形和工具,使用户能够轻松地搜索、分析和可视化日志数据,从而更好地理解系统的运行状态和性能
环境准备
1. 服务启动
在提供的虚拟机中,已经安装了ELK这三个组件,直接启动即可:
docker start es
docker start kibana
docker start logstash
这三个服务占用内存较大,平常开发阶段可关闭
注意:如果ES容器的宿主机IP地址不为192.168.100.168,还需要进入logstash容器中修改配置:
# 进入 Logstash 容器
docker exec -it logstash bash
# 查看 pipeline 配置
cat /usr/share/logstash/pipeline/logstash.conf
# 修改配置
cat > /usr/local/logstash/pipeline/logstash.conf << EOF
input {
tcp {
mode => "server"
host => "0.0.0.0"
port => 5044
codec => json_lines
}
}
output {
elasticsearch {
hosts => ["http://192.168.2.17:9200"] # 修改为正确的ES地址
index => "log-%{+YYYY.MM.dd}"
codec => "json"
}
stdout {
codec => rubydebug
}
}
EOF
- logback.xml 配置logstash
在zzyl-admin模块中引入logstash相关的依赖
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.6</version>
</dependency>
在zzyl-admin模块下新增一个文件:logback-logstash.xml(和logback.xml同级),内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志存放路径 -->
<property name="log.path" value="/home/ruoyi/logs" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!--logstash的服务地址和端口,可以实际情况设置-->
<destination>192.168.2.17:5044</destination>
<!-- 日志输出编码 -->
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
<pattern>
<pattern>
{
<!--应用名称 -->
"app": "ruoyi-admin",
<!--打印时间 -->
"timestamp": "%d{yyyy-MM-dd HH:mm:ss.SSS}",
<!--线程名称 -->
"thread": "%thread",
<!--日志级别 -->
"level": "%level",
<!--日志名称 -->
"logger_name": "%logger",
<!--日志信息 -->
"message": "%msg",
<!--日志堆栈 -->
"stack_trace": "%exception"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>DEBUG</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 用户访问日志输出 -->
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="logstash" />
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
<!--系统用户操作日志-->
<logger name="sys-user" level="info">
<appender-ref ref="sys-user"/>
</logger>
</configuration>
logstash的服务地址和端口要根据自己的情况设置
在正式环境集成logstash,方便监控日志,所以需修改application-prod.yml文件,指定新创建的日志文件
logging:
config: classpath:logback-logstash.xml
level:
com.zzyl: debug
org.springframework: warn
使用ELK检索日志
1. 查看索引文件
对接项目之后,可以启动项目,产生一些日志数据
然后打开kibana, http://192.168.2.17:5601/(容器所在宿主机的ip地址和端口)找到索引管理,导航:Stack Management –> 索引管理

可以看到,日志文件都是按照日期进行区分的,每天一个日志索引文件
2. 添加索引模式
如果想用kibana方便的查看日志的数据,可以添加索引模式,如下图

上图中,点击创建索引模式,然后可以添加索引模式,如下图

然后,选择时间戳作为时间段即可,就可以完成了,如下图

完成后的效果:

**3.检索日志 **
打开Discover

检索日志,选择不同的索引,可以按照不同的字段检索,或者在输入框直接输入内容,也是可以的

其他检索技巧
- 模糊搜索
-
使用通配符
*可以匹配任意数量的字符,?可以匹配单个字符。例如,nursing*会匹配任何以“nursing”开头的单词 2. 时间范围查询 -
一般检查时间检索的字段为:
@timestamp,可以提供以下几种时间范围查询方式
- 按照年查询:
@timestamp < "2024" - 按照年月查询:
@timestamp < "2024-09" - 按照年月日查询:
@timestamp:"2024-09-05" - 按照年月日时分秒查询:
@timestamp < "2024-09-02T21:55:59"3. 字段搜索:通过指定字段名进行搜索,可以更精确地定位到包含特定信息的日志条目。例如,message:"error"会匹配消息字段中包含“error”的日志条目