Skip to content

Commit e7e1c0d

Browse files
pthirunclaude
andcommitted
Merge upstream/main into controller-grpc-migration-list-child-clusters
Resolved merge conflict in TestControllerGrpcEndpoints.java by keeping both test methods: - testListChildClustersGrpcEndpoint (from this PR) - testGetKeySchemaGrpcEndpoint (from upstream/main) Both tests compile and pass successfully. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2 parents b7e4702 + 803ded4 commit e7e1c0d

45 files changed

Lines changed: 1748 additions & 418 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

clients/da-vinci-client/src/main/java/com/linkedin/davinci/kafka/consumer/AggKafkaConsumerService.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,26 @@ private static void reportStaleTopicPartitions(
286286
stringBuilder.append(CONSUMER_POLL_WARNING_MESSAGE_PREFIX);
287287
stringBuilder.append(consumerService.getKey());
288288
for (Map.Entry<PubSubTopicPartition, Long> staleTopicPartition: staleTopicPartitions.entrySet()) {
289-
stringBuilder.append("\n topic: ");
290-
stringBuilder.append(staleTopicPartition.getKey().getTopicName());
291-
stringBuilder.append(" partition: ");
292-
stringBuilder.append(staleTopicPartition.getKey().getPartitionNumber());
289+
PubSubTopicPartition topicPartition = staleTopicPartition.getKey();
290+
// Get consumer name for this topic partition
291+
SharedKafkaConsumer consumer = consumerService.getValue()
292+
.getConsumerAssignedToVersionTopicPartition(topicPartition.getPubSubTopic(), topicPartition);
293+
String consumerName = "unknown";
294+
if (consumer != null) {
295+
Map<PubSubTopicPartition, TopicPartitionIngestionInfo> ingestionInfoMap =
296+
consumerService.getValue().getIngestionInfoFor(topicPartition.getPubSubTopic(), topicPartition, true);
297+
if (!ingestionInfoMap.isEmpty()) {
298+
TopicPartitionIngestionInfo info = ingestionInfoMap.get(topicPartition);
299+
if (info != null) {
300+
consumerName = info.getConsumerIdStr();
301+
}
302+
}
303+
}
304+
stringBuilder.append(", replica: ");
305+
stringBuilder
306+
.append(Utils.getReplicaId(topicPartition.getPubSubTopic(), topicPartition.getPartitionNumber()));
307+
stringBuilder.append(" consumer: ");
308+
stringBuilder.append(consumerName);
293309
stringBuilder.append(" stale for: ");
294310
stringBuilder.append(now - staleTopicPartition.getValue());
295311
stringBuilder.append("ms");
@@ -331,7 +347,7 @@ public synchronized AbstractKafkaConsumerService createKafkaConsumerService(fina
331347
String resolvedKafkaUrl = kafkaClusterUrlResolver == null ? kafkaUrl : kafkaClusterUrlResolver.apply(kafkaUrl);
332348
final AbstractKafkaConsumerService alreadyCreatedConsumerService = getKafkaConsumerService(resolvedKafkaUrl);
333349
if (alreadyCreatedConsumerService != null) {
334-
LOGGER.warn("KafkaConsumerService has already been created for Kafka cluster with URL: {}", resolvedKafkaUrl);
350+
LOGGER.info("KafkaConsumerService has already been created for Kafka cluster with URL: {}", resolvedKafkaUrl);
335351
return alreadyCreatedConsumerService;
336352
}
337353

clients/da-vinci-client/src/main/java/com/linkedin/davinci/kafka/consumer/KafkaStoreIngestionService.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
import com.linkedin.venice.serialization.avro.OptimizedKafkaValueSerializer;
8383
import com.linkedin.venice.service.AbstractVeniceService;
8484
import com.linkedin.venice.service.ICProvider;
85+
import com.linkedin.venice.stats.ThreadPoolStats;
8586
import com.linkedin.venice.stats.VeniceMetricsRepository;
8687
import com.linkedin.venice.system.store.ControllerClientBackedSystemSchemaInitializer;
8788
import com.linkedin.venice.system.store.MetaStoreWriter;
@@ -118,6 +119,7 @@
118119
import java.util.concurrent.ExecutorService;
119120
import java.util.concurrent.Executors;
120121
import java.util.concurrent.ScheduledExecutorService;
122+
import java.util.concurrent.ThreadPoolExecutor;
121123
import java.util.concurrent.TimeUnit;
122124
import java.util.concurrent.atomic.AtomicBoolean;
123125
import java.util.concurrent.locks.ReentrantLock;
@@ -496,6 +498,10 @@ public void handleStoreDeleted(Store store) {
496498
this.aaWCWorkLoadProcessingThreadPool = Executors.newFixedThreadPool(
497499
serverConfig.getAAWCWorkloadParallelProcessingThreadPoolSize(),
498500
new DaemonThreadFactory("AA_WC_PARALLEL_PROCESSING", serverConfig.getLogContext()));
501+
new ThreadPoolStats(
502+
metricsRepository,
503+
(ThreadPoolExecutor) aaWCWorkLoadProcessingThreadPool,
504+
"aa_wc_parallel_processing_thread_pool");
499505
} else {
500506
this.aaWCWorkLoadProcessingThreadPool = null;
501507
}
@@ -509,6 +515,10 @@ public void handleStoreDeleted(Store store) {
509515
this.aaWCIngestionStorageLookupThreadPool = Executors.newFixedThreadPool(
510516
serverConfig.getAaWCIngestionStorageLookupThreadPoolSize(),
511517
new DaemonThreadFactory("AA_WC_INGESTION_STORAGE_LOOKUP", serverConfig.getLogContext()));
518+
new ThreadPoolStats(
519+
metricsRepository,
520+
(ThreadPoolExecutor) aaWCIngestionStorageLookupThreadPool,
521+
"aa_wc_ingestion_storage_lookup_thread_pool");
512522
LOGGER.info(
513523
"Enabled a thread pool for AA/WC ingestion lookup with {} threads.",
514524
serverConfig.getAaWCIngestionStorageLookupThreadPoolSize());

clients/da-vinci-client/src/main/java/com/linkedin/davinci/kafka/consumer/LeaderProducerCallback.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class LeaderProducerCallback implements ChunkAwareCallback {
2727
private static final RedundantExceptionFilter REDUNDANT_LOGGING_FILTER =
2828
RedundantExceptionFilter.getRedundantExceptionFilter();
2929
private static final Consumer<PubSubProduceResult> NO_OP = produceResult -> {};
30+
private static final double LEADER_PRODUCER_COMPLETION_LATENCY_THRESHOLD_MS = 30000;
3031
private Consumer<PubSubProduceResult> onCompletionFunction = NO_OP; // ran before onCompletion() runs
3132
private Consumer<PubSubProduceResult> onCompletionCallback = NO_OP; // ran after onCompletion() runs
3233

@@ -119,12 +120,24 @@ public void onCompletion(PubSubProduceResult produceResult, Exception e) {
119120
// queuing to drainer.
120121
// this indicates how much time kafka took to deliver the message to broker.
121122
if (!ingestionTask.isUserSystemStore()) {
123+
double leaderProducerCompletionLatencyMs = LatencyUtils.getElapsedTimeFromNSToMS(produceTimeNs);
122124
ingestionTask.getVersionIngestionStats()
123125
.recordLeaderProducerCompletionTime(
124126
ingestionTask.getStoreName(),
125127
ingestionTask.versionNumber,
126-
LatencyUtils.getElapsedTimeFromNSToMS(produceTimeNs),
128+
leaderProducerCompletionLatencyMs,
127129
currentTimeForMetricsMs);
130+
// Warn if producer completion latency exceeds threshold
131+
if (leaderProducerCompletionLatencyMs > LEADER_PRODUCER_COMPLETION_LATENCY_THRESHOLD_MS) {
132+
if (!REDUNDANT_LOGGING_FILTER
133+
.isRedundantException(partitionConsumptionState.getReplicaId(), "HighProducerLatency")) {
134+
LOGGER.warn(
135+
"High leader producer completion latency detected for replica: {}, latency: {} ms, threshold: {} ms",
136+
partitionConsumptionState.getReplicaId(),
137+
leaderProducerCompletionLatencyMs,
138+
LEADER_PRODUCER_COMPLETION_LATENCY_THRESHOLD_MS);
139+
}
140+
}
128141
if (ingestionTask.isHybridMode() && sourceConsumerRecord.getTopicPartition().getPubSubTopic().isRealTime()
129142
&& partitionConsumptionState.hasLagCaughtUp()) {
130143
ingestionTask.getVersionIngestionStats()

clients/da-vinci-client/src/main/java/com/linkedin/davinci/kafka/consumer/StoreIngestionTask.java

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3539,14 +3539,6 @@ private int internalProcessConsumerRecord(
35393539
partitionConsumptionState,
35403540
leaderProducedRecordContext,
35413541
currentTimeMs);
3542-
if (recordLevelMetricEnabled.get()) {
3543-
recordNearlineLocalBrokerToReadyToServerLatency(
3544-
storeName,
3545-
versionNumber,
3546-
partitionConsumptionState,
3547-
kafkaValue,
3548-
leaderProducedRecordContext);
3549-
}
35503542
}
35513543
if (recordLevelMetricEnabled.get()) {
35523544
versionedIngestionStats.recordConsumedRecordEndToEndProcessingLatency(
@@ -4804,48 +4796,6 @@ protected enum DelegateConsumerRecordResult {
48044796
SKIPPED_MESSAGE
48054797
}
48064798

4807-
/**
4808-
* The method measures the time between receiving the message from the local VT and when the message is committed in
4809-
* the local db and ready to serve.
4810-
* For a leader, it's the time when the callback to the version topic write returns.
4811-
*/
4812-
private void recordNearlineLocalBrokerToReadyToServerLatency(
4813-
String storeName,
4814-
int versionNumber,
4815-
PartitionConsumptionState partitionConsumptionState,
4816-
KafkaMessageEnvelope kafkaMessageEnvelope,
4817-
LeaderProducedRecordContext leaderProducedRecordContext) {
4818-
/**
4819-
* Record nearline latency only when it's a hybrid store, the lag has been caught up and ignore
4820-
* messages that are getting caughtup. Sometimes the producerTimestamp can be -1 if the
4821-
* leaderProducedRecordContext had an error after callback. Don't record latency for invalid timestamps.
4822-
*/
4823-
if (!isUserSystemStore() && isHybridMode() && partitionConsumptionState.hasLagCaughtUp()) {
4824-
long producerTimestamp = (leaderProducedRecordContext == null)
4825-
? kafkaMessageEnvelope.producerMetadata.messageTimestamp
4826-
: leaderProducedRecordContext.getProducedTimestampMs();
4827-
if (producerTimestamp > 0) {
4828-
if (partitionConsumptionState.isNearlineMetricsRecordingValid(producerTimestamp)) {
4829-
long afterProcessingRecordTimestampMs = System.currentTimeMillis();
4830-
versionedIngestionStats.recordNearlineLocalBrokerToReadyToServeLatency(
4831-
storeName,
4832-
versionNumber,
4833-
afterProcessingRecordTimestampMs - producerTimestamp,
4834-
afterProcessingRecordTimestampMs);
4835-
}
4836-
} else if (!REDUNDANT_LOGGING_FILTER.isRedundantException(storeName, "IllegalTimestamp")) {
4837-
LOGGER.warn(
4838-
"Illegal timestamp for storeName: {}, versionNumber: {}, replica: {}, "
4839-
+ "leaderProducedRecordContext: {}, producerTimestamp: {}",
4840-
storeName,
4841-
versionNumber,
4842-
partitionConsumptionState.getReplicaId(),
4843-
leaderProducedRecordContext == null ? "NA" : leaderProducedRecordContext,
4844-
producerTimestamp);
4845-
}
4846-
}
4847-
}
4848-
48494799
protected void recordProcessedRecordStats(
48504800
PartitionConsumptionState partitionConsumptionState,
48514801
int processedRecordSize) {

clients/da-vinci-client/src/main/java/com/linkedin/davinci/stats/AggVersionedIngestionStats.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -201,17 +201,6 @@ public void recordNearlineProducerToLocalBrokerLatency(String storeName, int ver
201201
stat -> stat.recordNearlineProducerToLocalBrokerLatency(value, timestamp));
202202
}
203203

204-
public void recordNearlineLocalBrokerToReadyToServeLatency(
205-
String storeName,
206-
int version,
207-
double value,
208-
long timestamp) {
209-
recordVersionedAndTotalStat(
210-
storeName,
211-
version,
212-
stat -> stat.recordNearlineLocalBrokerToReadyToServeLatency(value, timestamp));
213-
}
214-
215204
public void recordMaxIdleTime(String storeName, int version, long idleTimeMs) {
216205
getStats(storeName, version).recordIdleTime(idleTimeMs);
217206
}

clients/da-vinci-client/src/main/java/com/linkedin/davinci/stats/IngestionStats.java

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,78 @@ public class IngestionStats {
3535
protected static final String LEADER_RECORDS_PRODUCED_METRIC_NAME = "leader_records_produced";
3636
protected static final String LEADER_BYTES_PRODUCED_METRIC_NAME = "leader_bytes_produced";
3737
protected static final String SUBSCRIBE_ACTION_PREP_LATENCY = "subscribe_action_prep_latency";
38-
protected static final String CONSUMED_RECORD_END_TO_END_PROCESSING_LATENCY =
39-
"consumed_record_end_to_end_processing_latency";
4038
protected static final String UPDATE_IGNORED_DCR = "update_ignored_dcr";
4139
protected static final String TOTAL_DCR = "total_dcr";
4240
protected static final String TOTAL_DUPLICATE_KEY_UPDATE_COUNT = "total_duplicate_key_update_count";
43-
4441
protected static final String TIMESTAMP_REGRESSION_DCR_ERROR = "timestamp_regression_dcr_error";
4542
protected static final String OFFSET_REGRESSION_DCR_ERROR = "offset_regression_dcr_error";
4643
protected static final String TOMBSTONE_CREATION_DCR = "tombstone_creation_dcr";
44+
45+
/**
46+
* Consumer metric: Measures the total time from when a record starts being processed (after polling from Kafka and
47+
* schema checks) until it completes all processing stages. This includes leader preprocessing, producing to local
48+
* Kafka (for leaders), queueing to drainer, drainer processing (persisting to storage), and offset updates.
49+
*/
50+
protected static final String CONSUMED_RECORD_END_TO_END_PROCESSING_LATENCY =
51+
"consumed_record_end_to_end_processing_latency";
52+
/**
53+
* Leader metric: Measures the latency from when a nearline producer originally produced a message (with its producer
54+
* timestamp) to when that message is successfully written to the local broker's version topic by the leader.
55+
*/
4756
public static final String NEARLINE_PRODUCER_TO_LOCAL_BROKER_LATENCY = "nearline_producer_to_local_broker_latency";
48-
public static final String NEARLINE_LOCAL_BROKER_TO_READY_TO_SERVE_LATENCY =
49-
"nearline_local_broker_to_ready_to_serve_latency";
57+
58+
/**
59+
* Leader metric: Measures the latency from when a producer created a message (producer timestamp) to when the
60+
* source broker (remote region Kafka) received it.
61+
*/
62+
public static final String PRODUCER_TO_SOURCE_BROKER_LATENCY = "producer_to_source_broker_latency";
63+
64+
/**
65+
* Leader metric: Measures the latency from when the source broker (remote region Kafka) received a message to when
66+
* the leader consumer fetched it.
67+
*/
68+
public static final String SOURCE_BROKER_TO_LEADER_CONSUMER_LATENCY = "source_broker_to_leader_consumer_latency";
69+
70+
/**
71+
* Follower metric: Measures the latency from when the leader produced a message to when the local broker
72+
* (local region Kafka) received it.
73+
*/
74+
public static final String PRODUCER_TO_LOCAL_BROKER_LATENCY = "producer_to_local_broker_latency";
75+
76+
/**
77+
* Follower metric: Measures the latency from when the local broker (local region Kafka) received a message to when
78+
* the follower consumer fetched it.
79+
*/
80+
public static final String LOCAL_BROKER_TO_FOLLOWER_CONSUMER_LATENCY = "local_broker_to_follower_consumer_latency";
81+
82+
/**
83+
* Leader metric: Measures the time from when a produce call is made to when the producer callback is invoked,
84+
* indicating how long Kafka took to write the message to the broker and invoke the callback.
85+
*/
86+
public static final String LEADER_PRODUCER_COMPLETION_LATENCY = "leader_producer_completion_latency";
87+
5088
public static final String IDLE_TIME = "idle_time";
89+
/**
90+
* Leader metric: Measures the time spent within the leader's producer callback processing after a message is
91+
* successfully produced to the local broker. This includes chunking processing, producing to drainer buffer service,
92+
* producing deprecated chunk deletions, and recording stats.
93+
*/
5194
public static final String PRODUCER_CALLBACK_LATENCY = "producer_callback_latency";
95+
/**
96+
* Leader metric: Measures the time from when keys are locked for a batch of records to just before producing to Kafka.
97+
* When batch processing is enabled: includes batch processing (with partial update operations), record validation,
98+
* and for real-time topics, recording hybrid consumption stats.
99+
* When batch processing is disabled: includes only record validation and stats recording; partial update happens later.
100+
*/
52101
public static final String LEADER_PREPROCESSING_LATENCY = "leader_preprocessing_latency";
102+
/**
103+
* Drainer metric: Measures the time spent on lightweight preprocessing tasks before heavy message processing begins.
104+
* This includes recording write path latency stats (producer-to-broker, broker-to-consumer), drainer message
105+
* validation, and reporting batch end of incremental push status. Recorded at the start of internalProcessConsumerRecord,
106+
* before control message or data message processing.
107+
*/
53108
public static final String INTERNAL_PREPROCESSING_LATENCY = "internal_preprocessing_latency";
109+
54110
public static final String BATCH_PROCESSING_REQUEST = "batch_processing_request";
55111
public static final String BATCH_PROCESSING_REQUEST_SIZE = "batch_processing_request_size";
56112
public static final String BATCH_PROCESSING_REQUEST_RECORDS = "batch_processing_request_records";
@@ -84,7 +140,6 @@ public class IngestionStats {
84140
private final WritePathLatencySensor subscribePrepLatencySensor;
85141
private final WritePathLatencySensor consumedRecordEndToEndProcessingLatencySensor;
86142
private final WritePathLatencySensor nearlineProducerToLocalBrokerLatencySensor;
87-
private final WritePathLatencySensor nearlineLocalBrokerToReadyToServeLatencySensor;
88143
private final WritePathLatencySensor producerCallBackLatency;
89144
private final WritePathLatencySensor leaderPreprocessingLatency;
90145
private final WritePathLatencySensor internalPreprocessingLatency;
@@ -154,25 +209,21 @@ public IngestionStats(VeniceServerConfig serverConfig) {
154209
totalDuplicateKeyUpdateCountSensor.add(TOTAL_DUPLICATE_KEY_UPDATE_COUNT, totalDuplicateKeyUpdateCount);
155210

156211
producerSourceBrokerLatencySensor =
157-
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, "producer_to_source_broker_latency");
212+
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, PRODUCER_TO_SOURCE_BROKER_LATENCY);
158213
sourceBrokerLeaderConsumerLatencySensor =
159-
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, "source_broker_to_leader_consumer_latency");
214+
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, SOURCE_BROKER_TO_LEADER_CONSUMER_LATENCY);
160215
producerLocalBrokerLatencySensor =
161-
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, "producer_to_local_broker_latency");
216+
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, PRODUCER_TO_LOCAL_BROKER_LATENCY);
162217
localBrokerFollowerConsumerLatencySensor =
163-
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, "local_broker_to_follower_consumer_latency");
218+
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, LOCAL_BROKER_TO_FOLLOWER_CONSUMER_LATENCY);
164219
leaderProducerCompletionLatencySensor =
165-
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, "leader_producer_completion_latency");
220+
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, LEADER_PRODUCER_COMPLETION_LATENCY);
166221
subscribePrepLatencySensor =
167222
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, SUBSCRIBE_ACTION_PREP_LATENCY);
168223
consumedRecordEndToEndProcessingLatencySensor =
169224
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, CONSUMED_RECORD_END_TO_END_PROCESSING_LATENCY);
170225
nearlineProducerToLocalBrokerLatencySensor =
171226
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, NEARLINE_PRODUCER_TO_LOCAL_BROKER_LATENCY);
172-
nearlineLocalBrokerToReadyToServeLatencySensor = new WritePathLatencySensor(
173-
localMetricRepository,
174-
METRIC_CONFIG,
175-
NEARLINE_LOCAL_BROKER_TO_READY_TO_SERVE_LATENCY);
176227
producerCallBackLatency =
177228
new WritePathLatencySensor(localMetricRepository, METRIC_CONFIG, PRODUCER_CALLBACK_LATENCY);
178229
leaderPreprocessingLatency =
@@ -439,22 +490,10 @@ public double getNearlineProducerToLocalBrokerLatencyMax() {
439490
return unAvailableToZero(nearlineProducerToLocalBrokerLatencySensor.getMax());
440491
}
441492

442-
public double getNearlineLocalBrokerToReadyToServeLatencyAvg() {
443-
return unAvailableToZero(nearlineLocalBrokerToReadyToServeLatencySensor.getAvg());
444-
}
445-
446-
public double getNearlineLocalBrokerToReadyToServeLatencyMax() {
447-
return unAvailableToZero(nearlineLocalBrokerToReadyToServeLatencySensor.getMax());
448-
}
449-
450493
public void recordNearlineProducerToLocalBrokerLatency(double value, long currentTimeMs) {
451494
nearlineProducerToLocalBrokerLatencySensor.record(value, currentTimeMs);
452495
}
453496

454-
public void recordNearlineLocalBrokerToReadyToServeLatency(double value, long currentTimeMs) {
455-
nearlineLocalBrokerToReadyToServeLatencySensor.record(value, currentTimeMs);
456-
}
457-
458497
public void recordIdleTime(long value) {
459498
idleTimeSensor.record(value);
460499
}

0 commit comments

Comments
 (0)