Skip to content

Commit 31cd5c9

Browse files
committed
Fix Kafka lag instrumentation for version 2.7+ of Kafka
1 parent cb6a6fc commit 31cd5c9

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaConsumerInfoInstrumentation.java

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,28 @@ public void methodAdvice(MethodTransformer transformer) {
7878
.and(takesArgument(2, named("org.apache.kafka.common.serialization.Deserializer"))),
7979
KafkaConsumerInfoInstrumentation.class.getName() + "$ConstructorAdvice");
8080

81+
transformer.applyAdvice(
82+
isConstructor()
83+
.and(takesArgument(0, Map.class))
84+
.and(takesArgument(1, named("org.apache.kafka.common.serialization.Deserializer")))
85+
.and(takesArgument(2, named("org.apache.kafka.common.serialization.Deserializer"))),
86+
KafkaConsumerInfoInstrumentation.class.getName() + "$SecondConstructorAdvice");
87+
88+
transformer.applyAdvice(
89+
isMethod()
90+
.and(isPublic())
91+
.and(named("poll"))
92+
.and(takesArguments(1))
93+
.and(takesArgument(0, long.class))
94+
.and(returns(named("org.apache.kafka.clients.consumer.ConsumerRecords"))),
95+
KafkaConsumerInfoInstrumentation.class.getName() + "$RecordsAdvice");
96+
8197
transformer.applyAdvice(
8298
isMethod()
8399
.and(isPublic())
84100
.and(named("poll"))
85101
.and(takesArguments(1))
102+
.and(takesArgument(0, named("java.time.Duration")))
86103
.and(returns(named("org.apache.kafka.clients.consumer.ConsumerRecords"))),
87104
KafkaConsumerInfoInstrumentation.class.getName() + "$RecordsAdvice");
88105
}
@@ -94,6 +111,7 @@ public static void captureGroup(
94111
@Advice.FieldValue("metadata") Metadata metadata,
95112
@Advice.FieldValue("coordinator") ConsumerCoordinator coordinator,
96113
@Advice.Argument(0) ConsumerConfig consumerConfig) {
114+
System.out.println("constructor advice!!!");
97115
String consumerGroup = consumerConfig.getString(ConsumerConfig.GROUP_ID_CONFIG);
98116
String normalizedConsumerGroup =
99117
consumerGroup != null && !consumerGroup.isEmpty() ? consumerGroup : null;
@@ -131,6 +149,66 @@ public static void muzzleCheck(ConsumerRecord record) {
131149
}
132150
}
133151

152+
public static class SecondConstructorAdvice {
153+
@Advice.OnMethodExit(suppress = Throwable.class)
154+
public static void captureGroup(
155+
@Advice.This KafkaConsumer consumer,
156+
@Advice.FieldValue("metadata") Metadata metadata,
157+
@Advice.FieldValue("coordinator") ConsumerCoordinator coordinator,
158+
@Advice.Argument(0) Map<String, Object> consumerConfig) {
159+
System.out.println("new constructor advice!!!");
160+
Object groupID = consumerConfig.get("group.id");
161+
String consumerGroup = groupID instanceof String ? (String) groupID : null;
162+
String normalizedConsumerGroup =
163+
consumerGroup != null && !consumerGroup.isEmpty() ? consumerGroup : null;
164+
System.out.println("consume group " + normalizedConsumerGroup);
165+
166+
String bootstrapServers = null;
167+
Object bootstrapServersObj = consumerConfig.get("bootstrap.servers");
168+
if (bootstrapServersObj instanceof String) {
169+
bootstrapServers = (String) bootstrapServersObj;
170+
System.out.println("bootstrap servers " + bootstrapServers);
171+
} else {
172+
System.out.println("it s not a string");
173+
}
174+
// if (bootstrapServersList != null && !bootstrapServersList.isEmpty()) {
175+
// bootstrapServers = String.join(",", bootstrapServersList);
176+
// }
177+
// Object bootstrapServersObj = consumerConfig.get("bootstrap.servers");
178+
// if (bootstrapServersObj instanceof List) {
179+
// List<?> tempList = (List<?>) bootstrapServersObj;
180+
181+
// // Verify each element is a String
182+
// if (!tempList.isEmpty() && tempList.stream().allMatch(element -> element instanceof String)) {
183+
// bootstrapServers = String.join(",", (List<String>) tempList);
184+
// }
185+
// }
186+
KafkaConsumerInfo kafkaConsumerInfo;
187+
if (Config.get().isDataStreamsEnabled()) {
188+
kafkaConsumerInfo =
189+
new KafkaConsumerInfo(normalizedConsumerGroup, metadata, bootstrapServers);
190+
} else {
191+
kafkaConsumerInfo = new KafkaConsumerInfo(normalizedConsumerGroup, bootstrapServers);
192+
}
193+
194+
if (kafkaConsumerInfo.getConsumerGroup() != null
195+
|| kafkaConsumerInfo.getClientMetadata() != null) {
196+
InstrumentationContext.get(KafkaConsumer.class, KafkaConsumerInfo.class)
197+
.put(consumer, kafkaConsumerInfo);
198+
if (coordinator != null) {
199+
InstrumentationContext.get(ConsumerCoordinator.class, KafkaConsumerInfo.class)
200+
.put(coordinator, kafkaConsumerInfo);
201+
}
202+
}
203+
}
204+
205+
public static void muzzleCheck(ConsumerRecord record) {
206+
// KafkaConsumerInstrumentation only applies for kafka versions with headers
207+
// Make an explicit call so KafkaConsumerGroupInstrumentation does the same
208+
record.headers();
209+
}
210+
}
211+
134212
/**
135213
* this method transfers the consumer group from the KafkaConsumer class key to the
136214
* ConsumerRecords key. This is necessary because in the poll method, we don't have access to the
@@ -157,6 +235,7 @@ public static void captureGroup(
157235
@Advice.Enter final AgentScope scope,
158236
@Advice.This KafkaConsumer consumer,
159237
@Advice.Return ConsumerRecords records) {
238+
System.out.println("polling!");
160239
int recordsCount = 0;
161240
if (records != null) {
162241
KafkaConsumerInfo kafkaConsumerInfo =

dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaConsumerInstrumentation.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,11 @@ public static void wrap(
142142
KafkaConsumerInfo kafkaConsumerInfo =
143143
InstrumentationContext.get(ConsumerRecords.class, KafkaConsumerInfo.class).get(records);
144144
String group = KafkaConsumerInstrumentationHelper.extractGroup(kafkaConsumerInfo);
145+
System.out.println("consumer info retrieved" + group);
145146
String clusterId =
146147
KafkaConsumerInstrumentationHelper.extractClusterId(
147148
kafkaConsumerInfo, InstrumentationContext.get(Metadata.class, String.class));
149+
System.out.println("cluster ID retrieved" + clusterId);
148150
String bootstrapServers =
149151
KafkaConsumerInstrumentationHelper.extractBootstrapServers(kafkaConsumerInfo);
150152
iterator =

dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/MetadataInstrumentation.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public static class MetadataUpdateBefore22Advice {
6666
public static void onEnter(
6767
@Advice.This final Metadata metadata, @Advice.Argument(0) final Cluster newCluster) {
6868
if (newCluster != null && !newCluster.isBootstrapConfigured()) {
69+
System.out.println("getting cluster ID before 22: " + newCluster.clusterResource().clusterId());
6970
InstrumentationContext.get(Metadata.class, String.class)
7071
.put(metadata, newCluster.clusterResource().clusterId());
7172
}
@@ -83,6 +84,7 @@ public static class MetadataUpdate22AndAfterAdvice {
8384
public static void onEnter(
8485
@Advice.This final Metadata metadata, @Advice.Argument(1) final MetadataResponse response) {
8586
if (response != null) {
87+
System.out.println("getting cluster ID after 22: " + response.clusterId());
8688
InstrumentationContext.get(Metadata.class, String.class)
8789
.put(metadata, response.clusterId());
8890
}

0 commit comments

Comments
 (0)