Note
|
This repository contains the guide documentation source. To view the guide in published form, view it on the Open Liberty website. |
Explore how to enable and customize tracing of JAX-RS and non-JAX-RS methods by using MicroProfile OpenTracing and Jaeger.
You will learn how to enable automatic tracing for JAX-RS methods and create custom tracers for non-JAX-RS methods by using MicroProfile OpenTracing.
OpenTracing is a standard API for instrumenting microservices for distributed tracing. Distributed tracing helps troubleshoot microservices by examining and logging requests as they propagate through a distributed system, allowing developers to tackle the otherwise difficult task of debugging these requests. Without a distributed tracing system in place, analyzing the workflows of operations becomes difficult, particularly in regard to pinpointing when and by whom a request is received or when a response is sent back.
Tracer
and Span
are two critical types in the OpenTracing specification.
The Span
type is the primary building block of a distributed trace, representing an individual unit of work done
in a distributed system.
The Trace
type in OpenTracing can be thought of as a directed acyclic graph (DAG) of Spans
, where the edges between
Spans
are called References.
The Tracer
interface creates Spans
and Traces
and understands how to serialize and deserialize their metadata
across process boundaries.
MicroProfile OpenTracing enables distributed tracing in microservices. The MicroProfile OpenTracing specification doesn’t address the problem of defining, implementing, or configuring the underlying distributed tracing system. Rather, the specification makes it easier to instrument services with distributed tracing given an existing distributed tracing system.
Jaeger is an open source distributed tracing system that is compatible with the
OpenTracing specification.
Jaeger also provides an implementation of Tracer
in the client package that is compatible with MicroProfile
OpenTracing.
You’ll configure the provided inventory
and system
services to use Jaeger for distributed tracing with MicroProfile
OpenTracing.
You’ll run these services in two separate JVMs made of two server instances to demonstrate tracing in a distributed
environment.
If all the components were run on a single server, then any logging software would be sufficient.
Before you begin, deploy the Jaeger all-in-one executable file to start the Jaeger tracing system. The Jaeger all-in-one executable file is configured for quick local testing. You can find information about the Jaeger server and instructions for starting the all-in-one executable file in the Jaeger documentation.
Before you proceed, make sure that your Jaeger server is up and running. Jaeger can be found at the http://localhost:16686 URL.
The finish
directory in the root of this guide contains the finished application.
Give it a try before you proceed.
Open a command-line session and navigate to the finish/inventory
directory.
Run the following Maven goal to build the inventory
service and deploy it to Open Liberty:
mvn liberty:run
Open another command-line session and navigate to the finish/system
directory.
Run the following Maven goal to build the system
service and deploy it to Open Liberty:
mvn liberty:run
After you see the following message in both command-line sessions, both of your services are ready:
The defaultServer server is ready to run a smarter planet.
Make sure that your Jaeger server is running and point your browser to the http://localhost:9081/inventory/systems/localhost URL.
When you visit this endpoint, you make two GET HTTP requests, one to the system
service and one to the inventory
service. Both of these requests are configured to be traced, so a new trace is recorded in Jaeger.
To view the traces, go to the http://localhost:16686 URL. You can view the traces for the inventory or system services under the Search tab in the upper left of the page. Select the services in the Select a service menu and click the Find Traces button at the end of the section.
If you only see the jaeger-query listed in the dropdown, you might need to wait a little longer and refresh the page to see the application services.
View the traces for inventory
. You’ll see the following trace:
The trace has four spans, three from inventory and one from system. Click the trace to view its details. Under Service & Operation, you see the spans in this trace. You can inspect each span by clicking it to reveal more detailed information, such as the time at which a request was received and the time at which a response was sent back.
Verify that there are three spans from inventory
and one span from system
:
After you’re finished reviewing the application, stop the Open Liberty servers by pressing CTRL+C
in the command-line
sessions where you ran the system and inventory services.
Alternatively, you can run the following goals from the finish
directory in another command-line session:
mvn -pl system liberty:stop mvn -pl inventory liberty:stop
You need to start the services to see basic traces appear in Jaeger.
When you run Open Liberty in development mode, known as dev mode, the server listens for file changes and automatically recompiles and deploys your updates whenever you save a new change.
Open a command-line session and navigate to the start/inventory
directory.
Run the following Maven goal to start the inventory
service in dev mode:
mvn liberty:dev
Open a command-line session and navigate to the start/system
directory.
Run the following Maven goal to start the system
service in dev mode:
mvn liberty:dev
After you see the following message, your application server in dev mode is ready:
Press the Enter key to run tests on demand.
Dev mode holds your command-line session to listen for file changes. Open another command-line session to continue, or open the project in your editor.
When the servers start, you can find the system
and inventory
services at the following URLs:
To collect traces across your systems, you need to implement the OpenTracing Tracer
interface.
Jaeger provides a Tracer
implementation for the Jaeger server in the jaeger-client
package.
This package is already added as a dependency for you in your pom.xml
file.
It’s downloaded and installed automatically into each service when you run a Maven build.
In a development environment, it is important that every trace is sampled. When every trace is sampled, all spans are available in the Jaeger UI.
The JAEGER_SAMPLER_TYPE
and JAEGER_SAMPLER_PARAM
environment variables are set as
Open Liberty configuration properties
to sample all traces.
The const
value for JAEGER_SAMPLER_TYPE
environment variable configures the Jaeger client sampler to make the same
sampling decision for each trace, based on the sampler parameter.
If the sampler parameter is 1, it samples all traces.
If the sampler parameter is 0, it doesn’t sample any traces.
The 1
value for JAEGER_SAMPLER_PARAM
variable configures the Jaeger sampler to sample
all traces.
In a production environment, this configuration might cause a lot of overhead on the application and a lower sampling rate can be used. The different values for client sampling configuration can be found in the sampling documentation.
Similarly, in a production environment, Jaeger might not be running in the same host as the application.
In this case, set the hostname of the Jaeger server to the JAEGER_AGENT_HOST
environment variable and set the port
that communicates with the Jaeger host to the JAEGER_AGENT_PORT
environment variable.
You can view the configuration environment variables at the Jaeger Java client documentation.
pom.xml
link:finish/inventory/pom.xml[role=include]
The MicroProfile OpenTracing feature enables tracing of all JAX-RS methods by default.
To further control and customize these traces, use the @Traced
annotation to enable and disable
tracing of particular methods. You can also inject a custom Tracer
object to create and customize spans.
This feature is already enabled in the inventory
and system
configuration files.
Because tracing of all JAX-RS methods is enabled by default, you only need to enable the
MicroProfile OpenTracing
feature in the server.xml
file
to see some basic traces in Jaeger.
The OpenTracing API is exposed as a third-party API in Open Liberty.
To add the visibility of OpenTracing APIs to the application, add third-party
to the types of API packages
that this class loader supports.
Instead of explicitly configuring a list of API packages that includes third-party
, set the +third-party
value
to the apiTypeVisibility
attribute in the <classLoader />
configuration.
This configuration adds third-party
to the default list of API package types that are supported.
server.xml
link:finish/inventory/src/main/liberty/config/server.xml[role=include]
Make sure that your services are running. Then, point your browser to any of the services' endpoints and check your Jaeger server for traces.
Use the @Traced
annotation to define explicit span creation for specific classes and methods.
If you place the annotation on a class, then the annotation is automatically applied to all methods within that class.
If you place the annotation on a method, then the annotation overrides the class annotation if one exists.
The @Traced
annotation can be configured with the following two parameters:
-
The
value=[true|false]
parameter indicates whether a particular class or method is traced. For example, while all JAX-RS methods are traced by default, you can disable their tracing by using the@Traced(false)
annotation. This parameter is set totrue
by default. -
The
operationName=<Span name>
parameter indicates the name of the span that is assigned to the method that is traced. If you omit this parameter, the span is named with the<package name>.<class name>.<method name>
format. If you use this parameter at a class level, then all methods within that class have the same span name unless they are explicitly overridden by another@Traced
annotation.
Update theInventoryManager
class.inventory/src/main/java/io/openliberty/guides/inventory/InventoryManager.java
Enable tracing of the list()
non-JAX-RS method by updating @Traced
as shown.
Go to the http://localhost:9081/inventory/systems URL and check your Jaeger server at the http://localhost:16686 URL.
If you have the Jaeger UI open from a previous step, refresh the page.
Select the inventory
traces and click the Find Traces button.
You see a new trace record that is two spans long. One span is for the
listContents()
JAX-RS method in the
InventoryResource
class, and the other span is for the list()
method in the InventoryManager
class.
Verify that you see the following spans:
InventoryManager.java
link:finish/inventory/src/main/java/io/openliberty/guides/inventory/InventoryManager.java[role=include]
InventoryResource.java
link:finish/inventory/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[role=include]
You can use the @Traced
annotation with a value of false
to disable automatic distributed tracing of JAX-RS
methods.
Update theInventoryResource
class.inventory/src/main/java/io/openliberty/guides/inventory/InventoryResource.java
Disable tracing of the listContents()
JAX-RS method by setting @Traced(false)
.
Go to the http://localhost:9081/inventory/systems URL and check your Jaeger server at the http://localhost:16686 URL.
If you have the Jaeger UI open from a previous step, refresh the page.
Select the inventory
traces and click the Find Traces button.
You see a new trace record that is just one span long for the remaining list()
method in the
InventoryManager
class.
Verify that you see the following span:
InventoryManager.java
link:finish/inventory/src/main/java/io/openliberty/guides/inventory/InventoryManager.java[role=include]
InventoryResource.java
link:finish/inventory/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[role=include]
The MicroProfile OpenTracing specification also makes the underlying OpenTracing Tracer
instance
available for use. You can access the configured Tracer
by injecting it into a bean by using the @Inject
annotation from the Contexts and Dependency Injections API.
Inject the Tracer
object into the inventory/src/main/java/io/openliberty/guides/inventory/InventoryManager.java
file.
Then, use it to define a new child scope in the add()
call.
Replace theInventoryManager
class.inventory/src/main/java/io/openliberty/guides/inventory/InventoryManager.java
InventoryManager.java
link:finish/inventory/src/main/java/io/openliberty/guides/inventory/InventoryManager.java[role=include]
This try
block is called a try-with-resources
statement, meaning that the
childScope
object is closed at the end of the statement.
It’s good practice to define custom spans inside such statements.
Otherwise, any exceptions that are thrown before the span closes will leak the active span.
Go to the http://localhost:9081/inventory/systems/localhost URL and check your Jaeger server at the http://localhost:16686
URL.
If you have the Jaeger UI open from a previous step, refresh the page.
Select the inventory
traces and click the Find Traces button.
Verify that there are three spans from inventory
and one span from system
:
This simple example shows what you can do with the injected Tracer
object. More configuration
options are available to you, including setting a timestamp for when a span was created and destroyed.
However, these options require an implementation of their own, which doesn’t come as a part of the Jaeger
user feature that is provided. In a real-world scenario, implement all the OpenTracing interfaces that
you deem necessary, which might include the SpanBuilder
interface. You can use this interface for span
creation and customization, including setting timestamps.
SystemResource.java
link:finish/system/src/main/java/io/openliberty/guides/system/SystemResource.java[role=include]
InventoryResource.java
link:finish/inventory/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[role=include]
No automated tests are provided to verify the correctness of the traces. Manually verify these traces by viewing them on the Jaeger server.
A few tests are included for you to test the basic functionality of the services. If a test failure occurs, then you might have introduced a bug into the code.
Since you started Open Liberty in dev mode, run the tests for the system and inventory services by pressing the
enter/return
key in the command-line sessions where you started the services.
When you are done checking out the services, exit dev mode by pressing CTRL+C
in the shell sessions where you
ran the system
and inventory
services, or by typing q
and then pressing the enter/return key
.
Finally, stop the Jaeger
service that you started in the Additional prerequisites section.
You just used MicroProfile OpenTracing in Open Liberty to customize how and which traces are delivered to Jaeger.
Try out one of the related MicroProfile guides. These guides demonstrate more technologies that you can learn to expand on what you built in this guide.