I have implemented different microservice where internal communication is taking place by camel and rabbitMQ with different exchange and queue. I'm using camel-zipkin
for tracing, and log4j2
for logging.
Ex:
- Service1 Publish message to RabbitMQ ( i.e Exchange 1 -> Queue 1) where Service2 Consume message
- Service2 Publish message to RabbitMQ ( i.e Exchange 1 -> Queue 2) where Service3 Consume message and so on.
I am using Springboot 1.5.12.RELEASE
and Camel 2.21.5 version
with the following dependencies (of camel):
- camel-spring-boot-starter
- camel-rabbitmq-starter
- camel-core
- camel-spring
- camel-zipkin-starter
- camel-test
- camel-test-spring
I need suggestion for my two problems
- span-id, trace-id are not getting printed in logs. I have necessary placeholders added in my log4j2.xml.
- Whenever a message is sent to an exchange a unique span-id and trace-id is getting generated.
My Questions are :
- Is it possible to have a unique traceID for entire data traverse from Service 1 to Service N.
- How can I print span-id, trace-id to logs.
Sample Code :
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.12.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.camel</groupId>
<artifactId>example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<camel.version>2.21.5</camel.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- Camel Dependency -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-rabbitmq-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-zipkin-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test</artifactId>
<version>${camel.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-spring</artifactId>
<version>${camel.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
SpringBoot Application
@SpringBootApplication
@CamelZipkin
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
RabbitMQConfig
@EnableRabbit
@Profile("default")
@Configuration
public class RabbitMQConfig {
@Value("${camel.component.rabbitmq.hostname}")
private String host;
@Value("${camel.component.rabbitmq.port-number:5672}")
private int port;
@Value("${camel.component.rabbitmq.username}")
private String username;
@Value("${camel.component.rabbitmq.password}")
private String password;
@Value("${camel.component.rabbitmq.vhost}")
private String virtualHost;
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
connectionFactory.setCacheMode(CacheMode.CONNECTION);
return connectionFactory;
}
@Bean
public Channel amqpChannel(ConnectionFactory connectionFactory) throws IOException {
Connection connection = connectionFactory.createConnection();
Channel channel = connection.createChannel(false);
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
channel.exchangeDeclare("example-service", "x-delayed-message", true, false, args);
return channel;
}
}
Controller adding message to queue
@RestController
public class MessageController {
private static final Logger log = LoggerFactory.getLogger(MessageController.class);
@Autowired
protected ProducerTemplate producer;
@PostMapping(value = "send/message")
public void sendMessageTopic(@RequestBody MessageDto message) {
log.debug("In controller sending message ");
producer.requestBody("rabbitmq:example-service?routingKey=example-service.ers.send&queue=example-service-ers-send", message);
}
}
RouteBuilder
@Component
public class AppRouteBuilder extends RouteBuilder {
@Autowired
private MessageActivity messageActivity;
@Autowired
private SmsActivity smsActivity;
@Override
public void configure() throws Exception {
// TODO Auto-generated method stub
from("rabbitmq:example-service?routingKey=example-service.ers.send&queue=example-service-ers-send")
.bean(messageActivity).end();
from("rabbitmq:example-service?routingKey=example-service.sms.send&queue=example-service-sms-send")
.bean(smsActivity).end();
}
}
MessageActivity
@Service
public class MessageActivity {
private static final Logger log = LoggerFactory.getLogger(MessageActivity.class);
@Autowired
protected ProducerTemplate producer;
public void doAction() {
log.debug("Hello in message activity ");
producer.requestBody("rabbitmq:example-service?routingKey=example-service.sms.send&queue=example-service-sms-send", "Hello from message");
}
}
SmsActivity
@Service
public class SmsActivity {
private static final Logger log = LoggerFactory.getLogger(SmsActivity.class);
public void doAction() {
log.debug("Hello in sms activity ");
}
}
Output
2019-12-03T21:07:54.316+07:00|2|INFO|example-service|,,|50382|http-nio-8080-exec-2|o.a.c.c.C.[.[.[/]|Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-12-03T21:07:54.452+07:00|2|DEBUG|example-service|,,|50382|http-nio-8080-exec-2|c.c.e.MessageController|In controller sending message
2019-12-03T21:07:54.552+07:00|2|DEBUG|example-service|,,|50382|Camel (camel-1) thread #4 - RabbitMQConsumer|c.c.e.b.MessageActivity|Hello in message activity
2019-12-03T21:07:54.580+07:00|2|DEBUG|example-service|,,|50382|Camel (camel-1) thread #6 - RabbitMQConsumer|c.c.e.b.SmsActivity|Hello in sms activity