package nl.astraeus.jdbc; import nl.astraeus.jdbc.util.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; /** * User: riennentjes * Date: Jul 12, 2008 * Time: 9:15:21 AM */ public class JdbcLogger { private final static Logger logger = LoggerFactory.getLogger(JdbcLogger.class); private final static JdbcLogger instance = new JdbcLogger(); public static JdbcLogger get() { return instance; } public final static class LogEntry { private long threadId; private QueryType type; private String sql; private long timeStamp; private long milli; private long nano; private int hash; private int count; private boolean autoCommit; private StackTraceElement[] stackTrace = null; public LogEntry(int hash, QueryType type, String sql, long milli, long nano, boolean isAutoCommit) { this.threadId = Thread.currentThread().getId(); this.timeStamp = System.currentTimeMillis(); this.hash = hash; this.type = type; this.sql = sql; this.milli = milli; this.nano = nano; this.autoCommit = isAutoCommit; this.count = 1; } public LogEntry(LogEntry le) { this.timeStamp = System.currentTimeMillis(); this.hash = le.hash; this.type = le.type; this.sql = le .sql; this.milli = le.milli; this.nano = le.nano; this.count = le.count; this.autoCommit = le.autoCommit; } public QueryType getType() { return type; } public long getThreadId() { return threadId; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public int getHash() { return hash; } public long getTimestamp() { return timeStamp; } public String getFormattedTimestamp() { return Util.formatTimestamp(timeStamp); } public long getMilli() { return milli; } public long getNano() { return nano; } public String getFormattedMilli() { return Util.formatNano(milli*1000000/count); } public String getFormattedNano() { return Util.formatNano(nano/count); } public String getTotal() { return Util.formatNano(nano); } public String getSql() { String tmp = sql.toLowerCase(); tmp = tmp.replaceAll("create table ", "CREATE TABLE "); tmp = tmp.replaceAll("insert into ", "INSERT INTO "); tmp = tmp.replaceAll("delete from ", "DELETE FROM "); tmp = tmp.replaceAll("select ", "SELECT "); tmp = tmp.replaceAll(" from ", " \nFROM "); tmp = tmp.replaceAll(" where ", " \nWHERE "); tmp = tmp.replaceAll(" order by ", " \nORDER BY "); tmp = tmp.replaceAll(" group by ", " \nGROUP BY "); tmp = tmp.replaceAll(" having ", " \nHAVING "); tmp = tmp.replaceAll("update ", "UPDATE "); tmp = tmp.replaceAll(" set ", " \nSET "); return tmp; } public void addCount(LogEntry le) { count++; this.milli += le.getMilli(); this.nano += le.getNano(); this.timeStamp = 0; } public boolean hasStackTrace() { return stackTrace != null; } public void setStackTrace(StackTraceElement[] stackTrace) { this.stackTrace = stackTrace; } public StackTraceElement[] getStackTrace() { return stackTrace; } public boolean isAutoCommit() { return autoCommit; } } private final List<LogEntry> queries; private long startTime; private int cacheSize; private boolean recording = false; public JdbcLogger() { queries = new LinkedList<LogEntry>(); startTime = System.currentTimeMillis(); cacheSize = 2500; } public boolean isRecording() { return recording; } public void switchRecording() { recording = !recording; } public void clear() { queries.clear(); } public int getCacheSize() { return cacheSize; } public void setCacheSize(int cacheSize) { this.cacheSize = cacheSize; } public void logEntry(QueryType type, String sql, long milli, long nano, boolean isAutoCommit) { int hash = sql.hashCode(); LogEntry entry = new LogEntry(hash, type, sql, milli, nano, isAutoCommit); if (recording) { try { throw new IllegalStateException(); } catch (IllegalStateException e) { entry.setStackTrace(e.getStackTrace()); } } synchronized (queries) { queries.add(entry); while (queries.size() > cacheSize) { entry = queries.remove(0); startTime = entry.getMilli(); } } } public static void log(QueryType type, String sql, long milli, long nano, boolean isAutoCommit) { instance.logEntry(type, sql, milli, nano, isAutoCommit); } public List<LogEntry> getEntries() { synchronized (queries) { return new LinkedList<LogEntry>(queries); } } }