package com.linkedin.d2.balancer.util; import com.linkedin.util.clock.Clock; import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; /** * Simple logger wrapper to provide rate limiting of log messages. The rate is controlled by the duration, * ie how often (in millisecond) the message should be logged. After one message logged, the rest of the * messages within that duration will be ignored. */ public class RateLimitedLogger { private static final long INIT_TIME = -1; private final Logger _logger; private final long _logRate; private final Clock _clock; private final AtomicLong _lastLog = new AtomicLong(INIT_TIME); public RateLimitedLogger(Logger logger, long logRate, Clock clock) { _logger = logger; _logRate = logRate; _clock = clock; } public boolean isTraceEnabled() { return _logger.isTraceEnabled(); } public void trace(String msg) { if (logAllowed()) { _logger.trace(msg); } } public void trace(String format, Object[] argArray) { if (logAllowed()) { _logger.trace(format, argArray); } } public void trace(String msg, Throwable t) { if (logAllowed()) { _logger.trace(msg, t); } } public void trace(String format, Object obj) { if (logAllowed()) { _logger.trace(format, obj); } } public void trace(String format, Object obj1, Object obj2) { if (logAllowed()) { _logger.trace(format, obj1, obj2); } } public boolean isDebugEnabled() { return _logger.isDebugEnabled(); } public void debug(String msg) { if (logAllowed()) { _logger.debug(msg); } } public void debug(String format, Object[] argArray) { if (logAllowed()) { _logger.debug(format, argArray); } } public void debug(String msg, Throwable t) { if (logAllowed()) { _logger.debug(msg, t); } } public void debug(String format, Object obj) { if (logAllowed()) { _logger.debug(format, obj); } } public void debug(String format, Object obj1, Object obj2) { if (logAllowed()) { _logger.debug(format, obj1, obj2); } } public boolean isInfoEnabled() { return _logger.isInfoEnabled(); } public void info(String msg) { if (logAllowed()) { _logger.info(msg); } } public void info(String format, Object[] argArray) { if (logAllowed()) { _logger.info(format, argArray); } } public void info(String msg, Throwable t) { if (logAllowed()) { _logger.info(msg, t); } } public void info(String format, Object obj) { if (logAllowed()) { _logger.info(format, obj); } } public void info(String format, Object obj1, Object obj2) { if (logAllowed()) { _logger.info(format, obj1, obj2); } } public boolean isWarnEnabled() { return _logger.isWarnEnabled(); } public void warn(String msg) { if (logAllowed()) { _logger.warn(msg); } } public void warn(String format, Object[] argArray) { if (logAllowed()) { _logger.warn(format, argArray); } } public void warn(String msg, Throwable t) { if (logAllowed()) { _logger.warn(msg, t); } } public void warn(String format, Object obj) { if (logAllowed()) { _logger.warn(format, obj); } } public void warn(String format, Object obj1, Object obj2) { if (logAllowed()) { _logger.warn(format, obj1, obj2); } } public boolean isErrorEnabled() { return _logger.isErrorEnabled(); } public void error(String msg) { if (logAllowed()) { _logger.error(msg); } } public void error(String format, Object[] argArray) { if (logAllowed()) { _logger.error(format, argArray); } } public void error(String msg, Throwable t) { if (logAllowed()) { _logger.error(msg, t); } } public void error(String format, Object obj) { if (logAllowed()) { _logger.error(format, obj); } } public void error(String format, Object obj1, Object obj2) { if (logAllowed()) { _logger.error(format, obj1, obj2); } } private boolean logAllowed() { final long now = _clock.currentTimeMillis(); final long lastLog = _lastLog.get(); return (lastLog == INIT_TIME || now - lastLog >= _logRate) && _lastLog.compareAndSet(lastLog, now); } }