package uk.ac.bbsrc.tgac.miso.sqlstore; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; /** * uk.ac.bbsrc.tgac.miso.sqlstore * <p/> * Info * * @author Rob Davey * @date 08/10/12 * @since 0.1.9 */ @Aspect public class SqlProfiler { protected static final Logger log = LoggerFactory.getLogger(SqlProfiler.class); private final Map<String, SqlTiming> sqlTimings; public SqlProfiler() { sqlTimings = Collections.synchronizedMap(new HashMap<String, SqlTiming>()); } @Around("execution(* org.springframework.jdbc.core.JdbcTemplate.query(String,..))") public Object profile(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); Object obj = pjp.proceed(); long time = System.currentTimeMillis() - start; String statement = pjp.getArgs()[0].toString(); SqlTiming sqlTiming = null; synchronized (sqlTimings) { sqlTiming = sqlTimings.get(statement); if (sqlTiming == null) { sqlTiming = new SqlTiming(statement); sqlTimings.put(statement, sqlTiming); } } sqlTiming.recordTiming(time); System.out.println(pjp.getArgs()[0].toString() + " :: " + sqlTimings.get(pjp.getArgs()[0].toString()).getCumulativeExecutionTime()+"s"); return obj; } public List<SqlTiming> getTimings(final SortedBy sort) { List<SqlTiming> timings = new ArrayList<SqlTiming>(sqlTimings.values()); Collections.sort(timings, new Comparator<SqlTiming>() { public int compare(SqlTiming o1, SqlTiming o2) { switch (sort) { case AVG_EXECUTION_TIME: return Math.round(o1.getAvgExecutionTime() - o2.getAvgExecutionTime()); case CUMULATIVE_EXECUTION_TIME: long diff = o1.getCumulativeExecutionTime() - o2.getCumulativeExecutionTime(); if (diff > 0l) return 1; else if (diff == 0) return 0; else return -1; case NUMBER_OF_EXECUTIONS: return o1.getExecutionCount() - o2.getExecutionCount(); } return 0; } }); return timings; } private class SqlTiming { private final String statement; private int count; private long cumulativeMillis; SqlTiming(String statement) { this.statement = statement; } synchronized SqlTiming recordTiming(long time) { count++; cumulativeMillis += time; return this; } public String getSqlStatement() { return statement; } public int getExecutionCount() { return count; } public long getCumulativeExecutionTime() { return cumulativeMillis; } public float getAvgExecutionTime() { return (float) cumulativeMillis / (float) count; } } private enum SortedBy { AVG_EXECUTION_TIME, CUMULATIVE_EXECUTION_TIME, NUMBER_OF_EXECUTIONS } }