新增:新增系统监控/操作日志功能,优化日志表结构

This commit is contained in:
2023-01-16 23:00:54 +08:00
parent f4ea2d44d6
commit aa726fc6b6
26 changed files with 386 additions and 83 deletions

View File

@@ -22,14 +22,14 @@ import lombok.RequiredArgsConstructor;
import com.baomidou.mybatisplus.annotation.IEnum;
/**
* 操作结果枚举
* 操作状态枚举
*
* @author Charles7c
* @since 2022/12/25 9:09
*/
@Getter
@RequiredArgsConstructor
public enum LogResultEnum implements IEnum<Integer> {
public enum LogStatusEnum implements IEnum<Integer> {
/** 成功 */
SUCCESS(1, "成功"),

View File

@@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
@@ -32,7 +33,7 @@ import org.springframework.web.util.ContentCachingResponseWrapper;
import org.springframework.web.util.WebUtils;
/**
* 操作日志过滤器(缓存请求和响应体过滤器)
* 系统日志过滤器(缓存请求和响应体过滤器)
*
* <p>
* 由于 requestBody 和 responseBody 分别对应的是 InputStream 和 OutputStream由于流的特性读取完之后就无法再被使用了。 所以,需要额外缓存一次流信息。
@@ -50,8 +51,8 @@ public class LogFilter extends OncePerRequestFilter implements Ordered {
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {
// 包装流,可重复读取
if (!(request instanceof ContentCachingRequestWrapper)) {
request = new ContentCachingRequestWrapper(request);

View File

@@ -52,7 +52,7 @@ import top.charles7c.cnadmin.common.util.helper.LoginHelper;
import top.charles7c.cnadmin.common.util.holder.LogContextHolder;
import top.charles7c.cnadmin.monitor.annotation.Log;
import top.charles7c.cnadmin.monitor.config.properties.LogProperties;
import top.charles7c.cnadmin.monitor.enums.LogResultEnum;
import top.charles7c.cnadmin.monitor.enums.LogStatusEnum;
import top.charles7c.cnadmin.monitor.model.entity.SysLog;
/**
@@ -73,7 +73,7 @@ public class LogInterceptor implements HandlerInterceptor {
public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response,
@NonNull Object handler) {
if (checkIsNeedRecord(handler, request)) {
// 记录操作时间
// 记录时间
this.logCreateTime();
}
return true;
@@ -100,7 +100,7 @@ public class LogInterceptor implements HandlerInterceptor {
}
/**
* 记录操作时间
* 记录时间
*/
private void logCreateTime() {
LogContext logContext = new LogContext();
@@ -121,12 +121,12 @@ public class LogInterceptor implements HandlerInterceptor {
SysLog sysLog = new SysLog();
sysLog.setCreateTime(logContext.getCreateTime());
sysLog.setElapsedTime(System.currentTimeMillis() - LocalDateTimeUtil.toEpochMilli(sysLog.getCreateTime()));
sysLog.setResult(LogResultEnum.SUCCESS);
sysLog.setStatus(LogStatusEnum.SUCCESS);
// 记录异常信息
Exception exception = logContext.getException();
if (exception != null) {
sysLog.setResult(LogResultEnum.FAILURE);
sysLog.setStatus(LogStatusEnum.FAILURE);
sysLog.setException(ExceptionUtil.stacktraceToString(exception, -1));
}
return sysLog;
@@ -175,8 +175,8 @@ public class LogInterceptor implements HandlerInterceptor {
sysLog.setRequestBody(this.desensitize(
JSONUtil.isTypeJSON(requestBody) ? JSONUtil.parseObj(requestBody) : ServletUtil.getParamMap(request)));
}
sysLog.setRequestIp(ServletUtil.getClientIP(request));
sysLog.setLocation(IpUtils.getCityInfo(sysLog.getRequestIp()));
sysLog.setClientIp(ServletUtil.getClientIP(request));
sysLog.setLocation(IpUtils.getCityInfo(sysLog.getClientIp()));
sysLog.setBrowser(ServletUtils.getBrowser(request));
sysLog.setCreateUser(sysLog.getCreateUser() == null ? LoginHelper.getUserId() : sysLog.getCreateUser());
}
@@ -199,7 +199,7 @@ public class LogInterceptor implements HandlerInterceptor {
sysLog.setResponseBody(responseBody);
}
// 操作失败:>= 400
sysLog.setResult(status >= HttpStatus.HTTP_BAD_REQUEST ? LogResultEnum.FAILURE : sysLog.getResult());
sysLog.setStatus(status >= HttpStatus.HTTP_BAD_REQUEST ? LogStatusEnum.FAILURE : sysLog.getStatus());
}
/**
@@ -265,9 +265,9 @@ public class LogInterceptor implements HandlerInterceptor {
* 检查是否要记录系统日志
*
* @param handler
* /
* 处理器
* @param request
* /
* 请求对象
* @return true 需要记录false 不需要记录
*/
private boolean checkIsNeedRecord(Object handler, HttpServletRequest request) {

View File

@@ -24,7 +24,7 @@ import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import top.charles7c.cnadmin.monitor.enums.LogResultEnum;
import top.charles7c.cnadmin.monitor.enums.LogStatusEnum;
/**
* 系统日志实体
@@ -90,17 +90,17 @@ public class SysLog implements Serializable {
private Long elapsedTime;
/**
* 操作结果1成功 2失败
* 操作状态1成功 2失败
*/
private LogResultEnum result;
private LogStatusEnum status;
/**
* 操作IP
* 客户端IP
*/
private String requestIp;
private String clientIp;
/**
* 操作地点
* IP归属地
*/
private String location;
@@ -115,12 +115,12 @@ public class SysLog implements Serializable {
private String exception;
/**
* 操作
* 创建
*/
private Long createUser;
/**
* 操作时间
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@@ -19,12 +19,15 @@ package top.charles7c.cnadmin.monitor.model.query;
import static top.charles7c.cnadmin.common.annotation.Query.Type;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.format.annotation.DateTimeFormat;
import top.charles7c.cnadmin.common.annotation.Query;
@@ -47,4 +50,26 @@ public class OperationLogQuery implements Serializable {
@Schema(description = "操作人")
@Query(property = "createUser", type = Type.EQUAL)
private Long uid;
/**
* 操作内容
*/
@Schema(description = "操作内容")
@Query(type = Type.INNER_LIKE)
private String description;
/**
* 操作状态1成功 2失败
*/
@Schema(description = "操作状态1成功 2失败")
@Query(type = Type.EQUAL)
private Integer status;
/**
* 操作时间
*/
@Schema(description = "操作时间")
@Query(type = Type.BETWEEN)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private List<Date> createTime;
}

View File

@@ -25,7 +25,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import com.fasterxml.jackson.annotation.JsonIgnore;
import top.charles7c.cnadmin.monitor.enums.LogResultEnum;
import top.charles7c.cnadmin.monitor.enums.LogStatusEnum;
/**
* 操作日志信息
@@ -52,16 +52,16 @@ public class OperationLogVO implements Serializable {
private String description;
/**
* 操作结果1成功 2失败
* 操作状态1成功 2失败
*/
@Schema(description = "操作结果1成功 2失败", type = "Integer", allowableValues = {"1", "2"})
private LogResultEnum result;
@Schema(description = "操作状态1成功 2失败", type = "Integer", allowableValues = {"1", "2"})
private LogStatusEnum status;
/**
* 操作IP
*/
@Schema(description = "操作IP")
private String requestIp;
private String clientIp;
/**
* 操作地点

View File

@@ -69,7 +69,14 @@ public class OperationLogServiceImpl implements OperationLogService {
// 分页查询
IPage<SysLog> page = logMapper.selectPage(pageQuery.toPage(), queryWrapper);
PageInfo<OperationLogVO> pageInfo = PageInfo.build(page, OperationLogVO.class);
pageInfo.getList().forEach(this::fill);
// 填充数据(如果是查询个人操作日志,只查询一次用户信息即可)
if (query.getUid() != null) {
SysUser sysUser = userMapper.selectById(query.getUid());
pageInfo.getList().forEach(o -> o.setCreateUserString(sysUser.getUsername()));
} else {
pageInfo.getList().forEach(this::fill);
}
return pageInfo;
}
@@ -85,6 +92,6 @@ public class OperationLogServiceImpl implements OperationLogService {
return;
}
SysUser sysUser = userMapper.selectById(createUser);
vo.setCreateUserString(sysUser.getNickname());
vo.setCreateUserString(sysUser.getUsername());
}
}