Java

How to setup recording & monitoring for Java applications

Requirements

To enable RevDeBug in your Java application you will need to:

Adding RevDeBug repository

Add the following lines to the super pom.xml / build.gradle file in the Java application main node:

pom.xml
<project>
 ...
  <repositories>
     <repository>
        <id>rdb-repo</id>
        <name>RevDeBug Maven Repo</name>
        <url>https://release.revdebug.com/repository/maven</url>
     </repository>
  </repositories>
 ...
</project>

Adding RevDeBug dependency

Add the following lines to the super pom.xml / build.gradle file in the Java application main node:

pom.xml
 <project>
    ...
    <dependencies>
            <dependency>
                <groupId>com.revdebug</groupId>
                <artifactId>revdebug-compiler</artifactId>
                <version>7.2.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.revdebug</groupId>
                <artifactId>revdebug-runtime</artifactId>
                <version>7.2.0</version>
            </dependency>
    ...
</project>

For spring-boot projects additional exclusion in pom.xml is needed (without it build time dependencies will be packaged with application):

pom.xml
<project>
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>com.revdebug</groupId>
                            <artifactId>revdebug-compiler</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        ...
        </plugins>
    </build>    
    ...
</project>

Configure the connection to RevDeBug Server

RevDeBug can be easily added to all projects in the working directory. But if you want, you can add RevDeBug to the selected subset. In the examples below substitute [SERVER_ADDRESS] for actual fully qualified domain address of RevDeBug server.

pom.xml
<project>
 ...
 <plugins>
   <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-compiler-plugin</artifactId>
       <version>3.8.1</version>
       <configuration>
           <compilerArgs>
               <arg>-Xplugin:RevDeBugCompiler</arg>
               <arg>-AREVDEBUG_SERVER_HOSTNAME=[SERVER_ADDRESS]</arg>
               <arg>-AREVDEBUG_SECURE_CONNECTION=false</arg>
           </compilerArgs>
           <source>1.8</source>
           <target>1.8</target>
       </configuration>
   </plugin>
</plugins>
...
</project>

Spring Boot Starter Parent

If you are using a spring-boot-starter-parent, make sure its version is equal to or greater than 1.4.0, earlier versions are not supported.

pom.xml
<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>1.4.0.RELEASE</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>

Additional configuration for Java 17+

Starting from Java 17 you need to add additional exports to JVM arguments.

Requirements:

  • Gradle 7+ or Maven

For Gradle, create or edit gradle.properties in your project's root directory by adding:

gradle.properties
org.gradle.jvmargs = --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
                     --add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
                     --add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \
                     --add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED \
                     --add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
                     --add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \
                     --add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
                     --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
                     --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
                     --add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED

Adding --add-exports directly in build.gradle file wouldn't work - it is a known Gradle issue (link).

For Maven, create .mvn directory in the project's root directory (or in the user's $HOME directory) and create a jvm.config file in it with the following contents:

jvm.config
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED

Settings overview

There are configurable fields in the connection section of RevDeBug DevOps Monitor:

Add RevDeBug Java Agent

  • Download java-agent from nexus repo:

  • Unzip the archive and modify config/agent.config file

    • agent.service_name set to your app name

      • If you want to group applications in the services view, add a group name before your application name, according to this scheme: group_name::application_name.

    • collector.backend_service set to point to your record server instance

    • agent.force_tls set to true if your RevDeBug DevOps Monitor instance has been configured to work with an SSL certificate.

    • agent.instance_name set to your instance name. The instance name serves as the unique identifier for an instance within the service. In case it is left empty, the agent will generate a 32-bit UUID. By default, the instance name is set as UUID@hostname. The maximum allowed length is 50 characters (UTF-8 encoding). For example, if you want to name your instance my-instance-001 you can use the environment variable: SW_AGENT_INSTANCE_NAME=my-instance-001

  • Attach unzipped agent to your app with java argument: -javaagent:[Path-to-unzipped-agent]/agent/skywalking-agent.jar

Trace sampling

  • agent.sample_n_per_3_secs is a parameter related to an agent that employs a sampling method within a specific time interval. It determines the number of sampled traces the agent will collect within a duration of 3 seconds.

    Defaults to: 100

    Example value: 12

    Range: -1 to 2147483647

  • agent.sample_percentage, similar to sample_n_per_3_secs, is responsible for trace sampling. However, in this case, sampling is not time-dependent; instead, it is based solely on a percentage probability.

    Defaults to: -1

    Example value: 30

    Range: -1 to 100

To turn off agent.sample_n_per_3_secs or agent.sample_percentage set the value to 0 or -1.

In case both limits are set sample_n_per_3_secs acts as the top limit whilst the traces below this limit will still be sampled according to the percentage set in sample_percentage

Ignoring Paths in Distributed Tracing

The entire trace ignore process is defined in the ./config/apm-trace-ignore-plugin.config file

To understand and configure the option for ignoring paths in distributed tracing, we must comprehend the syntax and path matching patterns.

Syntax

The trace.ignore_path option allows you to define a list of path patterns that should be ignored by the distributed tracing system. Here is the syntax of this option:

trace.ignore_path=pattern1,pattern2,pattern3,...

Where pattern1, pattern2, etc., are the path patterns to be ignored. These patterns are separated by commas.

Path Matching Patterns

Path matching patterns are used to specify which paths should be ignored by the tracing system. Here are the available patterns:

  • ** - Matches any sequence of characters (including empty strings) in the path and supports multi-level directories.

Default Values

If the trace.ignore_path an option is not configured, it takes the following default values:

trace.ignore_path=/webjars/**,/resources/**

This means that by default, the distributed tracing system will ignore all requests starting with /webjars/ or /resources/ and followed by any characters.

Custom Configurations

You can customize this behavior by configuring the trace.ignore_path option according to your needs. For example, if you want to add additional patterns to ignore, append them to the list, separated by commas:

trace.ignore_path=/webjars/**,/resources/**,/eureka/**,/consul/**

In the above example, additional patterns were added also to ignore requests starting with /eureka/ and /consul/.

Make sure to thoroughly test your changes to avoid unexpected behavior in the tracing system.

In general, the trace.ignore_path option allows for more precise control over which requests are ignored by the tracing system, which can be useful in certain scenarios, such as requests related to static resources.

Controlling RevDeBug with environment variables

Put RevDeBug in Standby mode

Once the application is compiled with RevDeBug it reports exceptions and traces to the RevDeBug server. If you want to put RevDeBug in standby mode you have to set those environment variables and restart your application:

SW_AGENT_ACTIVE=false
REVDEBUG_RECORDING_MODE=noop

Disable RevDeBug from instrumenting application

If you want to completely disable RevDeBug from attaching to your application during compilation you can set the following environment variable on your build server and recompile:

REVDEBUG_DISABLE_ALL=true

Last updated