guoyu/log/导入进度显示优化说明.md

392 lines
9.9 KiB
Markdown
Raw Normal View History

# 导入进度显示优化说明
## ❌ **问题现象**
1. 导入100条数据进度不显示或显示很慢
2. 中断导入时显示"没有导入任何成功或失败的数据"
3. 看不到正在做什么
---
## 🔍 **问题原因**
### **原因1进度更新频率太低**
```java
int updateInterval = 100; // 每100条更新一次
```
**问题:**
- 100条数据只更新2次进度第100条和结束时
- 前99条处理时用户看不到任何进度
- 导致用户以为系统卡死
### **原因2中断时结果保存不正确**
```java
// 只设置了progress.setResult()
// 但没有调用progressManager的方法保存
progress.setResult(resultMsg.toString());
return; // 直接return结果丢失
```
### **原因3缺少详细的处理日志**
```java
// 只有进度日志
logger.info("任务 {} 进度更新: {}/{}", taskId, i, totalSize);
// 缺少:
// - 正在处理哪条记录
// - 新增还是更新
// - 处理结果如何
```
---
## ✅ **解决方案**
### **优化1提高进度更新频率**
**修改前:**
```java
int updateInterval = 100; // 每100条更新一次
```
**修改后:**
```java
int updateInterval = 5; // 每5条更新一次
```
**效果:**
- 100条数据会更新20次进度
- 用户每处理5条就能看到进度变化
- 实时反馈,体验更好
---
### **优化2修复中断时的结果保存**
**修改前:**
```java
com.ddnai.common.core.domain.ImportProgress progress = progressManager.getProgress(taskId);
if (progress != null) {
progress.setResult(resultMsg.toString());
}
return; // 结果可能丢失
```
**修改后:**
```java
// 使用progressManager的方法保存结果
progressManager.cancelTask(taskId, resultMsg.toString());
return;
```
**效果:**
- 中断时正确保存已处理的结果
- 显示新增、更新、失败的具体数量
- 显示失败的详细信息
---
### **优化3添加详细的处理日志**
**新增用户时:**
```java
logger.info("正在新增用户: 信息编号={}, 姓名={}", infoNo, prisonerName);
userMapper.insertUser(user);
logger.info("用户新增成功: 信息编号={}, userId={}", infoNo, user.getUserId());
```
**更新用户时:**
```java
logger.info("正在更新用户: 信息编号={}, 姓名={}", infoNo, prisonerName);
userMapper.updateUser(u);
logger.info("用户更新成功: 信息编号={}", infoNo);
```
**进度更新时:**
```java
String progressInfo = String.format("[%d/%d] 新增:%d 更新:%d 失败:%d 跳过:%d",
i + 1, totalSize, successNum, updateNum, errorNum, duplicateNum);
logger.info("任务 {} 进度: {}", taskId, progressInfo);
```
---
## 📊 **优化效果对比**
### **优化前**
| 项目 | 表现 |
|------|------|
| 进度更新 | 100条只更新2次 |
| 进度显示 | 99条时看不到进度 |
| 中断显示 | "没有导入任何数据" |
| 日志详细度 | 只有简单进度 |
### **优化后**
| 项目 | 表现 |
|------|------|
| 进度更新 | 100条更新20次 |
| 进度显示 | 每5条就能看到 |
| 中断显示 | 显示已处理的详情 |
| 日志详细度 | 每条记录都有日志 |
---
## 📋 **修改内容**
### **文件:** `StudyClassUserServiceImpl.java`
#### **修改1进度更新频率第905行**
```java
// 每处理5条更新一次进度让用户看到实时进度
int updateInterval = 5;
```
#### **修改2中断时保存结果第936行**
```java
// 保存取消状态和结果
progressManager.cancelTask(taskId, resultMsg.toString());
```
#### **修改3新增详细日志第998-1000行**
```java
logger.info("正在新增用户: 信息编号={}, 姓名={}", infoNo, prisonerName);
userMapper.insertUser(user);
logger.info("用户新增成功: 信息编号={}, userId={}", infoNo, user.getUserId());
```
#### **修改4更新详细日志第1092-1094行**
```java
logger.info("正在更新用户: 信息编号={}, 姓名={}", infoNo, prisonerName);
userMapper.updateUser(u);
logger.info("用户更新成功: 信息编号={}", infoNo);
```
#### **修改5进度日志格式第1235-1237行**
```java
String progressInfo = String.format("[%d/%d] 新增:%d 更新:%d 失败:%d 跳过:%d",
i + 1, totalSize, successNum, updateNum, errorNum, duplicateNum);
logger.info("任务 {} 进度: {}", taskId, progressInfo);
```
---
## 🔧 **部署步骤**
### **步骤1重新编译**
```bash
cd C:\Users\Administrator\Desktop\Project\ry_study-v_03\Study-Vue-redis
mvn clean package -DskipTests
```
### **步骤2重启服务**
停止旧服务,启动新服务
### **步骤3测试导入**
1. 导入50条数据
2. 观察进度是否实时更新
3. 测试中断功能
4. 查看日志详细程度
---
## 🧪 **测试场景**
### **场景1正常导入**
**操作:**
1. 导入100条数据
2. 观察进度条
**预期:**
- 进度条从0%逐步增加到100%
- 每5条更新一次约每秒更新几次
- 最终显示成功数量
**日志示例:**
```
正在新增用户: 信息编号=201, 姓名=张三
用户新增成功: 信息编号=201, userId=1001
任务 xxx 进度: [5/100] 新增:5 更新:0 失败:0 跳过:0
正在新增用户: 信息编号=206, 姓名=李四
用户新增成功: 信息编号=206, userId=1006
任务 xxx 进度: [10/100] 新增:10 更新:0 失败:0 跳过:0
...
```
---
### **场景2中断导入**
**操作:**
1. 开始导入100条数据
2. 处理到第30条时点击"中断导入"
**预期:**
- 显示中断提示
- 显示已处理30条的详情
```
导入已取消!
新增: 20 条
更新: 8 条
失败: 2 条
无变化跳过: 0 条
未处理: 70 条
失败详情:
1、信息编号 205罪犯姓名 王五 导入失败:班级 [三班] 不存在
2、信息编号 210罪犯姓名 赵六 导入失败:监区不能为空
```
---
### **场景3包含错误的导入**
**操作:**
1. 导入100条数据其中20条班级不存在
**预期:**
- 进度实时更新
- 最终显示:
```
导入完成新增70条更新10条失败20条。
失败详情:
1、信息编号 205罪犯姓名 张三 导入失败:班级 [三班] 不存在
...逐条列出20条失败记录
```
**日志示例:**
```
正在新增用户: 信息编号=205, 姓名=张三
用户新增成功: 信息编号=205, userId=1005
为学员 205 分配班级时失败: 班级 [三班] 不存在,请先创建该班级
任务 xxx 进度: [5/100] 新增:4 更新:0 失败:1 跳过:0
```
---
## 📊 **日志输出示例**
### **完整的导入过程日志**
```
[INFO] 任务 cce42e41-f819-4029-9c4e-0155fb3c2582 开始,共 100 条数据
[INFO] 预加载班级映射完成,共 5 个班级
[INFO] 正在新增用户: 信息编号=201, 姓名=张三
[INFO] 用户新增成功: 信息编号=201, userId=1001
[INFO] 为学员 201 分配班级 中级班1班 成功
[INFO] 正在新增用户: 信息编号=202, 姓名=李四
[INFO] 用户新增成功: 信息编号=202, userId=1002
[INFO] 为学员 202 分配班级 初级班1班 成功
[INFO] 正在新增用户: 信息编号=203, 姓名=王五
[INFO] 用户新增成功: 信息编号=203, userId=1003
[WARN] 为学员 203 分配班级时失败: 班级 [三班] 不存在,请先创建该班级
[INFO] 正在新增用户: 信息编号=204, 姓名=赵六
[INFO] 用户新增成功: 信息编号=204, userId=1004
[INFO] 为学员 204 分配班级 高级班1班 成功
[INFO] 正在新增用户: 信息编号=205, 姓名=孙七
[INFO] 用户新增成功: 信息编号=205, userId=1005
[INFO] 为学员 205 分配班级 攻坚转换班1班 成功
[INFO] 任务 xxx 进度: [5/100] 新增:5 更新:0 失败:0 跳过:0
[INFO] 正在更新用户: 信息编号=210, 姓名=周八
[INFO] 用户更新成功: 信息编号=210
[INFO] 为学员 210 更新班级为 中级班1班 成功
... (继续处理)
[INFO] 任务 xxx 进度: [10/100] 新增:8 更新:2 失败:0 跳过:0
[INFO] 任务 xxx 进度: [15/100] 新增:12 更新:3 失败:0 跳过:0
...
[INFO] 任务 xxx 进度: [100/100] 新增:70 更新:20 失败:5 跳过:5
[INFO] 任务 xxx 完成,最终结果:成功 70 条,更新 20 条,重复 5 条,失败 5 条
```
---
## 💡 **进一步优化建议**
### **1. 添加进度百分比**
```java
int percent = (i + 1) * 100 / totalSize;
logger.info("任务 {} 进度: {}% [{}]", taskId, percent, progressInfo);
```
### **2. 添加预计剩余时间**
```java
long elapsed = System.currentTimeMillis() - startTime;
long avgTime = elapsed / (i + 1);
long remaining = avgTime * (totalSize - i - 1);
logger.info("预计剩余时间: {} 秒", remaining / 1000);
```
### **3. 添加每秒处理速度**
```java
double speed = (i + 1) / (elapsed / 1000.0);
logger.info("处理速度: {:.1f} 条/秒", speed);
```
---
## ⚠️ **注意事项**
### **1. 日志量增加**
- 每条记录产生2-3条日志
- 100条数据约200-300条日志
- 建议定期清理日志文件
### **2. 性能影响**
- 日志输出有一定性能开销
- 但相比数据库操作可忽略
- 如果追求极致性能可以只在DEBUG级别输出详细日志
### **3. 进度更新频率**
- 当前设置为每5条更新一次
- 可根据实际情况调整3-10条都可以
- 太频繁会增加网络开销
---
## 📋 **验收标准**
- [ ] 导入100条数据进度实时更新每5条更新
- [ ] 进度条流畅增长,无卡顿
- [ ] 中断导入时显示已处理的详细信息
- [ ] 日志显示每条记录的处理过程
- [ ] 日志包含:正在处理、处理成功、失败原因
- [ ] 最终结果统计正确
---
## ✅ **总结**
### **核心改进**
1. 进度更新频率从100条提高到5条
2. 中断时正确保存和显示结果
3. 添加详细的处理日志
### **用户体验**
- ✅ 实时看到导入进度
- ✅ 知道正在处理什么
- ✅ 中断时有明确反馈
- ✅ 日志便于排查问题
### **开发调试**
- ✅ 日志详细便于调试
- ✅ 可以追踪每条记录
- ✅ 快速定位性能瓶颈
---
**现在重新编译并测试,应该能看到实时的进度更新和详细的处理日志了!** 🚀