Skip to content

Instrumentations for Java

uptrace-java

Introduction

In this tutorial we will be instrumenting Spring boot RealWorld example app using OpenTelemetry Java Agent.

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.

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-all.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>@api.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=none
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:

npm start

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

conduit

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.