From 0d6fcce274221f43d70ae247c672b6ac8c0ce9ef Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Wed, 17 Jan 2024 10:41:56 -0800
Subject: [PATCH 01/28] heartbeat metrics
---
.../internals/HeartbeatRequestManager.java | 35 +++++++++++++++++--
.../consumer/internals/RequestManagers.java | 3 +-
.../metrics/AbstractConsumerMetrics.java | 14 ++++++++
.../internals/metrics/HeartbeatMetrics.java | 31 ++++++++++++++++
.../internals/AsyncKafkaConsumerTest.java | 19 ++++++++++
.../internals/ConsumerTestBuilder.java | 4 ++-
.../HeartbeatRequestManagerTest.java | 29 ++++++++-------
7 files changed, 118 insertions(+), 17 deletions(-)
create mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 11846eedeafdc..04b342fa9a0a5 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -23,10 +23,13 @@
import org.apache.kafka.clients.consumer.internals.events.BackgroundEventHandler;
import org.apache.kafka.clients.consumer.internals.events.ErrorBackgroundEvent;
import org.apache.kafka.clients.consumer.internals.events.GroupMetadataUpdateEvent;
+import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetrics;
import org.apache.kafka.common.Uuid;
import org.apache.kafka.common.errors.GroupAuthorizationException;
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatRequestData;
+import org.apache.kafka.common.metrics.Measurable;
+import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.ConsumerGroupHeartbeatRequest;
import org.apache.kafka.common.requests.ConsumerGroupHeartbeatResponse;
@@ -41,6 +44,7 @@
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -78,6 +82,11 @@ public class HeartbeatRequestManager implements RequestManager {
*/
private final int maxPollIntervalMs;
+ /**
+ * The last time in Ms the heartbeat was sent to the coordinator
+ */
+ private long lastHeartbeatSend = 0L;
+
/**
* CoordinatorRequestManager manages the connection to the group coordinator
*/
@@ -108,6 +117,7 @@ public class HeartbeatRequestManager implements RequestManager {
* sending heartbeat until the next poll.
*/
private final Timer pollTimer;
+ private final HeartbeatMetrics heartbeatMetrics;
private GroupMetadataUpdateEvent previousGroupMetadataUpdateEvent = null;
@@ -118,7 +128,8 @@ public HeartbeatRequestManager(
final CoordinatorRequestManager coordinatorRequestManager,
final SubscriptionState subscriptions,
final MembershipManager membershipManager,
- final BackgroundEventHandler backgroundEventHandler) {
+ final BackgroundEventHandler backgroundEventHandler,
+ final Metrics metrics) {
this.coordinatorRequestManager = coordinatorRequestManager;
this.logger = logContext.logger(getClass());
this.membershipManager = membershipManager;
@@ -130,6 +141,8 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
+ this.heartbeatMetrics = new HeartbeatMetrics(metrics);
+ registerLastSentHeartbeatMetric(metrics);
}
// Visible for testing
@@ -141,7 +154,8 @@ public HeartbeatRequestManager(
final MembershipManager membershipManager,
final HeartbeatState heartbeatState,
final HeartbeatRequestState heartbeatRequestState,
- final BackgroundEventHandler backgroundEventHandler) {
+ final BackgroundEventHandler backgroundEventHandler,
+ final Metrics metrics) {
this.logger = logContext.logger(this.getClass());
this.maxPollIntervalMs = config.getInt(CommonClientConfigs.MAX_POLL_INTERVAL_MS_CONFIG);
this.coordinatorRequestManager = coordinatorRequestManager;
@@ -150,6 +164,8 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
+ this.heartbeatMetrics = new HeartbeatMetrics(metrics);
+ registerLastSentHeartbeatMetric(metrics);
}
/**
@@ -245,6 +261,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final long curr
NetworkClientDelegate.UnsentRequest request = makeHeartbeatRequest(ignoreResponse);
heartbeatRequestState.onSendAttempt(currentTimeMs);
membershipManager.onHeartbeatRequestSent();
+ lastHeartbeatSend = currentTimeMs;
return request;
}
@@ -415,6 +432,20 @@ private void handleFatalFailure(Throwable error) {
membershipManager.transitionToFatal();
}
+ private void registerLastSentHeartbeatMetric(Metrics metrics) {
+ Measurable lastHeartbeat = (config, now) -> {
+ if (lastHeartbeatSend == 0L)
+ // if no heartbeat is ever triggered, just return -1.
+ return -1d;
+ else
+ return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
+ };
+ heartbeatMetrics.registerMeasurable(
+ "heartbeat-time-max",
+ "The max time taken to receive a response to a heartbeat request",
+ lastHeartbeat);
+ }
+
/**
* Represents the state of a heartbeat request, including logic for timing, retries, and exponential backoff. The
* object extends {@link RequestState} to enable exponential backoff and duplicated request handling. The two fields
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
index 6dd9e01216343..7b3e75be0182c 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
@@ -190,7 +190,8 @@ protected RequestManagers create() {
coordinator,
subscriptions,
membershipManager,
- backgroundEventHandler);
+ backgroundEventHandler,
+ metrics);
}
return new RequestManagers(
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index 2273bfd494a3b..c9cd16b26f8cd 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -16,6 +16,10 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.stats.Meter;
+import org.apache.kafka.common.metrics.stats.WindowedCount;
+
import java.util.Optional;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
@@ -26,4 +30,14 @@ public abstract class AbstractConsumerMetrics {
public AbstractConsumerMetrics(Optional grpMetricsPrefix) {
grpMetricsPrefix.ifPresent(s -> this.groupMetricsName = s + COORDINATOR_METRICS_SUFFIX);
}
+
+ public AbstractConsumerMetrics() {}
+
+ public static Meter createMeter(Metrics metrics, String groupName, String baseName, String descriptiveName) {
+ return new Meter(new WindowedCount(),
+ metrics.metricName(baseName + "-rate", groupName,
+ String.format("The number of %s per second", descriptiveName)),
+ metrics.metricName(baseName + "-total", groupName,
+ String.format("The total number of %s", descriptiveName)));
+ }
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
new file mode 100644
index 0000000000000..43e2b0740bc16
--- /dev/null
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -0,0 +1,31 @@
+package org.apache.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Measurable;
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.Sensor;
+import org.apache.kafka.common.metrics.stats.Max;
+
+public class HeartbeatMetrics extends AbstractConsumerMetrics {
+
+ private final Metrics metrics;
+ public final Sensor heartbeatSensor;
+
+ public HeartbeatMetrics(Metrics metrics) {
+ super();
+ this.metrics = metrics;
+ heartbeatSensor = metrics.sensor("heartbeat-latency");
+ heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
+ groupMetricsName,
+ "The max time taken to receive a response to a heartbeat request"), new Max());
+ heartbeatSensor.add(createMeter(metrics, groupMetricsName, "heartbeat", "heartbeats"));
+
+ }
+
+ public void registerMeasurable(String name,
+ String description,
+ Measurable measurable) {
+ metrics.addMetric(
+ metrics.metricName(name, groupMetricsName, description),
+ measurable);
+ }
+}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
index f6fb2a8928631..1e4991131f453 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
@@ -59,6 +59,7 @@
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.errors.TimeoutException;
import org.apache.kafka.common.errors.WakeupException;
+import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.JoinGroupRequest;
@@ -141,6 +142,7 @@ public class AsyncKafkaConsumerTest {
private final ApplicationEventHandler applicationEventHandler = mock(ApplicationEventHandler.class);
private final ConsumerMetadata metadata = mock(ConsumerMetadata.class);
private final LinkedBlockingQueue backgroundEventQueue = new LinkedBlockingQueue<>();
+ long rlb = -1L;
@AfterEach
public void resetAll() {
@@ -1398,6 +1400,23 @@ public void testProcessBackgroundEventsTimesOut() throws Exception {
}
}
+ @Test
+ public void testBS() {
+ rlb = 1000L;
+ Measurable lastRebalance = (config, now) -> {
+ return TimeUnit.SECONDS.convert(now - rlb, TimeUnit.MILLISECONDS);
+ };
+
+ System.out.println(lastRebalance.measure(null, System.currentTimeMillis())); // Prints some value
+
+// Update lastRebalanceEndMs
+ rlb = 2000L;
+
+ System.out.println(lastRebalance.measure(null, System.currentTimeMillis())); // Still uses the captured value,
+ // not the updated one
+
+ }
+
private HashMap mockTopicPartitionOffset() {
final TopicPartition t0 = new TopicPartition("t0", 2);
final TopicPartition t1 = new TopicPartition("t0", 3);
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
index 17489eab716c0..bdd3836303ac9 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
@@ -217,6 +217,7 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
retryBackoffMs,
DEFAULT_RETRY_BACKOFF_MAX_MS,
gi.heartbeatJitterMs));
+
HeartbeatRequestManager heartbeat = spy(new HeartbeatRequestManager(
logContext,
pollTimer,
@@ -225,7 +226,8 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
mm,
heartbeatState,
heartbeatRequestState,
- backgroundEventHandler));
+ backgroundEventHandler,
+ metrics));
this.coordinatorRequestManager = Optional.of(coordinator);
this.commitRequestManager = Optional.of(commit);
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index e44414b0677b9..c6335d2a89400 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -28,6 +28,8 @@
import org.apache.kafka.common.errors.TimeoutException;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatRequestData;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatResponseData;
+import org.apache.kafka.common.metrics.KafkaMetric;
+import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.ApiKeys;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.ConsumerGroupHeartbeatRequest;
@@ -62,6 +64,7 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MAX_MS;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MS;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -78,6 +81,7 @@ public class HeartbeatRequestManagerTest {
private int heartbeatIntervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS;
private int maxPollIntervalMs = DEFAULT_MAX_POLL_INTERVAL_MS;
private long retryBackoffMaxMs = DEFAULT_RETRY_BACKOFF_MAX_MS;
+ private String metricGrpPrefix = "test-consumer";
private static final String DEFAULT_GROUP_ID = "groupId";
private ConsumerTestBuilder testBuilder;
@@ -95,6 +99,7 @@ public class HeartbeatRequestManagerTest {
private final int memberEpoch = 1;
private BackgroundEventHandler backgroundEventHandler;
private BlockingQueue backgroundEventQueue;
+ private Metrics metrics = new Metrics();
@BeforeEach
public void setUp() {
@@ -671,18 +676,15 @@ private ConsumerConfig config() {
return new ConsumerConfig(prop);
}
- private HeartbeatRequestManager createHeartbeatRequestManager() {
- LogContext logContext = new LogContext();
- pollTimer = time.timer(maxPollIntervalMs);
- return new HeartbeatRequestManager(
- logContext,
- pollTimer,
- config(),
- coordinatorRequestManager,
- membershipManager,
- heartbeatState,
- heartbeatRequestState,
- backgroundEventHandler);
+ private void assertMetricsRecorded() {
+ assertNotNull(getMetric("heartbeat-response-time-max"));
+ assertNotNull(getMetric("heartbeat-rate"));
+ assertNotNull(getMetric("heartbeat-total"));
+ assertNotNull(getMetric("last-heartbeat-seconds-ago"));
+ }
+
+ private KafkaMetric getMetric(final String name) {
+ return metrics.metrics().get(metrics.metricName(name, "consumer-coordinator-metrics"));
}
private HeartbeatRequestManager createHeartbeatRequestManager(
@@ -701,6 +703,7 @@ private HeartbeatRequestManager createHeartbeatRequestManager(
membershipManager,
heartbeatState,
heartbeatRequestState,
- backgroundEventHandler);
+ backgroundEventHandler,
+ metrics);
}
}
From 112f6cebb89b5341f10614ac4e80337d12c2bd59 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 19 Jan 2024 10:14:24 -0800
Subject: [PATCH 02/28] clean up
---
.../internals/metrics/HeartbeatMetrics.java | 16 ++++++++++++++++
.../internals/HeartbeatRequestManagerTest.java | 3 ---
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
index 43e2b0740bc16..912295accc41d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -1,3 +1,19 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
import org.apache.kafka.common.metrics.Measurable;
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index c6335d2a89400..41cf9e39fe69c 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -81,13 +81,11 @@ public class HeartbeatRequestManagerTest {
private int heartbeatIntervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS;
private int maxPollIntervalMs = DEFAULT_MAX_POLL_INTERVAL_MS;
private long retryBackoffMaxMs = DEFAULT_RETRY_BACKOFF_MAX_MS;
- private String metricGrpPrefix = "test-consumer";
private static final String DEFAULT_GROUP_ID = "groupId";
private ConsumerTestBuilder testBuilder;
private Time time;
private Timer pollTimer;
- private ConsumerConfig config;
private CoordinatorRequestManager coordinatorRequestManager;
private SubscriptionState subscriptions;
private Metadata metadata;
@@ -118,7 +116,6 @@ private void setUp(Optional groupInfo) {
subscriptions = testBuilder.subscriptions;
membershipManager = testBuilder.membershipManager.orElseThrow(IllegalStateException::new);
metadata = testBuilder.metadata;
- config = testBuilder.config;
when(coordinatorRequestManager.coordinator()).thenReturn(Optional.of(new Node(1, "localhost", 9999)));
}
From 946c7409fd5478ec547886bee7cb288f20bbf177 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Mon, 22 Jan 2024 14:04:26 -0800
Subject: [PATCH 03/28] remove lastHeartbeatsend and use the requestState var
instead
eee
wip
---
.../internals/HeartbeatRequestManager.java | 19 ++++-----
.../metrics/AbstractConsumerMetrics.java | 14 ++++++-
.../internals/metrics/HeartbeatMetrics.java | 20 +++------
.../HeartbeatRequestManagerTest.java | 41 ++++++++++++++++---
4 files changed, 63 insertions(+), 31 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 04b342fa9a0a5..6feb4154836d5 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -82,11 +82,6 @@ public class HeartbeatRequestManager implements RequestManager {
*/
private final int maxPollIntervalMs;
- /**
- * The last time in Ms the heartbeat was sent to the coordinator
- */
- private long lastHeartbeatSend = 0L;
-
/**
* CoordinatorRequestManager manages the connection to the group coordinator
*/
@@ -261,7 +256,6 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final long curr
NetworkClientDelegate.UnsentRequest request = makeHeartbeatRequest(ignoreResponse);
heartbeatRequestState.onSendAttempt(currentTimeMs);
membershipManager.onHeartbeatRequestSent();
- lastHeartbeatSend = currentTimeMs;
return request;
}
@@ -273,7 +267,10 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
return logResponse(request);
else
return request.whenComplete((response, exception) -> {
+ System.out.print("=====");
if (response != null) {
+ System.out.print("ehhh: " + response.requestLatencyMs());
+ heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
onResponse((ConsumerGroupHeartbeatResponse) response.responseBody(), request.handler().completionTimeMs());
} else {
onFailure(exception, request.handler().completionTimeMs());
@@ -433,16 +430,18 @@ private void handleFatalFailure(Throwable error) {
}
private void registerLastSentHeartbeatMetric(Metrics metrics) {
+ final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
Measurable lastHeartbeat = (config, now) -> {
- if (lastHeartbeatSend == 0L)
+ if (lastHeartbeatSend < 0L)
// if no heartbeat is ever triggered, just return -1.
return -1d;
else
return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
};
- heartbeatMetrics.registerMeasurable(
- "heartbeat-time-max",
- "The max time taken to receive a response to a heartbeat request",
+ heartbeatMetrics.addMetric(
+ metrics,
+ "last-heartbeat-seconds-ago",
+ "The number of seconds since the last coordinator heartbeat was sent",
lastHeartbeat);
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index c9cd16b26f8cd..1c380b116b14e 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -16,6 +16,7 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.stats.Meter;
import org.apache.kafka.common.metrics.stats.WindowedCount;
@@ -27,12 +28,12 @@
public abstract class AbstractConsumerMetrics {
protected String groupMetricsName = CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX;
+
+ public AbstractConsumerMetrics() {}
public AbstractConsumerMetrics(Optional grpMetricsPrefix) {
grpMetricsPrefix.ifPresent(s -> this.groupMetricsName = s + COORDINATOR_METRICS_SUFFIX);
}
- public AbstractConsumerMetrics() {}
-
public static Meter createMeter(Metrics metrics, String groupName, String baseName, String descriptiveName) {
return new Meter(new WindowedCount(),
metrics.metricName(baseName + "-rate", groupName,
@@ -40,4 +41,13 @@ public static Meter createMeter(Metrics metrics, String groupName, String baseNa
metrics.metricName(baseName + "-total", groupName,
String.format("The total number of %s", descriptiveName)));
}
+
+ public void addMetric(Metrics metrics,
+ String name,
+ String description,
+ Measurable measurable) {
+ metrics.addMetric(
+ metrics.metricName(name, groupMetricsName, description),
+ measurable);
+ }
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
index 912295accc41d..ced8aaca6900b 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -16,32 +16,24 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
-import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.Sensor;
import org.apache.kafka.common.metrics.stats.Max;
public class HeartbeatMetrics extends AbstractConsumerMetrics {
- private final Metrics metrics;
public final Sensor heartbeatSensor;
public HeartbeatMetrics(Metrics metrics) {
super();
- this.metrics = metrics;
heartbeatSensor = metrics.sensor("heartbeat-latency");
heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
groupMetricsName,
- "The max time taken to receive a response to a heartbeat request"), new Max());
- heartbeatSensor.add(createMeter(metrics, groupMetricsName, "heartbeat", "heartbeats"));
-
- }
-
- public void registerMeasurable(String name,
- String description,
- Measurable measurable) {
- metrics.addMetric(
- metrics.metricName(name, groupMetricsName, description),
- measurable);
+ "The max time taken to receive a response to a heartbeat request"),
+ new Max());
+ heartbeatSensor.add(createMeter(metrics,
+ groupMetricsName,
+ "heartbeat",
+ "heartbeats"));
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 41cf9e39fe69c..1dd5d4e1e6a53 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -64,7 +64,6 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MAX_MS;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MS;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -564,6 +563,41 @@ public void testPollTimerExpiration() {
assertHeartbeat(heartbeatRequestManager);
}
+ @Test
+ public void testHeartbeatMetrics() {
+ coordinatorRequestManager = mock(CoordinatorRequestManager.class);
+ membershipManager = mock(MembershipManager.class);
+ heartbeatState = mock(HeartbeatRequestManager.HeartbeatState.class);
+ heartbeatRequestState = new HeartbeatRequestManager.HeartbeatRequestState(
+ new LogContext(),
+ time,
+ heartbeatIntervalMs,
+ retryBackoffMs,
+ retryBackoffMaxMs,
+ 0);
+ backgroundEventHandler = mock(BackgroundEventHandler.class);
+
+ heartbeatRequestManager = createHeartbeatRequestManager(
+ coordinatorRequestManager,
+ membershipManager,
+ heartbeatState,
+ heartbeatRequestState,
+ backgroundEventHandler);
+ when(coordinatorRequestManager.coordinator()).thenReturn(Optional.of(new Node(1, "localhost", 9999)));
+ when(membershipManager.shouldSkipHeartbeat()).thenReturn(false);
+ when(membershipManager.state()).thenReturn(MemberState.STABLE);
+ time.sleep(maxPollIntervalMs);
+ NetworkClientDelegate.PollResult pollResult = heartbeatRequestManager.poll(time.milliseconds());
+ ClientResponse hr = createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE);
+ pollResult.unsentRequests.get(0).future().complete(hr);
+
+ assertEquals(1, pollResult.unsentRequests.size());
+ //assertEquals(1, getMetric("heartbeat-response-time-max").metricValue());
+ assertEquals(0.0, getMetric("heartbeat-rate").metricValue());
+ assertEquals(1.0, getMetric("heartbeat-total").metricValue());
+ assertEquals(1, getMetric("last-heartbeat-seconds-ago").metricValue());
+ }
+
private void assertHeartbeat(HeartbeatRequestManager hrm) {
NetworkClientDelegate.PollResult pollResult = hrm.poll(time.milliseconds());
assertEquals(1, pollResult.unsentRequests.size());
@@ -674,10 +708,7 @@ private ConsumerConfig config() {
}
private void assertMetricsRecorded() {
- assertNotNull(getMetric("heartbeat-response-time-max"));
- assertNotNull(getMetric("heartbeat-rate"));
- assertNotNull(getMetric("heartbeat-total"));
- assertNotNull(getMetric("last-heartbeat-seconds-ago"));
+
}
private KafkaMetric getMetric(final String name) {
From 6bd15e84976e211b242fbf84d9da546946a1e349 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Thu, 25 Jan 2024 12:48:09 -0800
Subject: [PATCH 04/28] update test
clean up
remove bad code
---
.../internals/HeartbeatRequestManager.java | 25 ++++----
.../internals/AsyncKafkaConsumerTest.java | 18 ------
.../internals/ConsumerTestBuilder.java | 1 -
.../HeartbeatRequestManagerTest.java | 58 ++++++++++---------
4 files changed, 44 insertions(+), 58 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 6feb4154836d5..fdf312a99beab 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -136,8 +136,7 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
- this.heartbeatMetrics = new HeartbeatMetrics(metrics);
- registerLastSentHeartbeatMetric(metrics);
+ this.heartbeatMetrics = createHeartbeatMetrics(metrics);
}
// Visible for testing
@@ -159,8 +158,7 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
- this.heartbeatMetrics = new HeartbeatMetrics(metrics);
- registerLastSentHeartbeatMetric(metrics);
+ this.heartbeatMetrics = createHeartbeatMetrics(metrics);
}
/**
@@ -267,9 +265,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
return logResponse(request);
else
return request.whenComplete((response, exception) -> {
- System.out.print("=====");
if (response != null) {
- System.out.print("ehhh: " + response.requestLatencyMs());
heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
onResponse((ConsumerGroupHeartbeatResponse) response.responseBody(), request.handler().completionTimeMs());
} else {
@@ -281,6 +277,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
private NetworkClientDelegate.UnsentRequest logResponse(final NetworkClientDelegate.UnsentRequest request) {
return request.whenComplete((response, exception) -> {
if (response != null) {
+ heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
Errors error =
Errors.forCode(((ConsumerGroupHeartbeatResponse) response.responseBody()).data().errorCode());
if (error == Errors.NONE)
@@ -429,20 +426,22 @@ private void handleFatalFailure(Throwable error) {
membershipManager.transitionToFatal();
}
- private void registerLastSentHeartbeatMetric(Metrics metrics) {
- final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
+ private HeartbeatMetrics createHeartbeatMetrics(Metrics metrics) {
+ HeartbeatMetrics hbm = new HeartbeatMetrics(metrics);
Measurable lastHeartbeat = (config, now) -> {
+ final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
if (lastHeartbeatSend < 0L)
// if no heartbeat is ever triggered, just return -1.
return -1d;
else
return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
};
- heartbeatMetrics.addMetric(
- metrics,
- "last-heartbeat-seconds-ago",
- "The number of seconds since the last coordinator heartbeat was sent",
- lastHeartbeat);
+ hbm.addMetric(
+ metrics,
+ "last-heartbeat-seconds-ago",
+ "The number of seconds since the last coordinator heartbeat was sent",
+ lastHeartbeat);
+ return hbm;
}
/**
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
index 1e4991131f453..7c5f4f999cde5 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
@@ -59,7 +59,6 @@
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.errors.TimeoutException;
import org.apache.kafka.common.errors.WakeupException;
-import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.JoinGroupRequest;
@@ -1400,23 +1399,6 @@ public void testProcessBackgroundEventsTimesOut() throws Exception {
}
}
- @Test
- public void testBS() {
- rlb = 1000L;
- Measurable lastRebalance = (config, now) -> {
- return TimeUnit.SECONDS.convert(now - rlb, TimeUnit.MILLISECONDS);
- };
-
- System.out.println(lastRebalance.measure(null, System.currentTimeMillis())); // Prints some value
-
-// Update lastRebalanceEndMs
- rlb = 2000L;
-
- System.out.println(lastRebalance.measure(null, System.currentTimeMillis())); // Still uses the captured value,
- // not the updated one
-
- }
-
private HashMap mockTopicPartitionOffset() {
final TopicPartition t0 = new TopicPartition("t0", 2);
final TopicPartition t1 = new TopicPartition("t0", 3);
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
index bdd3836303ac9..62886c7996631 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
@@ -217,7 +217,6 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
retryBackoffMs,
DEFAULT_RETRY_BACKOFF_MAX_MS,
gi.heartbeatJitterMs));
-
HeartbeatRequestManager heartbeat = spy(new HeartbeatRequestManager(
logContext,
pollTimer,
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 1dd5d4e1e6a53..e63112b92f46b 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -37,6 +37,7 @@
import org.apache.kafka.common.requests.RequestHeader;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.utils.LogContext;
+import org.apache.kafka.common.utils.MockTime;
import org.apache.kafka.common.utils.Time;
import org.apache.kafka.common.utils.Timer;
import org.apache.kafka.common.utils.annotation.ApiKeyVersionsSource;
@@ -63,6 +64,8 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_REMOTE_ASSIGNOR;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MAX_MS;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MS;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -568,34 +571,41 @@ public void testHeartbeatMetrics() {
coordinatorRequestManager = mock(CoordinatorRequestManager.class);
membershipManager = mock(MembershipManager.class);
heartbeatState = mock(HeartbeatRequestManager.HeartbeatState.class);
- heartbeatRequestState = new HeartbeatRequestManager.HeartbeatRequestState(
- new LogContext(),
- time,
- heartbeatIntervalMs,
- retryBackoffMs,
- retryBackoffMaxMs,
- 0);
+ time = new MockTime();
+ metrics = new Metrics(time);
+ heartbeatRequestState = spy(new HeartbeatRequestManager.HeartbeatRequestState(
+ new LogContext(),
+ time,
+ 0, // This initial interval should be 0 to ensure heartbeat on the clock
+ retryBackoffMs,
+ retryBackoffMaxMs,
+ 0));
backgroundEventHandler = mock(BackgroundEventHandler.class);
-
heartbeatRequestManager = createHeartbeatRequestManager(
- coordinatorRequestManager,
- membershipManager,
- heartbeatState,
- heartbeatRequestState,
- backgroundEventHandler);
+ coordinatorRequestManager,
+ membershipManager,
+ heartbeatState,
+ heartbeatRequestState,
+ backgroundEventHandler);
when(coordinatorRequestManager.coordinator()).thenReturn(Optional.of(new Node(1, "localhost", 9999)));
- when(membershipManager.shouldSkipHeartbeat()).thenReturn(false);
when(membershipManager.state()).thenReturn(MemberState.STABLE);
- time.sleep(maxPollIntervalMs);
NetworkClientDelegate.PollResult pollResult = heartbeatRequestManager.poll(time.milliseconds());
- ClientResponse hr = createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE);
- pollResult.unsentRequests.get(0).future().complete(hr);
-
assertEquals(1, pollResult.unsentRequests.size());
- //assertEquals(1, getMetric("heartbeat-response-time-max").metricValue());
- assertEquals(0.0, getMetric("heartbeat-rate").metricValue());
+ pollResult.unsentRequests.get(0).handler().onComplete(
+ createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE));
+ time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(1.0, getMetric("heartbeat-total").metricValue());
- assertEquals(1, getMetric("last-heartbeat-seconds-ago").metricValue());
+ assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
+
+ pollResult = heartbeatRequestManager.poll(time.milliseconds());
+ assertEquals(1, pollResult.unsentRequests.size());
+ pollResult.unsentRequests.get(0).handler().onComplete(
+ createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE));
+
+ assertEquals(0.06d, (double) getMetric("heartbeat-rate").metricValue(), 0.005d);
+ assertEquals(2.0, getMetric("heartbeat-total").metricValue());
+ time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
+ assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
}
private void assertHeartbeat(HeartbeatRequestManager hrm) {
@@ -707,12 +717,8 @@ private ConsumerConfig config() {
return new ConsumerConfig(prop);
}
- private void assertMetricsRecorded() {
-
- }
-
private KafkaMetric getMetric(final String name) {
- return metrics.metrics().get(metrics.metricName(name, "consumer-coordinator-metrics"));
+ return metrics.metrics().get(metrics.metricName(name, CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX));
}
private HeartbeatRequestManager createHeartbeatRequestManager(
From 6759da15f54b09df0e1970d01d0fc52485b891b0 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 26 Jan 2024 11:24:46 -0800
Subject: [PATCH 05/28] clean up
clean up test
---
.../consumer/internals/ConsumerUtils.java | 2 +
.../metrics/AbstractConsumerMetrics.java | 65 +++++++--
.../internals/metrics/HeartbeatMetrics.java | 3 +-
.../metrics/RebalanceCallbackMetrics.java | 4 +-
.../internals/AsyncKafkaConsumerTest.java | 1 -
.../internals/ConsumerMetricsTest.java | 125 ++++++++++++++++++
.../HeartbeatRequestManagerTest.java | 27 ++--
7 files changed, 196 insertions(+), 31 deletions(-)
create mode 100644 clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
index bc7590c38f819..ddb79b034c872 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
@@ -66,6 +66,8 @@ public final class ConsumerUtils {
public static final String CONSUMER_JMX_PREFIX = "kafka.consumer";
public static final String CONSUMER_METRIC_GROUP_PREFIX = "consumer";
public static final String COORDINATOR_METRICS_SUFFIX = "-coordinator-metrics";
+ public static final String CONSUMER_METRICS_SUFFIX = "-metrics";
+ public static final String FETCH_MANAGER_METRICS_SUFFIX = "-fetch-manager-metrics";
/**
* A fixed, large enough value will suffice for max.
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index 1c380b116b14e..56f1a310b3f0d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -16,30 +16,72 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.clients.consumer.internals.ConsumerUtils;
import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.stats.Meter;
import org.apache.kafka.common.metrics.stats.WindowedCount;
+import java.util.Objects;
import java.util.Optional;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
+/**
+ * This class encapsulates the creation of metrics for the kafka consumer. When constructing a metrics object, you
+ * need to provide the suffix of the metric group. These are:
+ *
+ * Group Coordinator: {@link MetricSuffix#COORDINATOR}
+ * Consumer metrics: {@link MetricSuffix#CONSUMER}
+ * Fetch manager metrics: {@link MetricSuffix#FETCH_MANAGER}
+ *
+ *
+ * If no prefix is provided, we will use the default prefix {@link ConsumerUtils#CONSUMER_METRIC_GROUP_PREFIX}.
+ */
public abstract class AbstractConsumerMetrics {
- protected String groupMetricsName = CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX;
+ protected final String groupMetricsName;
+
+ public enum MetricSuffix {
+ COORDINATOR(COORDINATOR_METRICS_SUFFIX),
+ CONSUMER(CONSUMER_METRICS_SUFFIX),
+ FETCH_MANAGER(FETCH_MANAGER_METRICS_SUFFIX);
+
+ private final String suffix;
+
+ MetricSuffix(String suffix) {
+ this.suffix = suffix;
+ }
+
+ public String getSuffix() {
+ return suffix;
+ }
+ }
+
+ public AbstractConsumerMetrics(MetricSuffix suffix) {
+ this(Optional.empty(), suffix.getSuffix());
+ }
- public AbstractConsumerMetrics() {}
- public AbstractConsumerMetrics(Optional grpMetricsPrefix) {
- grpMetricsPrefix.ifPresent(s -> this.groupMetricsName = s + COORDINATOR_METRICS_SUFFIX);
+ public AbstractConsumerMetrics(Optional grpMetricsPrefix, String suffix) {
+ Objects.requireNonNull(suffix, "suffix cannot be null");
+ String prefix = grpMetricsPrefix.orElse(CONSUMER_METRIC_GROUP_PREFIX);
+ groupMetricsName = prefix + suffix;
}
- public static Meter createMeter(Metrics metrics, String groupName, String baseName, String descriptiveName) {
+ public String groupMetricsName() {
+ return groupMetricsName;
+ }
+
+ public Meter createMeter(Metrics metrics, String baseName, String descriptiveName) {
return new Meter(new WindowedCount(),
- metrics.metricName(baseName + "-rate", groupName,
- String.format("The number of %s per second", descriptiveName)),
- metrics.metricName(baseName + "-total", groupName,
- String.format("The total number of %s", descriptiveName)));
+ metrics.metricName(baseName + "-rate",
+ groupMetricsName,
+ String.format("The number of %s per second", descriptiveName)),
+ metrics.metricName(baseName + "-total",
+ groupMetricsName,
+ String.format("The total number of %s", descriptiveName)));
}
public void addMetric(Metrics metrics,
@@ -47,7 +89,8 @@ public void addMetric(Metrics metrics,
String description,
Measurable measurable) {
metrics.addMetric(
- metrics.metricName(name, groupMetricsName, description),
- measurable);
+ metrics.metricName(name, groupMetricsName, description),
+ measurable);
}
}
+
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
index ced8aaca6900b..ed9c93947ae5e 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -25,14 +25,13 @@ public class HeartbeatMetrics extends AbstractConsumerMetrics {
public final Sensor heartbeatSensor;
public HeartbeatMetrics(Metrics metrics) {
- super();
+ super(MetricSuffix.COORDINATOR);
heartbeatSensor = metrics.sensor("heartbeat-latency");
heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
groupMetricsName,
"The max time taken to receive a response to a heartbeat request"),
new Max());
heartbeatSensor.add(createMeter(metrics,
- groupMetricsName,
"heartbeat",
"heartbeats"));
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
index a27581505c517..c5850cd241a6e 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
@@ -21,8 +21,6 @@
import org.apache.kafka.common.metrics.stats.Avg;
import org.apache.kafka.common.metrics.stats.Max;
-import java.util.Optional;
-
public class RebalanceCallbackMetrics extends AbstractConsumerMetrics {
public final Sensor revokeCallbackSensor;
public final Sensor assignCallbackSensor;
@@ -33,7 +31,7 @@ public RebalanceCallbackMetrics(Metrics metrics) {
}
public RebalanceCallbackMetrics(Metrics metrics, String grpMetricsPrefix) {
- super(Optional.ofNullable(grpMetricsPrefix));
+ super(MetricSuffix.COORDINATOR);
revokeCallbackSensor = metrics.sensor("partition-revoked-latency");
revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
groupMetricsName,
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
index 7c5f4f999cde5..f6fb2a8928631 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
@@ -141,7 +141,6 @@ public class AsyncKafkaConsumerTest {
private final ApplicationEventHandler applicationEventHandler = mock(ApplicationEventHandler.class);
private final ConsumerMetadata metadata = mock(ConsumerMetadata.class);
private final LinkedBlockingQueue backgroundEventQueue = new LinkedBlockingQueue<>();
- long rlb = -1L;
@AfterEach
public void resetAll() {
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
new file mode 100644
index 0000000000000..9072575bada0e
--- /dev/null
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.kafka.clients.consumer.internals;
+
+import org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.common.metrics.KafkaMetric;
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.utils.MockTime;
+import org.apache.kafka.common.utils.Time;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class ConsumerMetricsTest {
+ private Time time = new MockTime();
+ private Metrics metrics = new Metrics(time);
+
+ @Test
+ public void testRebalanceCallbackMetrics() {
+ // MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
+ RebalanceCallbackMetrics rebalanceCallbackMetrics = new RebalanceCallbackMetrics(metrics);
+ String groupName = "consumer-coordinator-metrics";
+ assertNotNull(getMetric("partition-revoked-latency-avg", groupName));
+ assertNotNull(getMetric("partition-revoked-latency-max", groupName));
+ assertNotNull(getMetric("partition-assigned-latency-avg", groupName));
+ assertNotNull(getMetric("partition-assigned-latency-max", groupName));
+ assertNotNull(getMetric("partition-lost-latency-avg", groupName));
+ assertNotNull(getMetric("partition-lost-latency-max", groupName));
+
+ rebalanceCallbackMetrics.assignCallbackSensor.record(100);
+ rebalanceCallbackMetrics.revokeCallbackSensor.record(101);
+ rebalanceCallbackMetrics.loseCallbackSensor.record(102);
+
+ assertEquals(101d, getMetric("partition-revoked-latency-avg", groupName).metricValue());
+ assertEquals(101d, getMetric("partition-revoked-latency-max", groupName).metricValue());
+ assertEquals(100d, getMetric("partition-assigned-latency-avg", groupName).metricValue());
+ assertEquals(100d, getMetric("partition-assigned-latency-max", groupName).metricValue());
+ assertEquals(102d, getMetric("partition-lost-latency-avg", groupName).metricValue());
+ assertEquals(102d, getMetric("partition-lost-latency-max", groupName).metricValue());
+ }
+
+ @Test
+ public void testHeartbeatMetrics() {
+ // MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
+ HeartbeatMetrics heartbeatMetrics = new HeartbeatMetrics(metrics);
+ String groupName = "consumer-coordinator-metrics";
+ assertNotNull(getMetric("heartbeat-response-time-max", groupName));
+ assertNotNull(getMetric("heartbeat-rate", groupName));
+ assertNotNull(getMetric("heartbeat-total", groupName));
+
+ heartbeatMetrics.heartbeatSensor.record(100);
+ heartbeatMetrics.heartbeatSensor.record(100);
+ heartbeatMetrics.heartbeatSensor.record(100);
+
+ assertEquals(100d, getMetric("heartbeat-response-time-max", groupName).metricValue());
+ assertEquals(0.1d, (double) getMetric("heartbeat-rate", groupName).metricValue(), 0.01d);
+ assertEquals(3d, getMetric("heartbeat-total", groupName).metricValue());
+ }
+
+ @Test
+ public void testMetricsGroupName() {
+ // consumer-coordinator-metrics
+ NoopCoordinatorMetrics defaultCoordinatorMetrics = new NoopCoordinatorMetrics(Optional.empty());
+ assertEquals(CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX, defaultCoordinatorMetrics.groupMetricsName());
+ NoopCoordinatorMetrics coordinatorMetrics = new NoopCoordinatorMetrics(Optional.of("customCoordinatorPrefix"));
+ assertEquals("customCoordinatorPrefix" + COORDINATOR_METRICS_SUFFIX, coordinatorMetrics.groupMetricsName());
+
+ // consumer-metrics
+ NoopConsumerMetrics defaultConsumerMetrics = new NoopConsumerMetrics(Optional.empty());
+ assertEquals(CONSUMER_METRIC_GROUP_PREFIX + CONSUMER_METRICS_SUFFIX, defaultConsumerMetrics.groupMetricsName());
+ NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics(Optional.of("customConsumerPrefix"));
+ assertEquals("customConsumerPrefix" + CONSUMER_METRICS_SUFFIX, consumerMetrics.groupMetricsName());
+
+ // consumer-fetch-manager-metrics
+ NoopFetchManagerMetrics defaultFetchMetrics = new NoopFetchManagerMetrics(Optional.empty());
+ assertEquals(CONSUMER_METRIC_GROUP_PREFIX + FETCH_MANAGER_METRICS_SUFFIX, defaultFetchMetrics.groupMetricsName());
+ NoopFetchManagerMetrics fetchMetrics = new NoopFetchManagerMetrics(Optional.of("customFetchPrefix"));
+ assertEquals("customFetchPrefix" + FETCH_MANAGER_METRICS_SUFFIX, fetchMetrics.groupMetricsName());
+ }
+
+ private KafkaMetric getMetric(String metricName, String groupName) {
+ return metrics.metrics().get(metrics.metricName(metricName, groupName));
+ }
+
+ static class NoopCoordinatorMetrics extends AbstractConsumerMetrics {
+ public NoopCoordinatorMetrics(Optional prefix) {
+ super(prefix, MetricSuffix.COORDINATOR.getSuffix());
+ }
+ }
+
+ static class NoopConsumerMetrics extends AbstractConsumerMetrics {
+ public NoopConsumerMetrics(Optional prefix) {
+ super(prefix, MetricSuffix.CONSUMER.getSuffix());
+ }
+ }
+
+ static class NoopFetchManagerMetrics extends AbstractConsumerMetrics {
+ public NoopFetchManagerMetrics(Optional prefix) {
+ super(prefix, MetricSuffix.FETCH_MANAGER.getSuffix());
+ }
+ }
+}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index e63112b92f46b..8857c0f6c7b44 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -67,6 +67,7 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -554,8 +555,7 @@ public void testPollTimerExpiration() {
when(membershipManager.state()).thenReturn(MemberState.STABLE);
time.sleep(maxPollIntervalMs);
- NetworkClientDelegate.PollResult pollResult = heartbeatRequestManager.poll(time.milliseconds());
- assertEquals(1, pollResult.unsentRequests.size());
+ assertHeartbeat(heartbeatRequestManager, heartbeatIntervalMs);
verify(heartbeatState).reset();
verify(heartbeatRequestState).reset();
verify(membershipManager).transitionToStale();
@@ -563,7 +563,7 @@ public void testPollTimerExpiration() {
assertNoHeartbeat(heartbeatRequestManager);
heartbeatRequestManager.resetPollTimer(time.milliseconds());
assertTrue(pollTimer.notExpired());
- assertHeartbeat(heartbeatRequestManager);
+ assertHeartbeat(heartbeatRequestManager, heartbeatIntervalMs);
}
@Test
@@ -589,29 +589,28 @@ public void testHeartbeatMetrics() {
backgroundEventHandler);
when(coordinatorRequestManager.coordinator()).thenReturn(Optional.of(new Node(1, "localhost", 9999)));
when(membershipManager.state()).thenReturn(MemberState.STABLE);
- NetworkClientDelegate.PollResult pollResult = heartbeatRequestManager.poll(time.milliseconds());
- assertEquals(1, pollResult.unsentRequests.size());
- pollResult.unsentRequests.get(0).handler().onComplete(
- createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE));
+
+ assertNotNull(getMetric("heartbeat-response-time-max"));
+ assertNotNull(getMetric("heartbeat-rate"));
+ assertNotNull(getMetric("heartbeat-total"));
+ assertNotNull(getMetric("last-heartbeat-seconds-ago"));
+
+ assertHeartbeat(heartbeatRequestManager, 0);
time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(1.0, getMetric("heartbeat-total").metricValue());
assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
- pollResult = heartbeatRequestManager.poll(time.milliseconds());
- assertEquals(1, pollResult.unsentRequests.size());
- pollResult.unsentRequests.get(0).handler().onComplete(
- createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE));
-
+ assertHeartbeat(heartbeatRequestManager, DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(0.06d, (double) getMetric("heartbeat-rate").metricValue(), 0.005d);
assertEquals(2.0, getMetric("heartbeat-total").metricValue());
time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
}
- private void assertHeartbeat(HeartbeatRequestManager hrm) {
+ private void assertHeartbeat(HeartbeatRequestManager hrm, int nextPollMs) {
NetworkClientDelegate.PollResult pollResult = hrm.poll(time.milliseconds());
assertEquals(1, pollResult.unsentRequests.size());
- assertEquals(DEFAULT_HEARTBEAT_INTERVAL_MS, pollResult.timeUntilNextPollMs);
+ assertEquals(nextPollMs, pollResult.timeUntilNextPollMs);
pollResult.unsentRequests.get(0).handler().onComplete(createHeartbeatResponse(pollResult.unsentRequests.get(0),
Errors.NONE));
}
From 39c5239236ce1c01dd6ed6d67bf1b1da1a8548cd Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 26 Jan 2024 12:04:01 -0800
Subject: [PATCH 06/28] allow the manager to accept a group prefix
---
.../clients/consumer/internals/HeartbeatRequestManager.java | 6 ++++--
.../kafka/clients/consumer/internals/RequestManagers.java | 2 ++
.../clients/consumer/internals/ConsumerTestBuilder.java | 2 ++
.../consumer/internals/HeartbeatRequestManagerTest.java | 2 ++
4 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index fdf312a99beab..9ab81ccef3230 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -124,6 +124,7 @@ public HeartbeatRequestManager(
final SubscriptionState subscriptions,
final MembershipManager membershipManager,
final BackgroundEventHandler backgroundEventHandler,
+ final String metricGroupPrefix,
final Metrics metrics) {
this.coordinatorRequestManager = coordinatorRequestManager;
this.logger = logContext.logger(getClass());
@@ -136,7 +137,7 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
- this.heartbeatMetrics = createHeartbeatMetrics(metrics);
+ this.heartbeatMetrics = createHeartbeatMetrics(metrics, metricGroupPrefix);
}
// Visible for testing
@@ -149,6 +150,7 @@ public HeartbeatRequestManager(
final HeartbeatState heartbeatState,
final HeartbeatRequestState heartbeatRequestState,
final BackgroundEventHandler backgroundEventHandler,
+ final String metricGroupPrefix,
final Metrics metrics) {
this.logger = logContext.logger(this.getClass());
this.maxPollIntervalMs = config.getInt(CommonClientConfigs.MAX_POLL_INTERVAL_MS_CONFIG);
@@ -158,7 +160,7 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
- this.heartbeatMetrics = createHeartbeatMetrics(metrics);
+ this.heartbeatMetrics = createHeartbeatMetrics(metrics, metricGroupPrefix);
}
/**
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
index 7b3e75be0182c..b98f82d738e82 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
@@ -35,6 +35,7 @@
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.common.utils.Utils.closeQuietly;
/**
@@ -191,6 +192,7 @@ protected RequestManagers create() {
subscriptions,
membershipManager,
backgroundEventHandler,
+ CONSUMER_METRIC_GROUP_PREFIX,
metrics);
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
index 62886c7996631..b747945b73a71 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
@@ -48,6 +48,7 @@
import static org.apache.kafka.clients.consumer.ConsumerConfig.GROUP_INSTANCE_ID_CONFIG;
import static org.apache.kafka.clients.consumer.ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG;
import static org.apache.kafka.clients.consumer.ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createFetchMetricsManager;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createMetrics;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createSubscriptionState;
@@ -226,6 +227,7 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
heartbeatState,
heartbeatRequestState,
backgroundEventHandler,
+ CONSUMER_METRIC_GROUP_PREFIX,
metrics));
this.coordinatorRequestManager = Optional.of(coordinator);
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 8857c0f6c7b44..41a31a7eb18f7 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -85,6 +85,7 @@ public class HeartbeatRequestManagerTest {
private int maxPollIntervalMs = DEFAULT_MAX_POLL_INTERVAL_MS;
private long retryBackoffMaxMs = DEFAULT_RETRY_BACKOFF_MAX_MS;
private static final String DEFAULT_GROUP_ID = "groupId";
+ private String metricGroupPrefix = CONSUMER_METRIC_GROUP_PREFIX;
private ConsumerTestBuilder testBuilder;
private Time time;
@@ -737,6 +738,7 @@ private HeartbeatRequestManager createHeartbeatRequestManager(
heartbeatState,
heartbeatRequestState,
backgroundEventHandler,
+ metricGroupPrefix,
metrics);
}
}
From c55dae2f3588ae76f265edace71fccce88964963 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 26 Jan 2024 14:31:20 -0800
Subject: [PATCH 07/28] clean up
---
.../internals/HeartbeatRequestManager.java | 2 +-
.../metrics/AbstractConsumerMetrics.java | 60 ++++++++++---------
.../internals/metrics/HeartbeatMetrics.java | 16 +++--
.../metrics/RebalanceCallbackMetrics.java | 14 ++---
.../internals/ConsumerMetricsTest.java | 41 ++++---------
.../HeartbeatRequestManagerTest.java | 2 +-
6 files changed, 65 insertions(+), 70 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 9ab81ccef3230..267b2c465d1b8 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -428,7 +428,7 @@ private void handleFatalFailure(Throwable error) {
membershipManager.transitionToFatal();
}
- private HeartbeatMetrics createHeartbeatMetrics(Metrics metrics) {
+ private HeartbeatMetrics createHeartbeatMetrics(Metrics metrics, String metricGroupPrefix) {
HeartbeatMetrics hbm = new HeartbeatMetrics(metrics);
Measurable lastHeartbeat = (config, now) -> {
final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index 56f1a310b3f0d..950fdf566cb0d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -22,74 +22,80 @@
import org.apache.kafka.common.metrics.stats.Meter;
import org.apache.kafka.common.metrics.stats.WindowedCount;
-import java.util.Objects;
-import java.util.Optional;
-
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
/**
- * This class encapsulates the creation of metrics for the kafka consumer. When constructing a metrics object, you
- * need to provide the suffix of the metric group. These are:
- *
- * Group Coordinator: {@link MetricSuffix#COORDINATOR}
- * Consumer metrics: {@link MetricSuffix#CONSUMER}
- * Fetch manager metrics: {@link MetricSuffix#FETCH_MANAGER}
- *
+ * Base class for different consumer metrics to extend. This class helps to construct the logical group name from the
+ * given prefix and suffix, and provides a few common utilities.
+ *
+ *
+ * Prefix can be provided by the user and is "consumer-" by default (see {@link ConsumerUtils#CONSUMER_METRIC_GROUP_PREFIX}).
+ *
*
- * If no prefix is provided, we will use the default prefix {@link ConsumerUtils#CONSUMER_METRIC_GROUP_PREFIX}.
+ *
+ * The suffix can be one of the following:
+ *
+ * -coordinator-metrics: {@link MetricGroupSuffix#COORDINATOR}
+ * -metrics: {@link MetricGroupSuffix#CONSUMER}
+ * -fetch-manager-metrics: {@link MetricGroupSuffix#FETCH_MANAGER}
+ *
+ *
*/
public abstract class AbstractConsumerMetrics {
- protected final String groupMetricsName;
+ protected final String metricGroupName;
- public enum MetricSuffix {
+ public enum MetricGroupSuffix {
COORDINATOR(COORDINATOR_METRICS_SUFFIX),
CONSUMER(CONSUMER_METRICS_SUFFIX),
FETCH_MANAGER(FETCH_MANAGER_METRICS_SUFFIX);
private final String suffix;
- MetricSuffix(String suffix) {
+ MetricGroupSuffix(String suffix) {
this.suffix = suffix;
}
- public String getSuffix() {
+ @Override
+ public String toString() {
return suffix;
}
}
- public AbstractConsumerMetrics(MetricSuffix suffix) {
- this(Optional.empty(), suffix.getSuffix());
+ public AbstractConsumerMetrics(MetricGroupSuffix suffix) {
+ this(CONSUMER_METRIC_GROUP_PREFIX, suffix.toString());
}
- public AbstractConsumerMetrics(Optional grpMetricsPrefix, String suffix) {
- Objects.requireNonNull(suffix, "suffix cannot be null");
- String prefix = grpMetricsPrefix.orElse(CONSUMER_METRIC_GROUP_PREFIX);
- groupMetricsName = prefix + suffix;
+ public AbstractConsumerMetrics(String prefix, String suffix) {
+ if (suffix == null)
+ throw new IllegalArgumentException("metric group suffix cannot be null");
+ if (prefix == null)
+ throw new IllegalArgumentException("metric group prefix cannot be null");
+ metricGroupName = prefix + suffix;
}
- public String groupMetricsName() {
- return groupMetricsName;
+ public String metricGroupName() {
+ return metricGroupName;
}
public Meter createMeter(Metrics metrics, String baseName, String descriptiveName) {
return new Meter(new WindowedCount(),
metrics.metricName(baseName + "-rate",
- groupMetricsName,
+ metricGroupName,
String.format("The number of %s per second", descriptiveName)),
metrics.metricName(baseName + "-total",
- groupMetricsName,
+ metricGroupName,
String.format("The total number of %s", descriptiveName)));
}
public void addMetric(Metrics metrics,
- String name,
+ String metricName,
String description,
Measurable measurable) {
metrics.addMetric(
- metrics.metricName(name, groupMetricsName, description),
+ metrics.metricName(metricName, metricGroupName, description),
measurable);
}
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
index ed9c93947ae5e..4ec2899188cf2 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -20,19 +20,25 @@
import org.apache.kafka.common.metrics.Sensor;
import org.apache.kafka.common.metrics.stats.Max;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+
public class HeartbeatMetrics extends AbstractConsumerMetrics {
public final Sensor heartbeatSensor;
public HeartbeatMetrics(Metrics metrics) {
- super(MetricSuffix.COORDINATOR);
+ this(metrics, CONSUMER_METRIC_GROUP_PREFIX);
+ }
+
+ public HeartbeatMetrics(Metrics metrics, String prefix) {
+ super(MetricGroupSuffix.COORDINATOR);
heartbeatSensor = metrics.sensor("heartbeat-latency");
heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
- groupMetricsName,
+ metricGroupName,
"The max time taken to receive a response to a heartbeat request"),
- new Max());
+ new Max());
heartbeatSensor.add(createMeter(metrics,
- "heartbeat",
- "heartbeats"));
+ "heartbeat",
+ "heartbeats"));
}
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
index c5850cd241a6e..b0c1bad324663 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
@@ -31,29 +31,29 @@ public RebalanceCallbackMetrics(Metrics metrics) {
}
public RebalanceCallbackMetrics(Metrics metrics, String grpMetricsPrefix) {
- super(MetricSuffix.COORDINATOR);
+ super(MetricGroupSuffix.COORDINATOR);
revokeCallbackSensor = metrics.sensor("partition-revoked-latency");
revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
- groupMetricsName,
+ metricGroupName,
"The average time taken for a partition-revoked rebalance listener callback"), new Avg());
revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-max",
- groupMetricsName,
+ metricGroupName,
"The max time taken for a partition-revoked rebalance listener callback"), new Max());
assignCallbackSensor = metrics.sensor("partition-assigned-latency");
assignCallbackSensor.add(metrics.metricName("partition-assigned-latency-avg",
- groupMetricsName,
+ metricGroupName,
"The average time taken for a partition-assigned rebalance listener callback"), new Avg());
assignCallbackSensor.add(metrics.metricName("partition-assigned-latency-max",
- groupMetricsName,
+ metricGroupName,
"The max time taken for a partition-assigned rebalance listener callback"), new Max());
loseCallbackSensor = metrics.sensor("partition-lost-latency");
loseCallbackSensor.add(metrics.metricName("partition-lost-latency-avg",
- groupMetricsName,
+ metricGroupName,
"The average time taken for a partition-lost rebalance listener callback"), new Avg());
loseCallbackSensor.add(metrics.metricName("partition-lost-latency-max",
- groupMetricsName,
+ metricGroupName,
"The max time taken for a partition-lost rebalance listener callback"), new Max());
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
index 9072575bada0e..343e74ce40965 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
@@ -25,14 +25,12 @@
import org.apache.kafka.common.utils.Time;
import org.junit.jupiter.api.Test;
-import java.util.Optional;
-
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
public class ConsumerMetricsTest {
private Time time = new MockTime();
@@ -83,43 +81,28 @@ public void testHeartbeatMetrics() {
@Test
public void testMetricsGroupName() {
// consumer-coordinator-metrics
- NoopCoordinatorMetrics defaultCoordinatorMetrics = new NoopCoordinatorMetrics(Optional.empty());
- assertEquals(CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX, defaultCoordinatorMetrics.groupMetricsName());
- NoopCoordinatorMetrics coordinatorMetrics = new NoopCoordinatorMetrics(Optional.of("customCoordinatorPrefix"));
- assertEquals("customCoordinatorPrefix" + COORDINATOR_METRICS_SUFFIX, coordinatorMetrics.groupMetricsName());
+ NoopConsumerMetrics coordinatorMetrics = new NoopConsumerMetrics("customCoordinatorPrefix", AbstractConsumerMetrics.MetricGroupSuffix.COORDINATOR);
+ assertEquals("customCoordinatorPrefix" + COORDINATOR_METRICS_SUFFIX, coordinatorMetrics.metricGroupName());
// consumer-metrics
- NoopConsumerMetrics defaultConsumerMetrics = new NoopConsumerMetrics(Optional.empty());
- assertEquals(CONSUMER_METRIC_GROUP_PREFIX + CONSUMER_METRICS_SUFFIX, defaultConsumerMetrics.groupMetricsName());
- NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics(Optional.of("customConsumerPrefix"));
- assertEquals("customConsumerPrefix" + CONSUMER_METRICS_SUFFIX, consumerMetrics.groupMetricsName());
+ NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics("customConsumerPrefix", AbstractConsumerMetrics.MetricGroupSuffix.CONSUMER);
+ assertEquals("customConsumerPrefix" + CONSUMER_METRICS_SUFFIX, consumerMetrics.metricGroupName());
// consumer-fetch-manager-metrics
- NoopFetchManagerMetrics defaultFetchMetrics = new NoopFetchManagerMetrics(Optional.empty());
- assertEquals(CONSUMER_METRIC_GROUP_PREFIX + FETCH_MANAGER_METRICS_SUFFIX, defaultFetchMetrics.groupMetricsName());
- NoopFetchManagerMetrics fetchMetrics = new NoopFetchManagerMetrics(Optional.of("customFetchPrefix"));
- assertEquals("customFetchPrefix" + FETCH_MANAGER_METRICS_SUFFIX, fetchMetrics.groupMetricsName());
+ NoopConsumerMetrics fetchMetrics = new NoopConsumerMetrics("customFetchPrefix", AbstractConsumerMetrics.MetricGroupSuffix.FETCH_MANAGER);
+ assertEquals("customFetchPrefix" + FETCH_MANAGER_METRICS_SUFFIX, fetchMetrics.metricGroupName());
+
+ assertThrows(IllegalArgumentException.class, () -> new NoopConsumerMetrics(null,
+ AbstractConsumerMetrics.MetricGroupSuffix.CONSUMER));
}
private KafkaMetric getMetric(String metricName, String groupName) {
return metrics.metrics().get(metrics.metricName(metricName, groupName));
}
- static class NoopCoordinatorMetrics extends AbstractConsumerMetrics {
- public NoopCoordinatorMetrics(Optional prefix) {
- super(prefix, MetricSuffix.COORDINATOR.getSuffix());
- }
- }
-
static class NoopConsumerMetrics extends AbstractConsumerMetrics {
- public NoopConsumerMetrics(Optional prefix) {
- super(prefix, MetricSuffix.CONSUMER.getSuffix());
- }
- }
-
- static class NoopFetchManagerMetrics extends AbstractConsumerMetrics {
- public NoopFetchManagerMetrics(Optional prefix) {
- super(prefix, MetricSuffix.FETCH_MANAGER.getSuffix());
+ public NoopConsumerMetrics(String prefix, MetricGroupSuffix suffix) {
+ super(prefix, suffix.toString());
}
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 41a31a7eb18f7..68822970c17eb 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -718,7 +718,7 @@ private ConsumerConfig config() {
}
private KafkaMetric getMetric(final String name) {
- return metrics.metrics().get(metrics.metricName(name, CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX));
+ return metrics.metrics().get(metrics.metricName(name, metricGroupPrefix + COORDINATOR_METRICS_SUFFIX));
}
private HeartbeatRequestManager createHeartbeatRequestManager(
From df8ac287e194315bd031c3e42c195067d6f91179 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 26 Jan 2024 15:39:38 -0800
Subject: [PATCH 08/28] Update AbstractConsumerMetrics.java
---
.../consumer/internals/metrics/AbstractConsumerMetrics.java | 5 -----
1 file changed, 5 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index 950fdf566cb0d..3e27167ddc286 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -16,7 +16,6 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
-import org.apache.kafka.clients.consumer.internals.ConsumerUtils;
import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.stats.Meter;
@@ -32,10 +31,6 @@
* given prefix and suffix, and provides a few common utilities.
*
*
- * Prefix can be provided by the user and is "consumer-" by default (see {@link ConsumerUtils#CONSUMER_METRIC_GROUP_PREFIX}).
- *
- *
- *
* The suffix can be one of the following:
*
* -coordinator-metrics: {@link MetricGroupSuffix#COORDINATOR}
From 61519640aba71332a512daa4a28bb86642e8ab50 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Sun, 28 Jan 2024 10:08:20 -0800
Subject: [PATCH 09/28] Reconsolidate metrics into consumer coordinator metrics
clean up
---
.../kafka/clients/consumer/KafkaConsumer.java | 2 +-
.../internals/AsyncKafkaConsumer.java | 7 +-
.../internals/CommitRequestManager.java | 33 +--------
.../internals/ConsumerCoordinator.java | 4 +-
.../consumer/internals/ConsumerDelegate.java | 1 +
.../ConsumerRebalanceListenerInvoker.java | 12 +--
.../consumer/internals/ConsumerUtils.java | 1 -
.../internals/HeartbeatRequestManager.java | 35 ++-------
.../internals/LegacyKafkaConsumer.java | 1 +
.../consumer/internals/RequestManagers.java | 2 -
...va => AbstractConsumerMetricsManager.java} | 19 ++---
.../internals/metrics/HeartbeatMetrics.java | 44 -----------
.../metrics/HeartbeatMetricsManager.java | 69 +++++++++++++++++
.../{ => metrics}/KafkaConsumerMetrics.java | 10 +--
.../metrics/OffsetCommitMetricsManager.java | 50 +++++++++++++
.../metrics/RebalanceCallbackMetrics.java | 59 ---------------
.../RebalanceCallbackMetricsManager.java | 74 +++++++++++++++++++
.../internals/CommitRequestManagerTest.java | 1 -
...t.java => ConsumerMetricsManagerTest.java} | 44 +++++------
.../internals/ConsumerTestBuilder.java | 6 +-
.../HeartbeatRequestManagerTest.java | 6 +-
.../internals/KafkaConsumerMetricsTest.java | 1 +
.../internals/MembershipManagerImplTest.java | 4 +-
23 files changed, 258 insertions(+), 227 deletions(-)
rename clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/{AbstractConsumerMetrics.java => AbstractConsumerMetricsManager.java} (81%)
delete mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
create mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
rename clients/src/main/java/org/apache/kafka/clients/consumer/internals/{ => metrics}/KafkaConsumerMetrics.java (93%)
create mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
delete mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
create mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
rename clients/src/test/java/org/apache/kafka/clients/consumer/internals/{ConsumerMetricsTest.java => ConsumerMetricsManagerTest.java} (75%)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java
index 82e1f8b93da3c..bb75a40657311 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java
@@ -20,7 +20,7 @@
import org.apache.kafka.clients.consumer.internals.ConsumerDelegate;
import org.apache.kafka.clients.consumer.internals.ConsumerDelegateCreator;
import org.apache.kafka.clients.consumer.internals.ConsumerMetadata;
-import org.apache.kafka.clients.consumer.internals.KafkaConsumerMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
import org.apache.kafka.clients.consumer.internals.SubscriptionState;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.Metric;
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java
index c6b9efa23aef5..9198039a85a44 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java
@@ -60,7 +60,8 @@
import org.apache.kafka.clients.consumer.internals.events.TopicMetadataApplicationEvent;
import org.apache.kafka.clients.consumer.internals.events.UnsubscribeApplicationEvent;
import org.apache.kafka.clients.consumer.internals.events.ValidatePositionsApplicationEvent;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.IsolationLevel;
import org.apache.kafka.common.KafkaException;
@@ -395,7 +396,7 @@ private void process(final ConsumerRebalanceListenerCallbackNeededEvent event) {
logContext,
subscriptions,
time,
- new RebalanceCallbackMetrics(metrics)
+ new RebalanceCallbackMetricsManager(metrics)
);
this.backgroundEventProcessor = new BackgroundEventProcessor(
logContext,
@@ -538,7 +539,7 @@ private void process(final ConsumerRebalanceListenerCallbackNeededEvent event) {
logContext,
subscriptions,
time,
- new RebalanceCallbackMetrics(metrics)
+ new RebalanceCallbackMetricsManager(metrics, CONSUMER_METRIC_GROUP_PREFIX)
);
ApiVersions apiVersions = new ApiVersions();
Supplier networkClientDelegateSupplier = () -> new NetworkClientDelegate(
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
index 4ab1084eaa479..286bc9d59b9bf 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
@@ -21,6 +21,7 @@
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.OffsetAndMetadata;
import org.apache.kafka.clients.consumer.RetriableCommitFailedException;
+import org.apache.kafka.clients.consumer.internals.metrics.OffsetCommitMetricsManager;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.errors.DisconnectException;
@@ -31,11 +32,6 @@
import org.apache.kafka.common.message.OffsetCommitRequestData;
import org.apache.kafka.common.message.OffsetCommitResponseData;
import org.apache.kafka.common.metrics.Metrics;
-import org.apache.kafka.common.metrics.Sensor;
-import org.apache.kafka.common.metrics.stats.Avg;
-import org.apache.kafka.common.metrics.stats.Max;
-import org.apache.kafka.common.metrics.stats.Meter;
-import org.apache.kafka.common.metrics.stats.WindowedCount;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.record.RecordBatch;
import org.apache.kafka.common.requests.OffsetCommitRequest;
@@ -64,8 +60,6 @@
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.THROW_ON_FETCH_STABLE_OFFSET_UNSUPPORTED;
import static org.apache.kafka.clients.consumer.internals.NetworkClientDelegate.PollResult.EMPTY;
import static org.apache.kafka.common.protocol.Errors.COORDINATOR_LOAD_IN_PROGRESS;
@@ -85,7 +79,7 @@ public class CommitRequestManager implements RequestManager, MemberStateListener
private final boolean throwOnFetchStableOffsetUnsupported;
final PendingRequests pendingRequests;
private boolean closing = false;
- private Sensor commitSensor;
+ private OffsetCommitMetricsManager offsetCommitMetricsManager;
/**
* Latest member ID and epoch received via the {@link #onMemberEpochUpdated(Optional, Optional)},
@@ -114,7 +108,6 @@ public CommitRequestManager(
config.getLong(ConsumerConfig.RETRY_BACKOFF_MS_CONFIG),
config.getLong(ConsumerConfig.RETRY_BACKOFF_MAX_MS_CONFIG),
OptionalDouble.empty(),
- CONSUMER_METRIC_GROUP_PREFIX,
metrics);
}
@@ -130,7 +123,6 @@ public CommitRequestManager(
final long retryBackoffMs,
final long retryBackoffMaxMs,
final OptionalDouble jitter,
- final String metricGroupPrefix,
final Metrics metrics) {
Objects.requireNonNull(coordinatorRequestManager, "Coordinator is needed upon committing offsets");
this.logContext = logContext;
@@ -152,7 +144,7 @@ public CommitRequestManager(
this.jitter = jitter;
this.throwOnFetchStableOffsetUnsupported = config.getBoolean(THROW_ON_FETCH_STABLE_OFFSET_UNSUPPORTED);
this.memberInfo = new MemberInfo();
- this.commitSensor = addCommitSensor(metrics, metricGroupPrefix);
+ this.offsetCommitMetricsManager = new OffsetCommitMetricsManager(metrics);
}
/**
@@ -392,23 +384,6 @@ public NetworkClientDelegate.PollResult drainPendingOffsetCommitRequests() {
return new NetworkClientDelegate.PollResult(Long.MAX_VALUE, requests);
}
- private Sensor addCommitSensor(Metrics metrics, String metricGrpPrefix) {
- String metricGrpName = metricGrpPrefix + COORDINATOR_METRICS_SUFFIX;
- Sensor sensor = metrics.sensor("commit-latency");
- sensor.add(metrics.metricName("commit-latency-avg",
- metricGrpName,
- "The average time taken for a commit request"), new Avg());
- sensor.add(metrics.metricName("commit-latency-max",
- metricGrpName,
- "The max time taken for a commit request"), new Max());
- sensor.add(new Meter(new WindowedCount(),
- metrics.metricName("commit-rate", metricGrpName,
- "The number of commit calls per second"),
- metrics.metricName("commit-total", metricGrpName,
- "The total number of commit calls")));
- return sensor;
- }
-
private class OffsetCommitRequestState extends RetriableRequestState {
private final Map offsets;
private final String groupId;
@@ -521,7 +496,7 @@ public NetworkClientDelegate.UnsentRequest toUnsentRequest() {
}
public void onResponse(final ClientResponse response) {
- commitSensor.record(response.requestLatencyMs());
+ offsetCommitMetricsManager.recordRequestLatency(response.requestLatencyMs());
long currentTimeMs = response.receivedTimeMs();
OffsetCommitResponse commitResponse = (OffsetCommitResponse) response.responseBody();
Set unauthorizedTopics = new HashSet<>();
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java
index 398baf7fb079c..5af8633806da8 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java
@@ -29,7 +29,7 @@
import org.apache.kafka.clients.consumer.OffsetCommitCallback;
import org.apache.kafka.clients.consumer.RetriableCommitFailedException;
import org.apache.kafka.clients.consumer.internals.Utils.TopicPartitionComparator;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.Node;
@@ -235,7 +235,7 @@ public ConsumerCoordinator(GroupRebalanceConfig rebalanceConfig,
logContext,
subscriptions,
time,
- new RebalanceCallbackMetrics(metrics, metricGrpPrefix)
+ new RebalanceCallbackMetricsManager(metrics, metricGrpPrefix)
);
this.metadata.requestUpdate(true);
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerDelegate.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerDelegate.java
index 612827ebe83df..67e8d991d639f 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerDelegate.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerDelegate.java
@@ -17,6 +17,7 @@
package org.apache.kafka.clients.consumer.internals;
import org.apache.kafka.clients.consumer.Consumer;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.utils.Timer;
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
index ea60436deb1ed..ca68158d4cf3b 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
@@ -17,7 +17,7 @@
package org.apache.kafka.clients.consumer.internals;
import org.apache.kafka.clients.consumer.ConsumerRebalanceListener;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.errors.InterruptException;
import org.apache.kafka.common.errors.WakeupException;
@@ -41,12 +41,12 @@ public class ConsumerRebalanceListenerInvoker {
private final Logger log;
private final SubscriptionState subscriptions;
private final Time time;
- private final RebalanceCallbackMetrics metrics;
+ private final RebalanceCallbackMetricsManager metrics;
ConsumerRebalanceListenerInvoker(LogContext logContext,
SubscriptionState subscriptions,
Time time,
- RebalanceCallbackMetrics metrics) {
+ RebalanceCallbackMetricsManager metrics) {
this.log = logContext.logger(getClass());
this.subscriptions = subscriptions;
this.time = time;
@@ -62,7 +62,7 @@ public Exception invokePartitionsAssigned(final SortedSet assign
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsAssigned(assignedPartitions);
- metrics.assignCallbackSensor.record(time.milliseconds() - startMs);
+ metrics.recordPartitionAssignLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -88,7 +88,7 @@ public Exception invokePartitionsRevoked(final SortedSet revoked
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsRevoked(revokedPartitions);
- metrics.revokeCallbackSensor.record(time.milliseconds() - startMs);
+ metrics.recordPartitionRevokeLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -114,7 +114,7 @@ public Exception invokePartitionsLost(final SortedSet lostPartit
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsLost(lostPartitions);
- metrics.loseCallbackSensor.record(time.milliseconds() - startMs);
+ metrics.recordPartitionLostLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
index ddb79b034c872..5a7745b40dd0d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
@@ -67,7 +67,6 @@ public final class ConsumerUtils {
public static final String CONSUMER_METRIC_GROUP_PREFIX = "consumer";
public static final String COORDINATOR_METRICS_SUFFIX = "-coordinator-metrics";
public static final String CONSUMER_METRICS_SUFFIX = "-metrics";
- public static final String FETCH_MANAGER_METRICS_SUFFIX = "-fetch-manager-metrics";
/**
* A fixed, large enough value will suffice for max.
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 267b2c465d1b8..2e0e63f786e40 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -23,12 +23,11 @@
import org.apache.kafka.clients.consumer.internals.events.BackgroundEventHandler;
import org.apache.kafka.clients.consumer.internals.events.ErrorBackgroundEvent;
import org.apache.kafka.clients.consumer.internals.events.GroupMetadataUpdateEvent;
-import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetricsManager;
import org.apache.kafka.common.Uuid;
import org.apache.kafka.common.errors.GroupAuthorizationException;
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatRequestData;
-import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.ConsumerGroupHeartbeatRequest;
@@ -44,7 +43,6 @@
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
-import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -112,7 +110,7 @@ public class HeartbeatRequestManager implements RequestManager {
* sending heartbeat until the next poll.
*/
private final Timer pollTimer;
- private final HeartbeatMetrics heartbeatMetrics;
+ private final HeartbeatMetricsManager heartbeatMetricsManager;
private GroupMetadataUpdateEvent previousGroupMetadataUpdateEvent = null;
@@ -124,7 +122,6 @@ public HeartbeatRequestManager(
final SubscriptionState subscriptions,
final MembershipManager membershipManager,
final BackgroundEventHandler backgroundEventHandler,
- final String metricGroupPrefix,
final Metrics metrics) {
this.coordinatorRequestManager = coordinatorRequestManager;
this.logger = logContext.logger(getClass());
@@ -137,7 +134,7 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
- this.heartbeatMetrics = createHeartbeatMetrics(metrics, metricGroupPrefix);
+ this.heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
}
// Visible for testing
@@ -150,7 +147,6 @@ public HeartbeatRequestManager(
final HeartbeatState heartbeatState,
final HeartbeatRequestState heartbeatRequestState,
final BackgroundEventHandler backgroundEventHandler,
- final String metricGroupPrefix,
final Metrics metrics) {
this.logger = logContext.logger(this.getClass());
this.maxPollIntervalMs = config.getInt(CommonClientConfigs.MAX_POLL_INTERVAL_MS_CONFIG);
@@ -160,7 +156,7 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
- this.heartbeatMetrics = createHeartbeatMetrics(metrics, metricGroupPrefix);
+ this.heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
}
/**
@@ -256,6 +252,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final long curr
NetworkClientDelegate.UnsentRequest request = makeHeartbeatRequest(ignoreResponse);
heartbeatRequestState.onSendAttempt(currentTimeMs);
membershipManager.onHeartbeatRequestSent();
+ heartbeatMetricsManager.recordHeartbeatSentMs(currentTimeMs);
return request;
}
@@ -268,7 +265,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
else
return request.whenComplete((response, exception) -> {
if (response != null) {
- heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
+ heartbeatMetricsManager.recordRequestLatency(response.requestLatencyMs());
onResponse((ConsumerGroupHeartbeatResponse) response.responseBody(), request.handler().completionTimeMs());
} else {
onFailure(exception, request.handler().completionTimeMs());
@@ -279,7 +276,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
private NetworkClientDelegate.UnsentRequest logResponse(final NetworkClientDelegate.UnsentRequest request) {
return request.whenComplete((response, exception) -> {
if (response != null) {
- heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
+ heartbeatMetricsManager.recordRequestLatency(response.requestLatencyMs());
Errors error =
Errors.forCode(((ConsumerGroupHeartbeatResponse) response.responseBody()).data().errorCode());
if (error == Errors.NONE)
@@ -428,24 +425,6 @@ private void handleFatalFailure(Throwable error) {
membershipManager.transitionToFatal();
}
- private HeartbeatMetrics createHeartbeatMetrics(Metrics metrics, String metricGroupPrefix) {
- HeartbeatMetrics hbm = new HeartbeatMetrics(metrics);
- Measurable lastHeartbeat = (config, now) -> {
- final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
- if (lastHeartbeatSend < 0L)
- // if no heartbeat is ever triggered, just return -1.
- return -1d;
- else
- return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
- };
- hbm.addMetric(
- metrics,
- "last-heartbeat-seconds-ago",
- "The number of seconds since the last coordinator heartbeat was sent",
- lastHeartbeat);
- return hbm;
- }
-
/**
* Represents the state of a heartbeat request, including logic for timing, retries, and exponential backoff. The
* object extends {@link RequestState} to enable exponential backoff and duplicated request handling. The two fields
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/LegacyKafkaConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/LegacyKafkaConsumer.java
index bcc8cb40f2d91..80be0959d69cb 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/LegacyKafkaConsumer.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/LegacyKafkaConsumer.java
@@ -35,6 +35,7 @@
import org.apache.kafka.clients.consumer.OffsetAndTimestamp;
import org.apache.kafka.clients.consumer.OffsetCommitCallback;
import org.apache.kafka.clients.consumer.OffsetResetStrategy;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.IsolationLevel;
import org.apache.kafka.common.KafkaException;
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
index b98f82d738e82..7b3e75be0182c 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
@@ -35,7 +35,6 @@
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.common.utils.Utils.closeQuietly;
/**
@@ -192,7 +191,6 @@ protected RequestManagers create() {
subscriptions,
membershipManager,
backgroundEventHandler,
- CONSUMER_METRIC_GROUP_PREFIX,
metrics);
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
similarity index 81%
rename from clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
rename to clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
index 3e27167ddc286..1eafcfa95bfbc 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
@@ -22,9 +22,7 @@
import org.apache.kafka.common.metrics.stats.WindowedCount;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
/**
* Base class for different consumer metrics to extend. This class helps to construct the logical group name from the
@@ -35,17 +33,16 @@
*
* -coordinator-metrics: {@link MetricGroupSuffix#COORDINATOR}
* -metrics: {@link MetricGroupSuffix#CONSUMER}
- * -fetch-manager-metrics: {@link MetricGroupSuffix#FETCH_MANAGER}
*
*
*/
-public abstract class AbstractConsumerMetrics {
+public abstract class AbstractConsumerMetricsManager {
protected final String metricGroupName;
+ final Metrics metrics;
public enum MetricGroupSuffix {
COORDINATOR(COORDINATOR_METRICS_SUFFIX),
- CONSUMER(CONSUMER_METRICS_SUFFIX),
- FETCH_MANAGER(FETCH_MANAGER_METRICS_SUFFIX);
+ CONSUMER(CONSUMER_METRICS_SUFFIX);
private final String suffix;
@@ -59,15 +56,12 @@ public String toString() {
}
}
- public AbstractConsumerMetrics(MetricGroupSuffix suffix) {
- this(CONSUMER_METRIC_GROUP_PREFIX, suffix.toString());
- }
-
- public AbstractConsumerMetrics(String prefix, String suffix) {
+ public AbstractConsumerMetricsManager(Metrics metrics, String prefix, MetricGroupSuffix suffix) {
if (suffix == null)
throw new IllegalArgumentException("metric group suffix cannot be null");
if (prefix == null)
throw new IllegalArgumentException("metric group prefix cannot be null");
+ this.metrics = metrics;
metricGroupName = prefix + suffix;
}
@@ -85,8 +79,7 @@ public Meter createMeter(Metrics metrics, String baseName, String descriptiveNam
String.format("The total number of %s", descriptiveName)));
}
- public void addMetric(Metrics metrics,
- String metricName,
+ public void addMetric(String metricName,
String description,
Measurable measurable) {
metrics.addMetric(
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
deleted file mode 100644
index 4ec2899188cf2..0000000000000
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.kafka.clients.consumer.internals.metrics;
-
-import org.apache.kafka.common.metrics.Metrics;
-import org.apache.kafka.common.metrics.Sensor;
-import org.apache.kafka.common.metrics.stats.Max;
-
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
-
-public class HeartbeatMetrics extends AbstractConsumerMetrics {
-
- public final Sensor heartbeatSensor;
-
- public HeartbeatMetrics(Metrics metrics) {
- this(metrics, CONSUMER_METRIC_GROUP_PREFIX);
- }
-
- public HeartbeatMetrics(Metrics metrics, String prefix) {
- super(MetricGroupSuffix.COORDINATOR);
- heartbeatSensor = metrics.sensor("heartbeat-latency");
- heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
- metricGroupName,
- "The max time taken to receive a response to a heartbeat request"),
- new Max());
- heartbeatSensor.add(createMeter(metrics,
- "heartbeat",
- "heartbeats"));
- }
-}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
new file mode 100644
index 0000000000000..708d89ea2d510
--- /dev/null
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
@@ -0,0 +1,69 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Measurable;
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.Sensor;
+import org.apache.kafka.common.metrics.stats.Max;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+
+public class HeartbeatMetricsManager extends AbstractConsumerMetricsManager {
+
+ public final Sensor heartbeatSensor;
+ private long lastHeartbeatMs = -1L;
+
+ public HeartbeatMetricsManager(Metrics metrics) {
+ this(metrics, CONSUMER_METRIC_GROUP_PREFIX);
+ }
+
+ public HeartbeatMetricsManager(Metrics metrics, String prefix) {
+ super(metrics, prefix, MetricGroupSuffix.COORDINATOR);
+ heartbeatSensor = metrics.sensor("heartbeat-latency");
+ heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
+ metricGroupName,
+ "The max time taken to receive a response to a heartbeat request"),
+ new Max());
+ heartbeatSensor.add(createMeter(metrics,
+ "heartbeat",
+ "heartbeats"));
+
+ Measurable lastHeartbeat = (config, now) -> {
+ final long lastHeartbeatSend = lastHeartbeatMs;
+ if (lastHeartbeatSend < 0L)
+ // if no heartbeat is ever triggered, just return -1.
+ return -1d;
+ else
+ return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
+ };
+ addMetric(
+ "last-heartbeat-seconds-ago",
+ "The number of seconds since the last coordinator heartbeat was sent",
+ lastHeartbeat);
+ }
+
+ public void recordHeartbeatSentMs(long lastHeartbeatMs) {
+ this.lastHeartbeatMs = lastHeartbeatMs;
+ }
+
+ public void recordRequestLatency(long requestLatencyMs) {
+ heartbeatSensor.record(requestLatencyMs);
+ }
+}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
similarity index 93%
rename from clients/src/main/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetrics.java
rename to clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
index 0dc8a33b11bbb..ce32b9d97e02b 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.kafka.clients.consumer.internals;
+package org.apache.kafka.clients.consumer.internals.metrics;
import org.apache.kafka.common.MetricName;
import org.apache.kafka.common.metrics.Measurable;
@@ -26,20 +26,20 @@
import java.util.concurrent.TimeUnit;
-public class KafkaConsumerMetrics implements AutoCloseable {
+import static org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetricsManager.MetricGroupSuffix.CONSUMER;
+
+public class KafkaConsumerMetrics extends AbstractConsumerMetricsManager implements AutoCloseable {
private final MetricName lastPollMetricName;
private final Sensor timeBetweenPollSensor;
private final Sensor pollIdleSensor;
private final Sensor committedSensor;
private final Sensor commitSyncSensor;
- private final Metrics metrics;
private long lastPollMs;
private long pollStartMs;
private long timeSinceLastPollMs;
public KafkaConsumerMetrics(Metrics metrics, String metricGrpPrefix) {
- this.metrics = metrics;
- String metricGroupName = metricGrpPrefix + "-metrics";
+ super(metrics, metricGrpPrefix, CONSUMER);
Measurable lastPoll = (mConfig, now) -> {
if (lastPollMs == 0L)
// if no poll is ever triggered, just return -1.
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
new file mode 100644
index 0000000000000..7aef981066820
--- /dev/null
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
@@ -0,0 +1,50 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.Sensor;
+import org.apache.kafka.common.metrics.stats.Avg;
+import org.apache.kafka.common.metrics.stats.Max;
+import org.apache.kafka.common.metrics.stats.Meter;
+import org.apache.kafka.common.metrics.stats.WindowedCount;
+
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+
+public class OffsetCommitMetricsManager extends AbstractConsumerMetricsManager {
+ private final Sensor commitSensor;
+
+ public OffsetCommitMetricsManager(Metrics metrics) {
+ super(metrics, CONSUMER_METRIC_GROUP_PREFIX, MetricGroupSuffix.COORDINATOR);
+ commitSensor = metrics.sensor("commit-latency");
+ commitSensor.add(metrics.metricName("commit-latency-avg",
+ metricGroupName(),
+ "The average time taken for a commit request"), new Avg());
+ commitSensor.add(metrics.metricName("commit-latency-max",
+ metricGroupName(),
+ "The max time taken for a commit request"), new Max());
+ commitSensor.add(new Meter(new WindowedCount(),
+ metrics.metricName("commit-rate", metricGroupName(),
+ "The number of commit calls per second"),
+ metrics.metricName("commit-total", metricGroupName(),
+ "The total number of commit calls")));
+ }
+
+ public void recordRequestLatency(long latencyMs) {
+ this.commitSensor.record(latencyMs);
+ }
+}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
deleted file mode 100644
index b0c1bad324663..0000000000000
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.kafka.clients.consumer.internals.metrics;
-
-import org.apache.kafka.common.metrics.Metrics;
-import org.apache.kafka.common.metrics.Sensor;
-import org.apache.kafka.common.metrics.stats.Avg;
-import org.apache.kafka.common.metrics.stats.Max;
-
-public class RebalanceCallbackMetrics extends AbstractConsumerMetrics {
- public final Sensor revokeCallbackSensor;
- public final Sensor assignCallbackSensor;
- public final Sensor loseCallbackSensor;
-
- public RebalanceCallbackMetrics(Metrics metrics) {
- this(metrics, null);
- }
-
- public RebalanceCallbackMetrics(Metrics metrics, String grpMetricsPrefix) {
- super(MetricGroupSuffix.COORDINATOR);
- revokeCallbackSensor = metrics.sensor("partition-revoked-latency");
- revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
- metricGroupName,
- "The average time taken for a partition-revoked rebalance listener callback"), new Avg());
- revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-max",
- metricGroupName,
- "The max time taken for a partition-revoked rebalance listener callback"), new Max());
-
- assignCallbackSensor = metrics.sensor("partition-assigned-latency");
- assignCallbackSensor.add(metrics.metricName("partition-assigned-latency-avg",
- metricGroupName,
- "The average time taken for a partition-assigned rebalance listener callback"), new Avg());
- assignCallbackSensor.add(metrics.metricName("partition-assigned-latency-max",
- metricGroupName,
- "The max time taken for a partition-assigned rebalance listener callback"), new Max());
-
- loseCallbackSensor = metrics.sensor("partition-lost-latency");
- loseCallbackSensor.add(metrics.metricName("partition-lost-latency-avg",
- metricGroupName,
- "The average time taken for a partition-lost rebalance listener callback"), new Avg());
- loseCallbackSensor.add(metrics.metricName("partition-lost-latency-max",
- metricGroupName,
- "The max time taken for a partition-lost rebalance listener callback"), new Max());
- }
-}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
new file mode 100644
index 0000000000000..19e7267805a0a
--- /dev/null
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
@@ -0,0 +1,74 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.Sensor;
+import org.apache.kafka.common.metrics.stats.Avg;
+import org.apache.kafka.common.metrics.stats.Max;
+
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+import static org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetricsManager.MetricGroupSuffix.COORDINATOR;
+
+public class RebalanceCallbackMetricsManager extends AbstractConsumerMetricsManager {
+ private final Sensor partitionRevokeCallbackSensor;
+ private final Sensor partitionAssignCallbackSensor;
+ private final Sensor partitionLostCallbackSensor;
+
+ public RebalanceCallbackMetricsManager(Metrics metrics) {
+ this(metrics, CONSUMER_METRIC_GROUP_PREFIX);
+ }
+
+ public RebalanceCallbackMetricsManager(Metrics metrics, String grpMetricsPrefix) {
+ super(metrics, grpMetricsPrefix, COORDINATOR);
+ partitionRevokeCallbackSensor = metrics.sensor("partition-revoked-latency");
+ partitionRevokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
+ metricGroupName,
+ "The average time taken for a partition-revoked rebalance listener callback"), new Avg());
+ partitionRevokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-max",
+ metricGroupName,
+ "The max time taken for a partition-revoked rebalance listener callback"), new Max());
+
+ partitionAssignCallbackSensor = metrics.sensor("partition-assigned-latency");
+ partitionAssignCallbackSensor.add(metrics.metricName("partition-assigned-latency-avg",
+ metricGroupName,
+ "The average time taken for a partition-assigned rebalance listener callback"), new Avg());
+ partitionAssignCallbackSensor.add(metrics.metricName("partition-assigned-latency-max",
+ metricGroupName,
+ "The max time taken for a partition-assigned rebalance listener callback"), new Max());
+
+ partitionLostCallbackSensor = metrics.sensor("partition-lost-latency");
+ partitionLostCallbackSensor.add(metrics.metricName("partition-lost-latency-avg",
+ metricGroupName,
+ "The average time taken for a partition-lost rebalance listener callback"), new Avg());
+ partitionLostCallbackSensor.add(metrics.metricName("partition-lost-latency-max",
+ metricGroupName,
+ "The max time taken for a partition-lost rebalance listener callback"), new Max());
+ }
+
+ public void recordPartitionRevokeLatency(long latencyMs) {
+ partitionRevokeCallbackSensor.record(latencyMs);
+ }
+
+ public void recordPartitionAssignLatency(long latencyMs) {
+ partitionAssignCallbackSensor.record(latencyMs);
+ }
+
+ public void recordPartitionLostLatency(long latencyMs) {
+ partitionLostCallbackSensor.record(latencyMs);
+ }
+}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
index 1ac58248c97be..26ca48502f36e 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
@@ -990,7 +990,6 @@ private CommitRequestManager create(final boolean autoCommitEnabled, final long
retryBackoffMs,
retryBackoffMaxMs,
OptionalDouble.of(0),
- consumerMetricGroupPrefix,
metrics));
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
similarity index 75%
rename from clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
rename to clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
index 343e74ce40965..5fad34987eeef 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
@@ -16,9 +16,9 @@
*/
package org.apache.kafka.clients.consumer.internals;
-import org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetrics;
-import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetrics;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetricsManager;
+import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetricsManager;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.metrics.KafkaMetric;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.utils.MockTime;
@@ -27,19 +27,18 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
-public class ConsumerMetricsTest {
+public class ConsumerMetricsManagerTest {
private Time time = new MockTime();
private Metrics metrics = new Metrics(time);
@Test
public void testRebalanceCallbackMetrics() {
// MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
- RebalanceCallbackMetrics rebalanceCallbackMetrics = new RebalanceCallbackMetrics(metrics);
+ RebalanceCallbackMetricsManager rebalanceCallbackMetricsManager = new RebalanceCallbackMetricsManager(metrics);
String groupName = "consumer-coordinator-metrics";
assertNotNull(getMetric("partition-revoked-latency-avg", groupName));
assertNotNull(getMetric("partition-revoked-latency-max", groupName));
@@ -48,9 +47,9 @@ public void testRebalanceCallbackMetrics() {
assertNotNull(getMetric("partition-lost-latency-avg", groupName));
assertNotNull(getMetric("partition-lost-latency-max", groupName));
- rebalanceCallbackMetrics.assignCallbackSensor.record(100);
- rebalanceCallbackMetrics.revokeCallbackSensor.record(101);
- rebalanceCallbackMetrics.loseCallbackSensor.record(102);
+ rebalanceCallbackMetricsManager.recordPartitionAssignLatency(100);
+ rebalanceCallbackMetricsManager.recordPartitionRevokeLatency(101);
+ rebalanceCallbackMetricsManager.recordPartitionLostLatency(102);
assertEquals(101d, getMetric("partition-revoked-latency-avg", groupName).metricValue());
assertEquals(101d, getMetric("partition-revoked-latency-max", groupName).metricValue());
@@ -63,15 +62,15 @@ public void testRebalanceCallbackMetrics() {
@Test
public void testHeartbeatMetrics() {
// MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
- HeartbeatMetrics heartbeatMetrics = new HeartbeatMetrics(metrics);
+ HeartbeatMetricsManager heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
String groupName = "consumer-coordinator-metrics";
assertNotNull(getMetric("heartbeat-response-time-max", groupName));
assertNotNull(getMetric("heartbeat-rate", groupName));
assertNotNull(getMetric("heartbeat-total", groupName));
- heartbeatMetrics.heartbeatSensor.record(100);
- heartbeatMetrics.heartbeatSensor.record(100);
- heartbeatMetrics.heartbeatSensor.record(100);
+ heartbeatMetricsManager.heartbeatSensor.record(100);
+ heartbeatMetricsManager.heartbeatSensor.record(100);
+ heartbeatMetricsManager.heartbeatSensor.record(100);
assertEquals(100d, getMetric("heartbeat-response-time-max", groupName).metricValue());
assertEquals(0.1d, (double) getMetric("heartbeat-rate", groupName).metricValue(), 0.01d);
@@ -81,28 +80,25 @@ public void testHeartbeatMetrics() {
@Test
public void testMetricsGroupName() {
// consumer-coordinator-metrics
- NoopConsumerMetrics coordinatorMetrics = new NoopConsumerMetrics("customCoordinatorPrefix", AbstractConsumerMetrics.MetricGroupSuffix.COORDINATOR);
+ NoopConsumerMetrics coordinatorMetrics = new NoopConsumerMetrics(metrics, "customCoordinatorPrefix", AbstractConsumerMetricsManager.MetricGroupSuffix.COORDINATOR);
assertEquals("customCoordinatorPrefix" + COORDINATOR_METRICS_SUFFIX, coordinatorMetrics.metricGroupName());
// consumer-metrics
- NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics("customConsumerPrefix", AbstractConsumerMetrics.MetricGroupSuffix.CONSUMER);
+ NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics(metrics, "customConsumerPrefix", AbstractConsumerMetricsManager.MetricGroupSuffix.CONSUMER);
assertEquals("customConsumerPrefix" + CONSUMER_METRICS_SUFFIX, consumerMetrics.metricGroupName());
- // consumer-fetch-manager-metrics
- NoopConsumerMetrics fetchMetrics = new NoopConsumerMetrics("customFetchPrefix", AbstractConsumerMetrics.MetricGroupSuffix.FETCH_MANAGER);
- assertEquals("customFetchPrefix" + FETCH_MANAGER_METRICS_SUFFIX, fetchMetrics.metricGroupName());
-
- assertThrows(IllegalArgumentException.class, () -> new NoopConsumerMetrics(null,
- AbstractConsumerMetrics.MetricGroupSuffix.CONSUMER));
+ assertThrows(IllegalArgumentException.class, () -> new NoopConsumerMetrics(metrics,
+ null,
+ AbstractConsumerMetricsManager.MetricGroupSuffix.CONSUMER));
}
private KafkaMetric getMetric(String metricName, String groupName) {
return metrics.metrics().get(metrics.metricName(metricName, groupName));
}
- static class NoopConsumerMetrics extends AbstractConsumerMetrics {
- public NoopConsumerMetrics(String prefix, MetricGroupSuffix suffix) {
- super(prefix, suffix.toString());
+ static class NoopConsumerMetrics extends AbstractConsumerMetricsManager {
+ public NoopConsumerMetrics(Metrics metrics, String prefix, MetricGroupSuffix suffix) {
+ super(metrics, prefix, suffix);
}
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
index b747945b73a71..06bcd22bb597f 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
@@ -25,7 +25,7 @@
import org.apache.kafka.clients.consumer.internals.events.ApplicationEventProcessor;
import org.apache.kafka.clients.consumer.internals.events.BackgroundEvent;
import org.apache.kafka.clients.consumer.internals.events.BackgroundEventHandler;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.internals.ClusterResourceListeners;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.requests.MetadataResponse;
@@ -48,7 +48,6 @@
import static org.apache.kafka.clients.consumer.ConsumerConfig.GROUP_INSTANCE_ID_CONFIG;
import static org.apache.kafka.clients.consumer.ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG;
import static org.apache.kafka.clients.consumer.ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createFetchMetricsManager;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createMetrics;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createSubscriptionState;
@@ -227,7 +226,6 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
heartbeatState,
heartbeatRequestState,
backgroundEventHandler,
- CONSUMER_METRIC_GROUP_PREFIX,
metrics));
this.coordinatorRequestManager = Optional.of(coordinator);
@@ -274,7 +272,7 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
logContext,
subscriptions,
time,
- new RebalanceCallbackMetrics(metrics)
+ new RebalanceCallbackMetricsManager(metrics)
);
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 68822970c17eb..33d54ab66389d 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -57,6 +57,7 @@
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_GROUP_INSTANCE_ID;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_HEARTBEAT_INTERVAL_MS;
@@ -599,13 +600,13 @@ public void testHeartbeatMetrics() {
assertHeartbeat(heartbeatRequestManager, 0);
time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(1.0, getMetric("heartbeat-total").metricValue());
- assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
+ assertEquals((double) TimeUnit.MILLISECONDS.toSeconds(heartbeatIntervalMs), getMetric("last-heartbeat-seconds-ago").metricValue());
assertHeartbeat(heartbeatRequestManager, DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(0.06d, (double) getMetric("heartbeat-rate").metricValue(), 0.005d);
assertEquals(2.0, getMetric("heartbeat-total").metricValue());
time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
- assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
+ assertEquals((double) TimeUnit.MILLISECONDS.toSeconds(heartbeatIntervalMs), getMetric("last-heartbeat-seconds-ago").metricValue());
}
private void assertHeartbeat(HeartbeatRequestManager hrm, int nextPollMs) {
@@ -738,7 +739,6 @@ private HeartbeatRequestManager createHeartbeatRequestManager(
heartbeatState,
heartbeatRequestState,
backgroundEventHandler,
- metricGroupPrefix,
metrics);
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetricsTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetricsTest.java
index 087f90b7efa31..c75ee906e535b 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetricsTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetricsTest.java
@@ -17,6 +17,7 @@
package org.apache.kafka.clients.consumer.internals;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
import org.apache.kafka.common.metrics.Metrics;
import org.junit.jupiter.api.Test;
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/MembershipManagerImplTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/MembershipManagerImplTest.java
index 7683a521e0d6a..a87b6efe16152 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/MembershipManagerImplTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/MembershipManagerImplTest.java
@@ -20,7 +20,7 @@
import org.apache.kafka.clients.consumer.internals.events.BackgroundEventHandler;
import org.apache.kafka.clients.consumer.internals.events.ConsumerRebalanceListenerCallbackCompletedEvent;
import org.apache.kafka.clients.consumer.internals.events.ConsumerRebalanceListenerCallbackNeededEvent;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.TopicIdPartition;
import org.apache.kafka.common.TopicPartition;
@@ -1388,7 +1388,7 @@ private ConsumerRebalanceListenerInvoker consumerRebalanceListenerInvoker() {
new LogContext(),
subscriptionState,
new MockTime(1),
- new RebalanceCallbackMetrics(new Metrics())
+ new RebalanceCallbackMetricsManager(new Metrics())
);
}
From a84f83b90500aa2b142b789e173c4ff92e3bccef Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Sun, 28 Jan 2024 17:04:37 -0800
Subject: [PATCH 10/28] clean up name
---
.../consumer/internals/CommitRequestManager.java | 6 +++---
.../internals/ConsumerRebalanceListenerInvoker.java | 12 ++++++------
.../consumer/internals/HeartbeatRequestManager.java | 12 ++++++------
3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
index 286bc9d59b9bf..dd9c138912360 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
@@ -79,7 +79,7 @@ public class CommitRequestManager implements RequestManager, MemberStateListener
private final boolean throwOnFetchStableOffsetUnsupported;
final PendingRequests pendingRequests;
private boolean closing = false;
- private OffsetCommitMetricsManager offsetCommitMetricsManager;
+ private OffsetCommitMetricsManager metricsManager;
/**
* Latest member ID and epoch received via the {@link #onMemberEpochUpdated(Optional, Optional)},
@@ -144,7 +144,7 @@ public CommitRequestManager(
this.jitter = jitter;
this.throwOnFetchStableOffsetUnsupported = config.getBoolean(THROW_ON_FETCH_STABLE_OFFSET_UNSUPPORTED);
this.memberInfo = new MemberInfo();
- this.offsetCommitMetricsManager = new OffsetCommitMetricsManager(metrics);
+ this.metricsManager = new OffsetCommitMetricsManager(metrics);
}
/**
@@ -496,7 +496,7 @@ public NetworkClientDelegate.UnsentRequest toUnsentRequest() {
}
public void onResponse(final ClientResponse response) {
- offsetCommitMetricsManager.recordRequestLatency(response.requestLatencyMs());
+ metricsManager.recordRequestLatency(response.requestLatencyMs());
long currentTimeMs = response.receivedTimeMs();
OffsetCommitResponse commitResponse = (OffsetCommitResponse) response.responseBody();
Set unauthorizedTopics = new HashSet<>();
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
index ca68158d4cf3b..93d5c65bee539 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
@@ -41,16 +41,16 @@ public class ConsumerRebalanceListenerInvoker {
private final Logger log;
private final SubscriptionState subscriptions;
private final Time time;
- private final RebalanceCallbackMetricsManager metrics;
+ private final RebalanceCallbackMetricsManager metricsManager;
ConsumerRebalanceListenerInvoker(LogContext logContext,
SubscriptionState subscriptions,
Time time,
- RebalanceCallbackMetricsManager metrics) {
+ RebalanceCallbackMetricsManager metricsManager) {
this.log = logContext.logger(getClass());
this.subscriptions = subscriptions;
this.time = time;
- this.metrics = metrics;
+ this.metricsManager = metricsManager;
}
public Exception invokePartitionsAssigned(final SortedSet assignedPartitions) {
@@ -62,7 +62,7 @@ public Exception invokePartitionsAssigned(final SortedSet assign
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsAssigned(assignedPartitions);
- metrics.recordPartitionAssignLatency(time.milliseconds() - startMs);
+ metricsManager.recordPartitionAssignLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -88,7 +88,7 @@ public Exception invokePartitionsRevoked(final SortedSet revoked
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsRevoked(revokedPartitions);
- metrics.recordPartitionRevokeLatency(time.milliseconds() - startMs);
+ metricsManager.recordPartitionRevokeLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -114,7 +114,7 @@ public Exception invokePartitionsLost(final SortedSet lostPartit
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsLost(lostPartitions);
- metrics.recordPartitionLostLatency(time.milliseconds() - startMs);
+ metricsManager.recordPartitionLostLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 2e0e63f786e40..7afdff75cd2dd 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -110,7 +110,7 @@ public class HeartbeatRequestManager implements RequestManager {
* sending heartbeat until the next poll.
*/
private final Timer pollTimer;
- private final HeartbeatMetricsManager heartbeatMetricsManager;
+ private final HeartbeatMetricsManager metricsManager;
private GroupMetadataUpdateEvent previousGroupMetadataUpdateEvent = null;
@@ -134,7 +134,7 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
- this.heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
+ this.metricsManager = new HeartbeatMetricsManager(metrics);
}
// Visible for testing
@@ -156,7 +156,7 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
- this.heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
+ this.metricsManager = new HeartbeatMetricsManager(metrics);
}
/**
@@ -252,7 +252,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final long curr
NetworkClientDelegate.UnsentRequest request = makeHeartbeatRequest(ignoreResponse);
heartbeatRequestState.onSendAttempt(currentTimeMs);
membershipManager.onHeartbeatRequestSent();
- heartbeatMetricsManager.recordHeartbeatSentMs(currentTimeMs);
+ metricsManager.recordHeartbeatSentMs(currentTimeMs);
return request;
}
@@ -265,7 +265,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
else
return request.whenComplete((response, exception) -> {
if (response != null) {
- heartbeatMetricsManager.recordRequestLatency(response.requestLatencyMs());
+ metricsManager.recordRequestLatency(response.requestLatencyMs());
onResponse((ConsumerGroupHeartbeatResponse) response.responseBody(), request.handler().completionTimeMs());
} else {
onFailure(exception, request.handler().completionTimeMs());
@@ -276,7 +276,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
private NetworkClientDelegate.UnsentRequest logResponse(final NetworkClientDelegate.UnsentRequest request) {
return request.whenComplete((response, exception) -> {
if (response != null) {
- heartbeatMetricsManager.recordRequestLatency(response.requestLatencyMs());
+ metricsManager.recordRequestLatency(response.requestLatencyMs());
Errors error =
Errors.forCode(((ConsumerGroupHeartbeatResponse) response.responseBody()).data().errorCode());
if (error == Errors.NONE)
From 4f3970128e4cec3cbc7562cc738eec8a7aed6d0a Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Wed, 17 Jan 2024 10:41:56 -0800
Subject: [PATCH 11/28] heartbeat metrics
---
.../internals/HeartbeatRequestManager.java | 35 +++++++++++++++++--
.../consumer/internals/RequestManagers.java | 3 +-
.../metrics/AbstractConsumerMetrics.java | 14 ++++++++
.../internals/metrics/HeartbeatMetrics.java | 31 ++++++++++++++++
.../internals/AsyncKafkaConsumerTest.java | 19 ++++++++++
.../internals/ConsumerTestBuilder.java | 4 ++-
.../HeartbeatRequestManagerTest.java | 29 ++++++++-------
7 files changed, 118 insertions(+), 17 deletions(-)
create mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 11846eedeafdc..04b342fa9a0a5 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -23,10 +23,13 @@
import org.apache.kafka.clients.consumer.internals.events.BackgroundEventHandler;
import org.apache.kafka.clients.consumer.internals.events.ErrorBackgroundEvent;
import org.apache.kafka.clients.consumer.internals.events.GroupMetadataUpdateEvent;
+import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetrics;
import org.apache.kafka.common.Uuid;
import org.apache.kafka.common.errors.GroupAuthorizationException;
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatRequestData;
+import org.apache.kafka.common.metrics.Measurable;
+import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.ConsumerGroupHeartbeatRequest;
import org.apache.kafka.common.requests.ConsumerGroupHeartbeatResponse;
@@ -41,6 +44,7 @@
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -78,6 +82,11 @@ public class HeartbeatRequestManager implements RequestManager {
*/
private final int maxPollIntervalMs;
+ /**
+ * The last time in Ms the heartbeat was sent to the coordinator
+ */
+ private long lastHeartbeatSend = 0L;
+
/**
* CoordinatorRequestManager manages the connection to the group coordinator
*/
@@ -108,6 +117,7 @@ public class HeartbeatRequestManager implements RequestManager {
* sending heartbeat until the next poll.
*/
private final Timer pollTimer;
+ private final HeartbeatMetrics heartbeatMetrics;
private GroupMetadataUpdateEvent previousGroupMetadataUpdateEvent = null;
@@ -118,7 +128,8 @@ public HeartbeatRequestManager(
final CoordinatorRequestManager coordinatorRequestManager,
final SubscriptionState subscriptions,
final MembershipManager membershipManager,
- final BackgroundEventHandler backgroundEventHandler) {
+ final BackgroundEventHandler backgroundEventHandler,
+ final Metrics metrics) {
this.coordinatorRequestManager = coordinatorRequestManager;
this.logger = logContext.logger(getClass());
this.membershipManager = membershipManager;
@@ -130,6 +141,8 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
+ this.heartbeatMetrics = new HeartbeatMetrics(metrics);
+ registerLastSentHeartbeatMetric(metrics);
}
// Visible for testing
@@ -141,7 +154,8 @@ public HeartbeatRequestManager(
final MembershipManager membershipManager,
final HeartbeatState heartbeatState,
final HeartbeatRequestState heartbeatRequestState,
- final BackgroundEventHandler backgroundEventHandler) {
+ final BackgroundEventHandler backgroundEventHandler,
+ final Metrics metrics) {
this.logger = logContext.logger(this.getClass());
this.maxPollIntervalMs = config.getInt(CommonClientConfigs.MAX_POLL_INTERVAL_MS_CONFIG);
this.coordinatorRequestManager = coordinatorRequestManager;
@@ -150,6 +164,8 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
+ this.heartbeatMetrics = new HeartbeatMetrics(metrics);
+ registerLastSentHeartbeatMetric(metrics);
}
/**
@@ -245,6 +261,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final long curr
NetworkClientDelegate.UnsentRequest request = makeHeartbeatRequest(ignoreResponse);
heartbeatRequestState.onSendAttempt(currentTimeMs);
membershipManager.onHeartbeatRequestSent();
+ lastHeartbeatSend = currentTimeMs;
return request;
}
@@ -415,6 +432,20 @@ private void handleFatalFailure(Throwable error) {
membershipManager.transitionToFatal();
}
+ private void registerLastSentHeartbeatMetric(Metrics metrics) {
+ Measurable lastHeartbeat = (config, now) -> {
+ if (lastHeartbeatSend == 0L)
+ // if no heartbeat is ever triggered, just return -1.
+ return -1d;
+ else
+ return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
+ };
+ heartbeatMetrics.registerMeasurable(
+ "heartbeat-time-max",
+ "The max time taken to receive a response to a heartbeat request",
+ lastHeartbeat);
+ }
+
/**
* Represents the state of a heartbeat request, including logic for timing, retries, and exponential backoff. The
* object extends {@link RequestState} to enable exponential backoff and duplicated request handling. The two fields
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
index 6dd9e01216343..7b3e75be0182c 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
@@ -190,7 +190,8 @@ protected RequestManagers create() {
coordinator,
subscriptions,
membershipManager,
- backgroundEventHandler);
+ backgroundEventHandler,
+ metrics);
}
return new RequestManagers(
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index 2273bfd494a3b..c9cd16b26f8cd 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -16,6 +16,10 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.stats.Meter;
+import org.apache.kafka.common.metrics.stats.WindowedCount;
+
import java.util.Optional;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
@@ -26,4 +30,14 @@ public abstract class AbstractConsumerMetrics {
public AbstractConsumerMetrics(Optional grpMetricsPrefix) {
grpMetricsPrefix.ifPresent(s -> this.groupMetricsName = s + COORDINATOR_METRICS_SUFFIX);
}
+
+ public AbstractConsumerMetrics() {}
+
+ public static Meter createMeter(Metrics metrics, String groupName, String baseName, String descriptiveName) {
+ return new Meter(new WindowedCount(),
+ metrics.metricName(baseName + "-rate", groupName,
+ String.format("The number of %s per second", descriptiveName)),
+ metrics.metricName(baseName + "-total", groupName,
+ String.format("The total number of %s", descriptiveName)));
+ }
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
new file mode 100644
index 0000000000000..43e2b0740bc16
--- /dev/null
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -0,0 +1,31 @@
+package org.apache.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Measurable;
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.Sensor;
+import org.apache.kafka.common.metrics.stats.Max;
+
+public class HeartbeatMetrics extends AbstractConsumerMetrics {
+
+ private final Metrics metrics;
+ public final Sensor heartbeatSensor;
+
+ public HeartbeatMetrics(Metrics metrics) {
+ super();
+ this.metrics = metrics;
+ heartbeatSensor = metrics.sensor("heartbeat-latency");
+ heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
+ groupMetricsName,
+ "The max time taken to receive a response to a heartbeat request"), new Max());
+ heartbeatSensor.add(createMeter(metrics, groupMetricsName, "heartbeat", "heartbeats"));
+
+ }
+
+ public void registerMeasurable(String name,
+ String description,
+ Measurable measurable) {
+ metrics.addMetric(
+ metrics.metricName(name, groupMetricsName, description),
+ measurable);
+ }
+}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
index f6fb2a8928631..1e4991131f453 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
@@ -59,6 +59,7 @@
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.errors.TimeoutException;
import org.apache.kafka.common.errors.WakeupException;
+import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.JoinGroupRequest;
@@ -141,6 +142,7 @@ public class AsyncKafkaConsumerTest {
private final ApplicationEventHandler applicationEventHandler = mock(ApplicationEventHandler.class);
private final ConsumerMetadata metadata = mock(ConsumerMetadata.class);
private final LinkedBlockingQueue backgroundEventQueue = new LinkedBlockingQueue<>();
+ long rlb = -1L;
@AfterEach
public void resetAll() {
@@ -1398,6 +1400,23 @@ public void testProcessBackgroundEventsTimesOut() throws Exception {
}
}
+ @Test
+ public void testBS() {
+ rlb = 1000L;
+ Measurable lastRebalance = (config, now) -> {
+ return TimeUnit.SECONDS.convert(now - rlb, TimeUnit.MILLISECONDS);
+ };
+
+ System.out.println(lastRebalance.measure(null, System.currentTimeMillis())); // Prints some value
+
+// Update lastRebalanceEndMs
+ rlb = 2000L;
+
+ System.out.println(lastRebalance.measure(null, System.currentTimeMillis())); // Still uses the captured value,
+ // not the updated one
+
+ }
+
private HashMap mockTopicPartitionOffset() {
final TopicPartition t0 = new TopicPartition("t0", 2);
final TopicPartition t1 = new TopicPartition("t0", 3);
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
index 17489eab716c0..bdd3836303ac9 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
@@ -217,6 +217,7 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
retryBackoffMs,
DEFAULT_RETRY_BACKOFF_MAX_MS,
gi.heartbeatJitterMs));
+
HeartbeatRequestManager heartbeat = spy(new HeartbeatRequestManager(
logContext,
pollTimer,
@@ -225,7 +226,8 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
mm,
heartbeatState,
heartbeatRequestState,
- backgroundEventHandler));
+ backgroundEventHandler,
+ metrics));
this.coordinatorRequestManager = Optional.of(coordinator);
this.commitRequestManager = Optional.of(commit);
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index e44414b0677b9..c6335d2a89400 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -28,6 +28,8 @@
import org.apache.kafka.common.errors.TimeoutException;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatRequestData;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatResponseData;
+import org.apache.kafka.common.metrics.KafkaMetric;
+import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.ApiKeys;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.ConsumerGroupHeartbeatRequest;
@@ -62,6 +64,7 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MAX_MS;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MS;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -78,6 +81,7 @@ public class HeartbeatRequestManagerTest {
private int heartbeatIntervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS;
private int maxPollIntervalMs = DEFAULT_MAX_POLL_INTERVAL_MS;
private long retryBackoffMaxMs = DEFAULT_RETRY_BACKOFF_MAX_MS;
+ private String metricGrpPrefix = "test-consumer";
private static final String DEFAULT_GROUP_ID = "groupId";
private ConsumerTestBuilder testBuilder;
@@ -95,6 +99,7 @@ public class HeartbeatRequestManagerTest {
private final int memberEpoch = 1;
private BackgroundEventHandler backgroundEventHandler;
private BlockingQueue backgroundEventQueue;
+ private Metrics metrics = new Metrics();
@BeforeEach
public void setUp() {
@@ -671,18 +676,15 @@ private ConsumerConfig config() {
return new ConsumerConfig(prop);
}
- private HeartbeatRequestManager createHeartbeatRequestManager() {
- LogContext logContext = new LogContext();
- pollTimer = time.timer(maxPollIntervalMs);
- return new HeartbeatRequestManager(
- logContext,
- pollTimer,
- config(),
- coordinatorRequestManager,
- membershipManager,
- heartbeatState,
- heartbeatRequestState,
- backgroundEventHandler);
+ private void assertMetricsRecorded() {
+ assertNotNull(getMetric("heartbeat-response-time-max"));
+ assertNotNull(getMetric("heartbeat-rate"));
+ assertNotNull(getMetric("heartbeat-total"));
+ assertNotNull(getMetric("last-heartbeat-seconds-ago"));
+ }
+
+ private KafkaMetric getMetric(final String name) {
+ return metrics.metrics().get(metrics.metricName(name, "consumer-coordinator-metrics"));
}
private HeartbeatRequestManager createHeartbeatRequestManager(
@@ -701,6 +703,7 @@ private HeartbeatRequestManager createHeartbeatRequestManager(
membershipManager,
heartbeatState,
heartbeatRequestState,
- backgroundEventHandler);
+ backgroundEventHandler,
+ metrics);
}
}
From 99d6fab721927ad87133552f9d04da1128d42ae9 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 19 Jan 2024 10:14:24 -0800
Subject: [PATCH 12/28] clean up
---
.../internals/metrics/HeartbeatMetrics.java | 16 ++++++++++++++++
.../internals/HeartbeatRequestManagerTest.java | 3 ---
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
index 43e2b0740bc16..912295accc41d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -1,3 +1,19 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
import org.apache.kafka.common.metrics.Measurable;
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index c6335d2a89400..41cf9e39fe69c 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -81,13 +81,11 @@ public class HeartbeatRequestManagerTest {
private int heartbeatIntervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS;
private int maxPollIntervalMs = DEFAULT_MAX_POLL_INTERVAL_MS;
private long retryBackoffMaxMs = DEFAULT_RETRY_BACKOFF_MAX_MS;
- private String metricGrpPrefix = "test-consumer";
private static final String DEFAULT_GROUP_ID = "groupId";
private ConsumerTestBuilder testBuilder;
private Time time;
private Timer pollTimer;
- private ConsumerConfig config;
private CoordinatorRequestManager coordinatorRequestManager;
private SubscriptionState subscriptions;
private Metadata metadata;
@@ -118,7 +116,6 @@ private void setUp(Optional groupInfo) {
subscriptions = testBuilder.subscriptions;
membershipManager = testBuilder.membershipManager.orElseThrow(IllegalStateException::new);
metadata = testBuilder.metadata;
- config = testBuilder.config;
when(coordinatorRequestManager.coordinator()).thenReturn(Optional.of(new Node(1, "localhost", 9999)));
}
From cf95499e6a7af89b67dd198b4e3e8dd6ad1b7965 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Mon, 22 Jan 2024 14:04:26 -0800
Subject: [PATCH 13/28] remove lastHeartbeatsend and use the requestState var
instead
eee
wip
---
.../internals/HeartbeatRequestManager.java | 19 ++++-----
.../metrics/AbstractConsumerMetrics.java | 14 ++++++-
.../internals/metrics/HeartbeatMetrics.java | 20 +++------
.../HeartbeatRequestManagerTest.java | 41 ++++++++++++++++---
4 files changed, 63 insertions(+), 31 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 04b342fa9a0a5..6feb4154836d5 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -82,11 +82,6 @@ public class HeartbeatRequestManager implements RequestManager {
*/
private final int maxPollIntervalMs;
- /**
- * The last time in Ms the heartbeat was sent to the coordinator
- */
- private long lastHeartbeatSend = 0L;
-
/**
* CoordinatorRequestManager manages the connection to the group coordinator
*/
@@ -261,7 +256,6 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final long curr
NetworkClientDelegate.UnsentRequest request = makeHeartbeatRequest(ignoreResponse);
heartbeatRequestState.onSendAttempt(currentTimeMs);
membershipManager.onHeartbeatRequestSent();
- lastHeartbeatSend = currentTimeMs;
return request;
}
@@ -273,7 +267,10 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
return logResponse(request);
else
return request.whenComplete((response, exception) -> {
+ System.out.print("=====");
if (response != null) {
+ System.out.print("ehhh: " + response.requestLatencyMs());
+ heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
onResponse((ConsumerGroupHeartbeatResponse) response.responseBody(), request.handler().completionTimeMs());
} else {
onFailure(exception, request.handler().completionTimeMs());
@@ -433,16 +430,18 @@ private void handleFatalFailure(Throwable error) {
}
private void registerLastSentHeartbeatMetric(Metrics metrics) {
+ final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
Measurable lastHeartbeat = (config, now) -> {
- if (lastHeartbeatSend == 0L)
+ if (lastHeartbeatSend < 0L)
// if no heartbeat is ever triggered, just return -1.
return -1d;
else
return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
};
- heartbeatMetrics.registerMeasurable(
- "heartbeat-time-max",
- "The max time taken to receive a response to a heartbeat request",
+ heartbeatMetrics.addMetric(
+ metrics,
+ "last-heartbeat-seconds-ago",
+ "The number of seconds since the last coordinator heartbeat was sent",
lastHeartbeat);
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index c9cd16b26f8cd..1c380b116b14e 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -16,6 +16,7 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.stats.Meter;
import org.apache.kafka.common.metrics.stats.WindowedCount;
@@ -27,12 +28,12 @@
public abstract class AbstractConsumerMetrics {
protected String groupMetricsName = CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX;
+
+ public AbstractConsumerMetrics() {}
public AbstractConsumerMetrics(Optional grpMetricsPrefix) {
grpMetricsPrefix.ifPresent(s -> this.groupMetricsName = s + COORDINATOR_METRICS_SUFFIX);
}
- public AbstractConsumerMetrics() {}
-
public static Meter createMeter(Metrics metrics, String groupName, String baseName, String descriptiveName) {
return new Meter(new WindowedCount(),
metrics.metricName(baseName + "-rate", groupName,
@@ -40,4 +41,13 @@ public static Meter createMeter(Metrics metrics, String groupName, String baseNa
metrics.metricName(baseName + "-total", groupName,
String.format("The total number of %s", descriptiveName)));
}
+
+ public void addMetric(Metrics metrics,
+ String name,
+ String description,
+ Measurable measurable) {
+ metrics.addMetric(
+ metrics.metricName(name, groupMetricsName, description),
+ measurable);
+ }
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
index 912295accc41d..ced8aaca6900b 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -16,32 +16,24 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
-import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.Sensor;
import org.apache.kafka.common.metrics.stats.Max;
public class HeartbeatMetrics extends AbstractConsumerMetrics {
- private final Metrics metrics;
public final Sensor heartbeatSensor;
public HeartbeatMetrics(Metrics metrics) {
super();
- this.metrics = metrics;
heartbeatSensor = metrics.sensor("heartbeat-latency");
heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
groupMetricsName,
- "The max time taken to receive a response to a heartbeat request"), new Max());
- heartbeatSensor.add(createMeter(metrics, groupMetricsName, "heartbeat", "heartbeats"));
-
- }
-
- public void registerMeasurable(String name,
- String description,
- Measurable measurable) {
- metrics.addMetric(
- metrics.metricName(name, groupMetricsName, description),
- measurable);
+ "The max time taken to receive a response to a heartbeat request"),
+ new Max());
+ heartbeatSensor.add(createMeter(metrics,
+ groupMetricsName,
+ "heartbeat",
+ "heartbeats"));
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 41cf9e39fe69c..1dd5d4e1e6a53 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -64,7 +64,6 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MAX_MS;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MS;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -564,6 +563,41 @@ public void testPollTimerExpiration() {
assertHeartbeat(heartbeatRequestManager);
}
+ @Test
+ public void testHeartbeatMetrics() {
+ coordinatorRequestManager = mock(CoordinatorRequestManager.class);
+ membershipManager = mock(MembershipManager.class);
+ heartbeatState = mock(HeartbeatRequestManager.HeartbeatState.class);
+ heartbeatRequestState = new HeartbeatRequestManager.HeartbeatRequestState(
+ new LogContext(),
+ time,
+ heartbeatIntervalMs,
+ retryBackoffMs,
+ retryBackoffMaxMs,
+ 0);
+ backgroundEventHandler = mock(BackgroundEventHandler.class);
+
+ heartbeatRequestManager = createHeartbeatRequestManager(
+ coordinatorRequestManager,
+ membershipManager,
+ heartbeatState,
+ heartbeatRequestState,
+ backgroundEventHandler);
+ when(coordinatorRequestManager.coordinator()).thenReturn(Optional.of(new Node(1, "localhost", 9999)));
+ when(membershipManager.shouldSkipHeartbeat()).thenReturn(false);
+ when(membershipManager.state()).thenReturn(MemberState.STABLE);
+ time.sleep(maxPollIntervalMs);
+ NetworkClientDelegate.PollResult pollResult = heartbeatRequestManager.poll(time.milliseconds());
+ ClientResponse hr = createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE);
+ pollResult.unsentRequests.get(0).future().complete(hr);
+
+ assertEquals(1, pollResult.unsentRequests.size());
+ //assertEquals(1, getMetric("heartbeat-response-time-max").metricValue());
+ assertEquals(0.0, getMetric("heartbeat-rate").metricValue());
+ assertEquals(1.0, getMetric("heartbeat-total").metricValue());
+ assertEquals(1, getMetric("last-heartbeat-seconds-ago").metricValue());
+ }
+
private void assertHeartbeat(HeartbeatRequestManager hrm) {
NetworkClientDelegate.PollResult pollResult = hrm.poll(time.milliseconds());
assertEquals(1, pollResult.unsentRequests.size());
@@ -674,10 +708,7 @@ private ConsumerConfig config() {
}
private void assertMetricsRecorded() {
- assertNotNull(getMetric("heartbeat-response-time-max"));
- assertNotNull(getMetric("heartbeat-rate"));
- assertNotNull(getMetric("heartbeat-total"));
- assertNotNull(getMetric("last-heartbeat-seconds-ago"));
+
}
private KafkaMetric getMetric(final String name) {
From 631a755ed1137ca88c87f458cb95ba96b7be48e2 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Thu, 25 Jan 2024 12:48:09 -0800
Subject: [PATCH 14/28] update test
clean up
remove bad code
---
.../internals/HeartbeatRequestManager.java | 25 ++++----
.../internals/AsyncKafkaConsumerTest.java | 18 ------
.../internals/ConsumerTestBuilder.java | 1 -
.../HeartbeatRequestManagerTest.java | 58 ++++++++++---------
4 files changed, 44 insertions(+), 58 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 6feb4154836d5..fdf312a99beab 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -136,8 +136,7 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
- this.heartbeatMetrics = new HeartbeatMetrics(metrics);
- registerLastSentHeartbeatMetric(metrics);
+ this.heartbeatMetrics = createHeartbeatMetrics(metrics);
}
// Visible for testing
@@ -159,8 +158,7 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
- this.heartbeatMetrics = new HeartbeatMetrics(metrics);
- registerLastSentHeartbeatMetric(metrics);
+ this.heartbeatMetrics = createHeartbeatMetrics(metrics);
}
/**
@@ -267,9 +265,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
return logResponse(request);
else
return request.whenComplete((response, exception) -> {
- System.out.print("=====");
if (response != null) {
- System.out.print("ehhh: " + response.requestLatencyMs());
heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
onResponse((ConsumerGroupHeartbeatResponse) response.responseBody(), request.handler().completionTimeMs());
} else {
@@ -281,6 +277,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
private NetworkClientDelegate.UnsentRequest logResponse(final NetworkClientDelegate.UnsentRequest request) {
return request.whenComplete((response, exception) -> {
if (response != null) {
+ heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
Errors error =
Errors.forCode(((ConsumerGroupHeartbeatResponse) response.responseBody()).data().errorCode());
if (error == Errors.NONE)
@@ -429,20 +426,22 @@ private void handleFatalFailure(Throwable error) {
membershipManager.transitionToFatal();
}
- private void registerLastSentHeartbeatMetric(Metrics metrics) {
- final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
+ private HeartbeatMetrics createHeartbeatMetrics(Metrics metrics) {
+ HeartbeatMetrics hbm = new HeartbeatMetrics(metrics);
Measurable lastHeartbeat = (config, now) -> {
+ final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
if (lastHeartbeatSend < 0L)
// if no heartbeat is ever triggered, just return -1.
return -1d;
else
return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
};
- heartbeatMetrics.addMetric(
- metrics,
- "last-heartbeat-seconds-ago",
- "The number of seconds since the last coordinator heartbeat was sent",
- lastHeartbeat);
+ hbm.addMetric(
+ metrics,
+ "last-heartbeat-seconds-ago",
+ "The number of seconds since the last coordinator heartbeat was sent",
+ lastHeartbeat);
+ return hbm;
}
/**
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
index 1e4991131f453..7c5f4f999cde5 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
@@ -59,7 +59,6 @@
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.errors.TimeoutException;
import org.apache.kafka.common.errors.WakeupException;
-import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.JoinGroupRequest;
@@ -1400,23 +1399,6 @@ public void testProcessBackgroundEventsTimesOut() throws Exception {
}
}
- @Test
- public void testBS() {
- rlb = 1000L;
- Measurable lastRebalance = (config, now) -> {
- return TimeUnit.SECONDS.convert(now - rlb, TimeUnit.MILLISECONDS);
- };
-
- System.out.println(lastRebalance.measure(null, System.currentTimeMillis())); // Prints some value
-
-// Update lastRebalanceEndMs
- rlb = 2000L;
-
- System.out.println(lastRebalance.measure(null, System.currentTimeMillis())); // Still uses the captured value,
- // not the updated one
-
- }
-
private HashMap mockTopicPartitionOffset() {
final TopicPartition t0 = new TopicPartition("t0", 2);
final TopicPartition t1 = new TopicPartition("t0", 3);
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
index bdd3836303ac9..62886c7996631 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
@@ -217,7 +217,6 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
retryBackoffMs,
DEFAULT_RETRY_BACKOFF_MAX_MS,
gi.heartbeatJitterMs));
-
HeartbeatRequestManager heartbeat = spy(new HeartbeatRequestManager(
logContext,
pollTimer,
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 1dd5d4e1e6a53..e63112b92f46b 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -37,6 +37,7 @@
import org.apache.kafka.common.requests.RequestHeader;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.utils.LogContext;
+import org.apache.kafka.common.utils.MockTime;
import org.apache.kafka.common.utils.Time;
import org.apache.kafka.common.utils.Timer;
import org.apache.kafka.common.utils.annotation.ApiKeyVersionsSource;
@@ -63,6 +64,8 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_REMOTE_ASSIGNOR;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MAX_MS;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MS;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -568,34 +571,41 @@ public void testHeartbeatMetrics() {
coordinatorRequestManager = mock(CoordinatorRequestManager.class);
membershipManager = mock(MembershipManager.class);
heartbeatState = mock(HeartbeatRequestManager.HeartbeatState.class);
- heartbeatRequestState = new HeartbeatRequestManager.HeartbeatRequestState(
- new LogContext(),
- time,
- heartbeatIntervalMs,
- retryBackoffMs,
- retryBackoffMaxMs,
- 0);
+ time = new MockTime();
+ metrics = new Metrics(time);
+ heartbeatRequestState = spy(new HeartbeatRequestManager.HeartbeatRequestState(
+ new LogContext(),
+ time,
+ 0, // This initial interval should be 0 to ensure heartbeat on the clock
+ retryBackoffMs,
+ retryBackoffMaxMs,
+ 0));
backgroundEventHandler = mock(BackgroundEventHandler.class);
-
heartbeatRequestManager = createHeartbeatRequestManager(
- coordinatorRequestManager,
- membershipManager,
- heartbeatState,
- heartbeatRequestState,
- backgroundEventHandler);
+ coordinatorRequestManager,
+ membershipManager,
+ heartbeatState,
+ heartbeatRequestState,
+ backgroundEventHandler);
when(coordinatorRequestManager.coordinator()).thenReturn(Optional.of(new Node(1, "localhost", 9999)));
- when(membershipManager.shouldSkipHeartbeat()).thenReturn(false);
when(membershipManager.state()).thenReturn(MemberState.STABLE);
- time.sleep(maxPollIntervalMs);
NetworkClientDelegate.PollResult pollResult = heartbeatRequestManager.poll(time.milliseconds());
- ClientResponse hr = createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE);
- pollResult.unsentRequests.get(0).future().complete(hr);
-
assertEquals(1, pollResult.unsentRequests.size());
- //assertEquals(1, getMetric("heartbeat-response-time-max").metricValue());
- assertEquals(0.0, getMetric("heartbeat-rate").metricValue());
+ pollResult.unsentRequests.get(0).handler().onComplete(
+ createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE));
+ time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(1.0, getMetric("heartbeat-total").metricValue());
- assertEquals(1, getMetric("last-heartbeat-seconds-ago").metricValue());
+ assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
+
+ pollResult = heartbeatRequestManager.poll(time.milliseconds());
+ assertEquals(1, pollResult.unsentRequests.size());
+ pollResult.unsentRequests.get(0).handler().onComplete(
+ createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE));
+
+ assertEquals(0.06d, (double) getMetric("heartbeat-rate").metricValue(), 0.005d);
+ assertEquals(2.0, getMetric("heartbeat-total").metricValue());
+ time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
+ assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
}
private void assertHeartbeat(HeartbeatRequestManager hrm) {
@@ -707,12 +717,8 @@ private ConsumerConfig config() {
return new ConsumerConfig(prop);
}
- private void assertMetricsRecorded() {
-
- }
-
private KafkaMetric getMetric(final String name) {
- return metrics.metrics().get(metrics.metricName(name, "consumer-coordinator-metrics"));
+ return metrics.metrics().get(metrics.metricName(name, CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX));
}
private HeartbeatRequestManager createHeartbeatRequestManager(
From e96a06e525b9b20e38787acedede126083d2ad07 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 26 Jan 2024 11:24:46 -0800
Subject: [PATCH 15/28] clean up
clean up test
---
.../consumer/internals/ConsumerUtils.java | 2 +
.../metrics/AbstractConsumerMetrics.java | 65 +++++++--
.../internals/metrics/HeartbeatMetrics.java | 3 +-
.../metrics/RebalanceCallbackMetrics.java | 4 +-
.../internals/AsyncKafkaConsumerTest.java | 1 -
.../internals/ConsumerMetricsTest.java | 125 ++++++++++++++++++
.../HeartbeatRequestManagerTest.java | 27 ++--
7 files changed, 196 insertions(+), 31 deletions(-)
create mode 100644 clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
index bc7590c38f819..ddb79b034c872 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
@@ -66,6 +66,8 @@ public final class ConsumerUtils {
public static final String CONSUMER_JMX_PREFIX = "kafka.consumer";
public static final String CONSUMER_METRIC_GROUP_PREFIX = "consumer";
public static final String COORDINATOR_METRICS_SUFFIX = "-coordinator-metrics";
+ public static final String CONSUMER_METRICS_SUFFIX = "-metrics";
+ public static final String FETCH_MANAGER_METRICS_SUFFIX = "-fetch-manager-metrics";
/**
* A fixed, large enough value will suffice for max.
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index 1c380b116b14e..56f1a310b3f0d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -16,30 +16,72 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.clients.consumer.internals.ConsumerUtils;
import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.stats.Meter;
import org.apache.kafka.common.metrics.stats.WindowedCount;
+import java.util.Objects;
import java.util.Optional;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
+/**
+ * This class encapsulates the creation of metrics for the kafka consumer. When constructing a metrics object, you
+ * need to provide the suffix of the metric group. These are:
+ * -
+ *
Group Coordinator: {@link MetricSuffix#COORDINATOR}
+ * Consumer metrics: {@link MetricSuffix#CONSUMER}
+ * Fetch manager metrics: {@link MetricSuffix#FETCH_MANAGER}
+ *
+ *
+ * If no prefix is provided, we will use the default prefix {@link ConsumerUtils#CONSUMER_METRIC_GROUP_PREFIX}.
+ */
public abstract class AbstractConsumerMetrics {
- protected String groupMetricsName = CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX;
+ protected final String groupMetricsName;
+
+ public enum MetricSuffix {
+ COORDINATOR(COORDINATOR_METRICS_SUFFIX),
+ CONSUMER(CONSUMER_METRICS_SUFFIX),
+ FETCH_MANAGER(FETCH_MANAGER_METRICS_SUFFIX);
+
+ private final String suffix;
+
+ MetricSuffix(String suffix) {
+ this.suffix = suffix;
+ }
+
+ public String getSuffix() {
+ return suffix;
+ }
+ }
+
+ public AbstractConsumerMetrics(MetricSuffix suffix) {
+ this(Optional.empty(), suffix.getSuffix());
+ }
- public AbstractConsumerMetrics() {}
- public AbstractConsumerMetrics(Optional grpMetricsPrefix) {
- grpMetricsPrefix.ifPresent(s -> this.groupMetricsName = s + COORDINATOR_METRICS_SUFFIX);
+ public AbstractConsumerMetrics(Optional grpMetricsPrefix, String suffix) {
+ Objects.requireNonNull(suffix, "suffix cannot be null");
+ String prefix = grpMetricsPrefix.orElse(CONSUMER_METRIC_GROUP_PREFIX);
+ groupMetricsName = prefix + suffix;
}
- public static Meter createMeter(Metrics metrics, String groupName, String baseName, String descriptiveName) {
+ public String groupMetricsName() {
+ return groupMetricsName;
+ }
+
+ public Meter createMeter(Metrics metrics, String baseName, String descriptiveName) {
return new Meter(new WindowedCount(),
- metrics.metricName(baseName + "-rate", groupName,
- String.format("The number of %s per second", descriptiveName)),
- metrics.metricName(baseName + "-total", groupName,
- String.format("The total number of %s", descriptiveName)));
+ metrics.metricName(baseName + "-rate",
+ groupMetricsName,
+ String.format("The number of %s per second", descriptiveName)),
+ metrics.metricName(baseName + "-total",
+ groupMetricsName,
+ String.format("The total number of %s", descriptiveName)));
}
public void addMetric(Metrics metrics,
@@ -47,7 +89,8 @@ public void addMetric(Metrics metrics,
String description,
Measurable measurable) {
metrics.addMetric(
- metrics.metricName(name, groupMetricsName, description),
- measurable);
+ metrics.metricName(name, groupMetricsName, description),
+ measurable);
}
}
+
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
index ced8aaca6900b..ed9c93947ae5e 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -25,14 +25,13 @@ public class HeartbeatMetrics extends AbstractConsumerMetrics {
public final Sensor heartbeatSensor;
public HeartbeatMetrics(Metrics metrics) {
- super();
+ super(MetricSuffix.COORDINATOR);
heartbeatSensor = metrics.sensor("heartbeat-latency");
heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
groupMetricsName,
"The max time taken to receive a response to a heartbeat request"),
new Max());
heartbeatSensor.add(createMeter(metrics,
- groupMetricsName,
"heartbeat",
"heartbeats"));
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
index a27581505c517..c5850cd241a6e 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
@@ -21,8 +21,6 @@
import org.apache.kafka.common.metrics.stats.Avg;
import org.apache.kafka.common.metrics.stats.Max;
-import java.util.Optional;
-
public class RebalanceCallbackMetrics extends AbstractConsumerMetrics {
public final Sensor revokeCallbackSensor;
public final Sensor assignCallbackSensor;
@@ -33,7 +31,7 @@ public RebalanceCallbackMetrics(Metrics metrics) {
}
public RebalanceCallbackMetrics(Metrics metrics, String grpMetricsPrefix) {
- super(Optional.ofNullable(grpMetricsPrefix));
+ super(MetricSuffix.COORDINATOR);
revokeCallbackSensor = metrics.sensor("partition-revoked-latency");
revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
groupMetricsName,
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
index 7c5f4f999cde5..f6fb2a8928631 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumerTest.java
@@ -141,7 +141,6 @@ public class AsyncKafkaConsumerTest {
private final ApplicationEventHandler applicationEventHandler = mock(ApplicationEventHandler.class);
private final ConsumerMetadata metadata = mock(ConsumerMetadata.class);
private final LinkedBlockingQueue backgroundEventQueue = new LinkedBlockingQueue<>();
- long rlb = -1L;
@AfterEach
public void resetAll() {
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
new file mode 100644
index 0000000000000..9072575bada0e
--- /dev/null
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.kafka.clients.consumer.internals;
+
+import org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.common.metrics.KafkaMetric;
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.utils.MockTime;
+import org.apache.kafka.common.utils.Time;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class ConsumerMetricsTest {
+ private Time time = new MockTime();
+ private Metrics metrics = new Metrics(time);
+
+ @Test
+ public void testRebalanceCallbackMetrics() {
+ // MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
+ RebalanceCallbackMetrics rebalanceCallbackMetrics = new RebalanceCallbackMetrics(metrics);
+ String groupName = "consumer-coordinator-metrics";
+ assertNotNull(getMetric("partition-revoked-latency-avg", groupName));
+ assertNotNull(getMetric("partition-revoked-latency-max", groupName));
+ assertNotNull(getMetric("partition-assigned-latency-avg", groupName));
+ assertNotNull(getMetric("partition-assigned-latency-max", groupName));
+ assertNotNull(getMetric("partition-lost-latency-avg", groupName));
+ assertNotNull(getMetric("partition-lost-latency-max", groupName));
+
+ rebalanceCallbackMetrics.assignCallbackSensor.record(100);
+ rebalanceCallbackMetrics.revokeCallbackSensor.record(101);
+ rebalanceCallbackMetrics.loseCallbackSensor.record(102);
+
+ assertEquals(101d, getMetric("partition-revoked-latency-avg", groupName).metricValue());
+ assertEquals(101d, getMetric("partition-revoked-latency-max", groupName).metricValue());
+ assertEquals(100d, getMetric("partition-assigned-latency-avg", groupName).metricValue());
+ assertEquals(100d, getMetric("partition-assigned-latency-max", groupName).metricValue());
+ assertEquals(102d, getMetric("partition-lost-latency-avg", groupName).metricValue());
+ assertEquals(102d, getMetric("partition-lost-latency-max", groupName).metricValue());
+ }
+
+ @Test
+ public void testHeartbeatMetrics() {
+ // MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
+ HeartbeatMetrics heartbeatMetrics = new HeartbeatMetrics(metrics);
+ String groupName = "consumer-coordinator-metrics";
+ assertNotNull(getMetric("heartbeat-response-time-max", groupName));
+ assertNotNull(getMetric("heartbeat-rate", groupName));
+ assertNotNull(getMetric("heartbeat-total", groupName));
+
+ heartbeatMetrics.heartbeatSensor.record(100);
+ heartbeatMetrics.heartbeatSensor.record(100);
+ heartbeatMetrics.heartbeatSensor.record(100);
+
+ assertEquals(100d, getMetric("heartbeat-response-time-max", groupName).metricValue());
+ assertEquals(0.1d, (double) getMetric("heartbeat-rate", groupName).metricValue(), 0.01d);
+ assertEquals(3d, getMetric("heartbeat-total", groupName).metricValue());
+ }
+
+ @Test
+ public void testMetricsGroupName() {
+ // consumer-coordinator-metrics
+ NoopCoordinatorMetrics defaultCoordinatorMetrics = new NoopCoordinatorMetrics(Optional.empty());
+ assertEquals(CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX, defaultCoordinatorMetrics.groupMetricsName());
+ NoopCoordinatorMetrics coordinatorMetrics = new NoopCoordinatorMetrics(Optional.of("customCoordinatorPrefix"));
+ assertEquals("customCoordinatorPrefix" + COORDINATOR_METRICS_SUFFIX, coordinatorMetrics.groupMetricsName());
+
+ // consumer-metrics
+ NoopConsumerMetrics defaultConsumerMetrics = new NoopConsumerMetrics(Optional.empty());
+ assertEquals(CONSUMER_METRIC_GROUP_PREFIX + CONSUMER_METRICS_SUFFIX, defaultConsumerMetrics.groupMetricsName());
+ NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics(Optional.of("customConsumerPrefix"));
+ assertEquals("customConsumerPrefix" + CONSUMER_METRICS_SUFFIX, consumerMetrics.groupMetricsName());
+
+ // consumer-fetch-manager-metrics
+ NoopFetchManagerMetrics defaultFetchMetrics = new NoopFetchManagerMetrics(Optional.empty());
+ assertEquals(CONSUMER_METRIC_GROUP_PREFIX + FETCH_MANAGER_METRICS_SUFFIX, defaultFetchMetrics.groupMetricsName());
+ NoopFetchManagerMetrics fetchMetrics = new NoopFetchManagerMetrics(Optional.of("customFetchPrefix"));
+ assertEquals("customFetchPrefix" + FETCH_MANAGER_METRICS_SUFFIX, fetchMetrics.groupMetricsName());
+ }
+
+ private KafkaMetric getMetric(String metricName, String groupName) {
+ return metrics.metrics().get(metrics.metricName(metricName, groupName));
+ }
+
+ static class NoopCoordinatorMetrics extends AbstractConsumerMetrics {
+ public NoopCoordinatorMetrics(Optional prefix) {
+ super(prefix, MetricSuffix.COORDINATOR.getSuffix());
+ }
+ }
+
+ static class NoopConsumerMetrics extends AbstractConsumerMetrics {
+ public NoopConsumerMetrics(Optional prefix) {
+ super(prefix, MetricSuffix.CONSUMER.getSuffix());
+ }
+ }
+
+ static class NoopFetchManagerMetrics extends AbstractConsumerMetrics {
+ public NoopFetchManagerMetrics(Optional prefix) {
+ super(prefix, MetricSuffix.FETCH_MANAGER.getSuffix());
+ }
+ }
+}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index e63112b92f46b..8857c0f6c7b44 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -67,6 +67,7 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -554,8 +555,7 @@ public void testPollTimerExpiration() {
when(membershipManager.state()).thenReturn(MemberState.STABLE);
time.sleep(maxPollIntervalMs);
- NetworkClientDelegate.PollResult pollResult = heartbeatRequestManager.poll(time.milliseconds());
- assertEquals(1, pollResult.unsentRequests.size());
+ assertHeartbeat(heartbeatRequestManager, heartbeatIntervalMs);
verify(heartbeatState).reset();
verify(heartbeatRequestState).reset();
verify(membershipManager).transitionToStale();
@@ -563,7 +563,7 @@ public void testPollTimerExpiration() {
assertNoHeartbeat(heartbeatRequestManager);
heartbeatRequestManager.resetPollTimer(time.milliseconds());
assertTrue(pollTimer.notExpired());
- assertHeartbeat(heartbeatRequestManager);
+ assertHeartbeat(heartbeatRequestManager, heartbeatIntervalMs);
}
@Test
@@ -589,29 +589,28 @@ public void testHeartbeatMetrics() {
backgroundEventHandler);
when(coordinatorRequestManager.coordinator()).thenReturn(Optional.of(new Node(1, "localhost", 9999)));
when(membershipManager.state()).thenReturn(MemberState.STABLE);
- NetworkClientDelegate.PollResult pollResult = heartbeatRequestManager.poll(time.milliseconds());
- assertEquals(1, pollResult.unsentRequests.size());
- pollResult.unsentRequests.get(0).handler().onComplete(
- createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE));
+
+ assertNotNull(getMetric("heartbeat-response-time-max"));
+ assertNotNull(getMetric("heartbeat-rate"));
+ assertNotNull(getMetric("heartbeat-total"));
+ assertNotNull(getMetric("last-heartbeat-seconds-ago"));
+
+ assertHeartbeat(heartbeatRequestManager, 0);
time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(1.0, getMetric("heartbeat-total").metricValue());
assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
- pollResult = heartbeatRequestManager.poll(time.milliseconds());
- assertEquals(1, pollResult.unsentRequests.size());
- pollResult.unsentRequests.get(0).handler().onComplete(
- createHeartbeatResponse(pollResult.unsentRequests.get(0), Errors.NONE));
-
+ assertHeartbeat(heartbeatRequestManager, DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(0.06d, (double) getMetric("heartbeat-rate").metricValue(), 0.005d);
assertEquals(2.0, getMetric("heartbeat-total").metricValue());
time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
}
- private void assertHeartbeat(HeartbeatRequestManager hrm) {
+ private void assertHeartbeat(HeartbeatRequestManager hrm, int nextPollMs) {
NetworkClientDelegate.PollResult pollResult = hrm.poll(time.milliseconds());
assertEquals(1, pollResult.unsentRequests.size());
- assertEquals(DEFAULT_HEARTBEAT_INTERVAL_MS, pollResult.timeUntilNextPollMs);
+ assertEquals(nextPollMs, pollResult.timeUntilNextPollMs);
pollResult.unsentRequests.get(0).handler().onComplete(createHeartbeatResponse(pollResult.unsentRequests.get(0),
Errors.NONE));
}
From 6043316c25234cb6a0799bf6cc468314d8afdefe Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 26 Jan 2024 12:04:01 -0800
Subject: [PATCH 16/28] allow the manager to accept a group prefix
---
.../clients/consumer/internals/HeartbeatRequestManager.java | 6 ++++--
.../kafka/clients/consumer/internals/RequestManagers.java | 2 ++
.../clients/consumer/internals/ConsumerTestBuilder.java | 2 ++
.../consumer/internals/HeartbeatRequestManagerTest.java | 2 ++
4 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index fdf312a99beab..9ab81ccef3230 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -124,6 +124,7 @@ public HeartbeatRequestManager(
final SubscriptionState subscriptions,
final MembershipManager membershipManager,
final BackgroundEventHandler backgroundEventHandler,
+ final String metricGroupPrefix,
final Metrics metrics) {
this.coordinatorRequestManager = coordinatorRequestManager;
this.logger = logContext.logger(getClass());
@@ -136,7 +137,7 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
- this.heartbeatMetrics = createHeartbeatMetrics(metrics);
+ this.heartbeatMetrics = createHeartbeatMetrics(metrics, metricGroupPrefix);
}
// Visible for testing
@@ -149,6 +150,7 @@ public HeartbeatRequestManager(
final HeartbeatState heartbeatState,
final HeartbeatRequestState heartbeatRequestState,
final BackgroundEventHandler backgroundEventHandler,
+ final String metricGroupPrefix,
final Metrics metrics) {
this.logger = logContext.logger(this.getClass());
this.maxPollIntervalMs = config.getInt(CommonClientConfigs.MAX_POLL_INTERVAL_MS_CONFIG);
@@ -158,7 +160,7 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
- this.heartbeatMetrics = createHeartbeatMetrics(metrics);
+ this.heartbeatMetrics = createHeartbeatMetrics(metrics, metricGroupPrefix);
}
/**
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
index 7b3e75be0182c..b98f82d738e82 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
@@ -35,6 +35,7 @@
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.common.utils.Utils.closeQuietly;
/**
@@ -191,6 +192,7 @@ protected RequestManagers create() {
subscriptions,
membershipManager,
backgroundEventHandler,
+ CONSUMER_METRIC_GROUP_PREFIX,
metrics);
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
index 62886c7996631..b747945b73a71 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
@@ -48,6 +48,7 @@
import static org.apache.kafka.clients.consumer.ConsumerConfig.GROUP_INSTANCE_ID_CONFIG;
import static org.apache.kafka.clients.consumer.ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG;
import static org.apache.kafka.clients.consumer.ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createFetchMetricsManager;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createMetrics;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createSubscriptionState;
@@ -226,6 +227,7 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
heartbeatState,
heartbeatRequestState,
backgroundEventHandler,
+ CONSUMER_METRIC_GROUP_PREFIX,
metrics));
this.coordinatorRequestManager = Optional.of(coordinator);
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 8857c0f6c7b44..41a31a7eb18f7 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -85,6 +85,7 @@ public class HeartbeatRequestManagerTest {
private int maxPollIntervalMs = DEFAULT_MAX_POLL_INTERVAL_MS;
private long retryBackoffMaxMs = DEFAULT_RETRY_BACKOFF_MAX_MS;
private static final String DEFAULT_GROUP_ID = "groupId";
+ private String metricGroupPrefix = CONSUMER_METRIC_GROUP_PREFIX;
private ConsumerTestBuilder testBuilder;
private Time time;
@@ -737,6 +738,7 @@ private HeartbeatRequestManager createHeartbeatRequestManager(
heartbeatState,
heartbeatRequestState,
backgroundEventHandler,
+ metricGroupPrefix,
metrics);
}
}
From d0e1728812cbd1c2ba0c435ffa4f3841718fe6eb Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 26 Jan 2024 14:31:20 -0800
Subject: [PATCH 17/28] clean up
---
.../internals/HeartbeatRequestManager.java | 2 +-
.../metrics/AbstractConsumerMetrics.java | 60 ++++++++++---------
.../internals/metrics/HeartbeatMetrics.java | 16 +++--
.../metrics/RebalanceCallbackMetrics.java | 14 ++---
.../internals/ConsumerMetricsTest.java | 41 ++++---------
.../HeartbeatRequestManagerTest.java | 2 +-
6 files changed, 65 insertions(+), 70 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 9ab81ccef3230..267b2c465d1b8 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -428,7 +428,7 @@ private void handleFatalFailure(Throwable error) {
membershipManager.transitionToFatal();
}
- private HeartbeatMetrics createHeartbeatMetrics(Metrics metrics) {
+ private HeartbeatMetrics createHeartbeatMetrics(Metrics metrics, String metricGroupPrefix) {
HeartbeatMetrics hbm = new HeartbeatMetrics(metrics);
Measurable lastHeartbeat = (config, now) -> {
final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index 56f1a310b3f0d..950fdf566cb0d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -22,74 +22,80 @@
import org.apache.kafka.common.metrics.stats.Meter;
import org.apache.kafka.common.metrics.stats.WindowedCount;
-import java.util.Objects;
-import java.util.Optional;
-
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
/**
- * This class encapsulates the creation of metrics for the kafka consumer. When constructing a metrics object, you
- * need to provide the suffix of the metric group. These are:
- * -
- *
Group Coordinator: {@link MetricSuffix#COORDINATOR}
- * Consumer metrics: {@link MetricSuffix#CONSUMER}
- * Fetch manager metrics: {@link MetricSuffix#FETCH_MANAGER}
- *
+ * Base class for different consumer metrics to extend. This class helps to construct the logical group name from the
+ * given prefix and suffix, and provides a few common utilities.
+ *
+ *
+ * Prefix can be provided by the user and is "consumer-" by default (see {@link ConsumerUtils#CONSUMER_METRIC_GROUP_PREFIX}).
+ *
*
- * If no prefix is provided, we will use the default prefix {@link ConsumerUtils#CONSUMER_METRIC_GROUP_PREFIX}.
+ *
+ * The suffix can be one of the following:
+ *
+ * -coordinator-metrics: {@link MetricGroupSuffix#COORDINATOR}
+ * -metrics: {@link MetricGroupSuffix#CONSUMER}
+ * -fetch-manager-metrics: {@link MetricGroupSuffix#FETCH_MANAGER}
+ *
+ *
*/
public abstract class AbstractConsumerMetrics {
- protected final String groupMetricsName;
+ protected final String metricGroupName;
- public enum MetricSuffix {
+ public enum MetricGroupSuffix {
COORDINATOR(COORDINATOR_METRICS_SUFFIX),
CONSUMER(CONSUMER_METRICS_SUFFIX),
FETCH_MANAGER(FETCH_MANAGER_METRICS_SUFFIX);
private final String suffix;
- MetricSuffix(String suffix) {
+ MetricGroupSuffix(String suffix) {
this.suffix = suffix;
}
- public String getSuffix() {
+ @Override
+ public String toString() {
return suffix;
}
}
- public AbstractConsumerMetrics(MetricSuffix suffix) {
- this(Optional.empty(), suffix.getSuffix());
+ public AbstractConsumerMetrics(MetricGroupSuffix suffix) {
+ this(CONSUMER_METRIC_GROUP_PREFIX, suffix.toString());
}
- public AbstractConsumerMetrics(Optional grpMetricsPrefix, String suffix) {
- Objects.requireNonNull(suffix, "suffix cannot be null");
- String prefix = grpMetricsPrefix.orElse(CONSUMER_METRIC_GROUP_PREFIX);
- groupMetricsName = prefix + suffix;
+ public AbstractConsumerMetrics(String prefix, String suffix) {
+ if (suffix == null)
+ throw new IllegalArgumentException("metric group suffix cannot be null");
+ if (prefix == null)
+ throw new IllegalArgumentException("metric group prefix cannot be null");
+ metricGroupName = prefix + suffix;
}
- public String groupMetricsName() {
- return groupMetricsName;
+ public String metricGroupName() {
+ return metricGroupName;
}
public Meter createMeter(Metrics metrics, String baseName, String descriptiveName) {
return new Meter(new WindowedCount(),
metrics.metricName(baseName + "-rate",
- groupMetricsName,
+ metricGroupName,
String.format("The number of %s per second", descriptiveName)),
metrics.metricName(baseName + "-total",
- groupMetricsName,
+ metricGroupName,
String.format("The total number of %s", descriptiveName)));
}
public void addMetric(Metrics metrics,
- String name,
+ String metricName,
String description,
Measurable measurable) {
metrics.addMetric(
- metrics.metricName(name, groupMetricsName, description),
+ metrics.metricName(metricName, metricGroupName, description),
measurable);
}
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
index ed9c93947ae5e..4ec2899188cf2 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
@@ -20,19 +20,25 @@
import org.apache.kafka.common.metrics.Sensor;
import org.apache.kafka.common.metrics.stats.Max;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+
public class HeartbeatMetrics extends AbstractConsumerMetrics {
public final Sensor heartbeatSensor;
public HeartbeatMetrics(Metrics metrics) {
- super(MetricSuffix.COORDINATOR);
+ this(metrics, CONSUMER_METRIC_GROUP_PREFIX);
+ }
+
+ public HeartbeatMetrics(Metrics metrics, String prefix) {
+ super(MetricGroupSuffix.COORDINATOR);
heartbeatSensor = metrics.sensor("heartbeat-latency");
heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
- groupMetricsName,
+ metricGroupName,
"The max time taken to receive a response to a heartbeat request"),
- new Max());
+ new Max());
heartbeatSensor.add(createMeter(metrics,
- "heartbeat",
- "heartbeats"));
+ "heartbeat",
+ "heartbeats"));
}
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
index c5850cd241a6e..b0c1bad324663 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
@@ -31,29 +31,29 @@ public RebalanceCallbackMetrics(Metrics metrics) {
}
public RebalanceCallbackMetrics(Metrics metrics, String grpMetricsPrefix) {
- super(MetricSuffix.COORDINATOR);
+ super(MetricGroupSuffix.COORDINATOR);
revokeCallbackSensor = metrics.sensor("partition-revoked-latency");
revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
- groupMetricsName,
+ metricGroupName,
"The average time taken for a partition-revoked rebalance listener callback"), new Avg());
revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-max",
- groupMetricsName,
+ metricGroupName,
"The max time taken for a partition-revoked rebalance listener callback"), new Max());
assignCallbackSensor = metrics.sensor("partition-assigned-latency");
assignCallbackSensor.add(metrics.metricName("partition-assigned-latency-avg",
- groupMetricsName,
+ metricGroupName,
"The average time taken for a partition-assigned rebalance listener callback"), new Avg());
assignCallbackSensor.add(metrics.metricName("partition-assigned-latency-max",
- groupMetricsName,
+ metricGroupName,
"The max time taken for a partition-assigned rebalance listener callback"), new Max());
loseCallbackSensor = metrics.sensor("partition-lost-latency");
loseCallbackSensor.add(metrics.metricName("partition-lost-latency-avg",
- groupMetricsName,
+ metricGroupName,
"The average time taken for a partition-lost rebalance listener callback"), new Avg());
loseCallbackSensor.add(metrics.metricName("partition-lost-latency-max",
- groupMetricsName,
+ metricGroupName,
"The max time taken for a partition-lost rebalance listener callback"), new Max());
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
index 9072575bada0e..343e74ce40965 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
@@ -25,14 +25,12 @@
import org.apache.kafka.common.utils.Time;
import org.junit.jupiter.api.Test;
-import java.util.Optional;
-
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
public class ConsumerMetricsTest {
private Time time = new MockTime();
@@ -83,43 +81,28 @@ public void testHeartbeatMetrics() {
@Test
public void testMetricsGroupName() {
// consumer-coordinator-metrics
- NoopCoordinatorMetrics defaultCoordinatorMetrics = new NoopCoordinatorMetrics(Optional.empty());
- assertEquals(CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX, defaultCoordinatorMetrics.groupMetricsName());
- NoopCoordinatorMetrics coordinatorMetrics = new NoopCoordinatorMetrics(Optional.of("customCoordinatorPrefix"));
- assertEquals("customCoordinatorPrefix" + COORDINATOR_METRICS_SUFFIX, coordinatorMetrics.groupMetricsName());
+ NoopConsumerMetrics coordinatorMetrics = new NoopConsumerMetrics("customCoordinatorPrefix", AbstractConsumerMetrics.MetricGroupSuffix.COORDINATOR);
+ assertEquals("customCoordinatorPrefix" + COORDINATOR_METRICS_SUFFIX, coordinatorMetrics.metricGroupName());
// consumer-metrics
- NoopConsumerMetrics defaultConsumerMetrics = new NoopConsumerMetrics(Optional.empty());
- assertEquals(CONSUMER_METRIC_GROUP_PREFIX + CONSUMER_METRICS_SUFFIX, defaultConsumerMetrics.groupMetricsName());
- NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics(Optional.of("customConsumerPrefix"));
- assertEquals("customConsumerPrefix" + CONSUMER_METRICS_SUFFIX, consumerMetrics.groupMetricsName());
+ NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics("customConsumerPrefix", AbstractConsumerMetrics.MetricGroupSuffix.CONSUMER);
+ assertEquals("customConsumerPrefix" + CONSUMER_METRICS_SUFFIX, consumerMetrics.metricGroupName());
// consumer-fetch-manager-metrics
- NoopFetchManagerMetrics defaultFetchMetrics = new NoopFetchManagerMetrics(Optional.empty());
- assertEquals(CONSUMER_METRIC_GROUP_PREFIX + FETCH_MANAGER_METRICS_SUFFIX, defaultFetchMetrics.groupMetricsName());
- NoopFetchManagerMetrics fetchMetrics = new NoopFetchManagerMetrics(Optional.of("customFetchPrefix"));
- assertEquals("customFetchPrefix" + FETCH_MANAGER_METRICS_SUFFIX, fetchMetrics.groupMetricsName());
+ NoopConsumerMetrics fetchMetrics = new NoopConsumerMetrics("customFetchPrefix", AbstractConsumerMetrics.MetricGroupSuffix.FETCH_MANAGER);
+ assertEquals("customFetchPrefix" + FETCH_MANAGER_METRICS_SUFFIX, fetchMetrics.metricGroupName());
+
+ assertThrows(IllegalArgumentException.class, () -> new NoopConsumerMetrics(null,
+ AbstractConsumerMetrics.MetricGroupSuffix.CONSUMER));
}
private KafkaMetric getMetric(String metricName, String groupName) {
return metrics.metrics().get(metrics.metricName(metricName, groupName));
}
- static class NoopCoordinatorMetrics extends AbstractConsumerMetrics {
- public NoopCoordinatorMetrics(Optional prefix) {
- super(prefix, MetricSuffix.COORDINATOR.getSuffix());
- }
- }
-
static class NoopConsumerMetrics extends AbstractConsumerMetrics {
- public NoopConsumerMetrics(Optional prefix) {
- super(prefix, MetricSuffix.CONSUMER.getSuffix());
- }
- }
-
- static class NoopFetchManagerMetrics extends AbstractConsumerMetrics {
- public NoopFetchManagerMetrics(Optional prefix) {
- super(prefix, MetricSuffix.FETCH_MANAGER.getSuffix());
+ public NoopConsumerMetrics(String prefix, MetricGroupSuffix suffix) {
+ super(prefix, suffix.toString());
}
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 41a31a7eb18f7..68822970c17eb 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -718,7 +718,7 @@ private ConsumerConfig config() {
}
private KafkaMetric getMetric(final String name) {
- return metrics.metrics().get(metrics.metricName(name, CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX));
+ return metrics.metrics().get(metrics.metricName(name, metricGroupPrefix + COORDINATOR_METRICS_SUFFIX));
}
private HeartbeatRequestManager createHeartbeatRequestManager(
From 2e425a6d88f4e2c9c419742c24b4410d200e8270 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Fri, 26 Jan 2024 15:39:38 -0800
Subject: [PATCH 18/28] Update AbstractConsumerMetrics.java
---
.../consumer/internals/metrics/AbstractConsumerMetrics.java | 5 -----
1 file changed, 5 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
index 950fdf566cb0d..3e27167ddc286 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
@@ -16,7 +16,6 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
-import org.apache.kafka.clients.consumer.internals.ConsumerUtils;
import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.stats.Meter;
@@ -32,10 +31,6 @@
* given prefix and suffix, and provides a few common utilities.
*
*
- * Prefix can be provided by the user and is "consumer-" by default (see {@link ConsumerUtils#CONSUMER_METRIC_GROUP_PREFIX}).
- *
- *
- *
* The suffix can be one of the following:
*
* -coordinator-metrics: {@link MetricGroupSuffix#COORDINATOR}
From 308daa21c1a232870a486c1f1ba771b24367d0a5 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Sun, 28 Jan 2024 10:08:20 -0800
Subject: [PATCH 19/28] Reconsolidate metrics into consumer coordinator metrics
clean up
---
.../kafka/clients/consumer/KafkaConsumer.java | 2 +-
.../internals/AsyncKafkaConsumer.java | 7 +-
.../internals/CommitRequestManager.java | 35 ++-------
.../internals/ConsumerCoordinator.java | 4 +-
.../consumer/internals/ConsumerDelegate.java | 1 +
.../ConsumerRebalanceListenerInvoker.java | 12 +--
.../consumer/internals/ConsumerUtils.java | 1 -
.../internals/HeartbeatRequestManager.java | 35 ++-------
.../internals/LegacyKafkaConsumer.java | 1 +
.../consumer/internals/RequestManagers.java | 2 -
...va => AbstractConsumerMetricsManager.java} | 19 ++---
.../internals/metrics/HeartbeatMetrics.java | 44 -----------
.../metrics/HeartbeatMetricsManager.java | 69 +++++++++++++++++
.../{ => metrics}/KafkaConsumerMetrics.java | 10 +--
.../metrics/OffsetCommitMetricsManager.java | 50 +++++++++++++
.../metrics/RebalanceCallbackMetrics.java | 59 ---------------
.../RebalanceCallbackMetricsManager.java | 74 +++++++++++++++++++
.../internals/CommitRequestManagerTest.java | 1 -
...t.java => ConsumerMetricsManagerTest.java} | 44 +++++------
.../internals/ConsumerTestBuilder.java | 6 +-
.../HeartbeatRequestManagerTest.java | 6 +-
.../internals/KafkaConsumerMetricsTest.java | 1 +
.../internals/MembershipManagerImplTest.java | 4 +-
23 files changed, 259 insertions(+), 228 deletions(-)
rename clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/{AbstractConsumerMetrics.java => AbstractConsumerMetricsManager.java} (81%)
delete mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
create mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
rename clients/src/main/java/org/apache/kafka/clients/consumer/internals/{ => metrics}/KafkaConsumerMetrics.java (93%)
create mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
delete mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
create mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
rename clients/src/test/java/org/apache/kafka/clients/consumer/internals/{ConsumerMetricsTest.java => ConsumerMetricsManagerTest.java} (75%)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java
index 82e1f8b93da3c..bb75a40657311 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java
@@ -20,7 +20,7 @@
import org.apache.kafka.clients.consumer.internals.ConsumerDelegate;
import org.apache.kafka.clients.consumer.internals.ConsumerDelegateCreator;
import org.apache.kafka.clients.consumer.internals.ConsumerMetadata;
-import org.apache.kafka.clients.consumer.internals.KafkaConsumerMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
import org.apache.kafka.clients.consumer.internals.SubscriptionState;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.Metric;
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java
index c6b9efa23aef5..9198039a85a44 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java
@@ -60,7 +60,8 @@
import org.apache.kafka.clients.consumer.internals.events.TopicMetadataApplicationEvent;
import org.apache.kafka.clients.consumer.internals.events.UnsubscribeApplicationEvent;
import org.apache.kafka.clients.consumer.internals.events.ValidatePositionsApplicationEvent;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.IsolationLevel;
import org.apache.kafka.common.KafkaException;
@@ -395,7 +396,7 @@ private void process(final ConsumerRebalanceListenerCallbackNeededEvent event) {
logContext,
subscriptions,
time,
- new RebalanceCallbackMetrics(metrics)
+ new RebalanceCallbackMetricsManager(metrics)
);
this.backgroundEventProcessor = new BackgroundEventProcessor(
logContext,
@@ -538,7 +539,7 @@ private void process(final ConsumerRebalanceListenerCallbackNeededEvent event) {
logContext,
subscriptions,
time,
- new RebalanceCallbackMetrics(metrics)
+ new RebalanceCallbackMetricsManager(metrics, CONSUMER_METRIC_GROUP_PREFIX)
);
ApiVersions apiVersions = new ApiVersions();
Supplier networkClientDelegateSupplier = () -> new NetworkClientDelegate(
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
index 08cc6638aad8c..72fd1dbfed0ae 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
@@ -21,6 +21,7 @@
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.OffsetAndMetadata;
import org.apache.kafka.clients.consumer.RetriableCommitFailedException;
+import org.apache.kafka.clients.consumer.internals.metrics.OffsetCommitMetricsManager;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.errors.DisconnectException;
@@ -32,11 +33,6 @@
import org.apache.kafka.common.message.OffsetCommitRequestData;
import org.apache.kafka.common.message.OffsetCommitResponseData;
import org.apache.kafka.common.metrics.Metrics;
-import org.apache.kafka.common.metrics.Sensor;
-import org.apache.kafka.common.metrics.stats.Avg;
-import org.apache.kafka.common.metrics.stats.Max;
-import org.apache.kafka.common.metrics.stats.Meter;
-import org.apache.kafka.common.metrics.stats.WindowedCount;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.record.RecordBatch;
import org.apache.kafka.common.requests.AbstractRequest;
@@ -66,8 +62,6 @@
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.THROW_ON_FETCH_STABLE_OFFSET_UNSUPPORTED;
import static org.apache.kafka.clients.consumer.internals.NetworkClientDelegate.PollResult.EMPTY;
import static org.apache.kafka.common.protocol.Errors.COORDINATOR_LOAD_IN_PROGRESS;
@@ -87,7 +81,7 @@ public class CommitRequestManager implements RequestManager, MemberStateListener
private final boolean throwOnFetchStableOffsetUnsupported;
final PendingRequests pendingRequests;
private boolean closing = false;
- private Sensor commitSensor;
+ private OffsetCommitMetricsManager offsetCommitMetricsManager;
/**
* Latest member ID and epoch received via the {@link #onMemberEpochUpdated(Optional, Optional)},
@@ -116,7 +110,6 @@ public CommitRequestManager(
config.getLong(ConsumerConfig.RETRY_BACKOFF_MS_CONFIG),
config.getLong(ConsumerConfig.RETRY_BACKOFF_MAX_MS_CONFIG),
OptionalDouble.empty(),
- CONSUMER_METRIC_GROUP_PREFIX,
metrics);
}
@@ -132,7 +125,6 @@ public CommitRequestManager(
final long retryBackoffMs,
final long retryBackoffMaxMs,
final OptionalDouble jitter,
- final String metricGroupPrefix,
final Metrics metrics) {
Objects.requireNonNull(coordinatorRequestManager, "Coordinator is needed upon committing offsets");
this.logContext = logContext;
@@ -154,7 +146,7 @@ public CommitRequestManager(
this.jitter = jitter;
this.throwOnFetchStableOffsetUnsupported = config.getBoolean(THROW_ON_FETCH_STABLE_OFFSET_UNSUPPORTED);
this.memberInfo = new MemberInfo();
- this.commitSensor = addCommitSensor(metrics, metricGroupPrefix);
+ this.offsetCommitMetricsManager = new OffsetCommitMetricsManager(metrics);
}
/**
@@ -394,23 +386,6 @@ public NetworkClientDelegate.PollResult drainPendingOffsetCommitRequests() {
return new NetworkClientDelegate.PollResult(Long.MAX_VALUE, requests);
}
- private Sensor addCommitSensor(Metrics metrics, String metricGrpPrefix) {
- String metricGrpName = metricGrpPrefix + COORDINATOR_METRICS_SUFFIX;
- Sensor sensor = metrics.sensor("commit-latency");
- sensor.add(metrics.metricName("commit-latency-avg",
- metricGrpName,
- "The average time taken for a commit request"), new Avg());
- sensor.add(metrics.metricName("commit-latency-max",
- metricGrpName,
- "The max time taken for a commit request"), new Max());
- sensor.add(new Meter(new WindowedCount(),
- metrics.metricName("commit-rate", metricGrpName,
- "The number of commit calls per second"),
- metrics.metricName("commit-total", metricGrpName,
- "The total number of commit calls")));
- return sensor;
- }
-
private class OffsetCommitRequestState extends RetriableRequestState {
private final Map offsets;
private final String groupId;
@@ -505,8 +480,8 @@ public NetworkClientDelegate.UnsentRequest toUnsentRequest() {
* - fail the future with a non-recoverable KafkaException for all unexpected errors (even if retriable)
*/
@Override
- void onResponse(final ClientResponse response) {
- commitSensor.record(response.requestLatencyMs());
+ public void onResponse(final ClientResponse response) {
+ offsetCommitMetricsManager.recordRequestLatency(response.requestLatencyMs());
long currentTimeMs = response.receivedTimeMs();
OffsetCommitResponse commitResponse = (OffsetCommitResponse) response.responseBody();
Set unauthorizedTopics = new HashSet<>();
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java
index 398baf7fb079c..5af8633806da8 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerCoordinator.java
@@ -29,7 +29,7 @@
import org.apache.kafka.clients.consumer.OffsetCommitCallback;
import org.apache.kafka.clients.consumer.RetriableCommitFailedException;
import org.apache.kafka.clients.consumer.internals.Utils.TopicPartitionComparator;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.Node;
@@ -235,7 +235,7 @@ public ConsumerCoordinator(GroupRebalanceConfig rebalanceConfig,
logContext,
subscriptions,
time,
- new RebalanceCallbackMetrics(metrics, metricGrpPrefix)
+ new RebalanceCallbackMetricsManager(metrics, metricGrpPrefix)
);
this.metadata.requestUpdate(true);
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerDelegate.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerDelegate.java
index 612827ebe83df..67e8d991d639f 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerDelegate.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerDelegate.java
@@ -17,6 +17,7 @@
package org.apache.kafka.clients.consumer.internals;
import org.apache.kafka.clients.consumer.Consumer;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.utils.Timer;
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
index ea60436deb1ed..ca68158d4cf3b 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
@@ -17,7 +17,7 @@
package org.apache.kafka.clients.consumer.internals;
import org.apache.kafka.clients.consumer.ConsumerRebalanceListener;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.errors.InterruptException;
import org.apache.kafka.common.errors.WakeupException;
@@ -41,12 +41,12 @@ public class ConsumerRebalanceListenerInvoker {
private final Logger log;
private final SubscriptionState subscriptions;
private final Time time;
- private final RebalanceCallbackMetrics metrics;
+ private final RebalanceCallbackMetricsManager metrics;
ConsumerRebalanceListenerInvoker(LogContext logContext,
SubscriptionState subscriptions,
Time time,
- RebalanceCallbackMetrics metrics) {
+ RebalanceCallbackMetricsManager metrics) {
this.log = logContext.logger(getClass());
this.subscriptions = subscriptions;
this.time = time;
@@ -62,7 +62,7 @@ public Exception invokePartitionsAssigned(final SortedSet assign
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsAssigned(assignedPartitions);
- metrics.assignCallbackSensor.record(time.milliseconds() - startMs);
+ metrics.recordPartitionAssignLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -88,7 +88,7 @@ public Exception invokePartitionsRevoked(final SortedSet revoked
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsRevoked(revokedPartitions);
- metrics.revokeCallbackSensor.record(time.milliseconds() - startMs);
+ metrics.recordPartitionRevokeLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -114,7 +114,7 @@ public Exception invokePartitionsLost(final SortedSet lostPartit
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsLost(lostPartitions);
- metrics.loseCallbackSensor.record(time.milliseconds() - startMs);
+ metrics.recordPartitionLostLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
index ddb79b034c872..5a7745b40dd0d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerUtils.java
@@ -67,7 +67,6 @@ public final class ConsumerUtils {
public static final String CONSUMER_METRIC_GROUP_PREFIX = "consumer";
public static final String COORDINATOR_METRICS_SUFFIX = "-coordinator-metrics";
public static final String CONSUMER_METRICS_SUFFIX = "-metrics";
- public static final String FETCH_MANAGER_METRICS_SUFFIX = "-fetch-manager-metrics";
/**
* A fixed, large enough value will suffice for max.
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 267b2c465d1b8..2e0e63f786e40 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -23,12 +23,11 @@
import org.apache.kafka.clients.consumer.internals.events.BackgroundEventHandler;
import org.apache.kafka.clients.consumer.internals.events.ErrorBackgroundEvent;
import org.apache.kafka.clients.consumer.internals.events.GroupMetadataUpdateEvent;
-import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetricsManager;
import org.apache.kafka.common.Uuid;
import org.apache.kafka.common.errors.GroupAuthorizationException;
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.message.ConsumerGroupHeartbeatRequestData;
-import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.requests.ConsumerGroupHeartbeatRequest;
@@ -44,7 +43,6 @@
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
-import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -112,7 +110,7 @@ public class HeartbeatRequestManager implements RequestManager {
* sending heartbeat until the next poll.
*/
private final Timer pollTimer;
- private final HeartbeatMetrics heartbeatMetrics;
+ private final HeartbeatMetricsManager heartbeatMetricsManager;
private GroupMetadataUpdateEvent previousGroupMetadataUpdateEvent = null;
@@ -124,7 +122,6 @@ public HeartbeatRequestManager(
final SubscriptionState subscriptions,
final MembershipManager membershipManager,
final BackgroundEventHandler backgroundEventHandler,
- final String metricGroupPrefix,
final Metrics metrics) {
this.coordinatorRequestManager = coordinatorRequestManager;
this.logger = logContext.logger(getClass());
@@ -137,7 +134,7 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
- this.heartbeatMetrics = createHeartbeatMetrics(metrics, metricGroupPrefix);
+ this.heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
}
// Visible for testing
@@ -150,7 +147,6 @@ public HeartbeatRequestManager(
final HeartbeatState heartbeatState,
final HeartbeatRequestState heartbeatRequestState,
final BackgroundEventHandler backgroundEventHandler,
- final String metricGroupPrefix,
final Metrics metrics) {
this.logger = logContext.logger(this.getClass());
this.maxPollIntervalMs = config.getInt(CommonClientConfigs.MAX_POLL_INTERVAL_MS_CONFIG);
@@ -160,7 +156,7 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
- this.heartbeatMetrics = createHeartbeatMetrics(metrics, metricGroupPrefix);
+ this.heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
}
/**
@@ -256,6 +252,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final long curr
NetworkClientDelegate.UnsentRequest request = makeHeartbeatRequest(ignoreResponse);
heartbeatRequestState.onSendAttempt(currentTimeMs);
membershipManager.onHeartbeatRequestSent();
+ heartbeatMetricsManager.recordHeartbeatSentMs(currentTimeMs);
return request;
}
@@ -268,7 +265,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
else
return request.whenComplete((response, exception) -> {
if (response != null) {
- heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
+ heartbeatMetricsManager.recordRequestLatency(response.requestLatencyMs());
onResponse((ConsumerGroupHeartbeatResponse) response.responseBody(), request.handler().completionTimeMs());
} else {
onFailure(exception, request.handler().completionTimeMs());
@@ -279,7 +276,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
private NetworkClientDelegate.UnsentRequest logResponse(final NetworkClientDelegate.UnsentRequest request) {
return request.whenComplete((response, exception) -> {
if (response != null) {
- heartbeatMetrics.heartbeatSensor.record(response.requestLatencyMs());
+ heartbeatMetricsManager.recordRequestLatency(response.requestLatencyMs());
Errors error =
Errors.forCode(((ConsumerGroupHeartbeatResponse) response.responseBody()).data().errorCode());
if (error == Errors.NONE)
@@ -428,24 +425,6 @@ private void handleFatalFailure(Throwable error) {
membershipManager.transitionToFatal();
}
- private HeartbeatMetrics createHeartbeatMetrics(Metrics metrics, String metricGroupPrefix) {
- HeartbeatMetrics hbm = new HeartbeatMetrics(metrics);
- Measurable lastHeartbeat = (config, now) -> {
- final long lastHeartbeatSend = heartbeatRequestState.lastSentMs;
- if (lastHeartbeatSend < 0L)
- // if no heartbeat is ever triggered, just return -1.
- return -1d;
- else
- return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
- };
- hbm.addMetric(
- metrics,
- "last-heartbeat-seconds-ago",
- "The number of seconds since the last coordinator heartbeat was sent",
- lastHeartbeat);
- return hbm;
- }
-
/**
* Represents the state of a heartbeat request, including logic for timing, retries, and exponential backoff. The
* object extends {@link RequestState} to enable exponential backoff and duplicated request handling. The two fields
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/LegacyKafkaConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/LegacyKafkaConsumer.java
index bcc8cb40f2d91..80be0959d69cb 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/LegacyKafkaConsumer.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/LegacyKafkaConsumer.java
@@ -35,6 +35,7 @@
import org.apache.kafka.clients.consumer.OffsetAndTimestamp;
import org.apache.kafka.clients.consumer.OffsetCommitCallback;
import org.apache.kafka.clients.consumer.OffsetResetStrategy;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.IsolationLevel;
import org.apache.kafka.common.KafkaException;
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
index b98f82d738e82..7b3e75be0182c 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestManagers.java
@@ -35,7 +35,6 @@
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.common.utils.Utils.closeQuietly;
/**
@@ -192,7 +191,6 @@ protected RequestManagers create() {
subscriptions,
membershipManager,
backgroundEventHandler,
- CONSUMER_METRIC_GROUP_PREFIX,
metrics);
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
similarity index 81%
rename from clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
rename to clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
index 3e27167ddc286..1eafcfa95bfbc 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
@@ -22,9 +22,7 @@
import org.apache.kafka.common.metrics.stats.WindowedCount;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
/**
* Base class for different consumer metrics to extend. This class helps to construct the logical group name from the
@@ -35,17 +33,16 @@
*
* -coordinator-metrics: {@link MetricGroupSuffix#COORDINATOR}
* -metrics: {@link MetricGroupSuffix#CONSUMER}
- * -fetch-manager-metrics: {@link MetricGroupSuffix#FETCH_MANAGER}
*
*
*/
-public abstract class AbstractConsumerMetrics {
+public abstract class AbstractConsumerMetricsManager {
protected final String metricGroupName;
+ final Metrics metrics;
public enum MetricGroupSuffix {
COORDINATOR(COORDINATOR_METRICS_SUFFIX),
- CONSUMER(CONSUMER_METRICS_SUFFIX),
- FETCH_MANAGER(FETCH_MANAGER_METRICS_SUFFIX);
+ CONSUMER(CONSUMER_METRICS_SUFFIX);
private final String suffix;
@@ -59,15 +56,12 @@ public String toString() {
}
}
- public AbstractConsumerMetrics(MetricGroupSuffix suffix) {
- this(CONSUMER_METRIC_GROUP_PREFIX, suffix.toString());
- }
-
- public AbstractConsumerMetrics(String prefix, String suffix) {
+ public AbstractConsumerMetricsManager(Metrics metrics, String prefix, MetricGroupSuffix suffix) {
if (suffix == null)
throw new IllegalArgumentException("metric group suffix cannot be null");
if (prefix == null)
throw new IllegalArgumentException("metric group prefix cannot be null");
+ this.metrics = metrics;
metricGroupName = prefix + suffix;
}
@@ -85,8 +79,7 @@ public Meter createMeter(Metrics metrics, String baseName, String descriptiveNam
String.format("The total number of %s", descriptiveName)));
}
- public void addMetric(Metrics metrics,
- String metricName,
+ public void addMetric(String metricName,
String description,
Measurable measurable) {
metrics.addMetric(
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
deleted file mode 100644
index 4ec2899188cf2..0000000000000
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetrics.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.kafka.clients.consumer.internals.metrics;
-
-import org.apache.kafka.common.metrics.Metrics;
-import org.apache.kafka.common.metrics.Sensor;
-import org.apache.kafka.common.metrics.stats.Max;
-
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
-
-public class HeartbeatMetrics extends AbstractConsumerMetrics {
-
- public final Sensor heartbeatSensor;
-
- public HeartbeatMetrics(Metrics metrics) {
- this(metrics, CONSUMER_METRIC_GROUP_PREFIX);
- }
-
- public HeartbeatMetrics(Metrics metrics, String prefix) {
- super(MetricGroupSuffix.COORDINATOR);
- heartbeatSensor = metrics.sensor("heartbeat-latency");
- heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
- metricGroupName,
- "The max time taken to receive a response to a heartbeat request"),
- new Max());
- heartbeatSensor.add(createMeter(metrics,
- "heartbeat",
- "heartbeats"));
- }
-}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
new file mode 100644
index 0000000000000..708d89ea2d510
--- /dev/null
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
@@ -0,0 +1,69 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Measurable;
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.Sensor;
+import org.apache.kafka.common.metrics.stats.Max;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+
+public class HeartbeatMetricsManager extends AbstractConsumerMetricsManager {
+
+ public final Sensor heartbeatSensor;
+ private long lastHeartbeatMs = -1L;
+
+ public HeartbeatMetricsManager(Metrics metrics) {
+ this(metrics, CONSUMER_METRIC_GROUP_PREFIX);
+ }
+
+ public HeartbeatMetricsManager(Metrics metrics, String prefix) {
+ super(metrics, prefix, MetricGroupSuffix.COORDINATOR);
+ heartbeatSensor = metrics.sensor("heartbeat-latency");
+ heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
+ metricGroupName,
+ "The max time taken to receive a response to a heartbeat request"),
+ new Max());
+ heartbeatSensor.add(createMeter(metrics,
+ "heartbeat",
+ "heartbeats"));
+
+ Measurable lastHeartbeat = (config, now) -> {
+ final long lastHeartbeatSend = lastHeartbeatMs;
+ if (lastHeartbeatSend < 0L)
+ // if no heartbeat is ever triggered, just return -1.
+ return -1d;
+ else
+ return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
+ };
+ addMetric(
+ "last-heartbeat-seconds-ago",
+ "The number of seconds since the last coordinator heartbeat was sent",
+ lastHeartbeat);
+ }
+
+ public void recordHeartbeatSentMs(long lastHeartbeatMs) {
+ this.lastHeartbeatMs = lastHeartbeatMs;
+ }
+
+ public void recordRequestLatency(long requestLatencyMs) {
+ heartbeatSensor.record(requestLatencyMs);
+ }
+}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
similarity index 93%
rename from clients/src/main/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetrics.java
rename to clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
index 0dc8a33b11bbb..ce32b9d97e02b 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.kafka.clients.consumer.internals;
+package org.apache.kafka.clients.consumer.internals.metrics;
import org.apache.kafka.common.MetricName;
import org.apache.kafka.common.metrics.Measurable;
@@ -26,20 +26,20 @@
import java.util.concurrent.TimeUnit;
-public class KafkaConsumerMetrics implements AutoCloseable {
+import static org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetricsManager.MetricGroupSuffix.CONSUMER;
+
+public class KafkaConsumerMetrics extends AbstractConsumerMetricsManager implements AutoCloseable {
private final MetricName lastPollMetricName;
private final Sensor timeBetweenPollSensor;
private final Sensor pollIdleSensor;
private final Sensor committedSensor;
private final Sensor commitSyncSensor;
- private final Metrics metrics;
private long lastPollMs;
private long pollStartMs;
private long timeSinceLastPollMs;
public KafkaConsumerMetrics(Metrics metrics, String metricGrpPrefix) {
- this.metrics = metrics;
- String metricGroupName = metricGrpPrefix + "-metrics";
+ super(metrics, metricGrpPrefix, CONSUMER);
Measurable lastPoll = (mConfig, now) -> {
if (lastPollMs == 0L)
// if no poll is ever triggered, just return -1.
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
new file mode 100644
index 0000000000000..7aef981066820
--- /dev/null
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
@@ -0,0 +1,50 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.Sensor;
+import org.apache.kafka.common.metrics.stats.Avg;
+import org.apache.kafka.common.metrics.stats.Max;
+import org.apache.kafka.common.metrics.stats.Meter;
+import org.apache.kafka.common.metrics.stats.WindowedCount;
+
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+
+public class OffsetCommitMetricsManager extends AbstractConsumerMetricsManager {
+ private final Sensor commitSensor;
+
+ public OffsetCommitMetricsManager(Metrics metrics) {
+ super(metrics, CONSUMER_METRIC_GROUP_PREFIX, MetricGroupSuffix.COORDINATOR);
+ commitSensor = metrics.sensor("commit-latency");
+ commitSensor.add(metrics.metricName("commit-latency-avg",
+ metricGroupName(),
+ "The average time taken for a commit request"), new Avg());
+ commitSensor.add(metrics.metricName("commit-latency-max",
+ metricGroupName(),
+ "The max time taken for a commit request"), new Max());
+ commitSensor.add(new Meter(new WindowedCount(),
+ metrics.metricName("commit-rate", metricGroupName(),
+ "The number of commit calls per second"),
+ metrics.metricName("commit-total", metricGroupName(),
+ "The total number of commit calls")));
+ }
+
+ public void recordRequestLatency(long latencyMs) {
+ this.commitSensor.record(latencyMs);
+ }
+}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
deleted file mode 100644
index b0c1bad324663..0000000000000
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetrics.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.kafka.clients.consumer.internals.metrics;
-
-import org.apache.kafka.common.metrics.Metrics;
-import org.apache.kafka.common.metrics.Sensor;
-import org.apache.kafka.common.metrics.stats.Avg;
-import org.apache.kafka.common.metrics.stats.Max;
-
-public class RebalanceCallbackMetrics extends AbstractConsumerMetrics {
- public final Sensor revokeCallbackSensor;
- public final Sensor assignCallbackSensor;
- public final Sensor loseCallbackSensor;
-
- public RebalanceCallbackMetrics(Metrics metrics) {
- this(metrics, null);
- }
-
- public RebalanceCallbackMetrics(Metrics metrics, String grpMetricsPrefix) {
- super(MetricGroupSuffix.COORDINATOR);
- revokeCallbackSensor = metrics.sensor("partition-revoked-latency");
- revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
- metricGroupName,
- "The average time taken for a partition-revoked rebalance listener callback"), new Avg());
- revokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-max",
- metricGroupName,
- "The max time taken for a partition-revoked rebalance listener callback"), new Max());
-
- assignCallbackSensor = metrics.sensor("partition-assigned-latency");
- assignCallbackSensor.add(metrics.metricName("partition-assigned-latency-avg",
- metricGroupName,
- "The average time taken for a partition-assigned rebalance listener callback"), new Avg());
- assignCallbackSensor.add(metrics.metricName("partition-assigned-latency-max",
- metricGroupName,
- "The max time taken for a partition-assigned rebalance listener callback"), new Max());
-
- loseCallbackSensor = metrics.sensor("partition-lost-latency");
- loseCallbackSensor.add(metrics.metricName("partition-lost-latency-avg",
- metricGroupName,
- "The average time taken for a partition-lost rebalance listener callback"), new Avg());
- loseCallbackSensor.add(metrics.metricName("partition-lost-latency-max",
- metricGroupName,
- "The max time taken for a partition-lost rebalance listener callback"), new Max());
- }
-}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
new file mode 100644
index 0000000000000..19e7267805a0a
--- /dev/null
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
@@ -0,0 +1,74 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.metrics.Sensor;
+import org.apache.kafka.common.metrics.stats.Avg;
+import org.apache.kafka.common.metrics.stats.Max;
+
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+import static org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetricsManager.MetricGroupSuffix.COORDINATOR;
+
+public class RebalanceCallbackMetricsManager extends AbstractConsumerMetricsManager {
+ private final Sensor partitionRevokeCallbackSensor;
+ private final Sensor partitionAssignCallbackSensor;
+ private final Sensor partitionLostCallbackSensor;
+
+ public RebalanceCallbackMetricsManager(Metrics metrics) {
+ this(metrics, CONSUMER_METRIC_GROUP_PREFIX);
+ }
+
+ public RebalanceCallbackMetricsManager(Metrics metrics, String grpMetricsPrefix) {
+ super(metrics, grpMetricsPrefix, COORDINATOR);
+ partitionRevokeCallbackSensor = metrics.sensor("partition-revoked-latency");
+ partitionRevokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
+ metricGroupName,
+ "The average time taken for a partition-revoked rebalance listener callback"), new Avg());
+ partitionRevokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-max",
+ metricGroupName,
+ "The max time taken for a partition-revoked rebalance listener callback"), new Max());
+
+ partitionAssignCallbackSensor = metrics.sensor("partition-assigned-latency");
+ partitionAssignCallbackSensor.add(metrics.metricName("partition-assigned-latency-avg",
+ metricGroupName,
+ "The average time taken for a partition-assigned rebalance listener callback"), new Avg());
+ partitionAssignCallbackSensor.add(metrics.metricName("partition-assigned-latency-max",
+ metricGroupName,
+ "The max time taken for a partition-assigned rebalance listener callback"), new Max());
+
+ partitionLostCallbackSensor = metrics.sensor("partition-lost-latency");
+ partitionLostCallbackSensor.add(metrics.metricName("partition-lost-latency-avg",
+ metricGroupName,
+ "The average time taken for a partition-lost rebalance listener callback"), new Avg());
+ partitionLostCallbackSensor.add(metrics.metricName("partition-lost-latency-max",
+ metricGroupName,
+ "The max time taken for a partition-lost rebalance listener callback"), new Max());
+ }
+
+ public void recordPartitionRevokeLatency(long latencyMs) {
+ partitionRevokeCallbackSensor.record(latencyMs);
+ }
+
+ public void recordPartitionAssignLatency(long latencyMs) {
+ partitionAssignCallbackSensor.record(latencyMs);
+ }
+
+ public void recordPartitionLostLatency(long latencyMs) {
+ partitionLostCallbackSensor.record(latencyMs);
+ }
+}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
index f7a5e6fd114cf..139d922efe2c6 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
@@ -1079,7 +1079,6 @@ private CommitRequestManager create(final boolean autoCommitEnabled, final long
retryBackoffMs,
retryBackoffMaxMs,
OptionalDouble.of(0),
- consumerMetricGroupPrefix,
metrics));
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
similarity index 75%
rename from clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
rename to clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
index 343e74ce40965..5fad34987eeef 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
@@ -16,9 +16,9 @@
*/
package org.apache.kafka.clients.consumer.internals;
-import org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetrics;
-import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetrics;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetricsManager;
+import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetricsManager;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.metrics.KafkaMetric;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.utils.MockTime;
@@ -27,19 +27,18 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.FETCH_MANAGER_METRICS_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
-public class ConsumerMetricsTest {
+public class ConsumerMetricsManagerTest {
private Time time = new MockTime();
private Metrics metrics = new Metrics(time);
@Test
public void testRebalanceCallbackMetrics() {
// MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
- RebalanceCallbackMetrics rebalanceCallbackMetrics = new RebalanceCallbackMetrics(metrics);
+ RebalanceCallbackMetricsManager rebalanceCallbackMetricsManager = new RebalanceCallbackMetricsManager(metrics);
String groupName = "consumer-coordinator-metrics";
assertNotNull(getMetric("partition-revoked-latency-avg", groupName));
assertNotNull(getMetric("partition-revoked-latency-max", groupName));
@@ -48,9 +47,9 @@ public void testRebalanceCallbackMetrics() {
assertNotNull(getMetric("partition-lost-latency-avg", groupName));
assertNotNull(getMetric("partition-lost-latency-max", groupName));
- rebalanceCallbackMetrics.assignCallbackSensor.record(100);
- rebalanceCallbackMetrics.revokeCallbackSensor.record(101);
- rebalanceCallbackMetrics.loseCallbackSensor.record(102);
+ rebalanceCallbackMetricsManager.recordPartitionAssignLatency(100);
+ rebalanceCallbackMetricsManager.recordPartitionRevokeLatency(101);
+ rebalanceCallbackMetricsManager.recordPartitionLostLatency(102);
assertEquals(101d, getMetric("partition-revoked-latency-avg", groupName).metricValue());
assertEquals(101d, getMetric("partition-revoked-latency-max", groupName).metricValue());
@@ -63,15 +62,15 @@ public void testRebalanceCallbackMetrics() {
@Test
public void testHeartbeatMetrics() {
// MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
- HeartbeatMetrics heartbeatMetrics = new HeartbeatMetrics(metrics);
+ HeartbeatMetricsManager heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
String groupName = "consumer-coordinator-metrics";
assertNotNull(getMetric("heartbeat-response-time-max", groupName));
assertNotNull(getMetric("heartbeat-rate", groupName));
assertNotNull(getMetric("heartbeat-total", groupName));
- heartbeatMetrics.heartbeatSensor.record(100);
- heartbeatMetrics.heartbeatSensor.record(100);
- heartbeatMetrics.heartbeatSensor.record(100);
+ heartbeatMetricsManager.heartbeatSensor.record(100);
+ heartbeatMetricsManager.heartbeatSensor.record(100);
+ heartbeatMetricsManager.heartbeatSensor.record(100);
assertEquals(100d, getMetric("heartbeat-response-time-max", groupName).metricValue());
assertEquals(0.1d, (double) getMetric("heartbeat-rate", groupName).metricValue(), 0.01d);
@@ -81,28 +80,25 @@ public void testHeartbeatMetrics() {
@Test
public void testMetricsGroupName() {
// consumer-coordinator-metrics
- NoopConsumerMetrics coordinatorMetrics = new NoopConsumerMetrics("customCoordinatorPrefix", AbstractConsumerMetrics.MetricGroupSuffix.COORDINATOR);
+ NoopConsumerMetrics coordinatorMetrics = new NoopConsumerMetrics(metrics, "customCoordinatorPrefix", AbstractConsumerMetricsManager.MetricGroupSuffix.COORDINATOR);
assertEquals("customCoordinatorPrefix" + COORDINATOR_METRICS_SUFFIX, coordinatorMetrics.metricGroupName());
// consumer-metrics
- NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics("customConsumerPrefix", AbstractConsumerMetrics.MetricGroupSuffix.CONSUMER);
+ NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics(metrics, "customConsumerPrefix", AbstractConsumerMetricsManager.MetricGroupSuffix.CONSUMER);
assertEquals("customConsumerPrefix" + CONSUMER_METRICS_SUFFIX, consumerMetrics.metricGroupName());
- // consumer-fetch-manager-metrics
- NoopConsumerMetrics fetchMetrics = new NoopConsumerMetrics("customFetchPrefix", AbstractConsumerMetrics.MetricGroupSuffix.FETCH_MANAGER);
- assertEquals("customFetchPrefix" + FETCH_MANAGER_METRICS_SUFFIX, fetchMetrics.metricGroupName());
-
- assertThrows(IllegalArgumentException.class, () -> new NoopConsumerMetrics(null,
- AbstractConsumerMetrics.MetricGroupSuffix.CONSUMER));
+ assertThrows(IllegalArgumentException.class, () -> new NoopConsumerMetrics(metrics,
+ null,
+ AbstractConsumerMetricsManager.MetricGroupSuffix.CONSUMER));
}
private KafkaMetric getMetric(String metricName, String groupName) {
return metrics.metrics().get(metrics.metricName(metricName, groupName));
}
- static class NoopConsumerMetrics extends AbstractConsumerMetrics {
- public NoopConsumerMetrics(String prefix, MetricGroupSuffix suffix) {
- super(prefix, suffix.toString());
+ static class NoopConsumerMetrics extends AbstractConsumerMetricsManager {
+ public NoopConsumerMetrics(Metrics metrics, String prefix, MetricGroupSuffix suffix) {
+ super(metrics, prefix, suffix);
}
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
index b747945b73a71..06bcd22bb597f 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerTestBuilder.java
@@ -25,7 +25,7 @@
import org.apache.kafka.clients.consumer.internals.events.ApplicationEventProcessor;
import org.apache.kafka.clients.consumer.internals.events.BackgroundEvent;
import org.apache.kafka.clients.consumer.internals.events.BackgroundEventHandler;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.internals.ClusterResourceListeners;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.requests.MetadataResponse;
@@ -48,7 +48,6 @@
import static org.apache.kafka.clients.consumer.ConsumerConfig.GROUP_INSTANCE_ID_CONFIG;
import static org.apache.kafka.clients.consumer.ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG;
import static org.apache.kafka.clients.consumer.ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createFetchMetricsManager;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createMetrics;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.createSubscriptionState;
@@ -227,7 +226,6 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
heartbeatState,
heartbeatRequestState,
backgroundEventHandler,
- CONSUMER_METRIC_GROUP_PREFIX,
metrics));
this.coordinatorRequestManager = Optional.of(coordinator);
@@ -274,7 +272,7 @@ public ConsumerTestBuilder(Optional groupInfo, boolean enableA
logContext,
subscriptions,
time,
- new RebalanceCallbackMetrics(metrics)
+ new RebalanceCallbackMetricsManager(metrics)
);
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 68822970c17eb..33d54ab66389d 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -57,6 +57,7 @@
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_GROUP_INSTANCE_ID;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_HEARTBEAT_INTERVAL_MS;
@@ -599,13 +600,13 @@ public void testHeartbeatMetrics() {
assertHeartbeat(heartbeatRequestManager, 0);
time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(1.0, getMetric("heartbeat-total").metricValue());
- assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
+ assertEquals((double) TimeUnit.MILLISECONDS.toSeconds(heartbeatIntervalMs), getMetric("last-heartbeat-seconds-ago").metricValue());
assertHeartbeat(heartbeatRequestManager, DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(0.06d, (double) getMetric("heartbeat-rate").metricValue(), 0.005d);
assertEquals(2.0, getMetric("heartbeat-total").metricValue());
time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
- assertEquals(heartbeatIntervalMs / 1000d, getMetric("last-heartbeat-seconds-ago").metricValue());
+ assertEquals((double) TimeUnit.MILLISECONDS.toSeconds(heartbeatIntervalMs), getMetric("last-heartbeat-seconds-ago").metricValue());
}
private void assertHeartbeat(HeartbeatRequestManager hrm, int nextPollMs) {
@@ -738,7 +739,6 @@ private HeartbeatRequestManager createHeartbeatRequestManager(
heartbeatState,
heartbeatRequestState,
backgroundEventHandler,
- metricGroupPrefix,
metrics);
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetricsTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetricsTest.java
index 087f90b7efa31..c75ee906e535b 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetricsTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/KafkaConsumerMetricsTest.java
@@ -17,6 +17,7 @@
package org.apache.kafka.clients.consumer.internals;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
import org.apache.kafka.common.metrics.Metrics;
import org.junit.jupiter.api.Test;
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/MembershipManagerImplTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/MembershipManagerImplTest.java
index 7683a521e0d6a..a87b6efe16152 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/MembershipManagerImplTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/MembershipManagerImplTest.java
@@ -20,7 +20,7 @@
import org.apache.kafka.clients.consumer.internals.events.BackgroundEventHandler;
import org.apache.kafka.clients.consumer.internals.events.ConsumerRebalanceListenerCallbackCompletedEvent;
import org.apache.kafka.clients.consumer.internals.events.ConsumerRebalanceListenerCallbackNeededEvent;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.KafkaException;
import org.apache.kafka.common.TopicIdPartition;
import org.apache.kafka.common.TopicPartition;
@@ -1388,7 +1388,7 @@ private ConsumerRebalanceListenerInvoker consumerRebalanceListenerInvoker() {
new LogContext(),
subscriptionState,
new MockTime(1),
- new RebalanceCallbackMetrics(new Metrics())
+ new RebalanceCallbackMetricsManager(new Metrics())
);
}
From 882460887ce1969237bf5553ee0072ef1ddbdb7c Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Sun, 28 Jan 2024 17:04:37 -0800
Subject: [PATCH 20/28] clean up name
---
.../consumer/internals/CommitRequestManager.java | 6 +++---
.../internals/ConsumerRebalanceListenerInvoker.java | 12 ++++++------
.../consumer/internals/HeartbeatRequestManager.java | 12 ++++++------
3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
index 72fd1dbfed0ae..58d1ffd2d3c6d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
@@ -81,7 +81,7 @@ public class CommitRequestManager implements RequestManager, MemberStateListener
private final boolean throwOnFetchStableOffsetUnsupported;
final PendingRequests pendingRequests;
private boolean closing = false;
- private OffsetCommitMetricsManager offsetCommitMetricsManager;
+ private OffsetCommitMetricsManager metricsManager;
/**
* Latest member ID and epoch received via the {@link #onMemberEpochUpdated(Optional, Optional)},
@@ -146,7 +146,7 @@ public CommitRequestManager(
this.jitter = jitter;
this.throwOnFetchStableOffsetUnsupported = config.getBoolean(THROW_ON_FETCH_STABLE_OFFSET_UNSUPPORTED);
this.memberInfo = new MemberInfo();
- this.offsetCommitMetricsManager = new OffsetCommitMetricsManager(metrics);
+ this.metricsManager = new OffsetCommitMetricsManager(metrics);
}
/**
@@ -481,7 +481,7 @@ public NetworkClientDelegate.UnsentRequest toUnsentRequest() {
*/
@Override
public void onResponse(final ClientResponse response) {
- offsetCommitMetricsManager.recordRequestLatency(response.requestLatencyMs());
+ metricsManager.recordRequestLatency(response.requestLatencyMs());
long currentTimeMs = response.receivedTimeMs();
OffsetCommitResponse commitResponse = (OffsetCommitResponse) response.responseBody();
Set unauthorizedTopics = new HashSet<>();
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
index ca68158d4cf3b..93d5c65bee539 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
@@ -41,16 +41,16 @@ public class ConsumerRebalanceListenerInvoker {
private final Logger log;
private final SubscriptionState subscriptions;
private final Time time;
- private final RebalanceCallbackMetricsManager metrics;
+ private final RebalanceCallbackMetricsManager metricsManager;
ConsumerRebalanceListenerInvoker(LogContext logContext,
SubscriptionState subscriptions,
Time time,
- RebalanceCallbackMetricsManager metrics) {
+ RebalanceCallbackMetricsManager metricsManager) {
this.log = logContext.logger(getClass());
this.subscriptions = subscriptions;
this.time = time;
- this.metrics = metrics;
+ this.metricsManager = metricsManager;
}
public Exception invokePartitionsAssigned(final SortedSet assignedPartitions) {
@@ -62,7 +62,7 @@ public Exception invokePartitionsAssigned(final SortedSet assign
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsAssigned(assignedPartitions);
- metrics.recordPartitionAssignLatency(time.milliseconds() - startMs);
+ metricsManager.recordPartitionAssignLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -88,7 +88,7 @@ public Exception invokePartitionsRevoked(final SortedSet revoked
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsRevoked(revokedPartitions);
- metrics.recordPartitionRevokeLatency(time.milliseconds() - startMs);
+ metricsManager.recordPartitionRevokeLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -114,7 +114,7 @@ public Exception invokePartitionsLost(final SortedSet lostPartit
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsLost(lostPartitions);
- metrics.recordPartitionLostLatency(time.milliseconds() - startMs);
+ metricsManager.recordPartitionLostLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 2e0e63f786e40..7afdff75cd2dd 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -110,7 +110,7 @@ public class HeartbeatRequestManager implements RequestManager {
* sending heartbeat until the next poll.
*/
private final Timer pollTimer;
- private final HeartbeatMetricsManager heartbeatMetricsManager;
+ private final HeartbeatMetricsManager metricsManager;
private GroupMetadataUpdateEvent previousGroupMetadataUpdateEvent = null;
@@ -134,7 +134,7 @@ public HeartbeatRequestManager(
this.heartbeatRequestState = new HeartbeatRequestState(logContext, time, 0, retryBackoffMs,
retryBackoffMaxMs, maxPollIntervalMs);
this.pollTimer = time.timer(maxPollIntervalMs);
- this.heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
+ this.metricsManager = new HeartbeatMetricsManager(metrics);
}
// Visible for testing
@@ -156,7 +156,7 @@ public HeartbeatRequestManager(
this.membershipManager = membershipManager;
this.backgroundEventHandler = backgroundEventHandler;
this.pollTimer = timer;
- this.heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
+ this.metricsManager = new HeartbeatMetricsManager(metrics);
}
/**
@@ -252,7 +252,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final long curr
NetworkClientDelegate.UnsentRequest request = makeHeartbeatRequest(ignoreResponse);
heartbeatRequestState.onSendAttempt(currentTimeMs);
membershipManager.onHeartbeatRequestSent();
- heartbeatMetricsManager.recordHeartbeatSentMs(currentTimeMs);
+ metricsManager.recordHeartbeatSentMs(currentTimeMs);
return request;
}
@@ -265,7 +265,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
else
return request.whenComplete((response, exception) -> {
if (response != null) {
- heartbeatMetricsManager.recordRequestLatency(response.requestLatencyMs());
+ metricsManager.recordRequestLatency(response.requestLatencyMs());
onResponse((ConsumerGroupHeartbeatResponse) response.responseBody(), request.handler().completionTimeMs());
} else {
onFailure(exception, request.handler().completionTimeMs());
@@ -276,7 +276,7 @@ private NetworkClientDelegate.UnsentRequest makeHeartbeatRequest(final boolean i
private NetworkClientDelegate.UnsentRequest logResponse(final NetworkClientDelegate.UnsentRequest request) {
return request.whenComplete((response, exception) -> {
if (response != null) {
- heartbeatMetricsManager.recordRequestLatency(response.requestLatencyMs());
+ metricsManager.recordRequestLatency(response.requestLatencyMs());
Errors error =
Errors.forCode(((ConsumerGroupHeartbeatResponse) response.responseBody()).data().errorCode());
if (error == Errors.NONE)
From b17455ed3dfd25ed1806527402b771e5f4d27728 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Sun, 28 Jan 2024 21:10:38 -0800
Subject: [PATCH 21/28] resolving conflict
---
.../consumer/internals/CommitRequestManager.java | 10 ++++++++--
.../internals/metrics/OffsetCommitMetricsManager.java | 7 +++++--
.../consumer/internals/CommitRequestManagerTest.java | 4 +++-
3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
index 58d1ffd2d3c6d..e0fc4f264b875 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
@@ -470,7 +470,14 @@ public NetworkClientDelegate.UnsentRequest toUnsentRequest() {
OffsetCommitRequest.Builder builder = new OffsetCommitRequest.Builder(data);
- return buildRequestWithResponseHandling(builder);
+ return recordCommitLatency(buildRequestWithResponseHandling(builder));
+ }
+
+ private NetworkClientDelegate.UnsentRequest recordCommitLatency(NetworkClientDelegate.UnsentRequest request) {
+ request.future().whenComplete(
+ (r, e) -> metricsManager.recordRequestLatency(r)
+ );
+ return request;
}
/**
@@ -481,7 +488,6 @@ public NetworkClientDelegate.UnsentRequest toUnsentRequest() {
*/
@Override
public void onResponse(final ClientResponse response) {
- metricsManager.recordRequestLatency(response.requestLatencyMs());
long currentTimeMs = response.receivedTimeMs();
OffsetCommitResponse commitResponse = (OffsetCommitResponse) response.responseBody();
Set unauthorizedTopics = new HashSet<>();
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
index 7aef981066820..4d6e192519e3f 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
@@ -16,6 +16,7 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.clients.ClientResponse;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.Sensor;
import org.apache.kafka.common.metrics.stats.Avg;
@@ -44,7 +45,9 @@ public OffsetCommitMetricsManager(Metrics metrics) {
"The total number of commit calls")));
}
- public void recordRequestLatency(long latencyMs) {
- this.commitSensor.record(latencyMs);
+ public void recordRequestLatency(ClientResponse response) {
+ if (response == null)
+ return;
+ this.commitSensor.record(response.requestLatencyMs());
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
index 139d922efe2c6..a71e542de56b9 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
@@ -134,7 +134,6 @@ public void testPollEnsureManualCommitSent() {
Map offsets = new HashMap<>();
offsets.put(new TopicPartition("t1", 0), new OffsetAndMetadata(0));
commitRequestManger.addOffsetCommitRequest(offsets, Optional.empty(), false);
- assertPoll(1, commitRequestManger);
}
@Test
@@ -154,6 +153,9 @@ public void testPollEnsureAutocommitSent() {
1,
(short) 1,
Errors.NONE)));
+
+ assertEquals(0.03, (double) getMetric("commit-rate").metricValue(), 0.01);
+ assertEquals(1.0, getMetric("commit-total").metricValue());
}
@Test
From 6285909acdb3ee1a7cb943ee2a1d388d1a2de21c Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Sun, 28 Jan 2024 21:18:45 -0800
Subject: [PATCH 22/28] resolve conflict
---
.../clients/consumer/internals/CommitRequestManager.java | 9 +--------
.../internals/metrics/OffsetCommitMetricsManager.java | 7 ++-----
2 files changed, 3 insertions(+), 13 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
index ac71c034c126e..58d1ffd2d3c6d 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
@@ -470,14 +470,7 @@ public NetworkClientDelegate.UnsentRequest toUnsentRequest() {
OffsetCommitRequest.Builder builder = new OffsetCommitRequest.Builder(data);
- return recordCommitLatency(buildRequestWithResponseHandling(builder));
- }
-
- private NetworkClientDelegate.UnsentRequest recordCommitLatency(NetworkClientDelegate.UnsentRequest request) {
- request.future().whenComplete(
- (r, e) -> metricsManager.recordRequestLatency(r)
- );
- return request;
+ return buildRequestWithResponseHandling(builder);
}
/**
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
index 4d6e192519e3f..022a21b67895e 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
@@ -16,7 +16,6 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
-import org.apache.kafka.clients.ClientResponse;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.Sensor;
import org.apache.kafka.common.metrics.stats.Avg;
@@ -45,9 +44,7 @@ public OffsetCommitMetricsManager(Metrics metrics) {
"The total number of commit calls")));
}
- public void recordRequestLatency(ClientResponse response) {
- if (response == null)
- return;
- this.commitSensor.record(response.requestLatencyMs());
+ public void recordRequestLatency(long responseLatencyMs) {
+ this.commitSensor.record(responseLatencyMs);
}
}
From 1424ed9e96351f5ead0357fe77e2a657c328a3fb Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Mon, 29 Jan 2024 08:10:13 -0800
Subject: [PATCH 23/28] make naming consistent
---
.../internals/ConsumerRebalanceListenerInvoker.java | 6 +++---
.../internals/metrics/RebalanceCallbackMetricsManager.java | 6 +++---
.../consumer/internals/ConsumerMetricsManagerTest.java | 6 +++---
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
index 93d5c65bee539..dcdd303fe95d1 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ConsumerRebalanceListenerInvoker.java
@@ -62,7 +62,7 @@ public Exception invokePartitionsAssigned(final SortedSet assign
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsAssigned(assignedPartitions);
- metricsManager.recordPartitionAssignLatency(time.milliseconds() - startMs);
+ metricsManager.recordPartitionsAssignedLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -88,7 +88,7 @@ public Exception invokePartitionsRevoked(final SortedSet revoked
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsRevoked(revokedPartitions);
- metricsManager.recordPartitionRevokeLatency(time.milliseconds() - startMs);
+ metricsManager.recordPartitionsRevokedLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
@@ -114,7 +114,7 @@ public Exception invokePartitionsLost(final SortedSet lostPartit
try {
final long startMs = time.milliseconds();
listener.get().onPartitionsLost(lostPartitions);
- metricsManager.recordPartitionLostLatency(time.milliseconds() - startMs);
+ metricsManager.recordPartitionsLostLatency(time.milliseconds() - startMs);
} catch (WakeupException | InterruptException e) {
throw e;
} catch (Exception e) {
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
index 19e7267805a0a..8a648e431f5d5 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
@@ -60,15 +60,15 @@ public RebalanceCallbackMetricsManager(Metrics metrics, String grpMetricsPrefix)
"The max time taken for a partition-lost rebalance listener callback"), new Max());
}
- public void recordPartitionRevokeLatency(long latencyMs) {
+ public void recordPartitionsRevokedLatency(long latencyMs) {
partitionRevokeCallbackSensor.record(latencyMs);
}
- public void recordPartitionAssignLatency(long latencyMs) {
+ public void recordPartitionsAssignedLatency(long latencyMs) {
partitionAssignCallbackSensor.record(latencyMs);
}
- public void recordPartitionLostLatency(long latencyMs) {
+ public void recordPartitionsLostLatency(long latencyMs) {
partitionLostCallbackSensor.record(latencyMs);
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
index 5fad34987eeef..06300fbfa9439 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
@@ -47,9 +47,9 @@ public void testRebalanceCallbackMetrics() {
assertNotNull(getMetric("partition-lost-latency-avg", groupName));
assertNotNull(getMetric("partition-lost-latency-max", groupName));
- rebalanceCallbackMetricsManager.recordPartitionAssignLatency(100);
- rebalanceCallbackMetricsManager.recordPartitionRevokeLatency(101);
- rebalanceCallbackMetricsManager.recordPartitionLostLatency(102);
+ rebalanceCallbackMetricsManager.recordPartitionsAssignedLatency(100);
+ rebalanceCallbackMetricsManager.recordPartitionsRevokedLatency(101);
+ rebalanceCallbackMetricsManager.recordPartitionsLostLatency(102);
assertEquals(101d, getMetric("partition-revoked-latency-avg", groupName).metricValue());
assertEquals(101d, getMetric("partition-revoked-latency-max", groupName).metricValue());
From 7076ba50f7cf0d84df52eda00f37d4228711591b Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Mon, 29 Jan 2024 10:50:23 -0800
Subject: [PATCH 24/28] clean up
---
.../internals/AsyncKafkaConsumer.java | 2 +-
.../AbstractConsumerMetricsManager.java | 2 +-
.../metrics/HeartbeatMetricsManager.java | 14 ++---
.../metrics/KafkaConsumerMetrics.java | 12 ++--
.../RebalanceCallbackMetricsManager.java | 12 ++--
.../internals/ConsumerMetricsManagerTest.java | 57 ++++++++++---------
6 files changed, 50 insertions(+), 49 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java
index 9198039a85a44..eaf21940912c9 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java
@@ -539,7 +539,7 @@ private void process(final ConsumerRebalanceListenerCallbackNeededEvent event) {
logContext,
subscriptions,
time,
- new RebalanceCallbackMetricsManager(metrics, CONSUMER_METRIC_GROUP_PREFIX)
+ new RebalanceCallbackMetricsManager(metrics)
);
ApiVersions apiVersions = new ApiVersions();
Supplier networkClientDelegateSupplier = () -> new NetworkClientDelegate(
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
index 1eafcfa95bfbc..9ccf2f8486725 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
@@ -37,7 +37,7 @@
*
*/
public abstract class AbstractConsumerMetricsManager {
- protected final String metricGroupName;
+ private final String metricGroupName;
final Metrics metrics;
public enum MetricGroupSuffix {
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
index 708d89ea2d510..e9b66ee53c732 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
@@ -27,18 +27,14 @@
public class HeartbeatMetricsManager extends AbstractConsumerMetricsManager {
- public final Sensor heartbeatSensor;
+ private final Sensor heartbeatSensor;
private long lastHeartbeatMs = -1L;
public HeartbeatMetricsManager(Metrics metrics) {
- this(metrics, CONSUMER_METRIC_GROUP_PREFIX);
- }
-
- public HeartbeatMetricsManager(Metrics metrics, String prefix) {
- super(metrics, prefix, MetricGroupSuffix.COORDINATOR);
+ super(metrics, CONSUMER_METRIC_GROUP_PREFIX, MetricGroupSuffix.COORDINATOR);
heartbeatSensor = metrics.sensor("heartbeat-latency");
heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
- metricGroupName,
+ metricGroupName(),
"The max time taken to receive a response to a heartbeat request"),
new Max());
heartbeatSensor.add(createMeter(metrics,
@@ -59,8 +55,8 @@ public HeartbeatMetricsManager(Metrics metrics, String prefix) {
lastHeartbeat);
}
- public void recordHeartbeatSentMs(long lastHeartbeatMs) {
- this.lastHeartbeatMs = lastHeartbeatMs;
+ public void recordHeartbeatSentMs(long timeMs) {
+ lastHeartbeatMs = timeMs;
}
public void recordRequestLatency(long requestLatencyMs) {
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
index ce32b9d97e02b..6badb9e35b95e 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
@@ -48,22 +48,22 @@ public KafkaConsumerMetrics(Metrics metrics, String metricGrpPrefix) {
return TimeUnit.SECONDS.convert(now - lastPollMs, TimeUnit.MILLISECONDS);
};
this.lastPollMetricName = metrics.metricName("last-poll-seconds-ago",
- metricGroupName, "The number of seconds since the last poll() invocation.");
+ metricGroupName(), "The number of seconds since the last poll() invocation.");
metrics.addMetric(lastPollMetricName, lastPoll);
this.timeBetweenPollSensor = metrics.sensor("time-between-poll");
this.timeBetweenPollSensor.add(metrics.metricName("time-between-poll-avg",
- metricGroupName,
+ metricGroupName(),
"The average delay between invocations of poll() in milliseconds."),
new Avg());
this.timeBetweenPollSensor.add(metrics.metricName("time-between-poll-max",
- metricGroupName,
+ metricGroupName(),
"The max delay between invocations of poll() in milliseconds."),
new Max());
this.pollIdleSensor = metrics.sensor("poll-idle-ratio-avg");
this.pollIdleSensor.add(metrics.metricName("poll-idle-ratio-avg",
- metricGroupName,
+ metricGroupName(),
"The average fraction of time the consumer's poll() is idle as opposed to waiting for the user code to process records."),
new Avg());
@@ -71,7 +71,7 @@ public KafkaConsumerMetrics(Metrics metrics, String metricGrpPrefix) {
this.commitSyncSensor.add(
metrics.metricName(
"commit-sync-time-ns-total",
- metricGroupName,
+ metricGroupName(),
"The total time the consumer has spent in commitSync in nanoseconds"
),
new CumulativeSum()
@@ -81,7 +81,7 @@ public KafkaConsumerMetrics(Metrics metrics, String metricGrpPrefix) {
this.committedSensor.add(
metrics.metricName(
"committed-time-ns-total",
- metricGroupName,
+ metricGroupName(),
"The total time the consumer has spent in committed in nanoseconds"
),
new CumulativeSum()
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
index 8a648e431f5d5..85bcaf9404ec8 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
@@ -37,26 +37,26 @@ public RebalanceCallbackMetricsManager(Metrics metrics, String grpMetricsPrefix)
super(metrics, grpMetricsPrefix, COORDINATOR);
partitionRevokeCallbackSensor = metrics.sensor("partition-revoked-latency");
partitionRevokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
- metricGroupName,
+ metricGroupName(),
"The average time taken for a partition-revoked rebalance listener callback"), new Avg());
partitionRevokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-max",
- metricGroupName,
+ metricGroupName(),
"The max time taken for a partition-revoked rebalance listener callback"), new Max());
partitionAssignCallbackSensor = metrics.sensor("partition-assigned-latency");
partitionAssignCallbackSensor.add(metrics.metricName("partition-assigned-latency-avg",
- metricGroupName,
+ metricGroupName(),
"The average time taken for a partition-assigned rebalance listener callback"), new Avg());
partitionAssignCallbackSensor.add(metrics.metricName("partition-assigned-latency-max",
- metricGroupName,
+ metricGroupName(),
"The max time taken for a partition-assigned rebalance listener callback"), new Max());
partitionLostCallbackSensor = metrics.sensor("partition-lost-latency");
partitionLostCallbackSensor.add(metrics.metricName("partition-lost-latency-avg",
- metricGroupName,
+ metricGroupName(),
"The average time taken for a partition-lost rebalance listener callback"), new Avg());
partitionLostCallbackSensor.add(metrics.metricName("partition-lost-latency-max",
- metricGroupName,
+ metricGroupName(),
"The max time taken for a partition-lost rebalance listener callback"), new Max());
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
index 06300fbfa9439..706b5dee137ca 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
@@ -16,8 +16,9 @@
*/
package org.apache.kafka.clients.consumer.internals;
-import org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetricsManager;
import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetricsManager;
+import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
+import org.apache.kafka.clients.consumer.internals.metrics.OffsetCommitMetricsManager;
import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
import org.apache.kafka.common.metrics.KafkaMetric;
import org.apache.kafka.common.metrics.Metrics;
@@ -25,11 +26,12 @@
import org.apache.kafka.common.utils.Time;
import org.junit.jupiter.api.Test;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
public class ConsumerMetricsManagerTest {
private Time time = new MockTime();
@@ -68,37 +70,40 @@ public void testHeartbeatMetrics() {
assertNotNull(getMetric("heartbeat-rate", groupName));
assertNotNull(getMetric("heartbeat-total", groupName));
- heartbeatMetricsManager.heartbeatSensor.record(100);
- heartbeatMetricsManager.heartbeatSensor.record(100);
- heartbeatMetricsManager.heartbeatSensor.record(100);
+ heartbeatMetricsManager.recordHeartbeatSentMs(time.milliseconds());
+ heartbeatMetricsManager.recordRequestLatency(100);
+ heartbeatMetricsManager.recordRequestLatency(103);
+ heartbeatMetricsManager.recordRequestLatency(102);
- assertEquals(100d, getMetric("heartbeat-response-time-max", groupName).metricValue());
+ assertEquals(103d, getMetric("heartbeat-response-time-max", groupName).metricValue());
assertEquals(0.1d, (double) getMetric("heartbeat-rate", groupName).metricValue(), 0.01d);
assertEquals(3d, getMetric("heartbeat-total", groupName).metricValue());
+
+ // Randomly sleep 1-10 seconds
+ Random rand = new Random();
+ int randomSleepS = rand.nextInt(10) + 1;
+ time.sleep(TimeUnit.SECONDS.toMillis(randomSleepS));
+ assertEquals((double) randomSleepS, getMetric("last-heartbeat-seconds-ago", groupName).metricValue());
}
@Test
- public void testMetricsGroupName() {
- // consumer-coordinator-metrics
- NoopConsumerMetrics coordinatorMetrics = new NoopConsumerMetrics(metrics, "customCoordinatorPrefix", AbstractConsumerMetricsManager.MetricGroupSuffix.COORDINATOR);
- assertEquals("customCoordinatorPrefix" + COORDINATOR_METRICS_SUFFIX, coordinatorMetrics.metricGroupName());
-
- // consumer-metrics
- NoopConsumerMetrics consumerMetrics = new NoopConsumerMetrics(metrics, "customConsumerPrefix", AbstractConsumerMetricsManager.MetricGroupSuffix.CONSUMER);
- assertEquals("customConsumerPrefix" + CONSUMER_METRICS_SUFFIX, consumerMetrics.metricGroupName());
-
- assertThrows(IllegalArgumentException.class, () -> new NoopConsumerMetrics(metrics,
- null,
- AbstractConsumerMetricsManager.MetricGroupSuffix.CONSUMER));
+ public void testDefaultMetricsGroupName() {
+ final String coordinatorMetricsGroupName = "consumer-coordinator-metrics";
+ HeartbeatMetricsManager heartbeatMetrics = new HeartbeatMetricsManager(metrics);
+ assertEquals(coordinatorMetricsGroupName, heartbeatMetrics.metricGroupName());
+
+ OffsetCommitMetricsManager commitMetrics = new OffsetCommitMetricsManager(metrics);
+ assertEquals(coordinatorMetricsGroupName, commitMetrics.metricGroupName());
+
+ RebalanceCallbackMetricsManager rebalanceCallbackMetrics = new RebalanceCallbackMetricsManager(metrics);
+ assertEquals(coordinatorMetricsGroupName, rebalanceCallbackMetrics.metricGroupName());
+
+ final String consumerMetricsGroupName = "consumer-metrics";
+ KafkaConsumerMetrics consumerMetrics = new KafkaConsumerMetrics(metrics, CONSUMER_METRIC_GROUP_PREFIX);
+ assertEquals(consumerMetricsGroupName, consumerMetrics.metricGroupName());
}
private KafkaMetric getMetric(String metricName, String groupName) {
return metrics.metrics().get(metrics.metricName(metricName, groupName));
}
-
- static class NoopConsumerMetrics extends AbstractConsumerMetricsManager {
- public NoopConsumerMetrics(Metrics metrics, String prefix, MetricGroupSuffix suffix) {
- super(metrics, prefix, suffix);
- }
- }
}
From 4eddba438cba94f4c84602605cbd3f7feee51f29 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Mon, 29 Jan 2024 10:58:47 -0800
Subject: [PATCH 25/28] Update HeartbeatRequestManagerTest.java
---
.../consumer/internals/HeartbeatRequestManagerTest.java | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index 33d54ab66389d..cb870120f5442 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -102,7 +102,7 @@ public class HeartbeatRequestManagerTest {
private final int memberEpoch = 1;
private BackgroundEventHandler backgroundEventHandler;
private BlockingQueue backgroundEventQueue;
- private Metrics metrics = new Metrics();
+ private Metrics metrics;
@BeforeEach
public void setUp() {
@@ -121,6 +121,7 @@ private void setUp(Optional groupInfo) {
subscriptions = testBuilder.subscriptions;
membershipManager = testBuilder.membershipManager.orElseThrow(IllegalStateException::new);
metadata = testBuilder.metadata;
+ metrics = new Metrics(time);
when(coordinatorRequestManager.coordinator()).thenReturn(Optional.of(new Node(1, "localhost", 9999)));
}
@@ -570,18 +571,19 @@ public void testPollTimerExpiration() {
@Test
public void testHeartbeatMetrics() {
+ // setup
coordinatorRequestManager = mock(CoordinatorRequestManager.class);
membershipManager = mock(MembershipManager.class);
heartbeatState = mock(HeartbeatRequestManager.HeartbeatState.class);
time = new MockTime();
metrics = new Metrics(time);
- heartbeatRequestState = spy(new HeartbeatRequestManager.HeartbeatRequestState(
+ heartbeatRequestState = new HeartbeatRequestManager.HeartbeatRequestState(
new LogContext(),
time,
0, // This initial interval should be 0 to ensure heartbeat on the clock
retryBackoffMs,
retryBackoffMaxMs,
- 0));
+ 0);
backgroundEventHandler = mock(BackgroundEventHandler.class);
heartbeatRequestManager = createHeartbeatRequestManager(
coordinatorRequestManager,
@@ -597,6 +599,7 @@ public void testHeartbeatMetrics() {
assertNotNull(getMetric("heartbeat-total"));
assertNotNull(getMetric("last-heartbeat-seconds-ago"));
+ // test poll
assertHeartbeat(heartbeatRequestManager, 0);
time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
assertEquals(1.0, getMetric("heartbeat-total").metricValue());
From 9c86077775e86cd0e17a68f68fc1dd39f616e2fb Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Mon, 29 Jan 2024 11:24:18 -0800
Subject: [PATCH 26/28] privatize metric field
---
.../metrics/AbstractConsumerMetricsManager.java | 6 +++++-
.../internals/metrics/KafkaConsumerMetrics.java | 10 +++++-----
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
index 9ccf2f8486725..fc980ce1a0fc8 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
@@ -38,7 +38,7 @@
*/
public abstract class AbstractConsumerMetricsManager {
private final String metricGroupName;
- final Metrics metrics;
+ private final Metrics metrics;
public enum MetricGroupSuffix {
COORDINATOR(COORDINATOR_METRICS_SUFFIX),
@@ -69,6 +69,10 @@ public String metricGroupName() {
return metricGroupName;
}
+ public Metrics metrics() {
+ return metrics;
+ }
+
public Meter createMeter(Metrics metrics, String baseName, String descriptiveName) {
return new Meter(new WindowedCount(),
metrics.metricName(baseName + "-rate",
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
index 6badb9e35b95e..6c62a066091da 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
@@ -111,10 +111,10 @@ public void recordCommitted(long duration) {
@Override
public void close() {
- metrics.removeMetric(lastPollMetricName);
- metrics.removeSensor(timeBetweenPollSensor.name());
- metrics.removeSensor(pollIdleSensor.name());
- metrics.removeSensor(commitSyncSensor.name());
- metrics.removeSensor(committedSensor.name());
+ metrics().removeMetric(lastPollMetricName);
+ metrics().removeSensor(timeBetweenPollSensor.name());
+ metrics().removeSensor(pollIdleSensor.name());
+ metrics().removeSensor(commitSyncSensor.name());
+ metrics().removeSensor(committedSensor.name());
}
}
From 8964a8d2be4d8cea0cca39c371691b0c6aed22c1 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Wed, 31 Jan 2024 09:15:00 -0800
Subject: [PATCH 27/28] PR comments
---
.../internals/CommitRequestManager.java | 2 +-
.../internals/HeartbeatRequestManager.java | 7 +++++--
.../HeartbeatRequestManagerTest.java | 19 +++++++++++--------
3 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
index 1751d98c75315..b81dc03a9bfec 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
@@ -82,7 +82,7 @@ public class CommitRequestManager implements RequestManager, MemberStateListener
private final boolean throwOnFetchStableOffsetUnsupported;
final PendingRequests pendingRequests;
private boolean closing = false;
- private OffsetCommitMetricsManager metricsManager;
+ private final OffsetCommitMetricsManager metricsManager;
/**
* Latest member ID and epoch received via the {@link #onMemberEpochUpdated(Optional, Optional)},
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
index 7afdff75cd2dd..03e11ddfa02b4 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManager.java
@@ -110,10 +110,13 @@ public class HeartbeatRequestManager implements RequestManager {
* sending heartbeat until the next poll.
*/
private final Timer pollTimer;
- private final HeartbeatMetricsManager metricsManager;
-
private GroupMetadataUpdateEvent previousGroupMetadataUpdateEvent = null;
+ /**
+ * Holding the heartbeat sensor to measure heartbeat timing and response latency
+ */
+ private final HeartbeatMetricsManager metricsManager;
+
public HeartbeatRequestManager(
final LogContext logContext,
final Time time,
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index cb870120f5442..bcc66c1f69970 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -56,6 +56,7 @@
import java.util.List;
import java.util.Optional;
import java.util.Properties;
+import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -65,8 +66,6 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_REMOTE_ASSIGNOR;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MAX_MS;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_RETRY_BACKOFF_MS;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -86,7 +85,7 @@ public class HeartbeatRequestManagerTest {
private int maxPollIntervalMs = DEFAULT_MAX_POLL_INTERVAL_MS;
private long retryBackoffMaxMs = DEFAULT_RETRY_BACKOFF_MAX_MS;
private static final String DEFAULT_GROUP_ID = "groupId";
- private String metricGroupPrefix = CONSUMER_METRIC_GROUP_PREFIX;
+ private String consumerMetricsGroupName = "consumer-coordinator-metrics";
private ConsumerTestBuilder testBuilder;
private Time time;
@@ -601,15 +600,19 @@ public void testHeartbeatMetrics() {
// test poll
assertHeartbeat(heartbeatRequestManager, 0);
- time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
+ time.sleep(heartbeatIntervalMs);
assertEquals(1.0, getMetric("heartbeat-total").metricValue());
assertEquals((double) TimeUnit.MILLISECONDS.toSeconds(heartbeatIntervalMs), getMetric("last-heartbeat-seconds-ago").metricValue());
- assertHeartbeat(heartbeatRequestManager, DEFAULT_HEARTBEAT_INTERVAL_MS);
+ assertHeartbeat(heartbeatRequestManager, heartbeatIntervalMs);
assertEquals(0.06d, (double) getMetric("heartbeat-rate").metricValue(), 0.005d);
assertEquals(2.0, getMetric("heartbeat-total").metricValue());
- time.sleep(DEFAULT_HEARTBEAT_INTERVAL_MS);
- assertEquals((double) TimeUnit.MILLISECONDS.toSeconds(heartbeatIntervalMs), getMetric("last-heartbeat-seconds-ago").metricValue());
+
+ // Randomly sleep for some time
+ Random rand = new Random();
+ int randomSleepS = rand.nextInt(11);
+ time.sleep(randomSleepS * 1000);
+ assertEquals((double) randomSleepS, getMetric("last-heartbeat-seconds-ago").metricValue());
}
private void assertHeartbeat(HeartbeatRequestManager hrm, int nextPollMs) {
@@ -722,7 +725,7 @@ private ConsumerConfig config() {
}
private KafkaMetric getMetric(final String name) {
- return metrics.metrics().get(metrics.metricName(name, metricGroupPrefix + COORDINATOR_METRICS_SUFFIX));
+ return metrics.metrics().get(metrics.metricName(name, consumerMetricsGroupName));
}
private HeartbeatRequestManager createHeartbeatRequestManager(
From 22fcb3915e4344f1fd6c4aafa52b423c5a3aec88 Mon Sep 17 00:00:00 2001
From: Philip Nee
Date: Wed, 31 Jan 2024 11:04:28 -0800
Subject: [PATCH 28/28] clean up according to PR comments
---
.../internals/CommitRequestManager.java | 2 +-
.../AbstractConsumerMetricsManager.java | 94 ---------------
.../metrics/HeartbeatMetricsManager.java | 40 ++++---
.../metrics/KafkaConsumerMetrics.java | 30 ++---
.../metrics/OffsetCommitMetricsManager.java | 36 ++++--
.../RebalanceCallbackMetricsManager.java | 55 +++++----
.../internals/CommitRequestManagerTest.java | 6 +-
.../internals/ConsumerMetricsManagerTest.java | 109 ------------------
.../HeartbeatRequestManagerTest.java | 4 +-
.../metrics/HeartbeatMetricsManagerTest.java | 62 ++++++++++
.../OffsetCommitMetricsManagerTest.java | 55 +++++++++
.../RebalanceCallbackMetricsManagerTest.java | 52 +++++++++
12 files changed, 275 insertions(+), 270 deletions(-)
delete mode 100644 clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
delete mode 100644 clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
create mode 100644 clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManagerTest.java
create mode 100644 clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManagerTest.java
create mode 100644 clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManagerTest.java
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
index b81dc03a9bfec..2ed6d6ca7da17 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CommitRequestManager.java
@@ -73,6 +73,7 @@ public class CommitRequestManager implements RequestManager, MemberStateListener
private final Optional autoCommitState;
private final CoordinatorRequestManager coordinatorRequestManager;
private final OffsetCommitCallbackInvoker offsetCommitCallbackInvoker;
+ private final OffsetCommitMetricsManager metricsManager;
private final long retryBackoffMs;
private final String groupId;
private final Optional groupInstanceId;
@@ -82,7 +83,6 @@ public class CommitRequestManager implements RequestManager, MemberStateListener
private final boolean throwOnFetchStableOffsetUnsupported;
final PendingRequests pendingRequests;
private boolean closing = false;
- private final OffsetCommitMetricsManager metricsManager;
/**
* Latest member ID and epoch received via the {@link #onMemberEpochUpdated(Optional, Optional)},
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
deleted file mode 100644
index fc980ce1a0fc8..0000000000000
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/AbstractConsumerMetricsManager.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.kafka.clients.consumer.internals.metrics;
-
-import org.apache.kafka.common.metrics.Measurable;
-import org.apache.kafka.common.metrics.Metrics;
-import org.apache.kafka.common.metrics.stats.Meter;
-import org.apache.kafka.common.metrics.stats.WindowedCount;
-
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
-
-/**
- * Base class for different consumer metrics to extend. This class helps to construct the logical group name from the
- * given prefix and suffix, and provides a few common utilities.
- *
- *
- * The suffix can be one of the following:
- *
- * -coordinator-metrics: {@link MetricGroupSuffix#COORDINATOR}
- * -metrics: {@link MetricGroupSuffix#CONSUMER}
- *
- *
- */
-public abstract class AbstractConsumerMetricsManager {
- private final String metricGroupName;
- private final Metrics metrics;
-
- public enum MetricGroupSuffix {
- COORDINATOR(COORDINATOR_METRICS_SUFFIX),
- CONSUMER(CONSUMER_METRICS_SUFFIX);
-
- private final String suffix;
-
- MetricGroupSuffix(String suffix) {
- this.suffix = suffix;
- }
-
- @Override
- public String toString() {
- return suffix;
- }
- }
-
- public AbstractConsumerMetricsManager(Metrics metrics, String prefix, MetricGroupSuffix suffix) {
- if (suffix == null)
- throw new IllegalArgumentException("metric group suffix cannot be null");
- if (prefix == null)
- throw new IllegalArgumentException("metric group prefix cannot be null");
- this.metrics = metrics;
- metricGroupName = prefix + suffix;
- }
-
- public String metricGroupName() {
- return metricGroupName;
- }
-
- public Metrics metrics() {
- return metrics;
- }
-
- public Meter createMeter(Metrics metrics, String baseName, String descriptiveName) {
- return new Meter(new WindowedCount(),
- metrics.metricName(baseName + "-rate",
- metricGroupName,
- String.format("The number of %s per second", descriptiveName)),
- metrics.metricName(baseName + "-total",
- metricGroupName,
- String.format("The total number of %s", descriptiveName)));
- }
-
- public void addMetric(String metricName,
- String description,
- Measurable measurable) {
- metrics.addMetric(
- metrics.metricName(metricName, metricGroupName, description),
- measurable);
- }
-}
-
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
index e9b66ee53c732..a5654dfc85532 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManager.java
@@ -16,30 +16,42 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.common.MetricName;
import org.apache.kafka.common.metrics.Measurable;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.Sensor;
import org.apache.kafka.common.metrics.stats.Max;
+import org.apache.kafka.common.metrics.stats.Meter;
+import org.apache.kafka.common.metrics.stats.WindowedCount;
import java.util.concurrent.TimeUnit;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
-public class HeartbeatMetricsManager extends AbstractConsumerMetricsManager {
-
+public class HeartbeatMetricsManager {
+ // MetricName visible for testing
+ final MetricName heartbeatResponseTimeMax;
+ final MetricName heartbeatRate;
+ final MetricName heartbeatTotal;
+ final MetricName lastHeartbeatSecondsAgo;
private final Sensor heartbeatSensor;
private long lastHeartbeatMs = -1L;
public HeartbeatMetricsManager(Metrics metrics) {
- super(metrics, CONSUMER_METRIC_GROUP_PREFIX, MetricGroupSuffix.COORDINATOR);
+ final String metricGroupName = CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX;
heartbeatSensor = metrics.sensor("heartbeat-latency");
- heartbeatSensor.add(metrics.metricName("heartbeat-response-time-max",
- metricGroupName(),
- "The max time taken to receive a response to a heartbeat request"),
- new Max());
- heartbeatSensor.add(createMeter(metrics,
- "heartbeat",
- "heartbeats"));
+ heartbeatResponseTimeMax = metrics.metricName("heartbeat-response-time-max",
+ metricGroupName,
+ "The max time taken to receive a response to a heartbeat request");
+ heartbeatSensor.add(heartbeatResponseTimeMax, new Max());
+
+ // windowed meters
+ heartbeatRate = metrics.metricName("heartbeat-rate", metricGroupName, "The number of heartbeats per second");
+ heartbeatTotal = metrics.metricName("heartbeat-total", metricGroupName, "The total number of heartbeats");
+ heartbeatSensor.add(new Meter(new WindowedCount(),
+ heartbeatRate,
+ heartbeatTotal));
Measurable lastHeartbeat = (config, now) -> {
final long lastHeartbeatSend = lastHeartbeatMs;
@@ -49,10 +61,10 @@ public HeartbeatMetricsManager(Metrics metrics) {
else
return TimeUnit.SECONDS.convert(now - lastHeartbeatSend, TimeUnit.MILLISECONDS);
};
- addMetric(
- "last-heartbeat-seconds-ago",
- "The number of seconds since the last coordinator heartbeat was sent",
- lastHeartbeat);
+ lastHeartbeatSecondsAgo = metrics.metricName("last-heartbeat-seconds-ago",
+ metricGroupName,
+ "The number of seconds since the last coordinator heartbeat was sent");
+ metrics.addMetric(lastHeartbeatSecondsAgo, lastHeartbeat);
}
public void recordHeartbeatSentMs(long timeMs) {
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
index 6c62a066091da..52502e714a947 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/KafkaConsumerMetrics.java
@@ -26,9 +26,10 @@
import java.util.concurrent.TimeUnit;
-import static org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetricsManager.MetricGroupSuffix.CONSUMER;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRICS_SUFFIX;
-public class KafkaConsumerMetrics extends AbstractConsumerMetricsManager implements AutoCloseable {
+public class KafkaConsumerMetrics implements AutoCloseable {
+ private final Metrics metrics;
private final MetricName lastPollMetricName;
private final Sensor timeBetweenPollSensor;
private final Sensor pollIdleSensor;
@@ -39,7 +40,8 @@ public class KafkaConsumerMetrics extends AbstractConsumerMetricsManager impleme
private long timeSinceLastPollMs;
public KafkaConsumerMetrics(Metrics metrics, String metricGrpPrefix) {
- super(metrics, metricGrpPrefix, CONSUMER);
+ this.metrics = metrics;
+ final String metricGroupName = metricGrpPrefix + CONSUMER_METRICS_SUFFIX;
Measurable lastPoll = (mConfig, now) -> {
if (lastPollMs == 0L)
// if no poll is ever triggered, just return -1.
@@ -48,22 +50,22 @@ public KafkaConsumerMetrics(Metrics metrics, String metricGrpPrefix) {
return TimeUnit.SECONDS.convert(now - lastPollMs, TimeUnit.MILLISECONDS);
};
this.lastPollMetricName = metrics.metricName("last-poll-seconds-ago",
- metricGroupName(), "The number of seconds since the last poll() invocation.");
+ metricGroupName, "The number of seconds since the last poll() invocation.");
metrics.addMetric(lastPollMetricName, lastPoll);
this.timeBetweenPollSensor = metrics.sensor("time-between-poll");
this.timeBetweenPollSensor.add(metrics.metricName("time-between-poll-avg",
- metricGroupName(),
+ metricGroupName,
"The average delay between invocations of poll() in milliseconds."),
new Avg());
this.timeBetweenPollSensor.add(metrics.metricName("time-between-poll-max",
- metricGroupName(),
+ metricGroupName,
"The max delay between invocations of poll() in milliseconds."),
new Max());
this.pollIdleSensor = metrics.sensor("poll-idle-ratio-avg");
this.pollIdleSensor.add(metrics.metricName("poll-idle-ratio-avg",
- metricGroupName(),
+ metricGroupName,
"The average fraction of time the consumer's poll() is idle as opposed to waiting for the user code to process records."),
new Avg());
@@ -71,7 +73,7 @@ public KafkaConsumerMetrics(Metrics metrics, String metricGrpPrefix) {
this.commitSyncSensor.add(
metrics.metricName(
"commit-sync-time-ns-total",
- metricGroupName(),
+ metricGroupName,
"The total time the consumer has spent in commitSync in nanoseconds"
),
new CumulativeSum()
@@ -81,7 +83,7 @@ public KafkaConsumerMetrics(Metrics metrics, String metricGrpPrefix) {
this.committedSensor.add(
metrics.metricName(
"committed-time-ns-total",
- metricGroupName(),
+ metricGroupName,
"The total time the consumer has spent in committed in nanoseconds"
),
new CumulativeSum()
@@ -111,10 +113,10 @@ public void recordCommitted(long duration) {
@Override
public void close() {
- metrics().removeMetric(lastPollMetricName);
- metrics().removeSensor(timeBetweenPollSensor.name());
- metrics().removeSensor(pollIdleSensor.name());
- metrics().removeSensor(commitSyncSensor.name());
- metrics().removeSensor(committedSensor.name());
+ metrics.removeMetric(lastPollMetricName);
+ metrics.removeSensor(timeBetweenPollSensor.name());
+ metrics.removeSensor(pollIdleSensor.name());
+ metrics.removeSensor(commitSyncSensor.name());
+ metrics.removeSensor(committedSensor.name());
}
}
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
index 022a21b67895e..d700299ef1801 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManager.java
@@ -16,6 +16,7 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.common.MetricName;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.Sensor;
import org.apache.kafka.common.metrics.stats.Avg;
@@ -24,24 +25,35 @@
import org.apache.kafka.common.metrics.stats.WindowedCount;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
-public class OffsetCommitMetricsManager extends AbstractConsumerMetricsManager {
+public class OffsetCommitMetricsManager {
+ final MetricName commitLatencyAvg;
+ final MetricName commitLatencyMax;
+ final MetricName commitRate;
+ final MetricName commitTotal;
private final Sensor commitSensor;
public OffsetCommitMetricsManager(Metrics metrics) {
- super(metrics, CONSUMER_METRIC_GROUP_PREFIX, MetricGroupSuffix.COORDINATOR);
+ final String metricGroupName = CONSUMER_METRIC_GROUP_PREFIX + COORDINATOR_METRICS_SUFFIX;
commitSensor = metrics.sensor("commit-latency");
- commitSensor.add(metrics.metricName("commit-latency-avg",
- metricGroupName(),
- "The average time taken for a commit request"), new Avg());
- commitSensor.add(metrics.metricName("commit-latency-max",
- metricGroupName(),
- "The max time taken for a commit request"), new Max());
+ commitLatencyAvg = metrics.metricName("commit-latency-avg",
+ metricGroupName,
+ "The average time taken for a commit request");
+ commitSensor.add(commitLatencyAvg, new Avg());
+ commitLatencyMax = metrics.metricName("commit-latency-max",
+ metricGroupName,
+ "The max time taken for a commit request");
+ commitSensor.add(commitLatencyMax, new Max());
+ commitRate = metrics.metricName("commit-rate",
+ metricGroupName,
+ "The number of commit calls per second");
+ commitTotal = metrics.metricName("commit-total",
+ metricGroupName,
+ "The total number of commit calls");
commitSensor.add(new Meter(new WindowedCount(),
- metrics.metricName("commit-rate", metricGroupName(),
- "The number of commit calls per second"),
- metrics.metricName("commit-total", metricGroupName(),
- "The total number of commit calls")));
+ commitRate,
+ commitTotal));
}
public void recordRequestLatency(long responseLatencyMs) {
diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
index 85bcaf9404ec8..f70b891864f1c 100644
--- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
+++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManager.java
@@ -16,15 +16,22 @@
*/
package org.apache.kafka.clients.consumer.internals.metrics;
+import org.apache.kafka.common.MetricName;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.metrics.Sensor;
import org.apache.kafka.common.metrics.stats.Avg;
import org.apache.kafka.common.metrics.stats.Max;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
-import static org.apache.kafka.clients.consumer.internals.metrics.AbstractConsumerMetricsManager.MetricGroupSuffix.COORDINATOR;
+import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
-public class RebalanceCallbackMetricsManager extends AbstractConsumerMetricsManager {
+public class RebalanceCallbackMetricsManager {
+ final MetricName partitionRevokeLatencyAvg;
+ final MetricName partitionAssignLatencyAvg;
+ final MetricName partitionLostLatencyAvg;
+ final MetricName partitionRevokeLatencyMax;
+ final MetricName partitionAssignLatencyMax;
+ final MetricName partitionLostLatencyMax;
private final Sensor partitionRevokeCallbackSensor;
private final Sensor partitionAssignCallbackSensor;
private final Sensor partitionLostCallbackSensor;
@@ -34,30 +41,36 @@ public RebalanceCallbackMetricsManager(Metrics metrics) {
}
public RebalanceCallbackMetricsManager(Metrics metrics, String grpMetricsPrefix) {
- super(metrics, grpMetricsPrefix, COORDINATOR);
+ final String metricGroupName = grpMetricsPrefix + COORDINATOR_METRICS_SUFFIX;
partitionRevokeCallbackSensor = metrics.sensor("partition-revoked-latency");
- partitionRevokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-avg",
- metricGroupName(),
- "The average time taken for a partition-revoked rebalance listener callback"), new Avg());
- partitionRevokeCallbackSensor.add(metrics.metricName("partition-revoked-latency-max",
- metricGroupName(),
- "The max time taken for a partition-revoked rebalance listener callback"), new Max());
+ partitionRevokeLatencyAvg = metrics.metricName("partition-revoked-latency-avg",
+ metricGroupName,
+ "The average time taken for a partition-revoked rebalance listener callback");
+ partitionRevokeCallbackSensor.add(partitionRevokeLatencyAvg, new Avg());
+ partitionRevokeLatencyMax = metrics.metricName("partition-revoked-latency-max",
+ metricGroupName,
+ "The max time taken for a partition-revoked rebalance listener callback");
+ partitionRevokeCallbackSensor.add(partitionRevokeLatencyMax, new Max());
partitionAssignCallbackSensor = metrics.sensor("partition-assigned-latency");
- partitionAssignCallbackSensor.add(metrics.metricName("partition-assigned-latency-avg",
- metricGroupName(),
- "The average time taken for a partition-assigned rebalance listener callback"), new Avg());
- partitionAssignCallbackSensor.add(metrics.metricName("partition-assigned-latency-max",
- metricGroupName(),
- "The max time taken for a partition-assigned rebalance listener callback"), new Max());
+ partitionAssignLatencyAvg = metrics.metricName("partition-assigned-latency-avg",
+ metricGroupName,
+ "The average time taken for a partition-assigned rebalance listener callback");
+ partitionAssignCallbackSensor.add(partitionAssignLatencyAvg, new Avg());
+ partitionAssignLatencyMax = metrics.metricName("partition-assigned-latency-max",
+ metricGroupName,
+ "The max time taken for a partition-assigned rebalance listener callback");
+ partitionAssignCallbackSensor.add(partitionAssignLatencyMax, new Max());
partitionLostCallbackSensor = metrics.sensor("partition-lost-latency");
- partitionLostCallbackSensor.add(metrics.metricName("partition-lost-latency-avg",
- metricGroupName(),
- "The average time taken for a partition-lost rebalance listener callback"), new Avg());
- partitionLostCallbackSensor.add(metrics.metricName("partition-lost-latency-max",
- metricGroupName(),
- "The max time taken for a partition-lost rebalance listener callback"), new Max());
+ partitionLostLatencyAvg = metrics.metricName("partition-lost-latency-avg",
+ metricGroupName,
+ "The average time taken for a partition-lost rebalance listener callback");
+ partitionLostCallbackSensor.add(partitionLostLatencyAvg, new Avg());
+ partitionLostLatencyMax = metrics.metricName("partition-lost-latency-max",
+ metricGroupName,
+ "The max time taken for a partition-lost rebalance listener callback");
+ partitionLostCallbackSensor.add(partitionLostLatencyMax, new Max());
}
public void recordPartitionsRevokedLatency(long latencyMs) {
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
index c32f63857a5d1..15e1e0b4fb4bc 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/CommitRequestManagerTest.java
@@ -75,7 +75,6 @@
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_GROUP_ID;
import static org.apache.kafka.clients.consumer.internals.ConsumerTestBuilder.DEFAULT_GROUP_INSTANCE_ID;
import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.COORDINATOR_METRICS_SUFFIX;
import static org.apache.kafka.test.TestUtils.assertFutureThrows;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -94,7 +93,7 @@ public class CommitRequestManagerTest {
private long retryBackoffMs = 100;
private long retryBackoffMaxMs = 1000;
private String consumerMetricGroupPrefix = CONSUMER_METRIC_GROUP_PREFIX;
- private String consumerMetricGroupName = consumerMetricGroupPrefix + COORDINATOR_METRICS_SUFFIX;
+ private static final String CONSUMER_COORDINATOR_METRICS = "consumer-coordinator-metrics";
private Node mockedNode = new Node(1, "host1", 9092);
private SubscriptionState subscriptionState;
private LogContext logContext;
@@ -139,6 +138,7 @@ public void testPollEnsureManualCommitSent() {
Map offsets = new HashMap<>();
offsets.put(new TopicPartition("t1", 0), new OffsetAndMetadata(0));
commitRequestManger.addOffsetCommitRequest(offsets, Optional.empty(), false);
+ assertPoll(1, commitRequestManger);
}
@Test
@@ -1247,6 +1247,6 @@ private ClientResponse buildOffsetFetchClientResponse(
private KafkaMetric getMetric(String name) {
return metrics.metrics().get(metrics.metricName(
name,
- consumerMetricGroupName));
+ CONSUMER_COORDINATOR_METRICS));
}
}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
deleted file mode 100644
index 706b5dee137ca..0000000000000
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/ConsumerMetricsManagerTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.kafka.clients.consumer.internals;
-
-import org.apache.kafka.clients.consumer.internals.metrics.HeartbeatMetricsManager;
-import org.apache.kafka.clients.consumer.internals.metrics.KafkaConsumerMetrics;
-import org.apache.kafka.clients.consumer.internals.metrics.OffsetCommitMetricsManager;
-import org.apache.kafka.clients.consumer.internals.metrics.RebalanceCallbackMetricsManager;
-import org.apache.kafka.common.metrics.KafkaMetric;
-import org.apache.kafka.common.metrics.Metrics;
-import org.apache.kafka.common.utils.MockTime;
-import org.apache.kafka.common.utils.Time;
-import org.junit.jupiter.api.Test;
-
-import java.util.Random;
-import java.util.concurrent.TimeUnit;
-
-import static org.apache.kafka.clients.consumer.internals.ConsumerUtils.CONSUMER_METRIC_GROUP_PREFIX;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-public class ConsumerMetricsManagerTest {
- private Time time = new MockTime();
- private Metrics metrics = new Metrics(time);
-
- @Test
- public void testRebalanceCallbackMetrics() {
- // MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
- RebalanceCallbackMetricsManager rebalanceCallbackMetricsManager = new RebalanceCallbackMetricsManager(metrics);
- String groupName = "consumer-coordinator-metrics";
- assertNotNull(getMetric("partition-revoked-latency-avg", groupName));
- assertNotNull(getMetric("partition-revoked-latency-max", groupName));
- assertNotNull(getMetric("partition-assigned-latency-avg", groupName));
- assertNotNull(getMetric("partition-assigned-latency-max", groupName));
- assertNotNull(getMetric("partition-lost-latency-avg", groupName));
- assertNotNull(getMetric("partition-lost-latency-max", groupName));
-
- rebalanceCallbackMetricsManager.recordPartitionsAssignedLatency(100);
- rebalanceCallbackMetricsManager.recordPartitionsRevokedLatency(101);
- rebalanceCallbackMetricsManager.recordPartitionsLostLatency(102);
-
- assertEquals(101d, getMetric("partition-revoked-latency-avg", groupName).metricValue());
- assertEquals(101d, getMetric("partition-revoked-latency-max", groupName).metricValue());
- assertEquals(100d, getMetric("partition-assigned-latency-avg", groupName).metricValue());
- assertEquals(100d, getMetric("partition-assigned-latency-max", groupName).metricValue());
- assertEquals(102d, getMetric("partition-lost-latency-avg", groupName).metricValue());
- assertEquals(102d, getMetric("partition-lost-latency-max", groupName).metricValue());
- }
-
- @Test
- public void testHeartbeatMetrics() {
- // MBean: kafka.consumer:type=consumer-coordinator-metrics,client-id={clientId}
- HeartbeatMetricsManager heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
- String groupName = "consumer-coordinator-metrics";
- assertNotNull(getMetric("heartbeat-response-time-max", groupName));
- assertNotNull(getMetric("heartbeat-rate", groupName));
- assertNotNull(getMetric("heartbeat-total", groupName));
-
- heartbeatMetricsManager.recordHeartbeatSentMs(time.milliseconds());
- heartbeatMetricsManager.recordRequestLatency(100);
- heartbeatMetricsManager.recordRequestLatency(103);
- heartbeatMetricsManager.recordRequestLatency(102);
-
- assertEquals(103d, getMetric("heartbeat-response-time-max", groupName).metricValue());
- assertEquals(0.1d, (double) getMetric("heartbeat-rate", groupName).metricValue(), 0.01d);
- assertEquals(3d, getMetric("heartbeat-total", groupName).metricValue());
-
- // Randomly sleep 1-10 seconds
- Random rand = new Random();
- int randomSleepS = rand.nextInt(10) + 1;
- time.sleep(TimeUnit.SECONDS.toMillis(randomSleepS));
- assertEquals((double) randomSleepS, getMetric("last-heartbeat-seconds-ago", groupName).metricValue());
- }
-
- @Test
- public void testDefaultMetricsGroupName() {
- final String coordinatorMetricsGroupName = "consumer-coordinator-metrics";
- HeartbeatMetricsManager heartbeatMetrics = new HeartbeatMetricsManager(metrics);
- assertEquals(coordinatorMetricsGroupName, heartbeatMetrics.metricGroupName());
-
- OffsetCommitMetricsManager commitMetrics = new OffsetCommitMetricsManager(metrics);
- assertEquals(coordinatorMetricsGroupName, commitMetrics.metricGroupName());
-
- RebalanceCallbackMetricsManager rebalanceCallbackMetrics = new RebalanceCallbackMetricsManager(metrics);
- assertEquals(coordinatorMetricsGroupName, rebalanceCallbackMetrics.metricGroupName());
-
- final String consumerMetricsGroupName = "consumer-metrics";
- KafkaConsumerMetrics consumerMetrics = new KafkaConsumerMetrics(metrics, CONSUMER_METRIC_GROUP_PREFIX);
- assertEquals(consumerMetricsGroupName, consumerMetrics.metricGroupName());
- }
-
- private KafkaMetric getMetric(String metricName, String groupName) {
- return metrics.metrics().get(metrics.metricName(metricName, groupName));
- }
-}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
index bcc66c1f69970..0df6fa94c39cb 100644
--- a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/HeartbeatRequestManagerTest.java
@@ -85,7 +85,7 @@ public class HeartbeatRequestManagerTest {
private int maxPollIntervalMs = DEFAULT_MAX_POLL_INTERVAL_MS;
private long retryBackoffMaxMs = DEFAULT_RETRY_BACKOFF_MAX_MS;
private static final String DEFAULT_GROUP_ID = "groupId";
- private String consumerMetricsGroupName = "consumer-coordinator-metrics";
+ private static final String CONSUMER_COORDINATOR_METRICS = "consumer-coordinator-metrics";
private ConsumerTestBuilder testBuilder;
private Time time;
@@ -725,7 +725,7 @@ private ConsumerConfig config() {
}
private KafkaMetric getMetric(final String name) {
- return metrics.metrics().get(metrics.metricName(name, consumerMetricsGroupName));
+ return metrics.metrics().get(metrics.metricName(name, CONSUMER_COORDINATOR_METRICS));
}
private HeartbeatRequestManager createHeartbeatRequestManager(
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManagerTest.java
new file mode 100644
index 0000000000000..1761bc2fef07c
--- /dev/null
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/HeartbeatMetricsManagerTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.utils.MockTime;
+import org.apache.kafka.common.utils.Time;
+import org.junit.jupiter.api.Test;
+
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class HeartbeatMetricsManagerTest {
+ private Time time = new MockTime();
+ private Metrics metrics = new Metrics(time);
+
+ @Test
+ public void testHeartbeatMetrics() {
+ // Assuming 'metrics' is an instance of your Metrics class
+ HeartbeatMetricsManager heartbeatMetricsManager = new HeartbeatMetricsManager(metrics);
+
+ // Assert the existence of metrics
+ assertNotNull(metrics.metric(heartbeatMetricsManager.heartbeatResponseTimeMax));
+ assertNotNull(metrics.metric(heartbeatMetricsManager.heartbeatRate));
+ assertNotNull(metrics.metric(heartbeatMetricsManager.heartbeatTotal));
+
+ // Record heartbeat sent time and request latencies
+ long currentTimeMs = time.milliseconds();
+ heartbeatMetricsManager.recordHeartbeatSentMs(currentTimeMs);
+ heartbeatMetricsManager.recordRequestLatency(100);
+ heartbeatMetricsManager.recordRequestLatency(103);
+ heartbeatMetricsManager.recordRequestLatency(102);
+
+ // Assert recorded metrics values
+ assertEquals(103d, metrics.metric(heartbeatMetricsManager.heartbeatResponseTimeMax).metricValue());
+ assertEquals(0.1d, (double) metrics.metric(heartbeatMetricsManager.heartbeatRate).metricValue(), 0.01d);
+ assertEquals(3d, metrics.metric(heartbeatMetricsManager.heartbeatTotal).metricValue());
+
+ // Randomly sleep 1-10 seconds
+ Random rand = new Random();
+ int randomSleepS = rand.nextInt(10) + 1;
+ time.sleep(TimeUnit.SECONDS.toMillis(randomSleepS));
+ assertEquals((double) randomSleepS, metrics.metric(heartbeatMetricsManager.lastHeartbeatSecondsAgo).metricValue());
+ }
+}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManagerTest.java
new file mode 100644
index 0000000000000..fa89456019a84
--- /dev/null
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/OffsetCommitMetricsManagerTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.utils.MockTime;
+import org.apache.kafka.common.utils.Time;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class OffsetCommitMetricsManagerTest {
+ private Time time = new MockTime();
+ private Metrics metrics = new Metrics(time);
+
+ @Test
+ public void testOffsetCommitMetrics() {
+ // Assuming 'metrics' is an instance of your Metrics class
+
+ // Create an instance of OffsetCommitMetricsManager
+ OffsetCommitMetricsManager metricsManager = new OffsetCommitMetricsManager(metrics);
+
+ // Assert the existence of metrics
+ assertNotNull(metrics.metric(metricsManager.commitLatencyAvg));
+ assertNotNull(metrics.metric(metricsManager.commitLatencyMax));
+ assertNotNull(metrics.metric(metricsManager.commitRate));
+ assertNotNull(metrics.metric(metricsManager.commitTotal));
+
+ // Record request latency
+ metricsManager.recordRequestLatency(100);
+ metricsManager.recordRequestLatency(102);
+ metricsManager.recordRequestLatency(98);
+
+ // Assert the recorded latency
+ assertEquals(100d, metrics.metric(metricsManager.commitLatencyAvg).metricValue());
+ assertEquals(102d, metrics.metric(metricsManager.commitLatencyMax).metricValue());
+ assertEquals(0.1d, metrics.metric(metricsManager.commitRate).metricValue());
+ assertEquals(3d, metrics.metric(metricsManager.commitTotal).metricValue());
+ }
+}
diff --git a/clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManagerTest.java b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManagerTest.java
new file mode 100644
index 0000000000000..c0b5e6eae4824
--- /dev/null
+++ b/clients/src/test/java/org/apache/kafka/clients/consumer/internals/metrics/RebalanceCallbackMetricsManagerTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.kafka.clients.consumer.internals.metrics;
+
+import org.apache.kafka.common.metrics.Metrics;
+import org.apache.kafka.common.utils.MockTime;
+import org.apache.kafka.common.utils.Time;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class RebalanceCallbackMetricsManagerTest {
+ private Time time = new MockTime();
+ private Metrics metrics = new Metrics(time);
+
+ @Test
+ public void testRebalanceCallbackMetrics() {
+ RebalanceCallbackMetricsManager metricsManager = new RebalanceCallbackMetricsManager(metrics);
+ assertNotNull(metrics.metric(metricsManager.partitionRevokeLatencyAvg));
+ assertNotNull(metrics.metric(metricsManager.partitionRevokeLatencyMax));
+ assertNotNull(metrics.metric(metricsManager.partitionAssignLatencyAvg));
+ assertNotNull(metrics.metric(metricsManager.partitionAssignLatencyMax));
+ assertNotNull(metrics.metric(metricsManager.partitionLostLatencyAvg));
+ assertNotNull(metrics.metric(metricsManager.partitionLostLatencyMax));
+
+ metricsManager.recordPartitionsAssignedLatency(100);
+ metricsManager.recordPartitionsRevokedLatency(101);
+ metricsManager.recordPartitionsLostLatency(102);
+
+ assertEquals(101d, metrics.metric(metricsManager.partitionRevokeLatencyAvg).metricValue());
+ assertEquals(101d, metrics.metric(metricsManager.partitionRevokeLatencyMax).metricValue());
+ assertEquals(100d, metrics.metric(metricsManager.partitionAssignLatencyAvg).metricValue());
+ assertEquals(100d, metrics.metric(metricsManager.partitionAssignLatencyMax).metricValue());
+ assertEquals(102d, metrics.metric(metricsManager.partitionLostLatencyAvg).metricValue());
+ assertEquals(102d, metrics.metric(metricsManager.partitionLostLatencyMax).metricValue());
+ }
+}