// Path: src/main/java/com/statful/utils/Pair.java
// public final class Pair<L, R> {
// 
//     /**
//      * Left element of the Pair
//      */
//     private L left;
//     /**
//      * Right element of the Pair
//      */
//     private R right;
// 
//     /**
//      * Pair constructor
//      *
//      * @param left  element of the pair
//      * @param right element of the pair
//      */
//     public Pair(final L left, final R right) {
//         this.left = left;
//         this.right = right;
//     }
// 
//     /**
//      * @return gets the value of the left element
//      */
//     public L getLeft() {
//         return left;
//     }
// 
//     /**
//      * @return gets the value of the right element
//      */
//     public R getRight() {
//         return right;
//     }
// 
//     @Override
//     public String toString() {
//         return "Pair{" + "left=" + left + ", right=" + right + '}';
//     }
// 
//     @Override
//     public boolean equals(final Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (o == null || getClass() != o.getClass()) {
//             return false;
//         }
//         Pair<?, ?> pair = (Pair<?, ?>) o;
//         return Objects.equals(left, pair.left)
//                 && Objects.equals(right, pair.right);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(left, right);
//     }
// }


import com.google.common.collect.Lists;
import com.statful.utils.Pair;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.http.HttpServer;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static java.util.Objects.nonNull;
    @Test
    public void testCustomMetricWithGlobalAppTag(TestContext context) throws Exception {
        StatfulMetricsOptions options = getCommonStatfulMetricsOptions();
        options.setApp("customApp");

        setupVertxTestContext(options);

        Async async = context.async();

        this.httpMetricsReceiver.requestHandler(packet -> packet.bodyHandler(body -> {
            String metric = body.toString();
            context.assertTrue(metric.contains("customMetricName"));
            context.assertTrue(metric.contains("app=customApp"));
            teardown(async, context, null);
        })).listen(HTTP_SENDER_PORT, HOST, event -> {
            if (event.failed()) {
                teardown(async, context, event.cause());
            }
        });

        CustomMetric metric = new CustomMetric.Builder()
                .withMetricName("customMetricName")
                .withValue(1L)
                .build();

        this.vertx.eventBus().send(CustomMetricsConsumer.ADDRESS, metric);
    }

    @Test
    public void testCustomMetricWithCustomTagsAndGlobalTags(TestContext context) throws Exception {
// Path: src/main/java/com/statful/utils/Pair.java
// public final class Pair<L, R> {
// 
//     /**
//      * Left element of the Pair
//      */
//     private L left;
//     /**
//      * Right element of the Pair
//      */
//     private R right;
// 
//     /**
//      * Pair constructor
//      *
//      * @param left  element of the pair
//      * @param right element of the pair
//      */
//     public Pair(final L left, final R right) {
//         this.left = left;
//         this.right = right;
//     }
// 
//     /**
//      * @return gets the value of the left element
//      */
//     public L getLeft() {
//         return left;
//     }
// 
//     /**
//      * @return gets the value of the right element
//      */
//     public R getRight() {
//         return right;
//     }
// 
//     @Override
//     public String toString() {
//         return "Pair{" + "left=" + left + ", right=" + right + '}';
//     }
// 
//     @Override
//     public boolean equals(final Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (o == null || getClass() != o.getClass()) {
//             return false;
//         }
//         Pair<?, ?> pair = (Pair<?, ?>) o;
//         return Objects.equals(left, pair.left)
//                 && Objects.equals(right, pair.right);
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(left, right);
//     }
// }


// Path: src/test/java/com/statful/client/StatfulCustomMetricIntegrationTest.java
import com.google.common.collect.Lists;
import com.statful.utils.Pair;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.http.HttpServer;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static java.util.Objects.nonNull;

    @Test
    public void testCustomMetricWithGlobalAppTag(TestContext context) throws Exception {
        StatfulMetricsOptions options = getCommonStatfulMetricsOptions();
        options.setApp("customApp");

        setupVertxTestContext(options);

        Async async = context.async();

        this.httpMetricsReceiver.requestHandler(packet -> packet.bodyHandler(body -> {
            String metric = body.toString();
            context.assertTrue(metric.contains("customMetricName"));
            context.assertTrue(metric.contains("app=customApp"));
            teardown(async, context, null);
        })).listen(HTTP_SENDER_PORT, HOST, event -> {
            if (event.failed()) {
                teardown(async, context, event.cause());
            }
        });

        CustomMetric metric = new CustomMetric.Builder()
                .withMetricName("customMetricName")
                .withValue(1L)
                .build();

        this.vertx.eventBus().send(CustomMetricsConsumer.ADDRESS, metric);
    }

    @Test
    public void testCustomMetricWithCustomTagsAndGlobalTags(TestContext context) throws Exception {
        List<Pair<String, String>> globalTags = new ArrayList<>(1);