Java Agent
Drill4J Java Agent is a runtime agent for JVM-based applications that provides deep observability into your testing process and codebase evolution.
Key capabilities:
- Code Coverage Measurement — collects precise code coverage data from running applications, giving teams visibility into which parts of the codebase are exercised by tests.
- Test Tracing & Test-to-Code Mapping — establishes bidirectional traceability between tests and the code they execute, enabling you to determine exactly which tests cover a given method and which code paths a specific test exercises.
- Context Propagation — automatically propagates test context across threads, asynchronous calls, HTTP requests, messaging systems (Kafka), ensuring accurate coverage attribution even in distributed and reactive architectures.
- Code Change Detection — identifies structural changes between application builds at the method level, powering intelligent test recommendations that highlight only the tests affected by recent changes.
General integration steps are:
Due to the diverse tools used in software development — such as CI/CD providers, deployment methods, testing stages — the exact process will depend on the environment.
How to download#
Download agent files manually#
The most basic way to get agent files is to download release .zip manually.
Download release appropriate for your platform at
https://github.com/Drill4J/java-agent/releases/tag/v0.9.20mingwX64is for Windows, Linux and Mac releases are called respectively.If your platform is not listed above, use the Java agent mode instead of native mode.
Unzip the file. Rename unzipped folder to
agent.Inside you'll find the following files:
libdrill_agent.so(on Windows -.dll, on Mac -.dylib)drill-runtime.jardrill.properties
Refer to next section for further steps.
Use Docker image with a download script#
Use case: when you are already using Docker Compose to start your application.
We provide a small Docker image, that executes download script upon startup.
The way it works is:
- You add our container to your docker-compose.yml file, passing the desired version to
JAVA_AGENTenv variable. - On startup, the container launches the download script.
- Docker's healthcheck waits for it to complete.
- Downloaded agent files are placed in a shared volume.
- Shared volume is mounted to your application's container.
See the example docker-compose.yml file for details.
Use Drill4J CI/CD Integration Plugin for Maven and Gradle#
Use cases: when application (or certain classes of application) is launched with Maven or Gradle. That's most often the case with Unit tests.
Drill4J CI/CD Integration Plugin automatically downloads agent files and passes required parameters to Java.
Because of that, the next sections of this page are irrelevant in this scenario. Instead, please refer to CI/CD Integration Plugin page for more info.
How to set path to agent#
To load Drill4J Java Agent, you need to instruct Java Virtual Machine (JVM) to use agent files. Drill4J has two modes of loading:
- Native mode - uses native library file (
.so,.dll,.dylib) - Java mode - uses
drill-runtime.jarfile
Depending on mode you choose, the way to set path to agent differs.
Native Agent Mode#
Java allows to load native agents using special command line argument:
Where <path-to-agent> must point to native agent library file (.so, .dll, .dylib).
Note: If you have any issues with native mode, you can switch to Java mode described in the next section.
Java Agent Mode#
If your platform is not supported with native library, you can use Java mode. To load Drill4J Java Agent in Java mode, use the following command line argument:
Where <path-to-drill-runtime-jar> must point to drill-runtime.jar file.
Setting agent path for applications#
Pass agent path argument directly to Java process#
Use case: when you have a direct access to Java's process launch arguments.
Considering your application is launched with:
Change it to:
Set agent path to JAVA_TOOL_OPTIONS env variable#
Use case: when you don't have direct access to the Java's process launch arguments. It's often the case when app is launched somewhere deep in scripts or inside Docker container.
Use JAVA_TOOL_OPTIONS to instruct Java to use Drill4J Java Agent. Its a built-in env variable supported by any Java version.
Setting agent path for tests#
In order to pass -agentpath command-line argument when running tests, you can configure the argLine for Maven
or jvmArgs for Gradle parameters.
There are two ways to pass -agentpath parameter:
- In command line for running tests
- Inside the build configuration file
Note: If you're using Maven or Gradle to run tests, consider using Drill4J CI/CD Integration Plugin instead. It handles agent configuration automatically without requiring manual parameter setup.
Pass -agentpath in command line for running tests#
Gradle#
Add -DjvmArgs parameter to gradle command line:
Maven#
Add -DargLine parameter to Maven command line:
Set -agentpath in the build configuration file#
Gradle#
Add jvmArgs to Gradle test configuration:
Maven#
Add argLine to maven-surefire-plugin in pom.xml:
Troubleshooting#
To ensure you set agentpath correctly see how to confirm agent is loaded section below.
How to set agent parameters#
Drill4J agent supports 3 ways to set agent parameters.
Set parameters using environment variables#
This is the recommended way to set agent parameters.
Env variables names are prefixed with DRILL_ with uppercase snake case. Examples:
- Given
packagePrefixesparameter the env variable isDRILL_PACKAGE_PREFIXES
Precedence: parameter values set with env variables have the highest precedence and will override values set in -agentpath string or drill.properties file.
Set parameters in -agentpath argument string#
Append parameters to -agentpath or -javaagent argument string. Add =<options> after <path-to-agent>:
Example:
Parameters are:
- passed after
<path-to-agent>(/agent/libdrill_agent.soabove) - start of parameters string is indicated with
=sign - parameters are
<key>=<value>pairs - each pair is separated by comma.
Precedence: parameter values set with -agentpath or -javaagent will override values set in drill.properties
Set parameters in drill.properties file#
Alternatively, Drill4J agent checks for values in drill.properties file. By default it is downloaded with agent files.
It adheres to the properties file syntax
Precedence: parameter values set in drill.properties file have the lowest precedence and can be overriden by -agentpath and env variables.
Agent parameters reference#
General Configuration#
| Parameter | Required | Example Value | Description |
|---|---|---|---|
| apiUrl | yes | http://localhost/api | URL to Drill4J Admin /api endpoint. |
| apiKey | yes | 1_01cdf51ff20544ee... | Drill4J Backend API key. Generate it using Drill4J UI. Please make sure to read the apiKey security section. |
| groupId | yes | my-cool-app | Unique arbitrary string identifying your application group. |
| appId | yes | api-service | Unique arbitrary string identifying your application. |
| packagePrefixes | yes | my/org/somecoolapp | Specifies the packages for Drill4J to monitor. See syntax and examples below. |
| buildVersion | recommended | v1.2.3 | Build version of your application. Typically set to version tag. See more. |
| commitSha | recommended | 8d87b0c2379a925... | Full SHA hash of commit from which your application .jar is built from. See more. |
| envId | no | develop | Environment identifier in which the application is running. |
| messageQueueLimit | no | 512Mb | Maximum queue capacity for sending messages to Drill4J Backend. The queue may accumulate, for example, if the server is unavailable. If none is specified, the default value is 512Mb. |
| messageMaxRetries | no | 10 | Maximum number of retries for sending messages to Drill4J Backend. If nothing is specified, there will be infinite attempts to send messages. |
| coverageCollectionEnabled | no | false | Enables or disables application code coverage collection. Default is true. |
Application Class Scanning#
| Parameter | Required | Example Value | Description |
|---|---|---|---|
| classScanningEnabled | no | false | Enables or disables class scanning procedure. If none is specified, class scanning is enabled by default. |
| scanClassPath | no | build/libs/myapp-0.0.1.jar | Path(s) to application's .class/.jar/.war/.ear files. If none are specified, the agent attempts to find application classes automatically. See syntax and examples below. |
| enableScanClassLoaders | no | true | Enables scanning of active thread class loaders. When enabled, the agent scans all active threads, retrieves their class loaders, and scans the files loaded by each class loader. |
| scanClassDelay | no | 5000 | Time in milliseconds to delay before scanning active thread class loaders, allowing the system to fully initialize first. If none is specified, the scanning starts immediately upon JVM startup. |
Test Tracing Configuration#
| Parameter | Required | Example Value | Description |
|---|---|---|---|
| testTracingEnabled | no | true | Enables test tracing. If enabled, collected coverage will be associated with individual test or test session. Default is false. |
| testTracingPerTestSessionEnabled | no | true | Enables test tracing per test session. Default is true. |
| testTracingPerTestLaunchEnabled | no | true | Enables test tracing per test launch. Default is true. |
| testTaskId | no | check | Name of the test task or test command that was launched to run tests. Configured automatically. Override only in exceptional cases. |
| testSessionId | no | test-session-1 | Explicit test session identifier. Configured automatically. Override only in exceptional cases. |
Recommended Tests#
| Parameter | Required | Description |
|---|---|---|
| recommendedTestsEnabled | no | Enables Test Recommendations. |
| recommendedTestsCoveragePeriodDays | no | Period of days for which coverage data is taken into account for test recommendations. |
| recommendedTestsTargetAppId | no | ID of the application under test. |
| recommendedTestsTargetCommitSha | no | Commit SHA of the application under test. |
| recommendedTestsTargetBuildVersion | no | Application under test version. |
| recommendedTestsBaselineCommitSha | no | Baseline commit SHA of the application under test. |
| recommendedTestsBaselineBuildVersion | no | Application under test baseline version. |
Instrumentation Parameters#
These parameters control which frameworks and protocols the agent instruments for context propagation.
| Parameter | Required | Default | Description |
|---|---|---|---|
| instrumentationEnabled | no | true | Enables or disables all instrumentation. |
| contextPropagationEnabled | no | true | Enables or disables context propagation. |
| instrumentationReactorEnabled | no | true | Enables instrumentation for Project Reactor. |
| instrumentationTtlEnabled | no | true | Enables instrumentation for Transmittable Thread Local (TTL). |
| instrumentationKafkaEnabled | no | false | Enables instrumentation for Apache Kafka. |
| instrumentationCadenceEnabled | no | false | Enables instrumentation for Uber Cadence. |
| instrumentationWsEnabled | no | false | Enables instrumentation for WebSocket connections. |
| instrumentationHttpEnabled | no | true | Enables instrumentation for HTTP server connections. |
| instrumentationSslEnabled | no | true | Enables instrumentation for SSL/TLS connections. |
| instrumentationJavaHttpClientEnabled | no | true | Enables instrumentation for Java's built-in HTTP client. |
| instrumentationApacheHttpClientEnabled | no | true | Enables instrumentation for Apache HTTP Client. |
| instrumentationOkHttpClientEnabled | no | true | Enables instrumentation for OkHttp Client. |
| instrumentationSpringWebClientEnabled | no | true | Enables instrumentation for Spring WebClient. |
| instrumentationJUnitEnabled | no | true | Enables instrumentation for JUnit. |
| instrumentationTestNGEnabled | no | true | Enables instrumentation for TestNG. |
| instrumentationCucumberEnabled | no | true | Enables instrumentation for Cucumber. |
| instrumentationSeleniumEnabled | no | true | Enables instrumentation for Selenium. |
| instrumentationJMeterEnabled | no | true | Enables instrumentation for JMeter. |
Env variables naming#
Environment variables start with the prefix DRILL_, followed by the parameter name in UPPERCASE_SNAKE_CASE.
Example:
- For
apiUrl, the env var isDRILL_API_URL. - For
packagePrefixes, the env var isDRILL_PACKAGE_PREFIXES.
How to set package prefixes#
packagePrefixes is the filter that specifies which packages Drill4J should monitor. It is usually set to the topmost common package of your application.
Avoid setting it to something very broad (like com or org) - otherwise you will be scanning and collecting metrics for third-party dependencies.
Syntax#
- Parts of package names are separated with forward slashes
/(and not dots.) - Multiple packages can be specified using
;delimiter - To exclude package use
!prefix.
Example#
Given you app packages are:
my.org.somecoolapp.usermy.org.somecoolapp.orders.repositorymy.org.somecoolapp.db.models
packagePrefixes parameter should be set to my/org/somecoolapp
Adding extra package#
Add package name separated by ; - my/org/somecoolapp;some/other/package.
This adds both my/org/somecoolapp and some.other.package to scanned packages.
Excluding package#
Add package name prefixed with ! - my/org/somecoolapp;!my.org.somecoolapp.db.models.
This adds my/org/somecoolapp to scanned packages, but excludes my.org.somecoolapp.db.models.
How to set scanClassPath#
Specifies path(s) for the agent to look for .jar, .war, or .ear files.
Useful when the agent is unable to locate these automatically (e.g. when running Wildfly or Tomcat).
API key security#
❗ Please avoid hardcoding apiKey and exposing it in plain text. Instead, use environment variables. ❗
Bad example:
Good example:
Considerations regarding buildVersion and commitSha#
Necessity: While
buildVersionandcommitShaare not strictly required, we recommend providing at least one (ideally both) for the following reasons:- It allows Drill4J to group metrics by version or commit.
- Without
buildVersionandcommitSha, Drill4J reports each application instance individually. Instances are identified with a random UUID.
Uniqueness: Both
buildVersionandcommitShaidentify a unique application version, each associated with a specific set of classes and methods.To maintain the integrity of metrics, ensure that different application versions do not share the same
buildVersionorcommitShavalues.Using identical values across different versions will lead to inaccurate metrics due to the mixing of unrelated data.
Semantics:
buildVersiontypically corresponds to the version tag of your application.Compliance with Semver is not required. Drill4J treats the build version as a unique string for grouping metrics, without any added semantics.
Troubleshooting#
How to confirm agent is loaded#
Once loaded Drill4J agent prints the following ASCII logo:
It indicates that you have configured agent path correctly and Java picked up and loaded agent files.
Cannot load the agent because some agent parameters are set incorrectly#
If below Drill4J ASCII logo you see the following message:
It indicates that you are missing some required parameters. Refer to the agent parameters section.
Error "Could not create an Appender of type ..."#
The following error can be safely ignored as it doesn't impact the functionality of the application or agent. It simply indicates that Logback is being used with a logback.xml file, which conflicts with the Drill4J logging configuration. However, logging will still function as expected.
Limitations and Known Issues#
- The Drill4J is not compatible with the JaCoCo code coverage tool. JaCoCo conflicts with the Drill4J Java Agent, so it needs to be removed. This shouldn't be a concern, as Drill4J includes the same functionality along with additional features.