Automatically instruments 3rd-party libraries in Java applications
This file contains the operational instructions for the use and development of SpecialAgent.
A Java agent that automatically instruments distinct 3rd-party libraries in Java applications via the OpenTracing API.
Vendor implementation of the io.opentracing.Tracer
interface.
Examples:
Tracers ARE NOT coupled to the SpecialAgent.
A bridge providing automatic discovery of Tracers in a runtime instrumented with the OpenTracing API. This bridge implements the TracerFactory
interface of TracerResolver, and is distributed as a single "fat JAR" that can be conveniently added to the classpath of a Java process.
Tracer Plugins ARE NOT coupled to the SpecialAgent.
An OpenTracing Instrumentation project that exist as individual repositories under opentracing-contrib.
Examples:
Instrumentation Plugins ARE NOT coupled to the SpecialAgent.
A submodule of the SpecialAgent that implements the auto-instrumentation rules for Instrumentation Plugins via the opentracing-specialagent-api
.
Examples:
rules/opentracing-specialagent-okhttp
rules/opentracing-specialagent-jdbc
rules/opentracing-specialagent-jms-1
rules/opentracing-specialagent-jms-2
Instrumentation Rules ARE coupled to the SpecialAgent.
These plugins have Instrumentation Rules implemented.
- OkHttp3
- JDBC API (
java.sql
) - Concurrent API (
java.util.concurrent
) - Java Web Servlet API (
javax.servlet
) - Mongo Driver
- Apache Camel
- AWS SDK
- Cassandra Driver
- JMS API (
javax.jms
v1 & v2) - Elasticsearch6 Client
- RxJava 2
- Kafka Client
- AsyncHttpClient
- RabbitMQ Client
- The SpecialAgent must allow any Instrumentation Plugin available in opentracing-contrib to be automatically installable in applications that utilize a 3rd-party library for which an Instrumentation Plugin exists.
- The SpecialAgent must automatically install the Instrumentation Plugin for each 3rd-party library for which a module exists, regardless in which class loader the 3rd-party library is loaded.
- The SpecialAgent must not adversely affect the runtime stability of the application on which it is intended to be used. This goal applies only to the code in the SpecialAgent, and cannot apply to the code of the Instrumentation Plugins made available in opentracing-contrib.
- The SpecialAgent must support static and dynamic attach to applications running on JVM versions 1.7, 1.8, 9, and 11.
- The SpecialAgent must implement a lightweight test methodology that can be easily applied to a module that implements instrumentation for a 3rd-party library. This test must simulate:
- Launch the test in a process simulating the
-javaagent
vm argument that points to the SpecialAgent (in order to test auto-instrumentation functionality). - Elevate the test code to be executed from a custom class loader that is disconnected from the system class loader (in order to test bytecode injection into an isolated class loader that cannot resolve classes on the system classpath).
- Allow tests to specify their own
Tracer
instances viaGlobalTracer
, or initialize aMockTracer
if no instance is specified. The test must provide a reference to theTracer
instance in the test method for assertions with JUnit.
- Launch the test in a process simulating the
- The SpecialAgent must provide a means by which Instrumentation Plugins can be configured before use on a target application.
- The SpecialAgent is not designed to modify application code, beyond the installation of Instrumentation Plugins. For example, there is no facility for dynamically tracing arbitrary code.
When SpecialAgent attaches to an application, either statically or dynamically, it will automatically load the Instrumentation Plugins explicitly specified as dependencies in its POM.
Any exception that occurs during the execution of the bootstrap process will not adversely affect the stability of the target application. It is, however, possible that the Instrumentation Plugin code may result in exceptions that are not properly handled, and could destabilize the target application.
The SpecialAgent has 2 artifacts: main and test. These artifacts are built by Maven, and can be obtained by cloning this repository and following the Building instructions, or downloading directly from Maven's Central Repository.
-
RELEASE:
opentracing-specialagent-1.0.2.jar
SNAPSHOT:opentracing-specialagent-1.0.3-SNAPSHOT.jar
This is the main artifact that contains within it the Instrumentation Plugins from the opentracing-contrib organization for which Instrumentation Rules have been implemented. This JAR can be specified as the
-javaagent
target for static attach to an application. This JAR can also be executed, standalone, with an argument representing the PID of a target process to which it should dynamically attach. Please refer to Usage section for usage instructions. -
RELEASE:
opentracing-specialagent-1.0.2-tests.jar
SNAPSHOT:opentracing-specialagent-1.0.3-SNAPSHOT-tests.jar
This is the test artifact that contains within it the
AgentRunner
, which is a JUnit runner class provided for testing of the ByteBuddy auto-instrumentation rules. This JAR does not contain within it any Instrumentation Plugins themselves, and is only intended to be applied to the test phase of the build lifecycle of a single plugin for an Instrumentation Plugin implementation. For direction with theAgentRunner
, please refer to theopentracing-specialagent-api
module.
The SpecialAgent uses Java’s Instrumentation mechanism to transform the behavior of a target application. The entrypoint into the target application is performed via Java’s Agent convention. SpecialAgent supports both static and dynamic attach.
Statically attaching to a Java application involves the use of the -javaagent
vm argument at the time of startup of the target Java application. The following command can be used as an example:
java -javaagent:opentracing-specialagent-1.0.2.jar -jar myapp.jar
This command statically attaches SpecialAgent into the application in myapp.jar
.
Dynamically attaching to a Java application involves the use of a running application’s PID, after the application’s startup. The following commands can be used as an example:
-
Call this to obtain the
PID
of the target application:jps
-
For jdk1.8
java -Xbootclasspath/a:$JAVA_HOME/lib/tools.jar -jar opentracing-specialagent-1.0.2.jar <PID>
-
For jdk9+
java -jar opentracing-specialagent-1.0.2.jar <PID>
The SpecialAgent exposes a simple pattern for configuration of SpecialAgent, the Instrumentation Plugins, as well as Tracer Plugins. The configuration pattern is based on system properties, which can be defined on the command-line, in a properties file, or in @AgentRunner.Config:
-
Properties passed on the command-line via
-D${PROPERTY}=...
override same-named properties defined in layers below. -
The @AgentRunner.Config annotation allows one to define log level and transformation event logging settings. Properties defined in the
@Config
annotation override same-named properties defined in layers below. -
The
-Dconfig=${PROPERTIES_FILE}
command-line argument can be specified to have the SpecialAgent load property names from a${PROPERTIES_FILE}
. Properties defined in the${PROPERTIES_FILE}
override same-named properties defined in the layer below. -
The SpecialAgent has a
default.properties
file that defines default values for properties that need to be defined.
The SpecialAgent supports 2 ways to connect to a OpenTracing-compatible tracer:
-
Internal Tracer Plugins
The SpecialAgent includes the collowing Tracer Plugins:
The
-Dsa.tracer=${TRACER_PLUGIN}
property is used on the command-line to specify which Tracer Plugin will be used. The value of${TRACER_PLUGIN}
is the short name of the Tracer Plugin, i.e.jaeger
orlightstep
. -
External Tracer Plugins
The SpecialAgent allows external Tracer Plugins to be attached to the runtime.
The
-Dsa.tracer=${TRACER_JAR}
property is used on the command-line to specify the JAR path of the Tracer Plugin to be used. The${TRACER_JAR}
must be a JAR that conforms to theTracerFactory
API of the TracerResolver project.
NOTE: If a tracer is not specified with the -Dsa.tracer=...
property, the SpecialAgent will present a warning in the log that states: Tracer NOT RESOLVED
.
The SpecialAgent allows Instrumentation Plugins to be disabled. To disable a plugin, specify a system property, either on the command-line or in the properties file referenced by -Dconfig=${PROPERTIES_FILE}
.
${PLUGIN_NAME}.enable=false
The value of ${PLUGIN_NAME}
is the artifactId
of the plugin as it is included in the SpecialAgent, such as opentracing-specialagent-okhttp
or opentracing-specialagent-web-servlet-filter
.
Prerequisite: The SpecialAgent requires Oracle Java to build successfully.
The SpecialAgent is built in 2 passes that utilize different profiles:
-
The
default
profile is used for development of Instrumentation Rules. It builds and runs tests for each rule, but does not bundle the rules intoopentracing-specialagent-1.0.2.jar
To run this profile:
mvn clean install
-
The
assemble
profile is used to bundle the Instrumentation Rules intoopentracing-specialagent-1.0.2.jar
. It builds each rule, but does not run tests. Once the build with theassemble
profile is finished, theopentracing-specialagent-1.0.2.jar
will contain the built rules inside it.Note: If you do not run this step, the
opentracing-specialagent-1.0.2.jar
from the previous step will not contain any Instrumentation Plugins within it!Note: It is important to not run Maven's
clean
lifecycle when executing theassemble
profile.To run this profile:
mvn -Dassemble package
-
For a one-line build command to build SpecialAgent, its rules, run all tests, and create the
assemble
package:mvn clean install && mvn -Dassemble package
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
This project is licensed under the Apache 2 License - see the LICENSE.txt file for details.