Bitryon Logger Docs
GitHub
Guides

Tracing over Kafka

No more MDC.
Tracing requires writing step log id through clients and reading it in servers.
With bitryon-logger library, developers can customize tracing over other protocols.

Configuration YAML file - in spring

In pure java applications, developers need to manually write and read step log id

bitryon:
  app-node: 
    http-header-id-type: 1 # write log/trace id to the http response header; 0 default no write header, 1 trace id, 2 step log id

Write step log id - trace id

Write step log id (trace id) over Kafka:

//  Write next step log id (trace id) to metadata/header of the message 
import io.bitryon.logger.Logger;
import io.bitryon.logger.PreDefinition;
import io.bitryon.logger.provider.LoggerFactory;

public class ProducerLoggerInterceptor implements ProducerInterceptor<String, String> {
    private static final Logger logger = LoggerFactory.getLogger();

    @Override
    public ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {
        // CRITICAL .getNextStepLogId()
        String nextSteplogId = logger.getNextStepLogId();
        record.headers().add(PreDefinition.HTTP_HEADER_STEP_LOG_ID, nextSteplogId.getBytes(PreDefinition.CharsetEncoding));
        return record;
    }
// other code
}

Read step log id - trace id

Read step log id (trace id) over HTTP:

//  Read the step log id (trace id) from metadata/header of the message 
import io.bitryon.logger.Logger;
import io.bitryon.logger.PreDefinition;
import io.bitryon.logger.provider.LoggerFactory;

public class ConsumerLoggerInterceptor implements ConsumerInterceptor<String, String> {
    private static final Logger logger = LoggerFactory.getLogger();

    @Override
    public ConsumerRecords<String, String> onConsume(ConsumerRecords<String, String> records) {
        records.forEach(record -> {
            Header header = record.headers().lastHeader(PreDefinition.HTTP_HEADER_STEP_LOG_ID);
            if (header!=null) {
                String stepLogId = new String(header.value(), PreDefinition.CharsetEncoding);
                logger.setStepLogId(stepLogId);
            }else {
                logger.reset();// reset to restart trace for each consume
            }
        });

        return records;
    }
// other code
}

Tracing by reusing HTTP headers

TypeKeyDefaultDescription
HTTP_HEADER_STEP_LOG_IDX-Step-Log-Idnull

Pass the step log id to the next service to track all of the traces.

HTTP_HEADER_STEP_TRACE_IDX-Step-Trace-Idnull

Expose the trace id to HTTP headers

HTTP_HEADER_STEP_LOG_SKIPX-Step-Log-Skipfalse

to tell the next service to skip the trace, true skip, null or false not skip

💡 NoteKafka requires configuring metadata/header Interceptors

Send messages

public class KafkaProducer {

    @Resource
    MedicService medicService;

    private final KafkaTemplate kafkaTemplate;

    @Autowired
    public KafkaProducer(KafkaTemplate kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }

    public void sendMessage(String message) {
        medicService.callSelfInvocation(message);
        kafkaTemplate.send("demo-topic", message);
    }
}

Receive messages

@Service
public class KafkaConsumer {

    @Resource
    UserService userService;

    @KafkaListener(topics = "demo-topic", groupId = "demo-group")
    public void listen(String message) {
        userService.getBySessionId(message);
    }
}

Tracing Logs


2025-11-20 15:42:24.785|http-nio-80-exec-1#38|7G5HPZyA3QWSF2f1SMRN5qV2U95tjOLi|4|JSON|
MedicService.java#io.bitryon.example.web.service.MedicService#callSelfInvocation#68#|
[{
    "testString": "68ssTfeP43IeSVqFWx1jH1VigFuEdUbt"
}]
2025-11-20 15:42:24.787|http-nio-80-exec-1#38|7G5HPZyA3QWSF2f1SMRN5qV2U95tjOLi|13|JSON|
MedicService.java#io.bitryon.example.web.service.MedicService#callSelfInvocation#68#R|
["1763653344787"]
2025-11-20 15:42:26.073|org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1#51|7G5HPZyA3QWSF2f1SMRN5qV2U95tjOLi|14-1|JSON|
UserService.java#io.bitryon.example.web.service.rpc.UserService#getBySessionId#0#|
[{
    "sessionId": "68ssTfeP43IeSVqFWx1jH1VigFuEdUbt"
}]
2025-11-20 15:42:26.693|http-nio-80-exec-4#41|7G5HPZyA3QWSF2f1SMRN5qV2U95tjOLi|14-1-2|JSON|
UserServiceImpl.java#io.bitryon.example.web.service.rpc.UserServiceImpl#getBySessionId#45#|
[{
    "sessionId": "68ssTfeP43IeSVqFWx1jH1VigFuEdUbt"
}]
2025-11-20 15:42:26.694|http-nio-80-exec-4#41|7G5HPZyA3QWSF2f1SMRN5qV2U95tjOLi|14-1-3|JSON|
UserServiceImpl.java#io.bitryon.example.web.service.rpc.UserServiceImpl#getBySessionId#45#R|
[{
    "name": "ra***ly",
    "id": 456,
    "driverLisenceId": "****************************",
    "age": null
}]
2025-11-20 15:42:26.918|org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1#51|7G5HPZyA3QWSF2f1SMRN5qV2U95tjOLi|14-2|JSON|
UserService.java#io.bitryon.example.web.service.rpc.UserService#getBySessionId#0#R|
[{
    "name": "ra***ly",
    "id": 456,
    "driverLisenceId": "****************************",
    "age": null
}]