查看日志信息对于运维 和开发人员来说是非常必要的,常见的查看日志情况如下:
- 当应用程序或服务出现故障时,查看日志可帮助快速定位问题,了解故障前后的系统状态。
- 通过分析日志,可以监控应用程序性能,识别性能瓶颈或资源消耗异常。
- 在开发和测试过程中,查看日志有助于开发人员调试代码、定位并修复bug,同时也是验证应用程序功能是否正常的重要依据。
线上项目问题的排查思路和解决办法
线上项目一旦出问题,那可是牵一发而动全身 ------ 用户投诉、业务中断、数据风险,分分钟让人头大。但老手都知道,再棘手的问题也不是无迹可寻,而日志就是咱们最靠谱的 "破案线索库"。从服务器突然卡顿到接口频繁报错,从数据异常到用户操作失败,顺着日志这条线摸下去,总能找到问题的源头。接下来,咱们就结合前面讲的日志管理技巧,聊聊线上问题排查的实用思路:怎么快速定位日志中的关键信息?不同场景下该用哪些工具和命令?遇到复杂问题时又该如何串联日志碎片还原真相?掌握了这些,面对线上故障就能从手忙脚乱变成胸有成竹。
日志采集方式
咱们项目里用的是 SpringBoot 自带的 logback 框架来收集日志,步骤超简单,跟着做就行:
- 加依赖?不用!
SpringBoot 早就把 logback 的依赖打好包了,咱们直接用就行,省事儿~
- 准备 logback 配置文件
得在项目里放个 logback.xml 文件,这里面可讲究了 ------ 日志存哪儿、长啥样、哪些级别要记录,全在这儿定规矩。给你们看个例子,我标了重点注释,一看就懂:
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>
<!-- 只保留60天的日志,不然硬盘要炸 -->
<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>
<!-- 咱们自己写的代码,日志级别设为INFO就行 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring框架的日志别太啰嗦,WARN及以上就行 -->
<logger name="org.springframework" level="warn" />
<!-- 根日志配置:默认输出到控制台 -->
<root level="info">
<appender-ref ref="console" />
</root>
<!-- 系统日志同时输出到文件和控制台 -->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
<!-- 用户操作日志专门写到sys-user.log -->
<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记录的是用户登录相关的日志数据

- 在代码里打日志
在类上添个@Slf4j注解,就不用自己写日志对象了,直接用这些方法打日志:
- 调试的时候用log.debug("用户输入了xxx")
- 正常运行信息用log.info("订单创建成功,ID是xxx")
- 需要注意的情况用log.warn("库存快不够了,当前只剩xxx")
- 出问题了用log.error("数据库连接失败!", e)(记得把异常传进去)
现在咱们的日志文件主要有三种:
- sys-info.log:系统大杂烩,啥日志都有,最全面
- sys-error.log:只记错误,排查问题首选这个
- sys-user.log:专门记用户登录、退出这些操作
不带日期的是当天的日志,带日期的是以前的归档文件,很好区分~
Linux 里查看日志
查日志是咱们的基本功,线上服务大多用 docker 部署,我教你们几招实用的:
docker logs 命令
用这个命令查容器里的日志超方便,格式是docker logs [参数] 容器名或ID:
- 想实时看着日志更新?加个-f参数:docker logs -f 容器名,就像看直播一样
- 只看最后 100 行?docker logs --tail=100 容器名,避免日志太多刷屏
进容器里查日志
如果想细看日志文件,先用docker exec -it 容器名 /bin/bash进容器(如果提示找不到 bash,就换/bin/sh),然后用这些 Linux 命令:
- 看整个日志文件:cat sys-info.log(文件大的话慎用,会卡死);想慢慢翻就用more sys-info.log或less sys-info.log
- 实时盯日志:tail -f sys-info.log,新日志会自动出来;只想看最后 100 行的更新?tail -n 100 -f sys-info.log(这个超常用)
- 按关键词搜日志:比如找所有带 error 的记录,cat sys-info.log | grep 'error';日志太多翻不完?加个| more分页看:cat sys-info.log | grep 'error' | more
ELK 日志管理
小项目用上面的方法够了,但公司大了、服务多了,日志堆成山,光靠命令行就不够用了。这时候就得请出 ELK 这个神器组合了!
啥是 ELK?
ELK是一个开源的日志管理平台,由三个核心组件组成:E lasticsearch、L ogstash 和 Kibana。这三个组件共同协作,提供了对日志从收集、处理、存储到分析、可视化的完整解决方案。
- Elasticsearch:这是一个基于Lucene的搜索引擎,用于存储和搜索日志数据。它提供了强大的全文搜索功能,支持复杂的查询和聚合操作,并且能够处理大规模的日志数据。
- Logstash:这是一个日志收集和处理工具,用于从各种数据源(如文件、数据库、网络等)中收集日志,并将其转换为Elasticsearch可以理解的格式。Logstash还提供了丰富的过滤功能,可以对日志数据进行清洗、转换和增强。
- Kibana:这是一个Web界面,用于可视化Elasticsearch中的日志数据。它提供了直观的图形和工具,使用户能够轻松地搜索、分析和可视化日志数据,从而更好地理解系统的运行状态和性能。
动手搭 ELK
装好了这三个工具,直接启动就行:
启动服务
先运行这三条命令启动服务(注意:这仨很吃内存,用完记得关掉):
sql
docker start es
docker start kibana
docker start logstash
不过启动后虚拟机可能会有点卡,咱们调整一下:
- 先把虚拟机里的前后端服务停了:
arduino
docker stop zzyl-admin
docker stop zzyl-vue
- 改在自己电脑上启动服务:
- 后端:在 application.yml 里把spring.profiles.active改成prod,然后启动
- 前端:改 vite.config.js 里的后端地址为http://localhost:9000,重启一下
让项目日志发给 ELK
得让咱们的项目把日志传给 Logstash,步骤如下:
- 先在 zzyl-admin 模块里加个依赖:
xml
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.6</version>
</dependency>
- 新增个logback-logstash.xml文件(其实就是在原来的配置上加了 Logstash 的配置):
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>
<!-- 重点:这个配置让日志发给Logstash -->
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!-- 填Logstash的地址和端口,咱们虚拟机里是192.168.100.168:5044 -->
<destination>192.168.100.168:5044</destination>
<!-- 日志格式转成JSON,方便Elasticsearch处理 -->
<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>
<!-- 下面这些和之前的logback.xml一样,省略... -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 内容不变 -->
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 内容不变 -->
</appender>
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 内容不变 -->
</appender>
<logger name="com.ruoyi" level="info" />
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!-- 关键:让日志同时发给Logstash和文件 -->
<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>
- 让正式环境用这个新配置:改application-prod.yml,指定日志配置文件:
yaml
logging:
config: classpath:logback-logstash.xml
level:
com.zzyl: debug
org.springframework: warn
改完重启服务,随便点点页面,多制造点日志(比如故意点些没完成的功能,弄点错误日志出来)。
用 Kibana 查日志
打开 Kibana 的地址:http://192.168.100.168:5601/,第一次用得先设置索引。
加个索引模式
- 点左边菜单的Stack Management

- 找到索引模式,点创建索引模式
- 输入索引名(比如logstash-*,匹配所有日志索引)

- 选个时间字段(一般用@timestamp)

- 点创建索引模式就搞定了

管理索引

在Stack Management里点索引管理,能看到所有日志索引,都是按日期存的,每天一个,清清楚楚。
搜日志
点左边的Discover,就能搜日志了:
- 选刚才创建的索引模式

- 直接在搜索框输关键词,比如error
- 想按条件搜?比如只看 ERROR 级别的:level:"ERROR"
- 想限定时间?用@timestamp,比如@timestamp:"2025-08-05"只看 8 月 5 号的日志
高级搜法
给你们几个超实用的技巧:
- 模糊搜:比如想找所有带nursing开头的日志,用nursing*;找user1或user2,用user?(? 匹配一个字符)
- 时间范围:@timestamp < "2025-08-05"(8 月 5 号之前),@timestamp > "2025-08-05T08:00:00"(8 月 5 号早上 8 点之后)
- 多条件组合:比如找今天的 ERROR 日志,level:"ERROR" AND @timestamp:"2025-08-05"
有了这些技巧,再多日志也能轻松搞定啦!