|
| 1 | +package com.nr.instrumentation.spring.kafka; |
| 2 | + |
| 3 | +import com.newrelic.agent.bridge.AgentBridge; |
| 4 | +import com.newrelic.api.agent.DestinationType; |
| 5 | +import com.newrelic.api.agent.InboundHeaders; |
| 6 | +import com.newrelic.api.agent.MessageConsumeParameters; |
| 7 | +import com.newrelic.api.agent.NewRelic; |
| 8 | +import com.newrelic.api.agent.TransactionNamePriority; |
| 9 | +import org.apache.kafka.clients.consumer.ConsumerRecord; |
| 10 | +import org.apache.kafka.clients.consumer.ConsumerRecords; |
| 11 | + |
| 12 | +import java.util.Map; |
| 13 | + |
| 14 | +public class SpringKafkaUtil { |
| 15 | + |
| 16 | + public static Map<Object, Boolean> recordsCache = AgentBridge.collectionFactory.createConcurrentWeakKeyedMap(); |
| 17 | + |
| 18 | + public static String CATEGORY = "Message"; |
| 19 | + public static String LIBRARY = "Kafka"; |
| 20 | + |
| 21 | + private static final boolean DT_CONSUMER_ENABLED = NewRelic.getAgent().getConfig() |
| 22 | + .getValue("kafka.spans.distributed_trace.consumer_poll.enabled", false); |
| 23 | + |
| 24 | + public static <T> void processConsume(T record) { |
| 25 | + if (recordsCache.containsKey(record)) { |
| 26 | + return; |
| 27 | + } |
| 28 | + if (record instanceof ConsumerRecord) { |
| 29 | + processConsumeRecord((ConsumerRecord<?, ?>) record); |
| 30 | + } else if (record instanceof ConsumerRecords<?, ?>) { |
| 31 | + processConsumeBatch((ConsumerRecords<?, ?>) record); |
| 32 | + } |
| 33 | + recordsCache.put(record, true); |
| 34 | + } |
| 35 | + |
| 36 | + private static <K,V> void processConsumeRecord(ConsumerRecord<K, V> record) { |
| 37 | + NewRelic.getAgent().getTransaction().setTransactionName(TransactionNamePriority.FRAMEWORK_HIGH, |
| 38 | + false, CATEGORY, "Kafka/Listen/Topic/Named", record.topic()); |
| 39 | + |
| 40 | + HeadersWrapper inboundHeaders = new HeadersWrapper(record.headers()); |
| 41 | + reportExternalConsume(record, inboundHeaders); |
| 42 | + } |
| 43 | + |
| 44 | + private static <K,V> void processConsumeBatch(ConsumerRecords<K,V> records) { |
| 45 | + NewRelic.getAgent().getTransaction().setTransactionName(TransactionNamePriority.FRAMEWORK_HIGH, |
| 46 | + false, CATEGORY, "Kafka/Listen/Batch"); |
| 47 | + |
| 48 | + for (ConsumerRecord<?, ?> record : records) { |
| 49 | + HeadersWrapper inboundHeaders = DT_CONSUMER_ENABLED ? new HeadersWrapper(record.headers()) : null; |
| 50 | + reportExternalConsume(record, inboundHeaders); |
| 51 | + break; |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + private static <K,V> void reportExternalConsume(ConsumerRecord<K,V> record, HeadersWrapper inboundHeaders) { |
| 56 | + MessageConsumeParameters params = MessageConsumeParameters.library(LIBRARY) |
| 57 | + .destinationType(DestinationType.NAMED_TOPIC) |
| 58 | + .destinationName(record.topic()) |
| 59 | + .inboundHeaders(inboundHeaders) |
| 60 | + .build(); |
| 61 | + NewRelic.getAgent().getTracedMethod().reportAsExternal(params); |
| 62 | + } |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | +} |
0 commit comments