Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent

In this article, we’ll explore how to instrument Java application built with Gradle using the OpenTelemetry Java Agent. OpenTelemetry provides powerful tools for observability, allowing developers to gain insights into application performance by collecting telemetry data such as traces, metrics, and logs. We’ll set up a simple Spring Boot application, add an endpoint for rolling a dice, and configure OpenTelemetry with java agent for logging.

Prerequisites

Before we begin, ensure you have the following  installed on your Ubuntu system:

  • AWS Account with Ubuntu 24.04 LTS EC2 Instance.
  • OpenJDK 17: The Java Development Kit (JDK) for running Java  applications.
  • Gradle: A build automation tool that manages dependencies and build tasks.

Step #1:Set Up Ubuntu EC2 Instance

If you don’t have JDK or Gradle installed on your system, you can install them using the following commands.

First, update the package list.

sudo apt update
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 1

Then install OpenJDK 17, which is required to run your Spring Boot application.

sudo apt install openjdk-17-jdk -y
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 2

Verify the Java installation.

java -version
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 3

You should see the version details of your Java installation.

Now let’s install Gradle. Gradle can be installed using the following command,

sudo apt install gradle -y
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 4

Step #2:Initialize a New Java Application with Gradle

To create a new Spring Boot project, you can use the command line. Run the following command to generate a new project.

First create a directory for the project and navigate to that directory.

mkdir java-simple
cd java-simple
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 5

Next, initialize the project using Gradle.

gradle init --type java-application
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 6

This command sets up a basic Gradle project structure.

Open the build.gradle file.

nano build.gradle
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 7

Replace its content with the following.

plugins {
        id 'java'
        id 'org.springframework.boot' version '3.3.5'
}

apply plugin: 'io.spring.dependency-management'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
        mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
}
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 8

Explanation of the code:

This is a Gradle build script for a simple Java Spring Boot project, using the Spring Boot plugin and dependency management for easier setup and version control.

  1. Plugins Block:
    • id 'java': Adds support for Java compilation and packaging.
    • id 'org.springframework.boot' version '3.3.5': Adds Spring Boot’s Gradle plugin (version 3.3.5) for Spring Boot application support, which includes tasks for running and packaging the app.
  2. apply plugin:
    • This applies the Spring Dependency Management plugin, which manages transitive dependencies for Spring projects, making it easier to handle compatible versions of libraries.
  3. Project Metadata:
    • group: Defines the package namespace (e.g., com.example) for identifying the project.
    • version: Sets the current version of the project (0.0.1-SNAPSHOT), where “SNAPSHOT” denotes a work-in-progress.
    • sourceCompatibility: Specifies Java 17 as the target version.
  4. Repositories:
    • Defines mavenCentral as the source for downloading dependencies, the main repository for Java libraries.
  5. Dependencies Block:
    • implementation 'org.springframework.boot:spring-boot-starter-web': Adds the Spring Boot Web Starter dependency, which includes everything necessary to create a web application, including a Tomcat server and essential Spring components.

Step #3:Create the Java Application and Controller

Next navigate to the Main Java source directory.

cd src/main/java
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 9

Remove the default App.java file that was generated.

sudo rm App.java
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 10

Create the package structure and navigate into it.

mkdir -p com/example
cd com/example
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 11

Create the main application file DiceApplication.java

nano DiceApplication.java
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 12

Add the following code.

package com.example;

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DiceApplication {
  public static void main(String[] args) {
    SpringApplication app = new SpringApplication(DiceApplication.class);
    app.setBannerMode(Banner.Mode.OFF);
    app.run(args);
  }
}
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 13

Explanation of the code:

This is the main application code for a simple Java Spring Boot project, which launches a web application without displaying the Spring Boot banner.

  1. Package Declaration:
    • package com.example;: Defines the package for the DiceApplication class. In Java, packages help organize classes logically and avoid naming conflicts.
  2. Import Statements:
    • Imports Spring Boot classes for app startup (SpringApplication) and configuration (SpringBootApplication), along with Banner for optional customization.
  3. Class Annotation:
    • @SpringBootApplication: This annotation marks the main class of the Spring Boot application, enabling features like:
      • @Configuration: Allows Java-based configuration in place of XML.
      • @EnableAutoConfiguration: Enables automatic configuration of Spring based on dependencies.
      • @ComponentScan: Scans the package for Spring components (like controllers and services), making them available to the application.
  4. Class and main Method:
    • Declares DiceApplication as the main class.
    • SpringApplication app = new SpringApplication(DiceApplication.class); – Initializes the application.
    • app.setBannerMode(Banner.Mode.OFF); – Disables the banner for cleaner console output.
    • app.run(args); – Starts the application, launching the embedded web server.

Create the RollController class to simulate a dice roll.

nano RollController.java
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 14

Add the following code.

package com.example;

import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RollController {
  private static final Logger logger = LoggerFactory.getLogger(RollController.class);

  @GetMapping("/rolldice")
  public String index(@RequestParam("player") Optional<String> player) {
    int result = this.getRandomNumber(1, 6);
    if (player.isPresent()) {
      logger.info("{} is rolling the dice: {}", player.get(), result);
    } else {
      logger.info("Anonymous player is rolling the dice: {}", result);
    }
    return Integer.toString(result);
  }

  public int getRandomNumber(int min, int max) {
    return ThreadLocalRandom.current().nextInt(min, max + 1);
  }
}
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 15

Explanation of the code:

This RollController class handles HTTP requests for rolling a dice. It provides an endpoint (/rolldice) that simulates rolling a dice and logs the result, optionally associating it with a player name.

  1. Package Declaration:
    • package com.example; – Organizes the class under the com.example package.
  2. Imports:
    • java.util.Optional, java.util.concurrent.ThreadLocalRandom: For handling optional player input and generating random dice numbers.
    • org.slf4j.Logger, org.slf4j.LoggerFactory: For logging the dice roll results.
    • org.springframework.web.bind.annotation.GetMapping, org.springframework.web.bind.annotation.RequestParam, org.springframework.web.bind.annotation.RestController: For defining the RESTful controller and handling GET requests with optional query parameters.
  3. @RestController Annotation:
    • Indicates that the class is a Spring REST controller, capable of handling HTTP requests and returning HTTP responses.
  4. Logger:
    • private static final Logger logger = LoggerFactory.getLogger(RollController.class); – Initializes a logger for the class to log dice roll information.
  5. index Method:
    • @GetMapping("/rolldice"): Maps the /rolldice URL to this method, allowing HTTP GET requests to trigger the dice roll logic.
    • @RequestParam("player") Optional<String> player: Captures the optional player query parameter from the URL (e.g., /rolldice?player=John).
    • int result = this.getRandomNumber(1, 6);: Rolls the dice by generating a random number between 1 and 6.
    • Logs the dice roll result, either associating it with a player if the name is provided or logging it as an anonymous roll.
    • Returns the dice roll result as a string.
  6. getRandomNumber Method:
    • Generates a random number between the specified min and max values using ThreadLocalRandom.current().nextInt(min, max + 1).

Step #4:Build and Run the Application

Navigate back to the root directory of the project.

cd ../../../../..
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 16

Now note that, here system  install older version of gradle which is not compatible with our project setup.

gradle -version
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 17

so lets upgrade Gradle Wrapper.

Open the gradle-wrapper.properties file to configure the Gradle wrapper. This file is located in the gradle/wrapper directory. You can adjust the Gradle version here.

nano gradle/wrapper/gradle-wrapper.properties
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 18

specify the Gradle version you want to use in this file. Here we are using 8.1.1.

How to Build Spring Boot Project Using Gradle 18

Once done, check the Gradle wrapper version.

./gradlew -version
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 19

Build the application.

./gradlew assemble
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 20

This command compiles the application and prepares it for execution, generating a JAR file in the build/libs directory.

Now lets run the application.

java -jar ./build/libs/java-simple-0.0.1-SNAPSHOT.jar
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 21

The application is now running, and you can access it at http://<EC2-Instance-IP>:8080/rolldice.

Integrate OpenTelemetry for PHP Application with Zero-Code Instrumentation 16

Stop the application by pressing ctrl+c in console.

Step #5:Download and Configure OpenTelemetry Java Agent

Download the OpenTelemetry Java Agent.

curl -L -O https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 22

This Java agent automatically instruments your Java application and sends telemetry data to the configured backend.

Set environment variables to specify logging exporters and interval.

export JAVA_TOOL_OPTIONS="-javaagent:/home/ubuntu/java-simple/opentelemetry-javaagent.jar" \
OTEL_TRACES_EXPORTER=logging \
OTEL_METRICS_EXPORTER=logging \
OTEL_LOGS_EXPORTER=logging \
OTEL_METRIC_EXPORT_INTERVAL=15000
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 23

Step #6:Run and Verify OpenTelemetry Instrumentation

Finally, run the application to start capturing telemetry data.

java -jar ./build/libs/java-simple-0.0.1-SNAPSHOT.jar
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 24

The application is now running, lets access it again at http://<EC2-Instance-IP>:8080/rolldice.

Integrate OpenTelemetry for PHP Application with Zero-Code Instrumentation 16

The OpenTelemetry Java Agent should now be generating logs for traces, metrics, and other telemetry data in the console. Verify this output to confirm the application is instrumented.

Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 25
Instrumenting Java Application with Gradle Using OpenTelemetry Java Agent 26

Conclusion:

In this article, we configured a Java application with Gradle and integrated OpenTelemetry using the Java Agent for seamless observability. Gradle is a powerful tool that simplifies the process of building and managing Java projects. OpenTelemetry provides powerful tools for observability, allowing developers to gain insights into application performance by collecting telemetry data such as traces, metrics, and logs. This setup allows you to monitor, trace, and gather performance insights effortlessly.

Related Articles:

How to Build Spring Boot Project Using Gradle

Reference:

Official Opentelemetry Page

Prasad Hole

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Share via
Copy link
Powered by Social Snap