背景:前几天公司上线了一个项目(手机H5项目)说是用户和老板都觉得相应速度比较慢,然后下来要查找原因,所以就需要统计服务器端接口调用时长。
方案:
1.Logback+code
具体的操作步骤就是在每个方法的调用前后加上时间点,然后再把这些结果记录到日志中。
接口内调用的代码:
@Override
public User getUserInfo(int userId) {
Long correspondingStartTime = System.currentTimeMillis();
logger.debug("debug_getUserInfo userId\t" + userId);
try {
User user = userInfoService.getUserInfo(userId);
if(user==null||userId<=0){
logger.debug("getUserInfo userId==null"+userId);
}else{
logger.debug("getUserInfo userId\t" + userId + ",response:" + user.toString());
}
Long correspondingEndTime = System.currentTimeMillis();
CorrespondingTime.correspondingTime("UserServiceImpl", "getUserInfo", correspondingStartTime, correspondingEndTime);
return user;
} catch (RuntimeException e) {
logger.error("getUserInfo userId:" + userId, e);
// 封装对象。
User user = new User();
return user.setError(getBaseResponse(e));
}
}
相应时长统计类:
public class CorrespondingTime {
private static final Logger logger = LoggerFactory.getLogger("CorrespondingTimeLog");
public static void correspondingTime(String clazzName,String methodName,Long correspondingStartTime,Long correspondingEndTime){
logger.info(clazzName+";"+methodName+";"+(correspondingEndTime-correspondingStartTime));
}
}
Logback添加日志文件:
<appender name="correspondingTime" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>../user-log/server-correspondingTime.log</File>
<encoder>
<pattern>%m%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>../user-log/server-correspondingTime.log.%d{yyyy-MM-dd}</fileNamePattern>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
</appender>
/*日志文件名称*/
<logger name="CorrespondingTimeLog" additivity="false">
<appender-ref ref="correspondingTime" />
</logger>
2.Spring AOP
既然Spring aop能够在方法内输出日志,那么在方法内部肯定能够实现对接口响应时长的统计。查找资料如下:
@Aspect
@Component
public class TimestatAspect {
private static final Logger LOG = LoggerFactory.getLogger(TimestatAspect.class);
@Around("execution(* com.baidu.soa.crm.user.dao.impl.*DaoImpl.*(..))")
public Object printTime(ProceedingJoinPoint pjp) throws Throwable {
long l1 = System.currentTimeMillis();
Object obj = pjp.proceed();
String param = "(";
Object[] params = pjp.getArgs();
if (params != null) {
boolean first = true;
for (Object o : params) {
String p = (o == null ? "null" : o.toString());
if (first) {
param = param + p;
first = false;
} else
param = param + ":" + p;
}
}
param = param + ")";
LOG.debug("类名为:" + pjp.getTarget().getClass().getName() + "|方法名为:" + pjp.getSignature().getName() + "|参数为:" + param + "|执行时间为:" + (System.currentTimeMillis() - l1));
return obj;
}
}
总结:
1、比较好想,也容易实现但是有点土鳖。如果需要统计的接口过多,那么改动量就很大,不推荐。
2、调用Spring AOP自身属性,比较简单,能够实现对多出接口的统计,赞!