/* 
 * Copyright 1999,2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;

/**
 * 
 * The <code>BurstFilter</code> is a logging filter that regulates logging
 * traffic. Use this filter when you want to control the maximum burst of log
 * statements that can be sent to an appender. The filter is configured in the
 * log4j configuration file. For example, the following configuration limits the
 * number of log statements that can be sent to the console to a burst of 100
 * and allows a maximum of 10 log statements to be sent to the appender every 6
 * seconds after that burst.<br>
 * <br>
 * 
 * <code>
 * &lt;appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender"&gt;<br>
 *  &nbsp;&lt;layout class="org.apache.log4j.PatternLayout"&gt;<br>
 * 		&nbsp;&nbsp;&lt;param name="ConversionPattern" value="%-5p %d{dd-MMM-yyyy HH:mm:ss} %x %t %m%n"/&gt;<br>
 * 	&nbsp;&lt;/layout&gt;<br>
 * 	&nbsp;&lt;filter class="BurstFilter"&gt;<br>
 * 		&nbsp;&nbsp;&lt;param name="burstRecoveryAmount" value="10"/&gt;<br>
 * 		&nbsp;&nbsp;&lt;param name="burstRecoveryInterval" value="6"/&gt;<br>
 * 		&nbsp;&nbsp;&lt;param name="maxBurst" value="100"/&gt;<br>
 * 	&nbsp;&lt;/filter&gt;<br>
 * &lt;/appender&gt;<br>
 * </code><br>
 * 
 * @author Chad LaVigne
 * 
 */
public class BurstFilter extends Filter {
  /**
   * Number of log statments to allow following a traffic burst of more than
   * <code>maxBurst</code>. This many statements is added to the total number
   * allowed every <code>burstRecoveryInterval</code> seconds.
   */
  private long burstRecoveryAmount;

  /**
   * Interval, in seconds, at which to add to the number of log statements that
   * will be allowed following a burst. This value specifies how often
   * <code>burstRecoverAmount</code> statements will be added to the total
   * number allowed for every <code>burstRecoveryInterval</code> that passes
   * following a burst, up to but not exceeding <code>maxBurst</code>.
   */
  private long burstRecoveryInterval;

  /**
   * This value dictates the maximum traffic burst that can be logged to any
   * appender that uses the <code>BurstFilter</code>, i.e. there can never be
   * more than <code>maxBurst</code> log statements sent to an appender in
   * <code>burstRecoveryInterval</code> seconds.
   */
  private long maxBurst;

  private TokenBucket tokenBucket;

  public int decide(LoggingEvent event) {
    // initialize tokenBucket here because the burstRecoveryAmount,
    // burstRecoveryInterval & maxBurst attributes get set
    // via log4J configuration when it instantiates the filter
    if (tokenBucket == null) {
      tokenBucket = new TokenBucket(burstRecoveryAmount, burstRecoveryInterval,
          maxBurst);
    }

    return tokenBucket.getToken() ? Filter.DENY : Filter.NEUTRAL;
  }

  public long getMaxBurst() {
    return maxBurst;
  }

  public void setMaxBurst(long maxTokens) {
    this.maxBurst = maxTokens;
  }

  public long getBurstRecoveryInterval() {
    return burstRecoveryInterval;
  }

  public void setBurstRecoveryInterval(long tokenFillInterval) {
    this.burstRecoveryInterval = tokenFillInterval;
  }

  public long getBurstRecoveryAmount() {
    return burstRecoveryAmount;
  }

  public void setBurstRecoveryAmount(long tokenFillRate) {
    this.burstRecoveryAmount = tokenFillRate;
  }
}