一、需求分析 1.日志记录目的: -追踪用户行为,便于问题排查和系统审计 -分析用户操作模式,优化系统体验 -满足合规性要求(如食品安全追溯) 2.核心功能需求: -记录所有关键用户操作(登录、下单、修改订单、支付等) -记录操作时间、操作人、操作内容、操作结果 -支
一、需求分析
1. 日志记录目的:
- 追踪用户行为,便于问题排查和系统审计
- 分析用户操作模式,优化系统体验
- 满足合规性要求(如食品安全追溯)
2. 核心功能需求:
- 记录所有关键用户操作(登录、下单、修改订单、支付等)
- 记录操作时间、操作人、操作内容、操作结果
- 支持日志查询和导出功能
- 确保日志数据安全性和完整性
二、系统设计
1. 日志数据结构
```json
{
"log_id": "唯一标识符",
"user_id": "用户ID",
"username": "用户名",
"operation_type": "操作类型(登录/下单/修改订单等)",
"operation_detail": "操作详情(JSON格式)",
"operation_time": "操作时间(ISO8601)",
"ip_address": "用户IP",
"device_info": "设备信息",
"result": "操作结果(成功/失败)",
"error_code": "错误代码(如有)",
"module": "所属模块(采购/仓储/配送等)"
}
```
2. 技术选型
- 存储方案:Elasticsearch(快速查询) + MySQL(持久化存储)
- 日志采集:AOP切面编程 + 手动记录关键操作
- 日志级别:INFO(常规操作)、WARN(可疑操作)、ERROR(错误操作)
- 数据安全:敏感信息脱敏、访问权限控制
三、开发实现
1. 后端实现(Spring Boot示例)
```java
// 日志实体类
@Data
public class UserOperationLog {
@Id
private String logId;
private String userId;
private String username;
private String operationType;
private String operationDetail;
private LocalDateTime operationTime;
private String ipAddress;
private String deviceInfo;
private String result;
private String errorCode;
private String module;
}
// 日志切面
@Aspect
@Component
public class OperationLogAspect {
@Autowired
private LogService logService;
@Around("execution(* com.kuailv.fresh.controller.*.*(..))")
public Object logOperation(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取方法签名
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 获取注解信息
OperationLog annotation = method.getAnnotation(OperationLog.class);
if (annotation != null) {
// 执行方法前记录开始时间
long startTime = System.currentTimeMillis();
// 执行目标方法
Object result = joinPoint.proceed();
// 执行方法后记录耗时
long costTime = System.currentTimeMillis() - startTime;
// 构建日志详情
String operationDetail = buildOperationDetail(joinPoint, result, costTime);
// 获取用户信息
User user = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
// 记录日志
UserOperationLog log = new UserOperationLog();
log.setUserId(user.getId());
log.setUsername(user.getUsername());
log.setOperationType(annotation.value());
log.setOperationDetail(operationDetail);
log.setOperationTime(LocalDateTime.now());
log.setIpAddress(getIpAddress());
log.setDeviceInfo(getDeviceInfo());
log.setResult("SUCCESS");
log.setModule(annotation.module());
logService.saveLog(log);
return result;
}
return joinPoint.proceed();
}
// 其他辅助方法...
}
// 自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationLog {
String value(); // 操作类型
String module() default ""; // 所属模块
}
```
2. 前端实现(Vue示例)
```javascript
// 在Vuex中添加日志记录方法
const actions = {
async recordOperation({ commit }, logData) {
try {
await api.post(/api/logs, {
...logData,
operationTime: new Date().toISOString(),
deviceInfo: navigator.userAgent
});
} catch (error) {
console.error(日志记录失败:, error);
}
}
}
// 在关键操作处调用
methods: {
async submitOrder() {
try {
// 提交订单逻辑...
const orderId = await orderService.createOrder(this.orderData);
// 记录成功日志
this.$store.dispatch(recordOperation, {
operationType: CREATE_ORDER,
operationDetail: JSON.stringify({ orderId, amount: this.orderData.amount }),
result: SUCCESS
});
} catch (error) {
// 记录失败日志
this.$store.dispatch(recordOperation, {
operationType: CREATE_ORDER,
operationDetail: JSON.stringify({ error: error.message }),
result: FAIL,
errorCode: error.code || UNKNOWN_ERROR
});
throw error;
}
}
}
```
四、关键功能实现
1. 敏感信息脱敏处理
```java
public class SensitiveDataUtils {
public static String desensitizePhone(String phone) {
if (phone == null || phone.length() < 7) {
return phone;
}
return phone.substring(0, 3) + "" + phone.substring(7);
}
public static String desensitizeAddress(String address) {
// 实现地址脱敏逻辑
// ...
}
}
// 使用示例
String phone = "13812345678";
log.setOperationDetail("用户手机号: " + SensitiveDataUtils.desensitizePhone(phone));
```
2. 日志查询接口
```java
@RestController
@RequestMapping("/api/logs")
public class LogController {
@Autowired
private LogService logService;
@GetMapping
public ResponseEntity
> queryLogs(
@RequestParam(required = false) String userId,
@RequestParam(required = false) String operationType,
@RequestParam(required = false) LocalDateTime startTime,
@RequestParam(required = false) LocalDateTime endTime,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("operationTime").descending());
Page logs = logService.queryLogs(
userId, operationType, startTime, endTime, pageable);
return ResponseEntity.ok(logs);
}
@GetMapping("/export")
public void exportLogs(
@RequestParam(required = false) String userId,
@RequestParam(required = false) String operationType,
@RequestParam(required = false) LocalDateTime startTime,
@RequestParam(required = false) LocalDateTime endTime,
HttpServletResponse response) throws IOException {
List logs = logService.queryLogsForExport(
userId, operationType, startTime, endTime);
// 生成Excel文件
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), UserOperationLog.class)
.sheet("操作日志")
.build()) {
excelWriter.write(logs);
}
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=operation_logs.xlsx");
}
}
```
五、部署与监控
1. 日志存储策略:
- 近7天日志存储在Elasticsearch中,便于快速查询
- 超过7天的日志归档到对象存储(如OSS/S3)
- 定期清理过期的日志数据
2. 监控指标:
- 日志写入成功率
- 日志查询响应时间
- 日志存储空间使用率
- 错误日志频率
3. 告警规则:
- 日志写入失败率 > 1% 时告警
- 特定错误代码频繁出现时告警
- 日志存储空间不足时告警
六、测试与优化
1. 测试用例:
- 正常操作日志记录测试
- 异常操作日志记录测试
- 高并发场景下的日志写入性能测试
- 日志查询功能测试
2. 性能优化:
- 采用异步方式写入日志,减少对主业务流程的影响
- 对日志数据进行压缩存储
- 实现批量写入功能,减少I/O操作
3. 安全优化:
- 实现日志数据的加密存储
- 严格限制日志查询权限
- 定期审计日志访问记录
七、维护与迭代
1. 维护计划:
- 每月检查日志系统健康状况
- 每季度评估日志存储需求并调整策略
- 每年对日志系统进行安全审计
2. 迭代方向:
- 增加日志智能分析功能,自动识别异常模式
- 实现日志与业务数据的关联分析
- 开发日志可视化大屏,便于实时监控
通过以上设计和实现,快驴生鲜系统的用户操作日志功能能够全面记录用户行为,为系统运维、安全审计和业务分析提供有力支持。