Pull requests for bug fixes are welcome, but before submitting new features or changes to current functionality open an issue and discuss your ideas or propose the changes you wish to make. After a resolution is reached a PR can be submitted for review.
In order to fully build and test this whole repository you need the following:
java -version
should give you version 8.JAVA_8_HOME
and JAVA_9_HOME
which point to the corresponding java homes.OpenTelemetry Auto Instrumentation java agent's jar can logically be divided into 3 parts.
java-agent
moduleThis module consists of single class io.opentelemetry.auto.bootstrap.AgentBootstrap
which implements Java instrumentation agent.
This class is loaded during application startup by application classloader.
Its sole responsibility is to push agent's classes into JVM's bootstrap classloader
and immediately delegate to io.opentelemetry.auto.bootstrap.Agent
(now in the bootstrap class loader) class from there.
agent-bootstrap
moduleThis module contains support classes for actual instrumentations to be loaded later and separately.
These classes should be available from all possible classloaders in the running application.
For this reason java-agent
puts all these classes into JVM's bootstrap classloader.
For the same reason this module should be as small as possible and have as few dependencies as possible.
Otherwise, there is a risk of accidentally exposing this classes to the actual application.
agent-tooling
module and instrumentation
submodulesContains everything necessary to make instrumentation machinery work, including integration with ByteBuddy and actual library-specific instrumentations. As these classes depend on many classes from different libraries, it is paramount to hide all these classes from the host application. This is achieved in the following way:
java-agent
module builds the final agent, it moves all classes from instrumentation
submodules
and agent-tooling
module into a separate folder inside final jar file, called auto-tooling-and-instrumentation.isolated
.
In addition, the extension of all class files is changed from class
to classdata
.
This ensures that general classloaders cannot find nor load these classes.io.opentelemetry.auto.bootstrap.Agent
starts up,
it creates an instance of io.opentelemetry.auto.bootstrap.AgentClassLoader
,
loads an io.opentelemetry.auto.tooling.AgentInstaller
from that AgentClassLoader
and then passes control on to the AgentInstaller
(now in the AgentClassLoader
). The AgentInstaller
then installs all of the instrumentations with the help of ByteBuddy.The complicated process above ensures that the majority of auto-instrumentation agent's classes are totally isolated from application classes, and an instrumented class from arbitrary classloader in JVM can still access helper classes from bootstrap classloader.
If you now look inside java-agent/build/libs/opentelemetry-auto-<version>.jar
,
you will see the following "clusters" of classes:
auto-tooling-and-instrumentation.isolated/
- contains agent-tooling
module and
instrumentation
submodules, loaded and isolated inside AgentClassLoader
.
Including OpenTelemetry SDK.io/opentelemetry/auto/bootstrap/
- contains agent-bootstrap
module and available in
bootstrap classloader.io/opentelemetry/auto/shaded/
- contains OpenTelemetry API and its dependencies.
Shaded during creation of java-agent
jar file by Shadow Gradle plugin.Open Telemetry Auto Instrumentation's minimal supported version is java 7. All jar files that we produce, unless noted otherwise, have bytecode compatible with java 7 runtime. In addition to that we test our code with all later java versions as well: from 8 to 14.
Some libraries that we auto-instrument may have higher minimal requirements. In this case we compile and test corresponding auto-instrumentation with higher java version as required by library. The resulting classes will have higher bytecode level, but as it matches library's java version, no runtime problem arise.
Executing ./gradlew instrumentation:test
will run tests for all supported auto-instrumentations
using that java version which runs the Gradle build itself.
These tests usually use the minimal supported version of the instrumented library.
In addition to that each instrumentation has a separate test set called latestDepTest
.
It was created by Gradle test sets plugin.
It uses the very same tests as before, but declares a dynamic dependency on the latest available version of this library.
You can run them all by executing ./gradlew latestDepTest
.
In order to run tests on a specific java version, just execute ./gradlew testJava7
(or testJava11
or latestDepTestJava14
etc).
Then Gradle task rule will kick in and do the following:
JAVA_N_HOME
, where N
is the requested java versionThis works both for tasks named test
and latestDepTest
.
But currently does not work for other custom test tasks, such as those created by test sets plugin.
We follow the Google Java Style Guide. Our build will fail if source code is not formatted according to that style.
To verify code style manually run the following command, which uses google-java-format library:
./gradlew verifyGoogleJavaFormat
or on Windows
gradlew.bat verifyGoogleJavaFormat
Instead of fixing style inconsistencies by hand, you can run gradle task googleJavaFormat
to automatically fix all found issues:
./gradlew googleJavaFormat
or on Windows
gradlew.bat googleJavaFormat
To completely delegate code style formatting to the machine,
you can add git pre-commit hook.
We provide an example script in buildscripts/pre-commit
file.
Just copy or symlink it into .git/hooks
folder.
As additional convenience for IntelliJ Idea users, we provide .editorconfig
file.
Idea will automatically use it to adjust its code formatting settings.
It does not support all required rules, so you still have to run googleJavaFormat
from time to time.
Required plugins:
Suggested plugins and settings: