<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>
<p>New Hawkular blog post from noreply@hawkular.org (Pavol Loffay): http://ift.tt/2tYLEaM<br><br></p>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>In the previous <a href="http://ift.tt/2soBcsg">demo</a> we have demonstrated how to instrument a Spring Boot app using <a href="http://opentracing.io">OpenTracing</a>, a vendor-neutral standard for distributed tracing. In this article we are going to instrument a Java API for RESTful Web Services (JAX-RS), and show you how to trace the business layer and add custom data to the trace.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_demo_application">Demo application</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Creating a JAX-RS app from scratch can be a time consuming task, therefore in this case we are going to use Wildfly Swarm’s <a href="http://ift.tt/1NgO20K">app generator</a>. Select JAX-RS and CDI dependencies and hit generate button.</p>
</div>
<div class="imageblock">
<div class="content"><img src="http://ift.tt/2uxdFD9" alt="wf swarm generator"></div>
<div class="title">Figure 1: Wildfly Swarm generator.</div>
</div>
<div class="paragraph">
<p>The generated application contains one REST endpoint which returns hello world string. This endpoint is accessible on <code><a href="http://localhost:8080/hello" class="bare">http://localhost:8080/hello</a></code>. In the next step we are going to add instrumentation and simple business logic.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_instrumentation">Instrumentation</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Adding OpenTracing instrumentation to JAX-RS is very simple, just include the following dependency in the classpath and the tracing feature will be automatically registered.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>
&lt;dependency&gt;
    &lt;groupId&gt;io.opentracing.contrib&lt;/groupId&gt;
    &lt;artifactId&gt;opentracing-jaxrs2&lt;/artifactId&gt;
&lt;/dependency&gt;
</pre>
</div>
</div>
<div class="paragraph">
<p>OpenTracing is just an API, therefore it is required to register a specific tracer instance. In this demo we are going to use <a href="http://ift.tt/2eOSqHE">Jaeger tracing system</a>. The tracer should be created and initialized only once per process, hence <code>ServletContextListener</code> is the ideal place for this task:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight">
<code class="language-java" data-lang="java">@WebListener
public class TracingContextListener implements ServletContextListener {

  @Inject
  private io.opentracing.Tracer tracer;

  @Override
  public void contextInitialized(ServletContextEvent sce) {
    GlobalTracer.register(tracer);
  }

  @Override
  public void contextDestroyed(ServletContextEvent sce) {}

  @Produces
  @Singleton
  public static io.opentracing.Tracer jaegerTracer() {
    return new Configuration("wildfly-swarm", new Configuration.SamplerConfiguration(
        ProbabilisticSampler.TYPE, 1),
        new Configuration.ReporterConfiguration())
        .getTracer();
  }
}</code>
</pre>
</div>
</div>
<div class="paragraph">
<p>Tracer initialization code requires to specify app name, which is in this case <code>wildfly-swarm</code> and sampler configuration.</p>
</div>
<div class="paragraph">
<p>Note that we are suing Java’s Context and Dependency Injection (CDI) to share a tracer instance in our app. If we forget to register a specific tracer instance, then the tracing feature would use <code>NoopTracer</code>. Now we can verify tracing by starting Jaeger server using the following command: <code>docker run --rm -it --network=host jaegertracing/all-in-one</code> and accessing the endpoint at <code><a href="http://localhost:8080/hello" class="bare">http://localhost:8080/hello</a></code>. Our trace with one span should be present in the UI at <code><a href="http://localhost:16686" class="bare">http://localhost:16686</a></code>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_instrumenting_business_logic">Instrumenting business logic</h2>
<div class="sectionbody">
<div class="paragraph">
<p>JAX-RS instrumentation provides nice visibility into your app, however, it is often necessary to add custom data to the trace to see what is happening in the service or database layer.</p>
</div>
<div class="paragraph">
<p>The following code snippet shows how the service layer can create and add data to the trace:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight">
<code class="language-java" data-lang="java">public class BackendService {

  @Inject
  private io.opentracing.Tracer tracer;

  public String action() throws InterruptedException {
    int random = new Random().nextInt(200);

    try (ActiveSpan span = tracer.buildSpan("action").startActive()) {
      anotherAction();
      Thread.sleep(random);
    }

    return String.valueOf(random);
  }

  private void anotherAction() {
    tracer.activeSpan().setTag("anotherAction", "data");
  }</code>
</pre>
</div>
</div>
<div class="paragraph">
<p>Note that it’s not necessary to manually pass a span instance around. The method <code>anotherAction</code> accesses the current active span from the tracer.</p>
</div>
<div class="paragraph">
<p>With the additional instrumentation shown above, an invocation of the REST endpoint would result in a trace consisting of two spans, one representing the inbound server request, and the other the business logic. The span representing server processing is automatically considered as the parent for span created in business layer. If we created span in <code>anotherAction</code> then its parent would be span created in <code>action</code> method.</p>
</div>
<div class="imageblock">
<div class="content"><img src="http://ift.tt/2uxpZmR" alt="swarm jaeger"></div>
<div class="title">Figure 1: Jaeger showing reported spans.</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_video">Video</h2>
<div class="sectionbody">
<div class="videoblock">
<div class="content"></div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We have demonstrated that instrumenting a JAX-RS app is just a matter of adding a dependency and registering a tracer instance. If we would like to use a different OpenTracing implementation, Zipkin for instance, it would just require changing tracer producer code. No changes to the application or business logic! In the next demo we will wire this app with Spring Boot created in previous demo and deploy them on Kubernetes.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_links">Links</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>OpenTracing: <a href="http://opentracing.io" class="bare">http://opentracing.io</a></p>
</li>
<li>
<p>Github repository with demo: <a href="http://ift.tt/2s6QrTB" class="bare">http://ift.tt/2s6QrTB</a></p>
</li>
<li>
<p>OpenTracing JAX-RS instrumentation: <a href="http://ift.tt/2uxvWQO" class="bare">http://ift.tt/2uxvWQO</a></p>
</li>
<li>
<p>Jaeger: <a href="http://ift.tt/2eOSqHE" class="bare">http://ift.tt/2eOSqHE</a></p>
</li>
</ul>
</div>
</div>
</div>
<br><br>
from Hawkular Blog
</body></html>