/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.apache.hadoop.log;

import com.google.common.annotations.VisibleForTesting;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.hadoop.util.Timer;

/**
 * This is a class to help easily throttle log statements, so that they will
 * not be emitted more frequently than a certain rate. It is useful to help
 * prevent flooding the application logs with redundant messages.
 *
 * The instantiator specifies a minimum period at which statements should be
 * logged. When {@link #record(double...)} is called, if enough time has elapsed
 * since the last time it was called, the return value will indicate to the
 * caller that it should write to its actual log. Note that this class does not
 * write to any actual log; it only records information about how many times
 * {@code record} has been called and with what arguments, and indicates to the
 * caller whether or not it should write to its log. If not enough time has yet
 * elapsed, this class records the arguments and updates its summary
 * information, and indicates to the caller that it should not log.
 *
 * For example, say that you want to know whenever too large of a request is
 * received, but want to avoid flooding the logs if many such requests are
 * received.
 * <pre>{@code
 *   // Helper with a minimum period of 5 seconds
 *   private LogThrottlingHelper helper = new LogThrottlingHelper(5000);
 *
 *   public void receiveRequest(int requestedObjects) {
 *     if (requestedObjects > MAXIMUM_REQUEST_SIZE) {
 *       LogAction logAction = helper.record(requestedObjects);
 *       if (logAction.shouldLog()) {
 *         LOG.warn("Received {} large request(s) with a total of {} objects " +
 *             "requested; maximum objects requested was {}",
 *             logAction.getCount(), logAction.getStats(0).getSum(),
 *             logAction.getStats(0).getMax());
 *       }
 *     }
 *   }
 * }</pre>
 * The above snippet allows you to record extraneous events, but if they become
 * frequent, to limit their presence in the log to only every 5 seconds while
 * still maintaining overall information about how many large requests were
 * received.
 *
 * <p/>This class can also be used to coordinate multiple logging points; see
 * {@link #record(String, long, double...)} for more details.
 *
 * <p/>This class is not thread-safe.
 */
public class LogThrottlingHelper {

  /**
   * An indication of what action the caller should take. If
   * {@link #shouldLog()} is false, no other action should be taken, and it is
   * an error to try to access any of the summary information. If
   * {@link #shouldLog()} is true, then the caller should write to its log, and
   * can use the {@link #getCount()} and {@link #getStats(int)} methods to
   * determine summary information about what has been recorded into this
   * helper.
   *
   * All summary information in this action only represents
   * {@link #record(double...)} statements which were called <i>after</i> the
   * last time the caller logged something; that is, since the last time a log
   * action was returned with a true value for {@link #shouldLog()}. Information
   * about the {@link #record(double...)} statement which created this log
   * action is included.
   */
  public interface LogAction {

    /**
     * Return the number of records encapsulated in this action; that is, the
     * number of times {@code record} was called to produce this action,
     * including the current one.
     */
    int getCount();

    /**
     * Return summary information for the value that was recorded at index
     * {@code idx}. Corresponds to the ordering of values passed to
     * {@link #record(double...)}.
     */
    SummaryStatistics getStats(int idx);

    /**
     * If this is true, the caller should write to its log. Otherwise, the
     * caller should take no action, and it is an error to call other methods
     * on this object.
     */
    boolean shouldLog();

  }

  /**
   * A {@link LogAction} representing a state that should not yet be logged.
   * If any attempt is made to extract information from this, it will throw
   * an {@link IllegalStateException}.
   */
  public static final LogAction DO_NOT_LOG = new NoLogAction();
  private static final String DEFAULT_RECORDER_NAME =
      "__DEFAULT_RECORDER_NAME__";

  /**
   * This throttler will not trigger log statements more frequently than this
   * period.
   */
  private final long minLogPeriodMs;
  /**
   * The name of the recorder treated as the primary; this is the only one which
   * will trigger logging. Other recorders are dependent on the state of this
   * recorder. This may be null, in which case a primary has not yet been set.
   */
  private String primaryRecorderName;
  private final Timer timer;
  private final Map<String, LoggingAction> currentLogs;

  private long lastLogTimestampMs = Long.MIN_VALUE;

  /**
   * Create a log helper without any primary recorder.
   *
   * @see #LogThrottlingHelper(long, String)
   */
  public LogThrottlingHelper(long minLogPeriodMs) {
    this(minLogPeriodMs, null);
  }

  /**
   * Create a log helper with a specified primary recorder name; this can be
   * used in conjunction with {@link #record(String, long, double...)} to set up
   * primary and dependent recorders. See
   * {@link #record(String, long, double...)} for more details.
   *
   * @param minLogPeriodMs The minimum period with which to log; do not log
   *                       more frequently than this.
   * @param primaryRecorderName The name of the primary recorder.
   */
  public LogThrottlingHelper(long minLogPeriodMs, String primaryRecorderName) {
    this(minLogPeriodMs, primaryRecorderName, new Timer());
  }

  @VisibleForTesting
  LogThrottlingHelper(long minLogPeriodMs, String primaryRecorderName,
      Timer timer) {
    this.minLogPeriodMs = minLogPeriodMs;
    this.primaryRecorderName = primaryRecorderName;
    this.timer = timer;
    this.currentLogs = new HashMap<>();
  }

  /**
   * Record some set of values at the current time into this helper. Note that
   * this does <i>not</i> actually write information to any log. Instead, this
   * will return a LogAction indicating whether or not the caller should write
   * to its own log. The LogAction will additionally contain summary information
   * about the values specified since the last time the caller was expected to
   * write to its log.
   *
   * <p/>Specifying multiple values will maintain separate summary statistics
   * about each value. For example:
   * <pre>{@code
   *   helper.record(1, 0);
   *   LogAction action = helper.record(3, 100);
   *   action.getStats(0); // == 2
   *   action.getStats(1); // == 50
   * }</pre>
   *
   * @param values The values about which to maintain summary information. Every
   *               time this method is called, the same number of values must
   *               be specified.
   * @return A LogAction indicating whether or not the caller should write to
   *         its log.
   */
  public LogAction record(double... values) {
    return record(DEFAULT_RECORDER_NAME, timer.monotonicNow(), values);
  }

  /**
   * Record some set of values at the specified time into this helper. This can
   * be useful to avoid fetching the current time twice if the caller has
   * already done so for other purposes. This additionally allows the caller to
   * specify a name for this recorder. When multiple names are used, one is
   * denoted as the primary recorder. Only recorders named as the primary
   * will trigger logging; other names not matching the primary can <i>only</i>
   * be triggered by following the primary. This is used to coordinate multiple
   * logging points. A primary can be set via the
   * {@link #LogThrottlingHelper(long, String)} constructor. If no primary
   * is set in the constructor, then the first recorder name used becomes the
   * primary.
   *
   * If multiple names are used, they maintain entirely different sets of values
   * and summary information. For example:
   * <pre>{@code
   *   // Initialize "pre" as the primary recorder name
   *   LogThrottlingHelper helper = new LogThrottlingHelper(1000, "pre");
   *   LogAction preLog = helper.record("pre", Time.monotonicNow());
   *   if (preLog.shouldLog()) {
   *     // ...
   *   }
   *   double eventsProcessed = ... // perform some action
   *   LogAction postLog =
   *       helper.record("post", Time.monotonicNow(), eventsProcessed);
   *   if (postLog.shouldLog()) {
   *     // ...
   *     // Can use postLog.getStats(0) to access eventsProcessed information
   *   }
   * }</pre>
   * Since "pre" is the primary recorder name, logging to "pre" will trigger a
   * log action if enough time has elapsed. This will indicate that "post"
   * should log as well. This ensures that "post" is always logged in the same
   * iteration as "pre", yet each one is able to maintain its own summary
   * information.
   *
   * <p/>Other behavior is the same as {@link #record(double...)}.
   *
   * @param recorderName The name of the recorder. This is used to check if the
   *                     current recorder is the primary. Other names are
   *                     arbitrary and are only used to differentiate between
   *                     distinct recorders.
   * @param currentTimeMs The current time.
   * @param values The values to log.
   * @return The LogAction for the specified recorder.
   *
   * @see #record(double...)
   */
  public LogAction record(String recorderName, long currentTimeMs,
      double... values) {
    if (primaryRecorderName == null) {
      primaryRecorderName = recorderName;
    }
    LoggingAction currentLog = currentLogs.get(recorderName);
    if (currentLog == null || currentLog.hasLogged()) {
      currentLog = new LoggingAction(values.length);
      if (!currentLogs.containsKey(recorderName)) {
        // Always log newly created loggers
        currentLog.setShouldLog();
      }
      currentLogs.put(recorderName, currentLog);
    }
    currentLog.recordValues(values);
    if (primaryRecorderName.equals(recorderName) &&
        currentTimeMs - minLogPeriodMs >= lastLogTimestampMs) {
      lastLogTimestampMs = currentTimeMs;
      for (LoggingAction log : currentLogs.values()) {
        log.setShouldLog();
      }
    }
    if (currentLog.shouldLog()) {
      currentLog.setHasLogged();
      return currentLog;
    } else {
      return DO_NOT_LOG;
    }
  }

  /**
   * Helper function to create a message about how many log statements were
   * suppressed in the provided log action. If no statements were suppressed,
   * this returns an empty string. The message has the format (without quotes):
   *
   * <p/>' (suppressed logging <i>{suppression_count}</i> times)'
   *
   * @param action The log action to produce a message about.
   * @return A message about suppression within this action.
   */
  public static String getLogSupressionMessage(LogAction action) {
    if (action.getCount() > 1) {
      return " (suppressed logging " + (action.getCount() - 1) + " times)";
    } else {
      return "";
    }
  }

  /**
   * A standard log action which keeps track of all of the values which have
   * been logged. This is also used for internal bookkeeping via its private
   * fields and methods; it will maintain whether or not it is ready to be
   * logged ({@link #shouldLog()}) as well as whether or not it has been
   * returned for logging yet ({@link #hasLogged()}).
   */
  private static class LoggingAction implements LogAction {

    private int count = 0;
    private final SummaryStatistics[] stats;
    private boolean shouldLog = false;
    private boolean hasLogged = false;

    LoggingAction(int valueCount) {
      stats = new SummaryStatistics[valueCount];
      for (int i = 0; i < stats.length; i++) {
        stats[i] = new SummaryStatistics();
      }
    }

    public int getCount() {
      return count;
    }

    public SummaryStatistics getStats(int idx) {
      if (idx < 0 || idx >= stats.length) {
        throw new IllegalArgumentException("Requested stats at idx " + idx +
            " but this log only maintains " + stats.length + " stats");
      }
      return stats[idx];
    }

    public boolean shouldLog() {
      return shouldLog;
    }

    private void setShouldLog() {
      shouldLog = true;
    }

    private boolean hasLogged() {
      return hasLogged;
    }

    private void setHasLogged() {
      hasLogged = true;
    }

    private void recordValues(double... values) {
      if (values.length != stats.length) {
        throw new IllegalArgumentException("received " + values.length +
            " values but expected " + stats.length);
      }
      count++;
      for (int i = 0; i < values.length; i++) {
        stats[i].addValue(values[i]);
      }
    }

  }

  /**
   * A non-logging action.
   *
   * @see #DO_NOT_LOG
   */
  private static class NoLogAction implements LogAction {

    public int getCount() {
      throw new IllegalStateException("Cannot be logged yet!");
    }

    public SummaryStatistics getStats(int idx) {
      throw new IllegalStateException("Cannot be logged yet!");
    }

    public boolean shouldLog() {
      return false;
    }

  }

}
