You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by wc...@apache.org on 2023/12/06 14:54:21 UTC

(kafka) branch trunk updated: KAFKA-15972: Add support to exclude labels for telemetry metrics (KIP-714) (#14924)

This is an automated email from the ASF dual-hosted git repository.

wcarlson pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 71b4cbae378 KAFKA-15972: Add support to exclude labels for telemetry metrics (KIP-714) (#14924)
71b4cbae378 is described below

commit 71b4cbae378ea2a1b751c0fb9bf6a647df848610
Author: Apoorv Mittal <am...@confluent.io>
AuthorDate: Wed Dec 6 20:24:13 2023 +0530

    KAFKA-15972: Add support to exclude labels for telemetry metrics (KIP-714) (#14924)
    
    Changes in the PR are to support excluding client_id label when sending telemetry metrics.
    
    Some of the labels/tags which are present in metric should be skipped while collecting telemetry as data might already be known to broker hence, we should minimize the data transfer. One of such labels is client_id which is already present in RequestContext hence broker can append that label prior emitting metrics to telemetry backend.
    
    Reviewers: Andrew Schofield <as...@confluent.io>, Walker Carlson <wc...@apache.org>
---
 .../internals/ClientTelemetryReporter.java         |  10 +-
 .../telemetry/internals/KafkaMetricsCollector.java |  14 +-
 .../telemetry/internals/SinglePointMetric.java     |  33 ++---
 .../internals/ClientTelemetryEmitterTest.java      |   6 +-
 .../internals/KafkaMetricsCollectorTest.java       |  68 +++++++++-
 .../telemetry/internals/SinglePointMetricTest.java | 150 ++++++++++++++++++++-
 6 files changed, 248 insertions(+), 33 deletions(-)

diff --git a/clients/src/main/java/org/apache/kafka/common/telemetry/internals/ClientTelemetryReporter.java b/clients/src/main/java/org/apache/kafka/common/telemetry/internals/ClientTelemetryReporter.java
index 617674f7d00..959cec107db 100644
--- a/clients/src/main/java/org/apache/kafka/common/telemetry/internals/ClientTelemetryReporter.java
+++ b/clients/src/main/java/org/apache/kafka/common/telemetry/internals/ClientTelemetryReporter.java
@@ -53,6 +53,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.StringJoiner;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
@@ -103,6 +104,13 @@ import java.util.function.Predicate;
 public class ClientTelemetryReporter implements MetricsReporter {
 
     private static final Logger log = LoggerFactory.getLogger(ClientTelemetryReporter.class);
+    /*
+     Exclude client_id from the labels as the broker already knows the client_id from the request
+     context. These additional labels from the request context should be added by broker prior
+     exporting the metrics to the telemetry backend.
+    */
+    private static final Set<String> EXCLUDE_LABELS = Collections.singleton("client_id");
+
     public static final int DEFAULT_PUSH_INTERVAL_MS = 5 * 60 * 1000;
 
     private final ClientTelemetryProvider telemetryProvider;
@@ -226,7 +234,7 @@ public class ClientTelemetryReporter implements MetricsReporter {
     private void initCollectors() {
         kafkaMetricsCollector = new KafkaMetricsCollector(
             TelemetryMetricNamingConvention.getClientTelemetryMetricNamingStrategy(
-                telemetryProvider.domain()));
+                telemetryProvider.domain()), EXCLUDE_LABELS);
     }
 
     private ResourceMetrics buildMetric(Metric metric) {
diff --git a/clients/src/main/java/org/apache/kafka/common/telemetry/internals/KafkaMetricsCollector.java b/clients/src/main/java/org/apache/kafka/common/telemetry/internals/KafkaMetricsCollector.java
index 3aea4a11879..a888e8997ab 100644
--- a/clients/src/main/java/org/apache/kafka/common/telemetry/internals/KafkaMetricsCollector.java
+++ b/clients/src/main/java/org/apache/kafka/common/telemetry/internals/KafkaMetricsCollector.java
@@ -129,6 +129,7 @@ public class KafkaMetricsCollector implements MetricsCollector {
     private final StateLedger ledger;
     private final Time time;
     private final MetricNamingStrategy<MetricName> metricNamingStrategy;
+    private final Set<String> excludeLabels;
 
     private static final Field METRIC_VALUE_PROVIDER_FIELD;
 
@@ -141,15 +142,16 @@ public class KafkaMetricsCollector implements MetricsCollector {
         }
     }
 
-    public KafkaMetricsCollector(MetricNamingStrategy<MetricName> metricNamingStrategy) {
-        this(metricNamingStrategy, Time.SYSTEM);
+    public KafkaMetricsCollector(MetricNamingStrategy<MetricName> metricNamingStrategy, Set<String> excludeLabels) {
+        this(metricNamingStrategy, Time.SYSTEM, excludeLabels);
     }
 
     // Visible for testing
-    KafkaMetricsCollector(MetricNamingStrategy<MetricName> metricNamingStrategy, Time time) {
+    KafkaMetricsCollector(MetricNamingStrategy<MetricName> metricNamingStrategy, Time time, Set<String> excludeLabels) {
         this.metricNamingStrategy = metricNamingStrategy;
         this.time = time;
         this.ledger = new StateLedger();
+        this.excludeLabels = excludeLabels;
     }
 
     public void init(List<KafkaMetric> metrics) {
@@ -241,11 +243,11 @@ public class KafkaMetricsCollector implements MetricsCollector {
 
             metricsEmitter.emitMetric(
                 SinglePointMetric.deltaSum(metricKey, instantAndValue.getValue(), true, timestamp,
-                    instantAndValue.getIntervalStart())
+                    instantAndValue.getIntervalStart(), excludeLabels)
             );
         } else {
             metricsEmitter.emitMetric(
-                SinglePointMetric.sum(metricKey, value, true, timestamp, ledger.instantAdded(metricKey))
+                SinglePointMetric.sum(metricKey, value, true, timestamp, ledger.instantAdded(metricKey), excludeLabels)
             );
         }
     }
@@ -256,7 +258,7 @@ public class KafkaMetricsCollector implements MetricsCollector {
         }
 
         metricsEmitter.emitMetric(
-            SinglePointMetric.gauge(metricKey, value, timestamp)
+            SinglePointMetric.gauge(metricKey, value, timestamp, excludeLabels)
         );
     }
 
diff --git a/clients/src/main/java/org/apache/kafka/common/telemetry/internals/SinglePointMetric.java b/clients/src/main/java/org/apache/kafka/common/telemetry/internals/SinglePointMetric.java
index 4194bd469bf..e43814d578a 100644
--- a/clients/src/main/java/org/apache/kafka/common/telemetry/internals/SinglePointMetric.java
+++ b/clients/src/main/java/org/apache/kafka/common/telemetry/internals/SinglePointMetric.java
@@ -24,6 +24,7 @@ import io.opentelemetry.proto.metrics.v1.NumberDataPoint;
 
 import java.time.Instant;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -52,48 +53,48 @@ public class SinglePointMetric implements MetricKeyable {
     /*
         Methods to construct gauge metric type.
      */
-    public static SinglePointMetric gauge(MetricKey metricKey, Number value, Instant timestamp) {
+    public static SinglePointMetric gauge(MetricKey metricKey, Number value, Instant timestamp, Set<String> excludeLabels) {
         NumberDataPoint.Builder point = point(timestamp, value);
-        return gauge(metricKey, point);
+        return gauge(metricKey, point, excludeLabels);
     }
 
-    public static SinglePointMetric gauge(MetricKey metricKey, double value, Instant timestamp) {
+    public static SinglePointMetric gauge(MetricKey metricKey, double value, Instant timestamp, Set<String> excludeLabels) {
         NumberDataPoint.Builder point = point(timestamp, value);
-        return gauge(metricKey, point);
+        return gauge(metricKey, point, excludeLabels);
     }
 
     /*
         Methods to construct sum metric type.
      */
 
-    public static SinglePointMetric sum(MetricKey metricKey, double value, boolean monotonic, Instant timestamp) {
-        return sum(metricKey, value, monotonic, timestamp, null);
+    public static SinglePointMetric sum(MetricKey metricKey, double value, boolean monotonic, Instant timestamp, Set<String> excludeLabels) {
+        return sum(metricKey, value, monotonic, timestamp, null, excludeLabels);
     }
 
     public static SinglePointMetric sum(MetricKey metricKey, double value, boolean monotonic, Instant timestamp,
-        Instant startTimestamp) {
+        Instant startTimestamp, Set<String> excludeLabels) {
         NumberDataPoint.Builder point = point(timestamp, value);
         if (startTimestamp != null) {
             point.setStartTimeUnixNano(toTimeUnixNanos(startTimestamp));
         }
 
-        return sum(metricKey, AggregationTemporality.AGGREGATION_TEMPORALITY_CUMULATIVE, monotonic, point);
+        return sum(metricKey, AggregationTemporality.AGGREGATION_TEMPORALITY_CUMULATIVE, monotonic, point, excludeLabels);
     }
 
     public static SinglePointMetric deltaSum(MetricKey metricKey, double value, boolean monotonic,
-        Instant timestamp, Instant startTimestamp) {
+        Instant timestamp, Instant startTimestamp, Set<String> excludeLabels) {
         NumberDataPoint.Builder point = point(timestamp, value)
             .setStartTimeUnixNano(toTimeUnixNanos(startTimestamp));
 
-        return sum(metricKey, AggregationTemporality.AGGREGATION_TEMPORALITY_DELTA, monotonic, point);
+        return sum(metricKey, AggregationTemporality.AGGREGATION_TEMPORALITY_DELTA, monotonic, point, excludeLabels);
     }
 
     /*
         Helper methods to support metric construction.
      */
     private static SinglePointMetric sum(MetricKey metricKey, AggregationTemporality aggregationTemporality,
-        boolean monotonic, NumberDataPoint.Builder point) {
-        point.addAllAttributes(asAttributes(metricKey.tags()));
+        boolean monotonic, NumberDataPoint.Builder point, Set<String> excludeLabels) {
+        point.addAllAttributes(asAttributes(metricKey.tags(), excludeLabels));
 
         Metric.Builder metric = Metric.newBuilder().setName(metricKey.name());
         metric
@@ -104,8 +105,8 @@ public class SinglePointMetric implements MetricKeyable {
         return new SinglePointMetric(metricKey, metric);
     }
 
-    private static SinglePointMetric gauge(MetricKey metricKey, NumberDataPoint.Builder point) {
-        point.addAllAttributes(asAttributes(metricKey.tags()));
+    private static SinglePointMetric gauge(MetricKey metricKey, NumberDataPoint.Builder point, Set<String> excludeLabels) {
+        point.addAllAttributes(asAttributes(metricKey.tags(), excludeLabels));
 
         Metric.Builder metric = Metric.newBuilder().setName(metricKey.name());
         metric.getGaugeBuilder().addDataPoints(point);
@@ -132,8 +133,8 @@ public class SinglePointMetric implements MetricKeyable {
             .setAsDouble(value);
     }
 
-    private static Iterable<KeyValue> asAttributes(Map<String, String> labels) {
-        return labels.entrySet().stream().map(
+    private static Iterable<KeyValue> asAttributes(Map<String, String> labels, Set<String> excludeLabels) {
+        return labels.entrySet().stream().filter(entry -> !excludeLabels.contains(entry.getKey())).map(
             entry -> KeyValue.newBuilder()
                 .setKey(entry.getKey())
                 .setValue(AnyValue.newBuilder().setStringValue(entry.getValue())).build()
diff --git a/clients/src/test/java/org/apache/kafka/common/telemetry/internals/ClientTelemetryEmitterTest.java b/clients/src/test/java/org/apache/kafka/common/telemetry/internals/ClientTelemetryEmitterTest.java
index 32fd2a5ad93..ff055359b19 100644
--- a/clients/src/test/java/org/apache/kafka/common/telemetry/internals/ClientTelemetryEmitterTest.java
+++ b/clients/src/test/java/org/apache/kafka/common/telemetry/internals/ClientTelemetryEmitterTest.java
@@ -89,13 +89,13 @@ public class ClientTelemetryEmitterTest {
             Collections.singletonList("name"));
         ClientTelemetryEmitter emitter = new ClientTelemetryEmitter(selector, true);
 
-        SinglePointMetric gauge = SinglePointMetric.gauge(metricKey, Long.valueOf(1), now);
-        SinglePointMetric sum = SinglePointMetric.sum(metricKey, 1.0, true, now);
+        SinglePointMetric gauge = SinglePointMetric.gauge(metricKey, Long.valueOf(1), now, Collections.emptySet());
+        SinglePointMetric sum = SinglePointMetric.sum(metricKey, 1.0, true, now, Collections.emptySet());
         assertTrue(emitter.emitMetric(gauge));
         assertTrue(emitter.emitMetric(sum));
 
         MetricKey anotherKey = new MetricKey("io.name", Collections.emptyMap());
-        assertFalse(emitter.emitMetric(SinglePointMetric.gauge(anotherKey, Long.valueOf(1), now)));
+        assertFalse(emitter.emitMetric(SinglePointMetric.gauge(anotherKey, Long.valueOf(1), now, Collections.emptySet())));
 
         assertEquals(2, emitter.emittedMetrics().size());
         assertEquals(Arrays.asList(gauge, sum), emitter.emittedMetrics());
diff --git a/clients/src/test/java/org/apache/kafka/common/telemetry/internals/KafkaMetricsCollectorTest.java b/clients/src/test/java/org/apache/kafka/common/telemetry/internals/KafkaMetricsCollectorTest.java
index bb4e0cdc2d3..cd5a1848702 100644
--- a/clients/src/test/java/org/apache/kafka/common/telemetry/internals/KafkaMetricsCollectorTest.java
+++ b/clients/src/test/java/org/apache/kafka/common/telemetry/internals/KafkaMetricsCollectorTest.java
@@ -35,6 +35,7 @@ import org.junit.jupiter.api.Test;
 
 import java.time.Instant;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -72,7 +73,8 @@ public class KafkaMetricsCollectorTest {
         // Define collector to test.
         collector = new KafkaMetricsCollector(
             metricNamingStrategy,
-            time
+            time,
+            Collections.emptySet()
         );
 
         // Add reporter to metrics.
@@ -564,6 +566,70 @@ public class KafkaMetricsCollectorTest {
             Instant.ofEpochSecond(301L).getNano(), point.getStartTimeUnixNano());
     }
 
+    @Test
+    public void testCollectMetricsWithExcludeLabels() {
+        collector = new KafkaMetricsCollector(
+            metricNamingStrategy,
+            time,
+            Collections.singleton("tag2")
+        );
+
+        tags = new HashMap<>();
+        tags.put("tag1", "value1");
+        tags.put("tag2", "value2");
+
+        // Gauge metric.
+        MetricName name1 = metrics.metricName("nonMeasurable", "group1", tags);
+        metrics.addMetric(name1, (Gauge<Double>) (config, now) -> 99d);
+        // Sum metric.
+        MetricName name2 = metrics.metricName("counter", "group1", tags);
+        Sensor sensor = metrics.sensor("counter");
+        sensor.add(name2, new WindowedCount());
+        sensor.record();
+        testEmitter.reconfigurePredicate(k -> !k.key().name().endsWith(".count"));
+
+        // Collect sum metrics
+        collector.collect(testEmitter);
+        List<SinglePointMetric> result = testEmitter.emittedMetrics();
+        Metric metric = result.stream()
+            .flatMap(metrics -> Stream.of(metrics.builder().build()))
+            .filter(m -> m.getName().equals("test.domain.group1.nonmeasurable")).findFirst().get();
+
+        assertEquals(1, metric.getGauge().getDataPointsCount());
+        NumberDataPoint point = metric.getGauge().getDataPoints(0);
+        assertEquals(1, point.getAttributesCount());
+        assertEquals("tag1", point.getAttributes(0).getKey());
+        assertEquals("value1", point.getAttributes(0).getValue().getStringValue());
+
+        metric = result.stream()
+            .flatMap(metrics -> Stream.of(metrics.builder().build()))
+            .filter(m -> m.getName().equals("test.domain.group1.counter")).findFirst().get();
+
+        assertEquals(AggregationTemporality.AGGREGATION_TEMPORALITY_CUMULATIVE, metric.getSum().getAggregationTemporality());
+        assertEquals(1, metric.getSum().getDataPointsCount());
+        point = metric.getSum().getDataPoints(0);
+        assertEquals(1, point.getAttributesCount());
+        assertEquals("tag1", point.getAttributes(0).getKey());
+        assertEquals("value1", point.getAttributes(0).getValue().getStringValue());
+
+        testEmitter.reset();
+        testEmitter.onlyDeltaMetrics(true);
+        collector.collect(testEmitter);
+        result = testEmitter.emittedMetrics();
+
+        // Delta metrics.
+        metric = result.stream()
+            .flatMap(metrics -> Stream.of(metrics.builder().build()))
+            .filter(m -> m.getName().equals("test.domain.group1.counter")).findFirst().get();
+
+        assertEquals(AggregationTemporality.AGGREGATION_TEMPORALITY_DELTA, metric.getSum().getAggregationTemporality());
+        assertEquals(1, metric.getSum().getDataPointsCount());
+        point = metric.getSum().getDataPoints(0);
+        assertEquals(1, point.getAttributesCount());
+        assertEquals("tag1", point.getAttributes(0).getKey());
+        assertEquals("value1", point.getAttributes(0).getValue().getStringValue());
+    }
+
     private MetricsReporter getTestMetricsReporter() {
         // Inline implementation of MetricsReporter for testing.
         return new MetricsReporter() {
diff --git a/clients/src/test/java/org/apache/kafka/common/telemetry/internals/SinglePointMetricTest.java b/clients/src/test/java/org/apache/kafka/common/telemetry/internals/SinglePointMetricTest.java
index 97801b1e069..8774383233a 100644
--- a/clients/src/test/java/org/apache/kafka/common/telemetry/internals/SinglePointMetricTest.java
+++ b/clients/src/test/java/org/apache/kafka/common/telemetry/internals/SinglePointMetricTest.java
@@ -25,6 +25,8 @@ import org.junit.jupiter.api.Test;
 
 import java.time.Instant;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -58,7 +60,7 @@ public class SinglePointMetricTest {
 
     @Test
     public void testGaugeWithNumberValue() {
-        SinglePointMetric gaugeNumber = SinglePointMetric.gauge(metricKey, Long.valueOf(1), now);
+        SinglePointMetric gaugeNumber = SinglePointMetric.gauge(metricKey, Long.valueOf(1), now, Collections.emptySet());
         MetricKey metricKey = gaugeNumber.key();
         assertEquals("name", metricKey.name());
 
@@ -74,7 +76,7 @@ public class SinglePointMetricTest {
 
     @Test
     public void testGaugeWithDoubleValue() {
-        SinglePointMetric gaugeNumber = SinglePointMetric.gauge(metricKey, 1.0, now);
+        SinglePointMetric gaugeNumber = SinglePointMetric.gauge(metricKey, 1.0, now, Collections.emptySet());
         MetricKey metricKey = gaugeNumber.key();
         assertEquals("name", metricKey.name());
 
@@ -91,7 +93,7 @@ public class SinglePointMetricTest {
     @Test
     public void testGaugeWithMetricTags() {
         MetricKey metricKey = new MetricKey("name", Collections.singletonMap("tag", "value"));
-        SinglePointMetric gaugeNumber = SinglePointMetric.gauge(metricKey, 1.0, now);
+        SinglePointMetric gaugeNumber = SinglePointMetric.gauge(metricKey, 1.0, now, Collections.emptySet());
 
         MetricKey key = gaugeNumber.key();
         assertEquals("name", key.name());
@@ -108,9 +110,77 @@ public class SinglePointMetricTest {
         assertEquals("value", point.getAttributes(0).getValue().getStringValue());
     }
 
+    @Test
+    public void testGaugeNumberWithExcludeLabels() {
+        Map<String, String> tags = new HashMap<>();
+        tags.put("tag1", "value1");
+        tags.put("tag2", "value2");
+        MetricKey metricKey = new MetricKey("name", tags);
+
+        SinglePointMetric gaugeNumber = SinglePointMetric.gauge(metricKey, Long.valueOf(1), now, Collections.singleton("random"));
+        Metric metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getGauge().getDataPointsCount());
+        NumberDataPoint point = metric.getGauge().getDataPoints(0);
+        assertEquals(2, point.getAttributesCount());
+        for (int i = 0; i < point.getAttributesCount(); i++) {
+            assertTrue(
+                point.getAttributes(i).getKey().equals("tag1") || point.getAttributes(i).getKey().equals("tag2"));
+            assertTrue(
+                point.getAttributes(i).getValue().getStringValue().equals("value1") || point.getAttributes(i).getValue().getStringValue().equals("value2"));
+        }
+
+        gaugeNumber = SinglePointMetric.gauge(metricKey, Long.valueOf(1), now, Collections.singleton("tag1"));
+        metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getGauge().getDataPointsCount());
+        point = metric.getGauge().getDataPoints(0);
+        assertEquals(1, point.getAttributesCount());
+        assertEquals("tag2", point.getAttributes(0).getKey());
+        assertEquals("value2", point.getAttributes(0).getValue().getStringValue());
+
+        gaugeNumber = SinglePointMetric.gauge(metricKey, Long.valueOf(1), now, tags.keySet());
+        metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getGauge().getDataPointsCount());
+        point = metric.getGauge().getDataPoints(0);
+        assertEquals(0, point.getAttributesCount());
+    }
+
+    @Test
+    public void testGaugeDoubleWithExcludeLabels() {
+        Map<String, String> tags = new HashMap<>();
+        tags.put("tag1", "value1");
+        tags.put("tag2", "value2");
+        MetricKey metricKey = new MetricKey("name", tags);
+
+        SinglePointMetric gaugeNumber = SinglePointMetric.gauge(metricKey, 1.0, now, Collections.singleton("random"));
+        Metric metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getGauge().getDataPointsCount());
+        NumberDataPoint point = metric.getGauge().getDataPoints(0);
+        assertEquals(2, point.getAttributesCount());
+        for (int i = 0; i < point.getAttributesCount(); i++) {
+            assertTrue(
+                point.getAttributes(i).getKey().equals("tag1") || point.getAttributes(i).getKey().equals("tag2"));
+            assertTrue(
+                point.getAttributes(i).getValue().getStringValue().equals("value1") || point.getAttributes(i).getValue().getStringValue().equals("value2"));
+        }
+
+        gaugeNumber = SinglePointMetric.gauge(metricKey, 1.0, now, Collections.singleton("tag1"));
+        metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getGauge().getDataPointsCount());
+        point = metric.getGauge().getDataPoints(0);
+        assertEquals(1, point.getAttributesCount());
+        assertEquals("tag2", point.getAttributes(0).getKey());
+        assertEquals("value2", point.getAttributes(0).getValue().getStringValue());
+
+        gaugeNumber = SinglePointMetric.gauge(metricKey, 1.0, now, tags.keySet());
+        metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getGauge().getDataPointsCount());
+        point = metric.getGauge().getDataPoints(0);
+        assertEquals(0, point.getAttributesCount());
+    }
+
     @Test
     public void testSum() {
-        SinglePointMetric sum = SinglePointMetric.sum(metricKey, 1.0, false, now);
+        SinglePointMetric sum = SinglePointMetric.sum(metricKey, 1.0, false, now, null, Collections.emptySet());
 
         MetricKey key = sum.key();
         assertEquals("name", key.name());
@@ -130,7 +200,7 @@ public class SinglePointMetricTest {
     @Test
     public void testSumWithStartTimeAndTags() {
         MetricKey metricKey = new MetricKey("name", Collections.singletonMap("tag", "value"));
-        SinglePointMetric sum = SinglePointMetric.sum(metricKey, 1.0, true, now, now);
+        SinglePointMetric sum = SinglePointMetric.sum(metricKey, 1.0, true, now, now, Collections.emptySet());
 
         MetricKey key = sum.key();
         assertEquals("name", key.name());
@@ -149,9 +219,43 @@ public class SinglePointMetricTest {
         assertEquals("value", point.getAttributes(0).getValue().getStringValue());
     }
 
+    @Test
+    public void testSumWithExcludeLabels() {
+        Map<String, String> tags = new HashMap<>();
+        tags.put("tag1", "value1");
+        tags.put("tag2", "value2");
+        MetricKey metricKey = new MetricKey("name", tags);
+
+        SinglePointMetric gaugeNumber = SinglePointMetric.sum(metricKey, 1.0, true, now, Collections.singleton("random"));
+        Metric metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getSum().getDataPointsCount());
+        NumberDataPoint point = metric.getSum().getDataPoints(0);
+        assertEquals(2, point.getAttributesCount());
+        for (int i = 0; i < point.getAttributesCount(); i++) {
+            assertTrue(
+                point.getAttributes(i).getKey().equals("tag1") || point.getAttributes(i).getKey().equals("tag2"));
+            assertTrue(
+                point.getAttributes(i).getValue().getStringValue().equals("value1") || point.getAttributes(i).getValue().getStringValue().equals("value2"));
+        }
+
+        gaugeNumber = SinglePointMetric.sum(metricKey, 1.0, true, now, Collections.singleton("tag1"));
+        metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getSum().getDataPointsCount());
+        point = metric.getSum().getDataPoints(0);
+        assertEquals(1, point.getAttributesCount());
+        assertEquals("tag2", point.getAttributes(0).getKey());
+        assertEquals("value2", point.getAttributes(0).getValue().getStringValue());
+
+        gaugeNumber = SinglePointMetric.sum(metricKey, 1.0, true, now, tags.keySet());
+        metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getSum().getDataPointsCount());
+        point = metric.getSum().getDataPoints(0);
+        assertEquals(0, point.getAttributesCount());
+    }
+
     @Test
     public void testDeltaSum() {
-        SinglePointMetric sum = SinglePointMetric.deltaSum(metricKey, 1.0, true, now, now);
+        SinglePointMetric sum = SinglePointMetric.deltaSum(metricKey, 1.0, true, now, now, Collections.emptySet());
 
         MetricKey key = sum.key();
         assertEquals("name", key.name());
@@ -167,4 +271,38 @@ public class SinglePointMetricTest {
         assertEquals(1.0, point.getAsDouble());
         assertEquals(0, point.getAttributesCount());
     }
+
+    @Test
+    public void testDeltaSumWithExcludeLabels() {
+        Map<String, String> tags = new HashMap<>();
+        tags.put("tag1", "value1");
+        tags.put("tag2", "value2");
+        MetricKey metricKey = new MetricKey("name", tags);
+
+        SinglePointMetric gaugeNumber = SinglePointMetric.deltaSum(metricKey, 1.0, true, now, now, Collections.singleton("random"));
+        Metric metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getSum().getDataPointsCount());
+        NumberDataPoint point = metric.getSum().getDataPoints(0);
+        assertEquals(2, point.getAttributesCount());
+        for (int i = 0; i < point.getAttributesCount(); i++) {
+            assertTrue(
+                point.getAttributes(i).getKey().equals("tag1") || point.getAttributes(i).getKey().equals("tag2"));
+            assertTrue(
+                point.getAttributes(i).getValue().getStringValue().equals("value1") || point.getAttributes(i).getValue().getStringValue().equals("value2"));
+        }
+
+        gaugeNumber = SinglePointMetric.deltaSum(metricKey, 1.0, true, now, now, Collections.singleton("tag1"));
+        metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getSum().getDataPointsCount());
+        point = metric.getSum().getDataPoints(0);
+        assertEquals(1, point.getAttributesCount());
+        assertEquals("tag2", point.getAttributes(0).getKey());
+        assertEquals("value2", point.getAttributes(0).getValue().getStringValue());
+
+        gaugeNumber = SinglePointMetric.deltaSum(metricKey, 1.0, true, now, now, tags.keySet());
+        metric = gaugeNumber.builder().build();
+        assertEquals(1, metric.getSum().getDataPointsCount());
+        point = metric.getSum().getDataPoints(0);
+        assertEquals(0, point.getAttributesCount());
+    }
 }