Tracing Red Hat Fuse Transaction with Jaeger
Jaeger is open source software for tracing transactions between distributed services. It’s used for monitoring and troubleshooting complex microservices environments. And in this example, im trying trying to use it for tracing http request on Red Hat Fuse, or its opensource version which is Apache Camel. The purpose is to see how much time is needed for each api to take, and what kind of information comes with it.
First lets start by installing Jaeger on your local,
docker pull jaegertracing/all-in-one:1.19 docker run -d --name jaeger -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \ -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 \ -p 16686:16686 -p 14268:14268 -p 14250:14250 -p 9411:9411 \ jaegertracing/all-in-one:1.19
And create a java project with this pom file,
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.edw</groupId> <artifactId>camel-with-jaeger</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <fuse.version>7.2.0.fuse-720020-redhat-00001</fuse.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.jboss.redhat-fuse</groupId> <artifactId>fuse-springboot-bom</artifactId> <version>${fuse.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-http-starter</artifactId> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-servlet-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> <version>2.1.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> <version>2.1.3.RELEASE</version> </dependency> </dependencies> <build> <pluginManagement> <plugins> <plugin> <groupId>org.jboss.redhat-fuse</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${fuse.version}</version> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> </project>
Set connection to Jaeger tracing
# The Camel context name camel.springboot.name=camel-with-jaeger # enable all management endpoints endpoints.enabled=true management.security.enabled=false camel.component.servlet.mapping.contextPath=/api/* logging.level.root=info # name for tracing spring.application.name=Camel Hello World spring.zipkin.base-url=http://localhost:9411/ spring.zipkin.enabled=true spring.zipkin.sender.type=web spring.sleuth.enabled=true spring.sleuth.sampler.probability=1.0
Create a simple helo-world api,
<?xml version="1.0" encoding="UTF-8"?> <rest path="/hello-world" xmlns="http://camel.apache.org/schema/spring"> <get> <route> <setHeader headerName="Content-Type"> <constant>application/json</constant> </setHeader> <setBody> <simple>{ "hello": "world" }</simple> </setBody> </route> </get> </rest>
We test our newly created api by using curl command,
curl -kv http://localhost:8080/api/hello-world
And the result can be viewed directly on Jaeger dashboard
Now lets say we have other requirement such as adding a specific information on every trace result on Jaeger. We can achieve that by using Tag inside current Trace Span.
package com.edw.routes; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Tracer; import org.springframework.stereotype.Component; @Component public class HelloWorldRoute extends RouteBuilder { @Autowired private Tracer tracer; @Override public void configure() throws Exception { rest() .get("hello") .route() .setHeader(Exchange.HTTP_RESPONSE_CODE, simple("200")) .setHeader(Exchange.CONTENT_TYPE, simple("application/json")) .process(exchange -> { Span span = tracer.getCurrentSpan(); span.tag("something", "whatever"); span.tag("pretending to do some queries", "select 1 from dual"); }) .setBody(constant("{\"world\":\"world\"}")) .endRest() ; } }
The result would be displayed on every trace like this,
Full code for this tutorial can be accessed in below url,
https://github.com/edwin/fuse-with-jaeger
Have fun with Jaeger and Camel 🙂