Integrating Spring Boot with OpenTelemetry

otel-spring-boot

In this post we will see how to use and integrate OpenTelemetry with Spring Boot Application. You can consider this as a Demo Post to my earlier post which was to understand what is OpenTelemetry.

So, lets get started.

This post demonstrates Observability by integrating –

  • Opentelemetry
  • Grafana Tempo Which internally uses Jaeger
  • Spring Boot

And it uses below tools –

  • Prometheus for monitoring and alerting
  • Loki for Distributed Logging
  • Tempo for Distributed Tracing
  • Grafana for visualization

Integrating OTel Libraries

Add below dependencies in your application’s pom.xml file

      <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-api</artifactId>
      </dependency>
       
       <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-extension-annotations</artifactId>
      </dependency>

Integrating Otel Agent/Collector

Add below Maven plugin configuration to register OTel Agent

<plugins>
   <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <configuration>
         <fork>true</fork>
                <skip>false</skip>
         <mainClass>io.opentelemetry.example.BootOtelTempoApiApplication</mainClass>
               <argLine>
                   -javaagent:../boot-otel-tempo-docker/agent/opentelemetry-javaagent-all.jar 
                   -Dotel.trace.exporter=jaeger 
                   -Dotel.exporter.jaeger.endpoint=localhost:14250  
                   -Dotel.resource.attributes=service.name=${project.artifactId} 
                   -Dotel.javaagent.debug=false 
                   -Dotel.metrics.exporter=none
               </argLine>
           </configuration>
   </plugin>
</plugins>

Setup Dockerfile

FROM mnadeem/boot-otel-tempo-docker:0.0.1-SNAPSHOT
ENV APP_NAME boot-otel-tempo-api

COPY ./target/${APP_NAME}-*.jar ${APP_HOME}/${APP_NAME}.jar


EXPOSE 8080
# OpenTelemetry:
# https://github.com/open-telemetry/opentelemetry-java-instrumentation
ENV JAVA_OPTS "${JAVA_OPTS} \
  -Dotel.traces.exporter=jaeger \
  -Dotel.exporter.jaeger.endpoint=http://tempo:14250 \
  -Dotel.metrics.exporter=none \
  -Dotel.resource.attributes="service.name=${APP_NAME}" \
  -Dotel.javaagent.debug=false \
  -javaagent:${APP_HOME}/${OTEL_AGENT_JAR_FILE}"

Project Structure

We will use exisitng Demo project given on the OpenTelemetry website.

There are 3 modules in the project.

  1. boot-otel-tempo-api: This is a Spring Boot Web Application which exposes REST endpoint. This is also registered with Otel Agent and shows how to use OpenTelemetry libraries to trace your application
  2. boot-otel-tempo-docker: This is our OTel agent application.
  3. boot-otel-tempo-provider1: This is another Spring Boot Application similar to 1st one with extra complexity.

Here is the link to the source code of this demo application

Setup Project

Configure the project in IntelliJ IDE or any other IDE you like. I am sharing details for IntelliJ.

Click on File->Open and select the project

otel-intellij

Once you import the project, IntelliJ will download all the dependencies. And here are modules of the project

otel-intellij-modules

Instrumentation

This is how you can add span and instrument your application

Refer FlighClient.java

@WithSpan
public List<Flight> getFlights(String origin) {
   LOGGER.info("Getting Flights from {}", provider1Url);

   ResponseEntity<Flight[]> response = restTemplate.getForEntity(provider1Url, Flight[].class);

   return Arrays.asList(response.getBody());
}

FlightService.java

public List<Flight> getFlights(String origin) {
   LOGGER.info("Getting flights for {}", origin);
   List<Flight> flights = this.flightClient.getFlights(origin);
   doSomeWorkNewSpan();
   return flights;
}

@WithSpan
   private void doSomeWorkNewSpan() {
   LOGGER.info("Doing some work In New span");
       Span span = Span.current();

       span.setAttribute("attribute.a2", "some value");

       span.addEvent("app.processing2.start", atttributes("321"));
       span.addEvent("app.processing2.end", atttributes("321"));
   }

 

Running

Execute the following on root folder

mvn clean package docker:build

This will create all the required docker images, then to start the applications run below command

Docker Compose

docker-compose up

Tracing

Make sure everything is up and running.

Test the endpoint with this url http://localhost:8080/flights

otel-api
otel-api

View the logs and Trace in Grafana

  1. First select Loki from the drop down
  2. Then Enter below text in the log label  {job=”boot-otel-tempo-api”}
  3. Then click on refresh
  4. Click on any log entry which has trace id. Then click on Tempo Button in front of TraceID.

On the right side you will see complete trace of the API.

otel-grafana-trace
otel-grafana-trace

 

Conclusion

So, we saw how to integrate OpenTelemetry with spring boot application with sample code. Hope it makes sense and help you.

 

Tags:

Leave a Reply