在实际项目开发中,我们常常需要实时监测一个方法的执行情况,如:方法执行开始、注入方法的参数列表、方法执行时间、方法结束等信息。将这些信息以日志形式进行记录,可以方便开发人员分析方法的执行情况,比如,可以自定义一个时间标准,将执行时间超过此标准时间的方法标记为慢速,以便能及时监测到执行时间过慢的方法,给检查和调试带来方便。
下面为一个记录方法执行情况的日志记录器,使用Spring AOP的方式实现,并可定义方法执行过慢的时间标准,以便监测方法的执行情况。
package com.zhangsx.util.log;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aopalliance.intercept.MethodInvocation;
import org.aopalliance.intercept.MethodInterceptor;
/**
* 记录方法执行情况的日志记录器。
* 使用Spring AOP的方式,记录方法运行情况,
* 包括方法开始、方法参数列表、方法执行时间、是否为执行慢速、方法结束等。
* 可配置将方法定义为执行慢速的时间参数slowExecuteTime,单位为毫秒。
*
* @author ZhangShixi
*/
public class OperationLog implements MethodInterceptor {
// 方法为执行慢速的时间标准,默认为 1000 毫秒
private long slowExecuteTime = 1000;
// 日志级别静态常量
private static final String LEVEL_INFO = "info";
private static final String LEVEL_DEBUG = "debug";
private static final String LEVEL_ERROR = "error";
private static final String LEVEL_WARAN = "waran";
// 日志记录器
private static Log log = LogFactory.getLog(OperationLog.class);
/**
* 获取将方法标记为执行慢速的时间标准,如果方法执行时间超过此值,将被标记为执行慢速。
* @return 执行慢速的时间标准
*/
public long getSlowExecuteTime() {
return slowExecuteTime;
}
/**
* 设置将方法标记为执行慢速的时间标准,如果方法执行时间超过此值,将被标记为执行慢速。
* 如果不配置此参数,将默认为 1000 毫秒。
* @param slowExecuteTime 执行慢速的时间标准
*/
public void setSlowExecuteTime(long slowExecuteTime) {
this.slowExecuteTime = slowExecuteTime;
}
/**
* 重写invoke(MethodInvocation invocation)方法,以便在日志中记录方法执行情况的信息。
* @param invocation 目标对象信息
* @return Object 方法返回值
* @throws java.lang.Throwable 异常
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
before(invocation);
long startTime = System.currentTimeMillis();
Object result = invocation.proceed();
long endTime = System.currentTimeMillis();
long executeTime = endTime - startTime;
logExecuteTime(invocation, executeTime);
after(invocation);
return result;
}
/**
* 在目标对象方法调用之前调用,以记录方法调用之前的情况。
* @param invocation 目标对象信息
*/
private void before(MethodInvocation invocation) {
String methodName = invocation.getMethod().getName();
StringBuilder builder = new StringBuilder();
builder.append("Started ");
builder.append(methodName);
builder.append(" method!");
recordLog(builder.toString(), LEVEL_DEBUG, null);
Object[] args = invocation.getArguments();
builder.delete(0, builder.length());
builder.append(methodName);
builder.append(" way into the parameters are different:");
recordLog(builder.toString(), LEVEL_DEBUG, null);
for (int count = 0; count < args.length; count++) {
builder.delete(0, builder.length());
builder.append("The ");
builder.append(count);
builder.append(" parameters for the ");
builder.append(args[count] == null ? null : args[count].toString());
recordLog(builder.toString(), LEVEL_DEBUG, null);
}
}
/**
* 在目标对象方法调用之后调用,以记录方法调用之后的情况。
* @param invocation 目标对象信息
*/
private void after(MethodInvocation invocation) {
String methodName = invocation.getMethod().getName();
recordLog(methodName + " the implementation of the end.", LEVEL_DEBUG,
null);
}
/**
* 记录方法执行时间。
* 如果执行时间超过 getSlowExecuteTime() 的返回值,
* 则将记录等级提升为 waran ,并标记为慢速执行。
* @param invocation 目标对象信息
* @param executeTime 方法执行时间
*/
private void logExecuteTime(MethodInvocation invocation, long executeTime) {
long slowTime = getSlowExecuteTime();
StringBuilder builder = new StringBuilder();
builder.append(invocation.getMethod().getName());
if (executeTime > slowTime) {
builder.append(" implementation of the method is much too slow,");
builder.append(" the execute time for the implementation is ");
builder.append(executeTime);
builder.append(" ms.");
recordLog(builder.toString(), LEVEL_WARAN, null);
} else {
builder.append(" execution time od the method is ");
builder.append(executeTime);
builder.append(" ms.");
recordLog(builder.toString(), LEVEL_DEBUG, null);
}
builder = null;
}
/**
* 记录日志信息。
* @param message 日志信息
* @param level 日志级别
* @param throwable 如果日志级别是异常,此属性用来描述异常信息。
*/
private void recordLog(String message, String level, Throwable throwable) {
if (message != null && !message.isEmpty() &&
level != null && !level.isEmpty()) {
if (LEVEL_INFO.equals(level)) {
if (log.isInfoEnabled()) {
log.info(message);
}
} else if (LEVEL_DEBUG.equals(level)) {
if (log.isDebugEnabled()) {
log.debug(message);
}
} else if (LEVEL_ERROR.equals(level)) {
if (log.isErrorEnabled()) {
log.error(message);
}
} else if (LEVEL_WARAN.equals(level)) {
if (log.isWarnEnabled()) {
if (throwable == null) {
log.warn(message);
} else {
log.warn(message, throwable);
}
}
}
}
}
}
在使用时,只需在Spring的配置文件中,配置要记录的方法即可。
例如,记录所有Dao层的方法执行情况的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<!-- 方法运行情况日志记录器 -->
<bean id="log" class="com.zhangsx.util.log.OperationLog">
<!-- 方法运行时间高于500毫秒定义为慢速 -->
<property name="slowExecutionTime" value="500" />
</bean>
<!-- 记录DAO方法的执行 -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*Dao" />
<property name="interceptorNames">
<list>
<value>log</value>
</list>
</property>
</bean>
</beans>
分享到:
相关推荐
日志记录器日志记录器日志记录器日志记录器日志记录器
离线串口日志记录器可以用于 UART 数据的离线记录,将 UART 数据线上发送的内容存 储于 SD 卡中, 为开发调试与产品测试带来极大方便。 AFU-XSP-0001 离线串口日志记录器是 AFUIOT 安服优物联网开放平台的智能工具,...
一具优秀的且免费的日志记录库,用起来简单,不像log4net还要到处各种设置,虽然功能强大,但是很多时候并根本不需要.当然如果需要玩复杂的请忽略
G3log - 异步日志记录器
工厂方法设计模式,某系统日志记录器要求支持多种日志记录方式,如文件日志记录和到数据库日志记录等,且用户在应用场景下可以根据要求动态选择日志记录方式,现使用工厂方法设计模式设计该系统。
基于express的访问日志记录器
这段代码实现了一个简单的日志记录器LoggerUtil,其中使用了Java的反射机制。在类的构造方法中,创建了一个Logger对象来记录日志信息。然后定义了两个静态方法logInfo()和logError(),分别用于记录不同级别的日志。...
使用python写的使用但里模式创建的一个日志记录器,具体相关知识可以参阅我的博客。
PHP实现工厂模式设计日志记录器,客户可通过修改配置文件灵活地改变日志记录方式
在代理方法中的在原有方法的前后新增日志记录,动态代理采用装饰器模式实现通常称为AOP,AOP方面的内容请参阅: https://msdn.microsoft.com/zh-cn/library/dn574804.aspx 。以上是对已经存在的类的方法进行日志记录...
记录上网时间与掉线时间的工具_绿色上网 断网记录器 ping 掉线时间 运维人员福星;
这段代码实现了一个简单的日志记录器Logger,其中使用了Java的单例模式。在类的构造方法中,首先定义了一个静态变量instance,用于保存Logger的唯一实例。然后定义了一个静态锁对象lock,用于保证线程安全。接着定义...
golang简单的日志记录器。日志可输出到控制台,文件或ElasticSearch。简单,易于使用
_配电线路故障指示器日志记录_配电线路故障指示器日志记录_配电线路故障指示器日志记录_配电线路故障指示器日志记录
说 明: 基于线程安全和文件缓存的单例多线程同步日志记录接口,本接口由一个 *) (* Delphi版本的动态链接库来提供相应的功能,采用Delphi的 String 类型 *) (* 传递参数,使用时请注意调用方式与Delphi一致,不...
对于我们做android开发的人来说,有很多时候需要捕获程序在真机上运行的异常记录,使用这个软件,你会很方便的追踪程序的运行日志。
拦截器记录日志
lumberjack - 简单的滚动日志记录器,实现 io.WriteCloser
logutils - Go (Golang) 扩展标准日志记录器