In this tutorial we will be instrumenting Spring boot RealWorld example app using OpenTelemetry Java Agent.
Intro
RealWorld example app is a fullstack app called "Conduit" that consists of a backend (JSON API) and a frontend (UI). There are numerous implementations for different languages and frameworks, but in this turorial we will be using the Spring backend and the React frontend.
OpenTelemetry Java agent dynamically injects bytecode into any Java 8+ application to capture telemetry from a number of popular libraries and frameworks. The instrumentation process is completely automatic and does not require any source code modifications.
Uptrace
Uptrace is an open source APM and blazingly fast distributed tracing tool powered by OpenTelemetry and ClickHouse. It is a popular alternative to Jaeger and can be installed by downloading a pre-compiled binary.
RealWorld backend
Let's start by downloading the backend source code:
git clone https://github.com/gothinkster/spring-boot-realworld-example-app.git
Then we 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 we 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 agent
It is time to setup OpenTelemetry agent. Let's download the latest pre-compiled JAR:
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
The agent accepts various configuration options either via system properties or environment variables. In the following example we are using environment variables to configure OTLP exporter to send data to Uptrace.
export OTEL_EXPORTER_OTLP_HEADERS=uptrace-dsn=https://<token>@uptrace.dev/<project_id>
export OTEL_RESOURCE_ATTRIBUTES=service.name=myservice,service.version=1.0.0
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.uptrace.dev:4317
export OTEL_EXPORTER_OTLP_TIMEOUT=5000
Let's start the backend app again, but this time we will be using Java agent to auto-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
We 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 we 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 we 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 arriving in your Uptrace project:
Conclusion
By using OpenTelemetry agent we were able to istrument a Java application without changing a single line of code. Curious to try instrumenting your app? Create an Uptrace project and follow this tutorial. Good luck.