// Path: src/main/java/com/statful/sender/Sender.java
// public interface Sender {
//     /**
//      * Sender method that gets a list of datapoints and sends them
//      *
//      * @param metrics     metrics to be sent. Each instance is responsible for creating the full metric line including tags
//      * @param sentHandler handler called if you want to be notified after the metrics are sent.
//      */
//     void send(@Nonnull List<DataPoint> metrics, @Nonnull Handler<AsyncResult<Void>> sentHandler);
// 
//     /**
//      * Sender method that gets a list of datapoints and sends them
//      *
//      * @param metrics metrics to be sent. Each instance is responsible for creating the full metric line including tags
//      */
//     void send(@Nonnull List<DataPoint> metrics);
// 
//     /**
//      * Stores metric in a buffer to be sent
//      *
//      * @param dataPoint metric to be stored
//      * @return true if the metric was inserted false otherwise
//      */
//     boolean addMetric(final DataPoint dataPoint);
// 
//     /**
//      * Closes the sender
//      *
//      * @param handler to execute when closed
//      */
//     void close(final Handler<AsyncResult<Void>> handler);
// }
// 
// Path: src/main/java/com/statful/sender/SenderFactory.java
// public final class SenderFactory {
// 
//     private static final Logger LOGGER = LoggerFactory.getLogger(SenderFactory.class);
// 
//     /**
//      * @param vertx Vertx instance to create the senders
//      * @param options statful options to configure the sender
//      * @return correct client instance for the configuration provided
//      */
//     @Nonnull
//     public Sender create(final Vertx vertx, @Nonnull final StatfulMetricsOptions options) {
//         Objects.requireNonNull(options);
// 
//         Transport transport = options.getTransport();
//         if (Transport.UDP.equals(transport)) {
//             LOGGER.info("creating udp sender");
//             return new UDPSender(vertx, options);
//         } else if (Transport.HTTP.equals(transport)) {
//             LOGGER.info("creating http sender");
//             return new HttpSender(vertx, options);
//         }
//         throw new UnsupportedOperationException("currently only UDP and HTTP are supported. Requested: " + options.getTransport());
//     }
// }


import com.statful.collector.*;
import com.statful.sender.Sender;
import com.statful.sender.SenderFactory;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.net.SocketAddress;
import io.vertx.core.spi.metrics.HttpClientMetrics;
import io.vertx.core.spi.metrics.HttpServerMetrics;
import io.vertx.core.spi.metrics.PoolMetrics;
import io.vertx.core.spi.metrics.VertxMetrics;
import java.util.concurrent.LinkedBlockingQueue;
        }
        return httpClientMetrics;
    }

    /**
     * We lazy load the pool metrics sender because it needs a vertx instance, and it is called before it is created because
     * of vertx's own thread pool instantiated on creation.
     */
    @Override
    public PoolMetrics<?> createPoolMetrics(final String poolType, final String poolName, final int maxPoolSize) {
        PoolMetricsImpl poolMetrics = null;
        if (statfulMetricsOptions.isEnablePoolMetrics()) {
            poolMetrics = new PoolMetricsImpl(statfulMetricsOptions, poolType, poolName, maxPoolSize);
            collectors.add(poolMetrics);
        }
        return poolMetrics;
    }

    @Override
    public void vertxCreated(final Vertx createdVertx) {
        this.vertx = createdVertx;
        this.customMetricsConsumer = new CustomMetricsConsumer(createdVertx.eventBus(), this.getOrCreateSender(createdVertx), statfulMetricsOptions);
        this.collectors.forEach(collector -> {
            collector.setVertx(createdVertx);
            collector.setSender(this.getOrCreateSender(createdVertx));
        });
    }

    private Sender getOrCreateSender(final Vertx senderVertx) {
        if (this.sender == null) {
// Path: src/main/java/com/statful/sender/Sender.java
// public interface Sender {
//     /**
//      * Sender method that gets a list of datapoints and sends them
//      *
//      * @param metrics     metrics to be sent. Each instance is responsible for creating the full metric line including tags
//      * @param sentHandler handler called if you want to be notified after the metrics are sent.
//      */
//     void send(@Nonnull List<DataPoint> metrics, @Nonnull Handler<AsyncResult<Void>> sentHandler);
// 
//     /**
//      * Sender method that gets a list of datapoints and sends them
//      *
//      * @param metrics metrics to be sent. Each instance is responsible for creating the full metric line including tags
//      */
//     void send(@Nonnull List<DataPoint> metrics);
// 
//     /**
//      * Stores metric in a buffer to be sent
//      *
//      * @param dataPoint metric to be stored
//      * @return true if the metric was inserted false otherwise
//      */
//     boolean addMetric(final DataPoint dataPoint);
// 
//     /**
//      * Closes the sender
//      *
//      * @param handler to execute when closed
//      */
//     void close(final Handler<AsyncResult<Void>> handler);
// }
// 
// Path: src/main/java/com/statful/sender/SenderFactory.java
// public final class SenderFactory {
// 
//     private static final Logger LOGGER = LoggerFactory.getLogger(SenderFactory.class);
// 
//     /**
//      * @param vertx Vertx instance to create the senders
//      * @param options statful options to configure the sender
//      * @return correct client instance for the configuration provided
//      */
//     @Nonnull
//     public Sender create(final Vertx vertx, @Nonnull final StatfulMetricsOptions options) {
//         Objects.requireNonNull(options);
// 
//         Transport transport = options.getTransport();
//         if (Transport.UDP.equals(transport)) {
//             LOGGER.info("creating udp sender");
//             return new UDPSender(vertx, options);
//         } else if (Transport.HTTP.equals(transport)) {
//             LOGGER.info("creating http sender");
//             return new HttpSender(vertx, options);
//         }
//         throw new UnsupportedOperationException("currently only UDP and HTTP are supported. Requested: " + options.getTransport());
//     }
// }


// Path: src/main/java/com/statful/client/VertxMetricsImpl.java
import com.statful.collector.*;
import com.statful.sender.Sender;
import com.statful.sender.SenderFactory;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.net.SocketAddress;
import io.vertx.core.spi.metrics.HttpClientMetrics;
import io.vertx.core.spi.metrics.HttpServerMetrics;
import io.vertx.core.spi.metrics.PoolMetrics;
import io.vertx.core.spi.metrics.VertxMetrics;
import java.util.concurrent.LinkedBlockingQueue;

        }
        return httpClientMetrics;
    }

    /**
     * We lazy load the pool metrics sender because it needs a vertx instance, and it is called before it is created because
     * of vertx's own thread pool instantiated on creation.
     */
    @Override
    public PoolMetrics<?> createPoolMetrics(final String poolType, final String poolName, final int maxPoolSize) {
        PoolMetricsImpl poolMetrics = null;
        if (statfulMetricsOptions.isEnablePoolMetrics()) {
            poolMetrics = new PoolMetricsImpl(statfulMetricsOptions, poolType, poolName, maxPoolSize);
            collectors.add(poolMetrics);
        }
        return poolMetrics;
    }

    @Override
    public void vertxCreated(final Vertx createdVertx) {
        this.vertx = createdVertx;
        this.customMetricsConsumer = new CustomMetricsConsumer(createdVertx.eventBus(), this.getOrCreateSender(createdVertx), statfulMetricsOptions);
        this.collectors.forEach(collector -> {
            collector.setVertx(createdVertx);
            collector.setSender(this.getOrCreateSender(createdVertx));
        });
    }

    private Sender getOrCreateSender(final Vertx senderVertx) {
        if (this.sender == null) {
            this.sender = new SenderFactory().create(senderVertx, statfulMetricsOptions);