Monitoring Spring Boot with OpenTelemetry

Monitoring Spring Boot with OpenTelemetry

Integrating OpenTelemetry with Spring Boot allows you to capture distributed traces and other telemetry data from your application, providing valuable insights into its performance and behavior in a distributed environment.

What is OpenTelemetry?

OpenTelemetry defines APIs and protocols for collecting telemetry data such as metrics, traces, and logs, and provides a variety of libraries, agents, and integrations for popular programming languages and technologies.

OpenTelemetry is an open and vendor-neutral solution that provides a unified approach to observability, making it easier for organizations to manage the complexity of their cloud-native infrastructure. It enables organizations to collect telemetry from their applications and send it to a variety of of distributed tracing tools.

Conduit app

Spring Boot is a popular Java framework that simplifies the development of Java applications. It provides a convention-over-configuration approach and comes with built-in support for dependency injection, configuration management, and several other features.

RealWorld example app is a full-stack application called "Conduit" that consists of a backend that serves JSON API and a frontend UI. There are numerous implementations for different languages and frameworks, but in this tutorial you will be using the Spring backend and the React frontend.

RealWorld backend

Let's start by downloading the backend source code:

git clone https://github.com/gothinkster/spring-boot-realworld-example-app.git

Then you need to build a JAR from the downloaded source code:

cd spring-boot-realworld-example-app
./gradlew bootJar

If you are getting Could not find snakeyaml-1.27-android.jar (org.yaml:snakeyaml:1.27), apply the following diff to build.gradle and try again:

diff --git a/build.gradle b/build.gradle
index 12781f0..52a8f71 100644
--- a/build.gradle
+++ b/build.gradle
@@ -33,6 +33,7 @@ dependencies {
     implementation 'io.jsonwebtoken:jjwt:0.9.1'
     implementation 'joda-time:joda-time:2.10.6'
     implementation 'org.xerial:sqlite-jdbc:3.34.0'
+    implementation 'org.yaml:snakeyaml:1.28'

Now you can start the app using the compiled JAR:

java -jar build/libs/spring-boot-realworld-example-app-0.0.1-SNAPSHOT.jar

You can check that the backend is working by visiting http://localhost:8080/tags:

curl http://localhost:8080/tags
{"tags":[]}

Let's stop the app for now by pressing CTRL+C.

OpenTelemetry Java Agent

To integrate OpenTelemetry with a Spring Boot application, you can use the OpenTelemetry Java Agent, which provides instrumentation for various Java frameworks, including Spring Boot, to automatically collect telemetry data.

OpenTelemetry Java Agent is a standalone process that provides automatic instrumentation and tracing capabilities for Java applications without requiring any code changes. It works by attaching to a Java application at runtime and intercepting method calls to collect telemetry data such as traces and metrics.

The agent sits between the instrumented application and the backend systems or observability platforms, allowing for centralized and streamlined telemetry data handling.

To download the latest OpenTelemetry Agent:

wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar

Otel Agent accepts various configuration options either via system properties or environment variables.

Uptrace

Uptrace is an open source APM for OpenTelemetry that supports distributed tracing, metrics, and logs. You can use it to monitor applications and troubleshoot issues.

Uptrace comes with an intuitive query builder, rich dashboards, alerting rules with notifications, and integrations for most languages and frameworks.

Uptrace can process billions of spans and metrics on a single server and allows you to monitor your applications at 10x lower cost.

Uptrace Home

Uptrace DSN (Data Source Name) is a connection string that is used to connect and send data to an Uptrace backend. You can obtain a DSN after installing Uptrace and creating a project.

Use the following environment variables to configure OpenTelemetry Java to send data to Uptrace.

export OTEL_RESOURCE_ATTRIBUTES=service.name=myservice,service.version=1.0.0
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_COMPRESSION=gzip
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.uptrace.dev:4317
export OTEL_EXPORTER_OTLP_HEADERS=uptrace-dsn=https://<token>@uptrace.dev/<project_id>
export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=DELTA
export OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION=BASE2_EXPONENTIAL_BUCKET_HISTOGRAM

Let's start the backend application again, but this time you're going to use the Java Agent to automatically instrument the JAR:

java -javaagent:opentelemetry-javaagent-all.jar -jar build/libs/spring-boot-realworld-example-app-0.0.1-SNAPSHOT.jar

As usually you can open http://localhost:8080/tags to check that API is working.

RealWorld frontend

You have a working backend, but it is not very interesting without a frontend. Let's go ahead and install a React + Redux frontend that will serve as a UI:

git clone https://github.com/gothinkster/react-redux-realworld-example-app.git

The app comes with various JS dependencies:

cd react-redux-realworld-example-app
npm install

Now you need to configure the frontend app to use our backend that is running at http://localhost:8080/. You can do that by editing src/agent.js file:

const API_ROOT = 'http://localhost:8080'

After which you can start the React app and enjoy the UI at http://localhost:4100/register:

npm start

After clicking a few links you should see traces like this one arriving in your Uptrace project:

Conduit

Conclusion

By using OpenTelemetry Java Agent, you can instrument a Java application without changing a single line of code. Curious to try instrumenting your app? Sign up for a free Uptrace account and follow this tutorial. Good luck.