// Path: api/src/main/java/com/vlkan/hrrs/api/HttpRequestRecord.java
// public interface HttpRequestRecord {
// 
//     String getId();
// 
//     Date getTimestamp();
// 
//     String getGroupName();
// 
//     String getUri();
// 
//     HttpRequestMethod getMethod();
// 
//     List<HttpRequestHeader> getHeaders();
// 
//     HttpRequestPayload getPayload();
// 
//     Builder toBuilder();
// 
//     interface Builder {
// 
//         Builder setId(String id);
// 
//         Builder setTimestamp(Date timestamp);
// 
//         Builder setGroupName(String groupName);
// 
//         Builder setUri(String uri);
// 
//         Builder setMethod(HttpRequestMethod method);
// 
//         Builder setHeaders(List<HttpRequestHeader> headers);
// 
//         Builder setPayload(HttpRequestPayload payload);
// 
//         HttpRequestRecord build();
// 
//     }
// 
// }
// 
// Path: commons/src/main/java/com/vlkan/hrrs/commons/logger/LoggerLevelAccessor.java
// public interface LoggerLevelAccessor {
// 
//     String getRootLevel();
// 
//     void setRootLevel(String levelName);
// 
//     String getLevel(String loggerName);
// 
//     void setLevel(String loggerName, String levelName);
// 
// }
// 
// Path: commons/src/main/java/com/vlkan/hrrs/commons/logger/LoggerLevels.java
// public enum LoggerLevels {;
// 
//     public static void applyLoggerLevelSpecs(String loggerLevelSpecs, LoggerLevelAccessor loggerLevelAccessor) {
//         if (loggerLevelSpecs != null) {
//             for (String loggerNameAndLoggerLevel : loggerLevelSpecs.split(",")) {
//                 String[] fields = loggerNameAndLoggerLevel.split("=", 2);
//                 String loggerName = fields[0];
//                 String loggerLevel = fields[1];
//                 if ("*".equals(loggerName)) {
//                     loggerLevelAccessor.setRootLevel(loggerLevel);
//                 } else {
//                     loggerLevelAccessor.setLevel(loggerName, loggerLevel);
//                 }
//             }
//         }
//     }
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/executor/CloseableExecutor.java
// public interface CloseableExecutor extends Closeable, Executor {
// 
//     // Do nothing.
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/http/HttpRequestRecordReplayer.java
// public interface HttpRequestRecordReplayer extends Closeable {
// 
//     void replay(HttpRequestRecord record);
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/metric/MetricReporter.java
// public interface MetricReporter extends Closeable {
// 
//     void start();
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/record/HttpRequestRecordStream.java
// public interface HttpRequestRecordStream {
// 
//     void consumeWhile(URI inputUri, boolean replayOnce, Callable<Boolean> predicate, HttpRequestRecordStreamConsumer consumer);
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/record/HttpRequestRecordStreamConsumer.java
// public interface HttpRequestRecordStreamConsumer {
// 
//     void consume(HttpRequestRecord record);
// 
// }


import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.MetricRegistry;
import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.RateLimiter;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.vlkan.hrrs.api.HttpRequestRecord;
import com.vlkan.hrrs.commons.logger.LoggerLevelAccessor;
import com.vlkan.hrrs.commons.logger.LoggerLevels;
import com.vlkan.hrrs.replayer.executor.CloseableExecutor;
import com.vlkan.hrrs.replayer.http.HttpRequestRecordReplayer;
import com.vlkan.hrrs.replayer.metric.MetricReporter;
import com.vlkan.hrrs.replayer.record.HttpRequestRecordStream;
import com.vlkan.hrrs.replayer.record.HttpRequestRecordStreamConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import static com.google.common.base.Preconditions.checkNotNull;
package com.vlkan.hrrs.replayer.cli;




@Singleton
public class Replayer implements Runnable, Closeable, HttpRequestRecordStreamConsumer {

    private static final Logger LOGGER = LoggerFactory.getLogger(Replayer.class);

    private final Config config;

    private final CloseableExecutor closeableExecutor;

    private final HttpRequestRecordStream recordStream;

    private final HttpRequestRecordReplayer recordReplayer;

    private final MetricRegistry metricRegistry;

    private final MetricReporter metricReporter;

    private volatile boolean closed = false;

    @Inject
    public Replayer(
            Config config,
            CloseableExecutor closeableExecutor,
            HttpRequestRecordStream recordStream,
            HttpRequestRecordReplayer recordReplayer,
            MetricRegistry metricRegistry,
            MetricReporter metricReporter) {

        // Check arguments.
        checkNotNull(config, "config");
        checkNotNull(closeableExecutor, "closeableExecutor");
        checkNotNull(recordStream, "recordStream");
        checkNotNull(recordReplayer, "recordReplayer");
        checkNotNull(metricRegistry, "metricRegistry");
        checkNotNull(metricReporter, "metricReporter");

        // Set class fields.
        this.config = config;
        this.closeableExecutor = closeableExecutor;
        this.recordStream = recordStream;
// Path: api/src/main/java/com/vlkan/hrrs/api/HttpRequestRecord.java
// public interface HttpRequestRecord {
// 
//     String getId();
// 
//     Date getTimestamp();
// 
//     String getGroupName();
// 
//     String getUri();
// 
//     HttpRequestMethod getMethod();
// 
//     List<HttpRequestHeader> getHeaders();
// 
//     HttpRequestPayload getPayload();
// 
//     Builder toBuilder();
// 
//     interface Builder {
// 
//         Builder setId(String id);
// 
//         Builder setTimestamp(Date timestamp);
// 
//         Builder setGroupName(String groupName);
// 
//         Builder setUri(String uri);
// 
//         Builder setMethod(HttpRequestMethod method);
// 
//         Builder setHeaders(List<HttpRequestHeader> headers);
// 
//         Builder setPayload(HttpRequestPayload payload);
// 
//         HttpRequestRecord build();
// 
//     }
// 
// }
// 
// Path: commons/src/main/java/com/vlkan/hrrs/commons/logger/LoggerLevelAccessor.java
// public interface LoggerLevelAccessor {
// 
//     String getRootLevel();
// 
//     void setRootLevel(String levelName);
// 
//     String getLevel(String loggerName);
// 
//     void setLevel(String loggerName, String levelName);
// 
// }
// 
// Path: commons/src/main/java/com/vlkan/hrrs/commons/logger/LoggerLevels.java
// public enum LoggerLevels {;
// 
//     public static void applyLoggerLevelSpecs(String loggerLevelSpecs, LoggerLevelAccessor loggerLevelAccessor) {
//         if (loggerLevelSpecs != null) {
//             for (String loggerNameAndLoggerLevel : loggerLevelSpecs.split(",")) {
//                 String[] fields = loggerNameAndLoggerLevel.split("=", 2);
//                 String loggerName = fields[0];
//                 String loggerLevel = fields[1];
//                 if ("*".equals(loggerName)) {
//                     loggerLevelAccessor.setRootLevel(loggerLevel);
//                 } else {
//                     loggerLevelAccessor.setLevel(loggerName, loggerLevel);
//                 }
//             }
//         }
//     }
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/executor/CloseableExecutor.java
// public interface CloseableExecutor extends Closeable, Executor {
// 
//     // Do nothing.
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/http/HttpRequestRecordReplayer.java
// public interface HttpRequestRecordReplayer extends Closeable {
// 
//     void replay(HttpRequestRecord record);
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/metric/MetricReporter.java
// public interface MetricReporter extends Closeable {
// 
//     void start();
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/record/HttpRequestRecordStream.java
// public interface HttpRequestRecordStream {
// 
//     void consumeWhile(URI inputUri, boolean replayOnce, Callable<Boolean> predicate, HttpRequestRecordStreamConsumer consumer);
// 
// }
// 
// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/record/HttpRequestRecordStreamConsumer.java
// public interface HttpRequestRecordStreamConsumer {
// 
//     void consume(HttpRequestRecord record);
// 
// }


// Path: replayer/src/main/java/com/vlkan/hrrs/replayer/cli/Replayer.java
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.MetricRegistry;
import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.RateLimiter;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.vlkan.hrrs.api.HttpRequestRecord;
import com.vlkan.hrrs.commons.logger.LoggerLevelAccessor;
import com.vlkan.hrrs.commons.logger.LoggerLevels;
import com.vlkan.hrrs.replayer.executor.CloseableExecutor;
import com.vlkan.hrrs.replayer.http.HttpRequestRecordReplayer;
import com.vlkan.hrrs.replayer.metric.MetricReporter;
import com.vlkan.hrrs.replayer.record.HttpRequestRecordStream;
import com.vlkan.hrrs.replayer.record.HttpRequestRecordStreamConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import static com.google.common.base.Preconditions.checkNotNull;

package com.vlkan.hrrs.replayer.cli;




@Singleton
public class Replayer implements Runnable, Closeable, HttpRequestRecordStreamConsumer {

    private static final Logger LOGGER = LoggerFactory.getLogger(Replayer.class);

    private final Config config;

    private final CloseableExecutor closeableExecutor;

    private final HttpRequestRecordStream recordStream;

    private final HttpRequestRecordReplayer recordReplayer;

    private final MetricRegistry metricRegistry;

    private final MetricReporter metricReporter;

    private volatile boolean closed = false;

    @Inject
    public Replayer(
            Config config,
            CloseableExecutor closeableExecutor,
            HttpRequestRecordStream recordStream,
            HttpRequestRecordReplayer recordReplayer,
            MetricRegistry metricRegistry,
            MetricReporter metricReporter) {

        // Check arguments.
        checkNotNull(config, "config");
        checkNotNull(closeableExecutor, "closeableExecutor");
        checkNotNull(recordStream, "recordStream");
        checkNotNull(recordReplayer, "recordReplayer");
        checkNotNull(metricRegistry, "metricRegistry");
        checkNotNull(metricReporter, "metricReporter");

        // Set class fields.
        this.config = config;
        this.closeableExecutor = closeableExecutor;
        this.recordStream = recordStream;
        this.recordReplayer = recordReplayer;