我有一个复杂的@RestController方法,如下所示:
@PostMapping("{id}")
@PreAuthorize("hasRole('ADMIN')")
@Transactional
public Response handleRequest(@PathVariable("id") long id, @RequestBody @Valid Request request) {
return service.handleRequest(id, request);
}
我们的请求处理非常慢,因此我们希望检查在特定请求处理任务上花费了多少时间。不幸的是,很多事情都是在我的方法之外完成的,比如:
反序列化请求 验证 权限检查 开始和结束事务 序列化响应 有没有办法简单地测量所有这些部件?也许一组记录器接收跟踪消息,这样我就可以在每一步的末尾提取时间戳了?
我现在看到的唯一方法是更改该方法以接受HttpServletRequest和HttpServletResponse,并在方法主体中执行这些部分。但是那样的话,我就会失去很多Spring Boot的好处。
没有必要更改该方法以期待HttpServletRequest。你可以用AspectJ
使用它,您可以收集在每个方法上花费的时间,并从中分析数据。
创建一个方法--时间标注
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodTiming {
}
在您的请求中,创建一个将保留所有方法及其所用时间的映射:
public class Request {
private Map<String, Long> methodTimings = new TreeMap<String, Long>();
public void addMethodTiming(String classAndMethodName, long executionTimeMillis) {
Long value = methodTimings.get(classAndMethodName);
if (value != null) {
executionTimeMillis += value;
}
methodTimings.put(classAndMethodName, executionTimeMillis);
}
}
创建处理它的方面类:
@Aspect
@Component
public class MethodTimingAspect {
private static final String DOT = ".";
@Around("@annotation(MethodTiming)")
public Object timeAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
StopWatch watch = new StopWatch();
try {
watch.start();
result = joinPoint.proceed();
} finally {
watch.stop();
long executionTime = watch.getLastTaskTimeMillis();
String className = joinPoint.getTarget().getClass().getSimpleName();
String methodName = joinPoint.getSignature().getName();
String classAndMethodName = className + DOT + methodName;
Object[] methodArgs = joinPoint.getArgs();
if (methodArgs != null) {
for (Object arg : methodArgs) {
if (arg instanceof Request) {
// inject time back into Request
Request request = (Request) arg;
request.addMethodTiming(classAndMethodName, executionTime);
break;
}
}
}
}
return result;
}
最后,只需在您希望度量的方法上添加@MethodTiming:
@MethodTiming
public Request handleRequest(Request request) {
// handle the Request
return request
}
您的请求对象在处理之后将有如下所示
"methodTimings": {
"RequestService.handleRequest": 2610,
"AnotherRequestService.anotherMethod": 1351
}
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。