perf: 优化日志保留与分页查询
- 降低普通只读请求的日志写入并保留敏感 GET 审计 - 增加数据库分批清理、时间索引和文件滚动容量上限 - 增加近 30 天筛选、稳定倒序和分页大小限制
This commit is contained in:
@@ -13,6 +13,7 @@ import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import tech.easyflow.log.annotation.LogRecord;
|
||||
import tech.easyflow.log.entity.WriteLog;
|
||||
import tech.easyflow.log.mapper.WriteLogMapper;
|
||||
|
||||
@@ -28,6 +29,7 @@ import static org.junit.Assert.assertSame;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -158,6 +160,47 @@ public class LogAspectTest {
|
||||
assertNull(captor.getValue().getActionBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证未显式标注的 GET 请求不会产生操作日志。
|
||||
*
|
||||
* @throws Throwable 切面执行异常
|
||||
*/
|
||||
@Test
|
||||
public void unannotatedGetShouldNotWriteLog() throws Throwable {
|
||||
WriteLogMapper mapper = mock(WriteLogMapper.class);
|
||||
LogAspect aspect = new LogAspect(mapper, properties());
|
||||
request("{}", "GET");
|
||||
ProceedingJoinPoint joinPoint = joinPoint("read");
|
||||
when(joinPoint.proceed()).thenReturn("ok");
|
||||
|
||||
assertEquals("ok", aspect.doAround(joinPoint));
|
||||
|
||||
verify(mapper, never()).insert(any(WriteLog.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证显式标注的 GET 请求仍会产生操作日志。
|
||||
*
|
||||
* @throws Throwable 切面执行异常
|
||||
*/
|
||||
@Test
|
||||
public void annotatedGetShouldWriteLog() throws Throwable {
|
||||
WriteLogMapper mapper = mock(WriteLogMapper.class);
|
||||
LogAspect aspect = new LogAspect(mapper, properties());
|
||||
request("{}", "GET");
|
||||
ProceedingJoinPoint joinPoint = joinPoint("auditedRead");
|
||||
when(joinPoint.proceed()).thenReturn("ok");
|
||||
|
||||
try (MockedStatic<StpUtil> stp = Mockito.mockStatic(StpUtil.class)) {
|
||||
stp.when(StpUtil::isLogin).thenReturn(false);
|
||||
assertEquals("ok", aspect.doAround(joinPoint));
|
||||
}
|
||||
|
||||
ArgumentCaptor<WriteLog> captor = ArgumentCaptor.forClass(WriteLog.class);
|
||||
verify(mapper).insert(captor.capture());
|
||||
assertEquals("审计读取", captor.getValue().getActionName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建测试日志配置。
|
||||
*
|
||||
@@ -177,8 +220,21 @@ public class LogAspectTest {
|
||||
* @throws IOException 输入流创建失败
|
||||
*/
|
||||
private HttpServletRequest request(String body) throws IOException {
|
||||
return request(body, "POST");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并绑定指定 HTTP 方法的测试请求。
|
||||
*
|
||||
* @param body JSON body
|
||||
* @param httpMethod HTTP 方法
|
||||
* @return 测试请求
|
||||
* @throws IOException 输入流创建失败
|
||||
*/
|
||||
private HttpServletRequest request(String body, String httpMethod) throws IOException {
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
when(request.getServletPath()).thenReturn("/api/v1/skill/update");
|
||||
when(request.getMethod()).thenReturn(httpMethod);
|
||||
when(request.getContentType()).thenReturn("application/json;charset=UTF-8");
|
||||
when(request.getCharacterEncoding()).thenReturn(StandardCharsets.UTF_8.name());
|
||||
when(request.getParameterNames()).thenReturn(Collections.emptyEnumeration());
|
||||
@@ -196,9 +252,20 @@ public class LogAspectTest {
|
||||
* @throws NoSuchMethodException 测试方法不存在
|
||||
*/
|
||||
private ProceedingJoinPoint joinPoint() throws NoSuchMethodException {
|
||||
return joinPoint("update");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建指定控制器方法的测试连接点。
|
||||
*
|
||||
* @param methodName 控制器方法名
|
||||
* @return 测试连接点
|
||||
* @throws NoSuchMethodException 测试方法不存在
|
||||
*/
|
||||
private ProceedingJoinPoint joinPoint(String methodName) throws NoSuchMethodException {
|
||||
ProceedingJoinPoint joinPoint = mock(ProceedingJoinPoint.class);
|
||||
MethodSignature signature = mock(MethodSignature.class);
|
||||
Method method = TestController.class.getMethod("update");
|
||||
Method method = TestController.class.getMethod(methodName);
|
||||
when(joinPoint.getSignature()).thenReturn(signature);
|
||||
when(signature.getDeclaringType()).thenReturn(TestController.class);
|
||||
when(signature.getMethod()).thenReturn(method);
|
||||
@@ -249,5 +316,24 @@ public class LogAspectTest {
|
||||
public Object update() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟普通读取入口。
|
||||
*
|
||||
* @return 空结果
|
||||
*/
|
||||
public Object read() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟需要审计的读取入口。
|
||||
*
|
||||
* @return 空结果
|
||||
*/
|
||||
@LogRecord("审计读取")
|
||||
public Object auditedRead() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user