Spring AOP监控SQL执行

对数据库连接池Proxool比较熟悉的读者,都知道Proxool可以记录SQL执行内容和时间等信息日志。我们可以将该日志记录专门的SQL日志文件,对于查找执行特别耗时的SQL起了不小的作用。对于一些其他连接池,没有该特性时,本文介绍Spring AOP切面方法来记录SQL日志。

当然也可以通过数据库提供的特性来查询执行效率较低的SQL,本文不做探讨。

本文介绍使用SpringJdbcTemplate执行SQL,使用其他方法或者ORM思路类似(Hibernate提供了日志记录功能)。

使用AOP,可以使用Around通知,在JdbcTemplate执行方法前,记录当前时间,在方法执行完后,计算SQL耗时,并记录日志。思路很简单,不过多介绍,代码如下。

package org.enyes.sql.util;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

/**
 * 对Spring JdbcTemplate进行切面,记录每个sql执行时间。
 */
@Aspect
public class SqlExecutionTimeAspect {
	/**
	 * logger
	 */
	private static final Logger LOG = Logger
			.getLogger(SqlExecutionTimeAspect.class);

	/**
	 * 当Sql执行时间超过该值时,则进行log warn级别题型,否则记录INFO日志。
	 */
	private long warnWhenOverTime = 2 * 60 * 1000L;

	@Around("execution(* org.springframework.jdbc.core.JdbcTemplate.*(..))")
	public Object logSqlExecutionTime(ProceedingJoinPoint joinPoint)
			throws Throwable {
		long startTime = System.currentTimeMillis();
		Object result = joinPoint.proceed();
		long costTime = System.currentTimeMillis() - startTime;
		if (costTime > warnWhenOverTime) {
			StringBuilder sb = new StringBuilder();
			sb.append("execute method :").append(joinPoint.getSignature());
			sb.append("args: ").append(arrayToString(joinPoint.getArgs()));
			sb.append(" cost time[").append(costTime).append("]ms");
			LOG.warn(sb);
		} else if (LOG.isInfoEnabled()) {
			StringBuilder sb = new StringBuilder();
			sb.append("execute method :").append(joinPoint.getSignature());
			sb.append("args: ").append(arrayToString(joinPoint.getArgs()));
			sb.append(" cost time[").append(costTime).append("]ms");
			LOG.info(sb);
		}
		return result;
	}

	private static String arrayToString(Object[] a) {
		if (a == null)
			return "null";

		int iMax = a.length - 1;
		if (iMax == -1)
			return "[]";

		StringBuilder b = new StringBuilder();
		b.append('[');
		for (int i = 0;; i++) {
			if (a[i] instanceof Object[]) {
				b.append(arrayToString((Object[]) a[i]));
			} else {
				b.append(String.valueOf(a[i]));
			}
			if (i == iMax)
				return b.append(']').toString();
			b.append(", ");
		}
	}
}

Springxml配置如下:

<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
     http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
     http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    http://www.springframework.org/schema/task
    http://www.springframework.org/schema/task/spring-task-3.1.xsd
">
<beans>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean class="org.enyes.sql.util.SqlExecutionTimeAspect"/>
</beans>

可以使用Log4J将SqlExecutionTimeAspect类的日志打印到专门的日志中,并且warnWhenOverTime提供setter方法,可以通过Spring xml来具体配置。

完毕。

时间: 2024-10-14 21:10:14

Spring AOP监控SQL执行的相关文章

监控sql执行时剩余时间

--监控sql执行时剩余时间 你知道正在运行的sql大概需要多长时间么? 你知道正在运行的sql大概完成了百分之几么? 你知道正在运行的sql大概还要多长时间完成么? V$SESSION_LONGOPS帮你忙. V$SESSION_LONGOPS在<span style="font-family: Arial, Helvetica, sans-serif;">官方文档中的描述:</span> V$SESSION_LONGOPS displays the stat

监控sql运行时剩余时间

--监控sql执行时剩余时间 你知道正在执行的sql大概须要多长时间么? 你知道正在执行的sql大概完毕了百分之几么? 你知道正在执行的sql大概还要多长时间完毕么? V$SESSION_LONGOPS帮你忙. V$SESSION_LONGOPS在<span style="font-family: Arial, Helvetica, sans-serif;">官方文档中的描写叙述:</span> V$SESSION_LONGOPS displays the st

应用Druid监控SQL语句的执行情况(转)

Druid是什么? Druid首先是一个数据库连接池.Druid是目前最好的数据库连接池,在功能.性能.扩展性方面,都超过其他数据库连接池,包括DBCP.C3P0.BoneCP.Proxool.JBoss DataSource. Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验. 同时Druid不仅仅是一个数据库连接池,它包括四个部分:Druid是一个JDBC组件,它包括三个部分: 基于Filter-Chain模式的插件体系. DruidDataSource

应用Druid监控SQL语句的执行情况

Druid是什么? Druid首先是一个数据库连接池.Druid是目前最好的数据库连接池,在功能.性能.扩展性方面,都超过其他数据库连接池,包括DBCP.C3P0.BoneCP.Proxool.JBoss DataSource. Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验. 同时Druid不仅仅是一个数据库连接池,它包括四个部分:Druid是一个JDBC组件,它包括三个部分: 基于Filter-Chain模式的插件体系. DruidDataSource

SQL监控:mysql及mssql数据库SQL执行过程监控审计

最近生活有很大的一个变动,所以博客也搁置了很长一段时间没写,好像写博客已经成了习惯,搁置一段时间就有那么点危机感,心里总觉得不自在.所以从今天起还是要继续拾起墨笔(键盘),继续好好维护这个博客,写出心里最真实的想法,写出平时接触到的一些人和事以及一些新的技术.当然写博客也不是单纯的为了记录,也想通过博客来结交更多的朋友,今天在公司图书馆看到一句话大致说的是“在今天这个年代,已经很难等到三顾茅庐,诸葛亮也需要博客.微博和影响力”,在一年前就曾想过写一篇关于怎样通过博客来提高个人影响力的文章,我会尽

监控mysql执行的sql语句

linux平台 为了做好配合开发做性能和功能测试,方便监控正在执行的sql语句,可以在/etc/mysqld中添加如下: log =/usr/local/mysql/var21005/mysql.log 就可以使用: tail -f mysql.log 来监控了  www.xxx.com 如果需要监控慢查询可以添加如下内容: log-slow-queries = /usr/local/mysql/var21005/slowquery.log long_query_time = 1 windows

设置 sqlserver Profiler 只监控 EF的sql执行请求

当我们用EF执行语句的时候,可以使用 sqlserver Profiler来监控到底执行了哪些sql语句,但是默认他是监控全局的,我们只想监控Ef的语句,这里如下设置 这样就只会监控 EF产生的 sql语句了 设置 sqlserver Profiler 只监控 EF的sql执行请求

基于Spring aop写的一个简单的耗时监控

前言:毕业后应该有一两年没有好好的更新博客了,回头看看自己这一年,似乎少了太多的沉淀了.让自己做一个爱分享的人,好的知识点拿出来和大家一起分享,一起学习. 背景: 在做项目的时候,大家肯定都遇到对一些对方法,模块耗时的监控,为了方便性能的监控,问题的定位等.如果每一个方法里都加上 ... Stopwatch watch = Stopwatch.createStarted(); ... watch.elapsed(TimeUnit.MILLISECONDS) ... 类似的代码肯定没问题,但是就会

浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring框架的,这就说明你有权选择是否要用AOP来完成一些业务. AOP面向切面编程,通过另一种思考的方式,来弥补面向对象编程OOP当中的不足,OOP当中最重要的单元是类,所以万物皆对象,万物皆是 对象类.而在AOP的模块单元中,最基础的单元是切面,切面对切点进行模块化的管理. 最后再提一句:Spring当