Automatically instruments 3rd-party libraries in Java applications
SpecialAgent automatically instruments Java applications to produce trace events via the OpenTracing API. This file contains the operational instructions for the use of SpecialAgent.
- 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.jmsv1 & v2) - Elasticsearch6 Client
When SpecialAgent attaches to an application, either statically or dynamically, it will automatically load the OpenTracing 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 must allow any Java 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 plugin 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 plugin. This test must simulate:
- Launch the test in a process simulating the
-javaagentvm 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
Tracerinstances viaGlobalTracer, or initialize aMockTracerif no instance is specified. The test must provide a reference to theTracerinstance in the test method for assertions with JUnit. The SpecialAgent must provide a means by which instrumentation plugins can be configured before use on a target application.
- Launch the test in a process simulating the
- The SpecialAgent is not designed to modify application code, beyond the installation of OpenTracing instrumentation plugins. For example, there is no facility for dynamically tracing arbitrary code.
The SpecialAgent has 2 artifacts: main and test. These artifacts are built by Maven, and can be created by cloning this repository and following the Building instructions. These artifacts can also be downloaded directly from Maven's Central Repository.
-
RELEASE:
opentracing-specialagent-0.9.0.jar
SNAPSHOT:opentracing-specialagent-0.9.1-SNAPSHOT.jarThis is the main artifact that contains within it all applicable instrumentation plugins from the opentracing-contrib organization. This JAR can be specified as the
-javaagenttarget 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-0.9.0-tests.jar
SNAPSHOT:opentracing-specialagent-0.9.1-SNAPSHOT-tests.jarThis 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 instrumentation plugin implementation. For direction with theAgentRunner, please refer to theopentracing-specialagent-apimodule.
The SpecialAgent uses Java’s Instrumentation interface 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-0.9.0.jar -jar myapp.jarThis 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
PIDof the target application:jps
-
For jdk1.8
java -Xbootclasspath/a:$JAVA_HOME/lib/tools.jar -jar opentracing-specialagent-0.9.0.jar <PID>
-
For jdk9+
java -jar opentracing-specialagent-0.9.0.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
@Configannotation 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.propertiesfile that defines default values for properties that need to be defined.
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}.enabled=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.
The SpecialAgent is built in 2 profiles:
-
The
defaultprofile is used for development of plugins. It builds and runs tests for each plugin, but does not put the plugins inopentracing-specialagent-0.9.0.jarTo run this profile:
mvn clean package
-
The
assembleprofile is used for packaging of plugins into theopentracing-specialagent-0.9.0.jar. It builds each plugin, but does not run their tests. Once the build with theassembleprofile is finished, theopentracing-specialagent-0.9.0.jarwill contain the built plugins inside it.Note: If you do not run this step, the
opentracing-specialagent-0.9.0.jarfrom the previous step will not contain any instrumentation plugins within it!Note: It is important to not run Maven's
cleanlifecycle when creating theassemblepackage.To run this profile:
mvn -Dassemble package
-
For a one-line build command to build SpecialAgent, its plugins, run all tests, and create the
assemblepackage:mvn clean package && 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.
