package net.codjo.segmentation.server.blackboard; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import net.codjo.util.time.TimeSource; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.commons.lang.mutable.MutableLong; import org.apache.log4j.Logger; /** * */ final public class DefaultErrorLogLimiter implements ErrorLogLimiter { private final Map<String, MutableLong> rootCauses = new HashMap<String, MutableLong>(); private final TimeSource timeSource; /** * Size of the time window in milliseconds. */ private final long timeWindow; private long skippedLogs; public DefaultErrorLogLimiter(TimeSource timeSource, long timeWindowValue, TimeUnit timeWindowUnit) { this.timeSource = timeSource; this.timeWindow = timeWindowUnit.toMillis(timeWindowValue); } // public void clearLogErrorCounters() { // synchronized (rootCauses) { // rootCauses.clear(); // } // } public boolean logError(SQLException e) { Throwable rootCause = ExceptionUtils.getRootCause(e); if (rootCause == null) { rootCause = e; } String key = rootCause.getClass().getName() + '#' + rootCause.getMessage(); boolean shouldLog = false; synchronized (rootCauses) { MutableLong firstOccurence = rootCauses.get(key); if (firstOccurence == null) { // this error never happened before (open a new time window) => log it firstOccurence = new MutableLong(timeSource.getTime()); rootCauses.put(key, firstOccurence); shouldLog = true; } else { if (isOldRecord(firstOccurence)) { // this occurence open a new time window => log it firstOccurence.setValue(timeSource.getTime()); shouldLog = true; } // else : this occurence is in the current time window => don't log it } if (!shouldLog) { skippedLogs++; } } return shouldLog; } public void close() { Logger.getLogger(getClass()).warn(skippedLogs + " error logs were skipped to avoid duplicates"); } private boolean isOldRecord(MutableLong firstOccurrence) { long time = timeSource.getTime(); return (firstOccurrence.longValue() + timeWindow) <= time; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("DefaultErrorLogLimiter"); sb.append("{timeWindow=").append(timeWindow).append(" ms}"); return sb.toString(); } }