-
Notifications
You must be signed in to change notification settings - Fork 599
MicroProfile: OpenTracing
The Eclipse MicroProfile (MP) project is an open collaboration between developers, the community, and vendors to create a programming model for microservices applications which is complementary to JEE.
The Eclipse MicroProfile OpenTracing project (MP OpenTracing) defines the specification and an API for tracing JAX-RS web service operations as they flow into, within, between, and out of servers. This trace information can be fed to OpenTracing-compliant distributed tracing systems such as Zipkin. Then, the distributed tracing systems may be used to display each JAX-RS call and how long it took, track performance, diagnose problems, feed load distribution algorithms, etc. This is particularly useful in a microservices architecture because such architectures often have many separate JVMs tied together with JAX-RS calls.
The MP OpenTracing project is largely a wrapper around the OpenTracing project which provides a vendor-neutral open standard for distributed tracing and MP OpenTracing uses parts of version 0.30.0 of OpenTracing's Java implementation.
Version 1.0 of MP OpenTracing was delivered as part of version 1.3 of the overall MicroProfile.
Important links:
- MP OpenTracing specification: https://github.com/eclipse/microprofile-opentracing/blob/master/spec/src/main/asciidoc/microprofile-opentracing.asciidoc
The Liberty OpenTracing Guide is a great walk-through of using OpenTracing in Liberty: https://openliberty.io/guides/microprofile-opentracing.html
OpenLiberty contains two features to support OpenTracing: opentracing-1.0
and mpOpenTracing-1.0
. opentracing-1.0
was delivered before the MP OpenTracing 1.0 specification was finalized, and mpOpenTracing-1.0
delivered the full specification compliance with OpenTracing 1.0. Therefore, unless a user is on a version of Liberty before mpOpenTracing-1.0
was released, users should just use mpOpenTracing-1.0
which is a superset of opentracing-1.0
and implicitly enables it. (Note: the feature microProfile-1.3
also implicitly enables mpOpenTracing-1.0
.)
To use MP OpenTracing in OpenLiberty, the user must create a user feature with a factory that returns an io.opentracing.Tracer implementation. IBM has created sample code for a user feature that connects to Zipkin. After the Tracer implementation has been properly installed as a user feature, mpOpenTracing-1.0
and the user feature must be enabled as features in server.xml
. For example:
<featureManager>
<feature>mpOpenTracing-1.0</feature>
<feature>usr:opentracingZipkin-0.30</feature>
</featureManager>
Additional configuration in server.xml
may be needed for the particular user feature.
The way the user feature works is that it uses an OpenLiberty Service Provider Interface through OpentracingTracerFactory to provide the Tracer implementation.
In addition to automatically tracing JAX-RS endpoints and clients, an application may additionally trace arbitrary Java classes used within a JAX-RS call, and/or disable or change the operation name of particular JAX-RS endpoints using an injected Tracer
and/or the @Traced
annotation, respectively.
Important links:
- Main development hub: https://github.com/eclipse/microprofile-opentracing/
- Real time development chat on Gitter: https://gitter.im/eclipse/microprofile-opentracing
- MicroProfile mailing list: https://groups.google.com/forum/#!forum/microprofile
- Google Calendar which may show periodic "MP OpenTracing bi-weekly call" meetings: https://calendar.google.com/calendar/embed?src=gbnbc373ga40n0tvbl88nkc3r4%40group.calendar.google.com
MP OpenTracing has a Technology Compatibility Toolkit (TCK) that's used to confirm that a Microprofile OpenTracing implementation (such as OpenLiberty) implements the MP OpenTracing specification.
The TCK tests are in OpentracingClientTests. The tests use @RunAsClient
so that they're run in the TCK runner harness and they make JAX-RS calls to various web services deployed into OpenLiberty (example). Each test then makes a call to the getTracer web service which assumes that the Tracer implementation is a MockTracer. The getTracer
web service reads all of the accumulated spans from the MockTracer
, converts them to a tree of POJOs, and sends them back to the TCK runner which then compares the tree to an expected tree of spans and asserts the tree is correct.
The original FAT tests use a different approach of the OpentracingMockTracer
which wraps the MockTracer and uses a toString
method to send back the spans which the FAT checks. This is still the default for the FAT user feature's tracer factory. However, the TCK requires that the Tracer is a MockTracer, but to simplify development, the TCK FAT uses the same user feature, so if -DUSE_MOCK_TRACER=true
is set on the JVM, then OpentracingMockTracerFactory
will return a MockTracer
instead. This is set in the TCK server in its jvm.options
file.
The TCK FAT is defined in the tck-suite.xml, the TCK runner pom.xml, and the arquillian.xml. The original FAT tests are largely redundant with the TCK FAT tests but mainly they're kept around because they test just opentracing-1.0
without mpOpenTracing-1.0
.
The logs of the TCK runner are in dev/com.ibm.ws.opentracing_fat/build/libs/autoFVT/results/mvnOutput_TCK
and the logs of the server under test are in dev/com.ibm.ws.opentracing_fat/build/libs/autoFVT/output/servers/OpentracingTCKServer*/logs/trace.log
.
To run the TCK FAT, run:
./gradlew :com.ibm.ws.opentracing_fat:buildandrun
After making a change to OpenLiberty, run:
./gradlew assemble && ./gradlew releaseNeeded && ./gradlew :com.ibm.ws.opentracing_fat:buildandrun
When doing open source development additions to a new version of the TCK, you'll need to update microprofile.opentracing.version
in the pom.xml above to something like 1.1-SNAPSHOT
and then build the TCK locally:
git clone https://github.com/eclipse/microprofile-opentracing
cd microprofile-opentracing
git checkout -b new_development
# make changes (including updating version to e.g. 1.1)
mvn install
# Then go run com.ibm.ws.opentracing_fat:buildandrun
- Incoming JAX-RS request starts: https://github.com/OpenLiberty/open-liberty/blob/18.0.0.1_RC/dev/com.ibm.ws.opentracing/src/com/ibm/ws/opentracing/OpentracingContainerFilter.java#L71
- Incoming JAX-RS request finishes: https://github.com/OpenLiberty/open-liberty/blob/18.0.0.1_RC/dev/com.ibm.ws.opentracing/src/com/ibm/ws/opentracing/OpentracingContainerFilter.java#L138
- Outgoing JAX-RS request starts: https://github.com/OpenLiberty/open-liberty/blob/18.0.0.1_RC/dev/com.ibm.ws.opentracing/src/com/ibm/ws/opentracing/OpentracingClientFilter.java#L81
- Outgoing JAX-RS request finishes: https://github.com/OpenLiberty/open-liberty/blob/18.0.0.1_RC/dev/com.ibm.ws.opentracing/src/com/ibm/ws/opentracing/OpentracingClientFilter.java#L152
-
@Traced
annotation processing: https://github.com/OpenLiberty/open-liberty/blob/18.0.0.1_RC/dev/com.ibm.ws.microprofile.opentracing/src/com/ibm/ws/microprofile/opentracing/cdi/TracedInterceptor.java#L34 - When
mpOpenTracing-1.0
is enabled (instead of justopentracing-1.0
),OpenTracingFilterHelper
is injected intoOpentracingContainerFilter
andOpentracingClientFilter
which performs the annotation processing that otherwise shouldn't happen foropentracing-1.0
. - Filtering (currently disabled; requires additional spec work): https://github.com/OpenLiberty/open-liberty/blob/18.0.0.1_RC/dev/com.ibm.ws.opentracing/src/com/ibm/ws/opentracing/filters/SpanFilter.java#L15
- Review the API specification.
- A
Span
represents an execution of code such as a JAX-RS web service method, a method annotated with@Traced
, or an explicitly traced block of code. TheSpan
is the main conceptual unit, representing a traced piece of code, how long it took, and any tags or baggage that add metadata to the span (e.g. the URL of a request). - The "main" way to create a span is to use
Tracer.buildSpan
with an operation name. WhenstartActive
is called, it returns anActiveSpan
object which must bedeactivate
d (ActiveSpan
implementsCloseable
so it can be wrapped in atry-with-resources
statement to automatically close at the end of the block).
The following trace specification should be used for the most common issues:
*=info:com.ibm.ws.opentracing*=all:com.ibm.ws.microprofile.opentracing*=all
If there may be CDI issues:
*=info:com.ibm.ws.opentracing*=all:com.ibm.ws.microprofile.opentracing*=all:CDI=all:com.ibm.ws.cdi*=all
- Excessive log output if an open tracing feature is enabled without an OpentracingTracerFactory: https://github.com/OpenLiberty/open-liberty/issues/2928