Java Agent for OpenTracing
Java Agent for instrumenting Java applications using an OpenTracing compliant Tracer.
The instrumentation is performed in a non-intrusive manner leveraging the ByteMan project to define a set of rules. These rules can be used in three ways:
-
Directly instrument a technology/framework (e.g. java.net.HttpURLConnection)
-
Install a framework integration (e.g. OkHttp, Servlet)
-
Define custom rules specific to an application (e.g. create spans to scope important internal units of work, or add tags to an existing span to identify business relevant properties)
Usage
The Java Agent for OpenTracing obtains an OpenTracing compliant Tracer using the Global Tracer project. It makes use of the Span Manager project to manage the propagation of active Spans through various frameworks and technologies used by the application - which can also be used by the application code to access the current active span to add tags or create its own Spans.
The Java Agent can be used in two ways:
Prepackaged Agent, Tracer and Dependencies
This approach is to build an uber jar, using the maven assembly or shade plugins, to package together
the opentracing-agent.jar
, the OpenTracing compliant Tracer
, any framework integrations, rules, etc.
The important point to remember is that, because the resulting jar will still be used as a javaagent, it needs the
manifest entries copied from the manifest in the opentracing-agent.jar
.
This approach is useful when wanting to instrument applications where modification of the classpath is not possible (e.g. executable jars), or wanting to maintain separation between the application and the tracing mechanism. It also benefits from being able to selective choose the framework integrations (and versions) that are required.
NOTE: An issue has been created to discuss providing tool support for this option.
Tracer and Framework Integrations on Classpath
This approach uses the plain opentracing-agent.jar
provided by this project, and obtains the OpenTracing
Tracer and any required framework integrations, rules, etc. from the classpath.
java -javaagent path/to/opentracing-agent.jar ...
Examples
This section lists examples of using the OpenTracing Java Agent.
- Spring Boot services (OpenTracing Tracer: Hawkular APM)
Creating custom rules
Custom rules are defined using the ByteMan rule format. These rules use a helper class (io.opentracing.contrib.agent.OpenTracingHelper) that provides access to the OpenTracing Tracer, as well as some additional support capabilities.
The custom rules should be placed in a file on the classpath called otarules.btm
.
Some example rules are:
RULE Custom instrumentation rule sayHello entry
CLASS example.MyClass
METHOD sayHello()
HELPER io.opentracing.contrib.agent.OpenTracingHelper
AT ENTRY
IF TRUE
DO
activateSpan(getTracer().buildSpan("MySpan").start());
ENDRULE
The first line defines the name of the rule. The second identifies the target class, although it is also possibly to specify an interface (using the INTERFACE keyword). The third line identifies the method name (optionally specifying the parameter types).
The AT clause identifies the point at which the identified method will be instrumented. ENTRY means that the rule should be applied at the beginning of the method (see ByteMan documentation for other locations).
The IF statement enables a predicate to be defined to guard whether the rule is performed.
The DO clause identifies the actions to be performed when the rule is triggered.
The getTracer()
method (provided by the OpenTracingHelper) is used to access the OpenTracing
compliant Tracer
. The helper class also provides methods for managing the current active span
(i.e. activateSpan
).
NOTE: Span management is being actively discussed in the OpenTracing standard so this area may change in the near future.
RULE Custom instrumentation rule sayHello exit
CLASS example.MyClass
METHOD sayHello()
HELPER io.opentracing.contrib.agent.OpenTracingHelper
AT EXIT
IF currentSpan() != null
DO
currentSpan().setTag("status.code","OK").finish();
deactivateCurrentSpan();
ENDRULE
This rule will trigger AT EXIT, so when the method is finished. The IF statement checks whether there is a current span, so will only trigger if an active span exists.
The actions performed in this case are to set a tag status.code on the current span, and then finish it. Finally the current span needs to be deactivated so that it is no longer considered the active span.
Supported framework integrations and directly instrumented technologies
Frameworks
NOTE: Currently the ByteMan rules for installing tracing filters/interceptors into the following frameworks is contained in this repository. However in the future the aim would be to move the rules to their associated framework integration projects, meaning that the rules would be detected only when the integration artifact is added to the classpath.
Servlet
Framework integration repo: Web Servlet Filter
Currently supported containers:
-
Jetty
-
Tomcat
OkHttp
Framework integration repo: OkHttp
Directly instrumented technologies
HttpURLConnection
The instrumentation rules for HttpURLConnection will only create a Span if the connection does not have a request property opentracing.ignore. This is to avoid REST calls, used to report tracing information to a server, resulting in further trace information being reported. Therefore any Tracer implementations that use HttpURLConnection to report their data to the server should ensure the connections have this request property.
It is also possible to include a custom rule to add such a property:
RULE Ignore server communications
CLASS java.net.URL
METHOD openConnection
HELPER io.opentracing.contrib.agent.OpenTracingHelper
AT EXIT
IF $0.getPath().startsWith("/TracerServerPath")
DO
$!.setRequestProperty("opentracing.ignore","true");
ENDRULE
Development
./mvnw clean install
If using JDK9, you will need to set the MAVEN_OPTS as follows:
MAVEN_OPTS="--add-modules java.se.ee" ./mvnw clean install
Release
Follow instructions in RELEASE