Implementing Custom Interceptors

1. Understanding Interceptor Concept

Aspect Description Detail
Interceptor Hook in send/consume path Cross-cutting
Use Metrics, tracing, audit Non-invasive
Chain Multiple in order Composable

Example: Interfaces

// ProducerInterceptor<K,V> and ConsumerInterceptor<K,V>

2. Creating Producer Interceptor

Method Description Detail
onSend() Before record sent Modify/inspect
onAcknowledgement() On ack/error Metrics
close() Cleanup Optional

Example: Producer interceptor

public class AuditInterceptor implements ProducerInterceptor<String,String> {
  public ProducerRecord<String,String> onSend(ProducerRecord<String,String> r){
    return r; }
  public void onAcknowledgement(RecordMetadata m, Exception e){}
  public void close(){}
  public void configure(Map<String,?> c){}
}

3. Creating Consumer Interceptor

Method Description Detail
onConsume() Before poll returns Inspect/modify
onCommit() After offset commit Tracking
close() Cleanup Optional

Example: Consumer interceptor

public ConsumerRecords<String,String> onConsume(
    ConsumerRecords<String,String> records){
  return records; // inspect/transform
}

4. Implementing onSend() Method

Aspect Description Detail
Input ProducerRecord Before serialize
Return Possibly modified record Same/new
No Throw Catch exceptions Don't break send

Example: Add header in onSend

public ProducerRecord<String,String> onSend(ProducerRecord<String,String> r){
  r.headers().add("trace-id", traceId().getBytes());
  return r;
}

5. Implementing onConsume() Method

Aspect Description Detail
Input ConsumerRecords batch All partitions
Return Filtered/modified batch Same type
Use Decrypt, filter, count Pre-process

Example: Count in onConsume

public ConsumerRecords<String,String> onConsume(
    ConsumerRecords<String,String> recs){
  meter.mark(recs.count());
  return recs;
}

6. Configuring Interceptor Chain

Config Description Detail
interceptor.classes Ordered FQN list Comma-separated
Producer ProducerInterceptor impls onSend order
Consumer ConsumerInterceptor impls onConsume order

Example: Register chain

props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,
  "com.acme.AuditInterceptor,com.acme.MetricsInterceptor");

7. Adding Monitoring Metrics

Metric Where Detail
Send Count onSend Throughput
Error Rate onAcknowledgement Failures
Lag onConsume timestamps Latency

Example: Track acks

public void onAcknowledgement(RecordMetadata m, Exception e){
  if (e != null) errors.inc(); else sent.inc();
}

8. Implementing Tracing

Aspect Description Detail
Inject Trace context to headers onSend
Extract Continue span on consume onConsume
Standard W3C traceparent OpenTelemetry

Example: Inject traceparent

r.headers().add("traceparent",
  span.context().toTraceparent().getBytes());

9. Adding Security Checks

Aspect Description Detail
PII Redaction Strip sensitive fields onSend
Validation Reject bad payloads Early
Audit Log principal/action Compliance

Example: Redact in onSend

String redacted = r.value().replaceAll("\\d{16}", "****");
return new ProducerRecord<>(r.topic(), r.key(), redacted);

10. Transforming Messages

Aspect Description Detail
Enrich Add fields/metadata onSend
Compress/Encrypt Transform payload Reversible
Caution Keep lightweight Hot path

Example: Enrich value

String enriched = addEnvelope(r.value(), System.currentTimeMillis());
return new ProducerRecord<>(r.topic(), r.partition(), r.key(), enriched);