Author: buildbot Date: Wed Nov 28 11:57:27 2018 New Revision: 1037363 Log: Production update by buildbot for cxf
Modified: websites/production/cxf/content/cache/docs.pageCache websites/production/cxf/content/docs/using-apache-htrace.html Modified: websites/production/cxf/content/cache/docs.pageCache ============================================================================== Binary files - no diff available. Modified: websites/production/cxf/content/docs/using-apache-htrace.html ============================================================================== --- websites/production/cxf/content/docs/using-apache-htrace.html (original) +++ websites/production/cxf/content/docs/using-apache-htrace.html Wed Nov 28 11:57:27 2018 @@ -119,11 +119,11 @@ Apache CXF -- Using Apache HTrace <!-- Content --> <div class="wiki-content"> <div id="ConfluenceContent"><p><style type="text/css">/*<![CDATA[*/ -div.rbtoc1524646610258 {padding: 0px;} -div.rbtoc1524646610258 ul {list-style: disc;margin-left: 0px;} -div.rbtoc1524646610258 li {margin-left: 0px;padding-left: 0px;} +div.rbtoc1543406209252 {padding: 0px;} +div.rbtoc1543406209252 ul {list-style: disc;margin-left: 0px;} +div.rbtoc1543406209252 li {margin-left: 0px;padding-left: 0px;} -/*]]>*/</style></p><div class="toc-macro rbtoc1524646610258"> +/*]]>*/</style></p><div class="toc-macro rbtoc1543406209252"> <ul class="toc-indentation"><li><a shape="rect" href="#UsingApacheHTrace-Overview">Overview</a></li><li><a shape="rect" href="#UsingApacheHTrace-DistributedTracinginNutshell">Distributed Tracing in Nutshell</a></li><li><a shape="rect" href="#UsingApacheHTrace-DistributedTracinginApacheCXFusingApacheHTrace">Distributed Tracing in Apache CXF using Apache HTrace</a></li><li><a shape="rect" href="#UsingApacheHTrace-ConfiguringClientconfigure.client">Configuring Client</a> <ul class="toc-indentation"><li><a shape="rect" href="#UsingApacheHTrace-Configuringtracingheadernames">Configuring tracing header names</a></li></ul> </li><li><a shape="rect" href="#UsingApacheHTrace-ConfiguringServerconfigure.server">Configuring Server</a> @@ -131,8 +131,8 @@ div.rbtoc1524646610258 li {margin-left: </li><li><a shape="rect" href="#UsingApacheHTrace-DistributedTracingInAction:UsageScenarios">Distributed Tracing In Action: Usage Scenarios</a> <ul class="toc-indentation"><li><a shape="rect" href="#UsingApacheHTrace-Example#1:ClientandServerwithdefaultdistributedtracingconfigured">Example #1: Client and Server with default distributed tracing configured</a></li><li><a shape="rect" href="#UsingApacheHTrace-Example#2:ClientandServerwithnestedtrace">Example #2: Client and Server with nested trace</a></li><li><a shape="rect" href="#UsingApacheHTrace-Example#3:ClientandServertracewithtimeline">Example #3: Client and Server trace with timeline</a></li><li><a shape="rect" href="#UsingApacheHTrace-Example#4:ClientandServerwithannotatedtrace(key/value)">Example #4: Client and Server with annotated trace (key/value)</a></li><li><a shape="rect" href="#UsingApacheHTrace-Example#5:ClientandServerwithparalleltrace(involvingthreadpools)">Example #5: Client and Server with parallel trace (involving thread pools)</a></li><li><a shape="rect" href="#UsingApacheHTrace-Example#6:ClientandServerwithasynchronousJAX-RSservice(server-side)">Exampl e #6: Client and Server with asynchronous JAX-RS service (server-side)</a></li><li><a shape="rect" href="#UsingApacheHTrace-Example#7:ClientandServerwithasynchronousinvocation(client-side)">Example #7: Client and Server with asynchronous invocation (client-side)</a></li></ul> </li><li><a shape="rect" href="#UsingApacheHTrace-DistributedTracingApacheHTraceandJAX-WSsupport">Distributed Tracing Apache HTrace and JAX-WS support</a></li><li><a shape="rect" href="#UsingApacheHTrace-PropagatingTraceDetailsToLogs">Propagating Trace Details To Logs</a></li><li><a shape="rect" href="#UsingApacheHTrace-FutureWork">Future Work</a></li></ul> -</div><h1 id="UsingApacheHTrace-Overview">Overview</h1><p><a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> is a tracing framework intended for use with distributed systems written in java. Since version <strong>3.1.3</strong>, Apache CXF fully supports integration with <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a>, both on client side and server side. This section gives a complete overview on how distributed tracing support is supported in JAX-RS applications built on top of Apache CXF.</p><h1 id="UsingApacheHTrace-DistributedTracinginNutshell">Distributed Tracing in Nutshell</h1><p>Distributed tracing, first described by Google in <a shape="rect" class="external-link" href="http://research.google.com/pubs/pub36356.html" rel="nofollow">Dapper, a Large-Scale Distributed Systems Tracing Infrastructure</a> paper became increasingly important topic these days. With microservices (aka SOA) gaining more and more adoption, the typical applications are built using dozens or even hundreds of small, distributed pieces. The end-to-end traceability of the requests (or any kind of work performed on user's behalf) is hard task to accomplish, particularly taking into account asyncronous or/and concurrent invocations. <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> is inspired by <a shape="rect" class="external-link" href="http://research.google.com/pubs/pub36356.html" rel="nofollow">Dapper, a Large-Scale Distributed Systems Tracing Infrastructure</a> paper and essentially is a full-fledged distributed tracing framework.</p><p>Distributed tracing is additional instrumentation layer on top of new or existing applications. In terms of distributed tracing, <strong>span</strong> represents a basic unit of work. For example, executing database query is a <strong>span</strong>. <strong>Spans</strong> are identified by a unique 128-bit ID. <strong>Spans</strong> also have other data, such as <strong>descriptions</strong>, <strong>timelines</strong>,<strong> key-value annotations</strong>, the <strong>ID</strong> of the <strong>span</strong> that caused them (parent), and <strong>process/tracer</strong> ID’s (normally IP address and process name). Spans are started and stopped, and they keep track of their timing information. Once <strong>span</strong> is created, it should be stopped at some point in the future. In turn, <strong>trace</strong> is a set of spans forming a tree-like structure. For example, if you are running a JAX-RS service, a trace might be formed by a <strong>PUT</strong> request and downstream work.</p><p>From implementation perspective, and in context of Java applications, <strong>spans</strong> are attached to their threads (in general, thread which created the <strong>span</strong> should close it). However it is possible to transfer <strong>spans</str ong> from thread to thread in order to model a complex execution flows. It is also possible to have many <strong>spans</strong> in the same thread, as long as they are properly created and closed. In the next sections we are going to see the examples of that.</p><p>Another two important concepts in context of distributed tracing are <strong>span receivers</strong> and <strong>samplers</strong>. Essentially, all spans (including start/stop time, key/value annotations, timelines, ..) should be persisted (or collected) somewhere. <strong>Span receiver</strong> is a collector within a process that is the destination of <strong>spans</strong> when a trace is running (it could be a console, local file, data store, ...). <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> provides span receivers for <a shape="rect" class="external-link" href="http://hbase.apache.org">Apache HBase</a>, <a shape="rect" class="external-link" href="https ://flume.apache.org/">Apache Flume</a> and <a shape="rect" class="external-link" href="http://zipkin.io/" rel="nofollow">Twitter Zipkin</a>. From other side, <strong>samplers</strong> allow to control the frequency of the tracing (all the time, never, probability driven, ...). Using the <strong>sampler</strong> is the way to minimize tracing overhead (or just amount of traces) by limiting them to particular conditions.</p><h1 id="UsingApacheHTrace-DistributedTracinginApacheCXFusingApacheHTrace">Distributed Tracing in Apache CXF using Apache HTrace</h1><p><a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> is a very popular framework for building services and web APIs. No doubts, it is going to play even more important role in context of microservices architecture letting developers to quickly build and deploy individual JAX-RS/JAX-WS services. As it was just mentioned before, distributed tracing is an essential technique to monitor the application as whole, breaking the req uest to individual service traces as it goes through and crosses the boundaries of threads, processes and machines.</p><p>The current integration of distributed tracing in <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> supports <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> (<strong>4.x+</strong> release branch) only in JAX-RS 2.x applications. From high-level prospective, it consists of three main parts:</p><ul style="list-style-type: square;"><li><strong>TracerContext</strong> (injectable through <strong>@Context</strong> annotation)</li><li><strong>HTraceProvider</strong> (server-side JAX-RS provider) and <strong>HTraceClientProvider</strong> (client-side JAX-RS provider)</li><li><strong>HTraceFeature</strong> (server-side <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> feature to simplify <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace </a> configuration and integration)</li></ul><p><a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> uses HTTP headers to hand off tracing context from the client to the service and from the service to service. Those headers are used internally by <strong>HTraceProvider</strong> and <strong>HTraceClientProvider</strong>, but are configurable. The default header names are declared in the TracerHeaders class:</p><ul style="list-style-type: square;"><li><strong>X-Span-Id</strong>: contains a current span ID</li></ul><p>By default, <strong>HTraceProvider</strong> will try to pass the currently active <strong>span</strong> through HTTP headers on each service invocation. If there is no active spans, the new span will be created and passed through HTTP headers on per-invocation basis. Essentially, just registering the <strong>HTraceClientProvider</strong> on the client and <strong>HTraceProvider</strong> on the server is enough to have tracing context to be properly passed ev erywhere. The only configuration part which is necessary are <strong>span receiver(s)</strong> and <strong>sampler</strong>(s).</p><p>It is also worth to mention the way <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> attaches the description to <strong>spans</strong>. With regards to the client integration, the description becomes a full URL being invoked prefixed by HTTP method, for example: <strong>GET </strong><a shape="rect" class="external-link" href="http://localhost:8282/books" rel="nofollow"><strong>http://localhost:8282</strong>/books</a>. On the server side integration, the description becomes a relative JAX-RS resource path prefixed by HTTP method, f.e.: <strong>GET books, POST book/123</strong></p><h1 id="UsingApacheHTrace-ConfiguringClientconfigure.client">Configuring Client <span class="confluence-anchor-link" id="UsingApacheHTrace-configure.client"></span></h1><p>There are a couple of ways the JAX-RS client could be configured, depending on the client im plementation. <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> provides its own <strong>WebClient</strong> which could be configured just like that (in future versions, there would be a simpler ways to do that using client specific features):</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">final Map<String, String> properties = new HashMap<String, String>(); +</div><div class="confluence-information-macro confluence-information-macro-warning"><span class="aui-icon aui-icon-small aui-iconfont-error confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>The <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> project has retired on<strong> 2018-04-11</strong> and is not developed anymore. The Apache CXF will no longer provide the <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> integration, staring from <strong>3.3.0</strong> release.  </p></div></div><h1 id="UsingApacheHTrace-Overview">Overview</h1><p><a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> is a tracing framework intended for use with distributed systems written in java. Since version <strong>3.1.3</strong>, Apache CXF fully supports integration with <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a>, both on client side and server side. This section gives a complete overview on how distributed tracing support is supported in JAX-RS applications built on top of Apache CXF.</p><h1 id="UsingApacheHTrace-DistributedTracinginNutshell">Distributed Tracing in Nutshell</h1><p>Distributed tracing, first described by Google in <a shape="rect" class="external-link" href="http://research.google.com/pubs/pub36356.html" rel="nofollow">Dapper, a Large-Scale Distributed Systems Tracing Infrastructure</a> paper became increasingly important topic these days. With microservices (aka SOA) gaining more and more adoption, the typical applications are built using dozens or even hundreds of small, distributed pieces. The end-to-end traceability of the requests (or any kind of work performed on user's behalf) is hard task to accomplish, particularly taking into account asyncronous or/and concurrent invocation s. <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> is inspired by <a shape="rect" class="external-link" href="http://research.google.com/pubs/pub36356.html" rel="nofollow">Dapper, a Large-Scale Distributed Systems Tracing Infrastructure</a> paper and essentially is a full-fledged distributed tracing framework.</p><p>Distributed tracing is additional instrumentation layer on top of new or existing applications. In terms of distributed tracing, <strong>span</strong> represents a basic unit of work. For example, executing database query is a <strong>span</strong>. <strong>Spans</strong> are identified by a unique 128-bit ID. <strong>Spans</strong> also have other data, such as <strong>descriptions</strong>, <strong>timelines</strong>,<strong> key-value annotations</strong>, the <strong>ID</strong> of the <strong>span</strong> that caused them (parent), and <strong>process/tracer</strong> ID’s (normally IP address and pr ocess name). Spans are started and stopped, and they keep track of their timing information. Once <strong>span</strong> is created, it should be stopped at some point in the future. In turn, <strong>trace</strong> is a set of spans forming a tree-like structure. For example, if you are running a JAX-RS service, a trace might be formed by a <strong>PUT</strong> request and downstream work.</p><p>From implementation perspective, and in context of Java applications, <strong>spans</strong> are attached to their threads (in general, thread which created the <strong>span</strong> should close it). However it is possible to transfer <strong>spans</strong> from thread to thread in order to model a complex execution flows. It is also possible to have many <strong>spans</strong> in the same thread, as long as they are properly created and closed. In the next sections we are going to see the examples of that.</p><p>Another two important concepts in context of distributed tracing are <strong>sp an receivers</strong> and <strong>samplers</strong>. Essentially, all spans (including start/stop time, key/value annotations, timelines, ..) should be persisted (or collected) somewhere. <strong>Span receiver</strong> is a collector within a process that is the destination of <strong>spans</strong> when a trace is running (it could be a console, local file, data store, ...). <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> provides span receivers for <a shape="rect" class="external-link" href="http://hbase.apache.org">Apache HBase</a>, <a shape="rect" class="external-link" href="https://flume.apache.org/">Apache Flume</a> and <a shape="rect" class="external-link" href="http://zipkin.io/" rel="nofollow">Twitter Zipkin</a>. From other side, <strong>samplers</strong> allow to control the frequency of the tracing (all the time, never, probability driven, ...). Using the <strong>sampler</strong> is the way to minimize tracing o verhead (or just amount of traces) by limiting them to particular conditions.</p><h1 id="UsingApacheHTrace-DistributedTracinginApacheCXFusingApacheHTrace">Distributed Tracing in Apache CXF using Apache HTrace</h1><p><a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> is a very popular framework for building services and web APIs. No doubts, it is going to play even more important role in context of microservices architecture letting developers to quickly build and deploy individual JAX-RS/JAX-WS services. As it was just mentioned before, distributed tracing is an essential technique to monitor the application as whole, breaking the request to individual service traces as it goes through and crosses the boundaries of threads, processes and machines.</p><p>The current integration of distributed tracing in <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> supports <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrac e</a> (<strong>4.x+</strong> release branch) only in JAX-RS 2.x applications. From high-level prospective, it consists of three main parts:</p><ul style="list-style-type: square;"><li><strong>TracerContext</strong> (injectable through <strong>@Context</strong> annotation)</li><li><strong>HTraceProvider</strong> (server-side JAX-RS provider) and <strong>HTraceClientProvider</strong> (client-side JAX-RS provider)</li><li><strong>HTraceFeature</strong> (server-side <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> feature to simplify <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> configuration and integration)</li></ul><p><a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> uses HTTP headers to hand off tracing context from the client to the service and from the service to service. Those headers are used internally by <strong>HTraceProvider</strong> and <strong>HTraceClientProvider</strong>, but are config urable. The default header names are declared in the TracerHeaders class:</p><ul style="list-style-type: square;"><li><strong>X-Span-Id</strong>: contains a current span ID</li></ul><p>By default, <strong>HTraceProvider</strong> will try to pass the currently active <strong>span</strong> through HTTP headers on each service invocation. If there is no active spans, the new span will be created and passed through HTTP headers on per-invocation basis. Essentially, just registering the <strong>HTraceClientProvider</strong> on the client and <strong>HTraceProvider</strong> on the server is enough to have tracing context to be properly passed everywhere. The only configuration part which is necessary are <strong>span receiver(s)</strong> and <strong>sampler</strong>(s).</p><p>It is also worth to mention the way <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> attaches the description to <strong>spans</strong>. With regards to the client integration, the description become s a full URL being invoked prefixed by HTTP method, for example: <strong>GET </strong><a shape="rect" class="external-link" href="http://localhost:8282/books" rel="nofollow"><strong>http://localhost:8282</strong>/books</a>. On the server side integration, the description becomes a relative JAX-RS resource path prefixed by HTTP method, f.e.: <strong>GET books, POST book/123</strong></p><h1 id="UsingApacheHTrace-ConfiguringClientconfigure.client">Configuring Client <span class="confluence-anchor-link" id="UsingApacheHTrace-configure.client"></span></h1><p>There are a couple of ways the JAX-RS client could be configured, depending on the client implementation. <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> provides its own <strong>WebClient</strong> which could be configured just like that (in future versions, there would be a simpler ways to do that using client specific features):</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelCon tent pdl"> +<pre class="brush: java; gutter: false; theme: Default">final Map<String, String> properties = new HashMap<String, String>(); properties.put(Tracer.SPAN_RECEIVER_CLASSES_KEY, ...); properties.put(Tracer.SAMPLER_CLASSES_KEY, ...); @@ -153,7 +153,7 @@ final Response response = WebClient .accept(MediaType.APPLICATION_JSON) .get();</pre> </div></div><p>The configuration based on using the standard JAX-RS <strong>Client</strong> is very similar:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">final Map<String, String> properties = new HashMap<String, String>(); +<pre class="brush: java; gutter: false; theme: Default">final Map<String, String> properties = new HashMap<String, String>(); properties.put(Tracer.SPAN_RECEIVER_CLASSES_KEY, ...); properties.put(Tracer.SAMPLER_CLASSES_KEY, ...); @@ -177,11 +177,11 @@ final Response response = client .accept(MediaType.APPLICATION_JSON) .get();</pre> </div></div><h3 id="UsingApacheHTrace-Configuringtracingheadernames">Configuring tracing header names</h3><p>To change the default HTTP header names, used to transfer the tracing context from client to server, it is enough to define one property: <strong>TracerHeaders.HEADER_SPAN_ID</strong>. For example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">final ClientConfiguration config = WebClient.getConfig(client); +<pre class="brush: java; gutter: false; theme: Default">final ClientConfiguration config = WebClient.getConfig(client); config.getRequestContext().put(TracerHeaders.HEADER_SPAN_ID, "CUSTOM_HEADER_SPAN_ID"); </pre> </div></div><div class="confluence-information-macro confluence-information-macro-warning"><span class="aui-icon aui-icon-small aui-iconfont-error confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>It is very important to keep client and server HTTP headers configuration in sync, otherwise the server won't be able to establish the current tracing context properly.</p></div></div><h1 id="UsingApacheHTrace-ConfiguringServerconfigure.server">Configuring Server <span class="confluence-anchor-link" id="UsingApacheHTrace-configure.server"></span></h1><p>Server configuration is a bit simpler than the client one thanks to the feature class available, <strong>HTraceFeature</strong>. Depending on the way the <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> is used to configure JAX-RS services, it could be part of JAX-RS application configuration, for example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="co deContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@ApplicationPath("/") +<pre class="brush: java; gutter: false; theme: Default">@ApplicationPath("/") public class CatalogApplication extends Application { @Override public Set<Object> getSingletons() { @@ -204,7 +204,7 @@ public class CatalogApplication extends } }</pre> </div></div><p>Or it could be configured using <strong>JAXRSServerFactoryBean</strong> as well, for example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">final Map<String, String> properties = new HashMap<String, String>(); +<pre class="brush: java; gutter: false; theme: Default">final Map<String, String> properties = new HashMap<String, String>(); properties.put(Tracer.SPAN_RECEIVER_CLASSES_KEY, ...); properties.put(Tracer.SAMPLER_CLASSES_KEY, ...); @@ -214,7 +214,7 @@ factory.setFeatures(Arrays.< Feature ... return factory.create();</pre> </div></div><p>Once the <strong>span receiver(s)</strong> and <strong>sampler</strong> are properly configured, all generated <strong>spans</strong> are going to be collected and available for analysis and/or visualization.</p><h3 id="UsingApacheHTrace-Configuringtracingheadernames.1">Configuring tracing header names</h3><p>As with the client, to change the default HTTP header names, used to establish the tracing context on the server, it is enough to define single property: <strong>TracerHeaders.HEADER_SPAN_ID</strong>. For example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">final Map<String, Object> headers = new HashMap<String, Object>(); +<pre class="brush: java; gutter: false; theme: Default">final Map<String, Object> headers = new HashMap<String, Object>(); headers.put(TracerHeaders.HEADER_SPAN_ID, "CUSTOM_HEADER_SPAN_ID"); final JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); @@ -222,7 +222,7 @@ sf.setProperties(headers); ... sf.create();</pre> </div></div><div class="confluence-information-macro confluence-information-macro-warning"><span class="aui-icon aui-icon-small aui-iconfont-error confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>It is very important to keep client and server HTTP headers configuration in sync, otherwise the server won't be able to establish the current tracing context properly.</p></div></div><h1 id="UsingApacheHTrace-DistributedTracingInAction:UsageScenarios">Distributed Tracing In Action: Usage Scenarios</h1><p>In the following subsections we are going to walk through many different scenarios to illustrate the distributed tracing in action, starting from the simplest ones and finishing with asynchronous JAX-RS services. All examples assume that configuration <strong>has been done</strong> (see please <a shape="rect" href="using-apache-htrace.html">Configuring Client</a> and <a shape="rect" href="using-apache-htrace.html">Configuring Server</a> secti ons above).</p><h2 id="UsingApacheHTrace-Example#1:ClientandServerwithdefaultdistributedtracingconfigured">Example #1: Client and Server with default distributed tracing configured</h2><p>In the first example we are going to see the effect of using default configuration on the client and on the server, with only <strong>HTraceClientProvider</strong>  and <strong>HTraceProvider</strong> registered. The JAX-RS resource endpoint is pretty basic stubbed method:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Produces( { MediaType.APPLICATION_JSON } ) +<pre class="brush: java; gutter: false; theme: Default">@Produces( { MediaType.APPLICATION_JSON } ) @GET public Collection<Book> getBooks() { return Arrays.asList( @@ -230,13 +230,13 @@ public Collection<Book> getBooks() ); }</pre> </div></div><p>The client is as simple as that:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">final Response response = client +<pre class="brush: java; gutter: false; theme: Default">final Response response = client .target("http://localhost:8282/books") .request() .accept(MediaType.APPLICATION_JSON) .get();</pre> </div></div><p>The actual invocation of the request by the client (with process name <strong><span class="label label-default service-filter-label service-tag-filtered">jaxrsclient/192.168.0.100</span></strong>) and consequent invocation of the service on the server side (process name<strong> <span class="label label-default service-filter-label">jaxrsserver/192.168.0.100</span></strong>) is going to generate the following sample traces:</p><p><span class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img class="confluence-embedded-image" height="250" src="using-apache-htrace.data/image2015-9-13%2016:17:53.png"></span></p><h2 id="UsingApacheHTrace-Example#2:ClientandServerwithnestedtrace">Example #2: Client and Server with nested trace</h2><p>In this example server-side implementation of the JAX-RS service is going to call an external system (simulated as a simple delay of 500ms) within its own span. The client-side code stays unchanged.</p><div class="code pane l pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Produces( { MediaType.APPLICATION_JSON } ) +<pre class="brush: java; gutter: false; theme: Default">@Produces( { MediaType.APPLICATION_JSON } ) @GET public Collection<Book> getBooks(@Context final TracerContext tracer) throws Exception { try(final TraceScope scope = tracer.startSpan("Calling External System")) { @@ -249,7 +249,7 @@ public Collection<Book> getBooks(@ } }</pre> </div></div><p>The actual invocation of the request by the client (with process name <strong><span class="label label-default service-filter-label service-tag-filtered">jaxrsclient/192.168.0.100</span></strong>) and consequent invocation of the service on the server side (process name<strong> <span class="label label-default service-filter-label">jaxrsserver/192.168.0.100</span></strong>) is going to generate the following sample traces:</p><p><span class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img class="confluence-embedded-image" height="250" src="using-apache-htrace.data/image2015-9-13%2017:5:12.png"></span></p><h2 id="UsingApacheHTrace-Example#3:ClientandServertracewithtimeline">Example #3: Client and Server trace with timeline</h2><p>In this example server-side implementation of the JAX-RS service is going to add timeline to the active span. The client-side code stays unchanged.</p><div class="code panel pdl" style="border-width: 1px;"><div class="co deContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Produces( { MediaType.APPLICATION_JSON } ) +<pre class="brush: java; gutter: false; theme: Default">@Produces( { MediaType.APPLICATION_JSON } ) @GET public Collection<Book> getBooks(@Context final TracerContext tracer) throws Exception { tracer.timeline("Preparing Books"); @@ -261,7 +261,7 @@ public Collection<Book> getBooks(@ ); }</pre> </div></div><p>The actual invocation of the request by the client (with process name <strong><span class="label label-default service-filter-label service-tag-filtered">jaxrsclient/192.168.0.100</span></strong>) and consequent invocation of the service on the server side (process name<strong> <span class="label label-default service-filter-label">jaxrsserver/192.168.0.100</span></strong>) is going to generate the following sample traces:</p><p><span class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img class="confluence-embedded-image" height="250" src="using-apache-htrace.data/image2015-9-14%2021:4:9.png"></span></p><h2 id="UsingApacheHTrace-Example#4:ClientandServerwithannotatedtrace(key/value)">Example #4: Client and Server with annotated trace (key/value)</h2><p>In this example server-side implementation of the JAX-RS service is going to add key/value annotations to the active span. The client-side code stays unchanged.</p><div class="code panel pdl" styl e="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Produces( { MediaType.APPLICATION_JSON } ) +<pre class="brush: java; gutter: false; theme: Default">@Produces( { MediaType.APPLICATION_JSON } ) @GET public Collection<Book> getBooks(@Context final TracerContext tracer) throws Exception { final Collection<Book> books = Arrays.asList( @@ -272,7 +272,7 @@ public Collection<Book> getBooks(@ return books; }</pre> </div></div><p>The actual invocation of the request by the client (with process name <strong><span class="label label-default service-filter-label service-tag-filtered">jaxrsclient/192.168.0.100</span></strong>) and consequent invocation of the service on the server side (process name<strong> <span class="label label-default service-filter-label">jaxrsserver/192.168.0.100</span></strong>) is going to generate the following sample server trace properties:</p><p><span class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img class="confluence-embedded-image" height="250" src="using-apache-htrace.data/image2015-9-14%2021:11:56.png"></span></p><h2 id="UsingApacheHTrace-Example#5:ClientandServerwithparalleltrace(involvingthreadpools)">Example #5: Client and Server with parallel trace (involving thread pools)</h2><p>In this example server-side implementation of the JAX-RS service is going to offload some work into thread pool and then return the response to the client, simulating parallel execution. The client-side code stays unchanged.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Produces( { MediaType.APPLICATION_JSON } ) +<pre class="brush: java; gutter: false; theme: Default">@Produces( { MediaType.APPLICATION_JSON } ) @GET public Collection<Book> getBooks(@Context final TracerContext tracer) throws Exception { final Future<Book> book1 = executor.submit( @@ -302,7 +302,7 @@ public Collection<Book> getBooks(@ return Arrays.asList(book1.get(), book2.get()); }</pre> </div></div><p>The actual invocation of the request by the client (with process name <strong><span class="label label-default service-filter-label service-tag-filtered">jaxrsclient/192.168.0.100</span></strong>) and consequent invocation of the service on the server side (process name<strong> <span class="label label-default service-filter-label">jaxrsserver/192.168.0.100</span></strong>) is going to generate the following sample traces:</p><p><span class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img class="confluence-embedded-image" height="250" src="using-apache-htrace.data/image2015-9-15%2020:44:20.png"></span></p><h2 id="UsingApacheHTrace-Example#6:ClientandServerwithasynchronousJAX-RSservice(server-side)">Example #6: Client and Server with asynchronous JAX-RS service (server-side)</h2><p>In this example server-side implementation of the JAX-RS service is going to be executed asynchronously. It poses a challenge from the tracing prospective as request a nd response are processed in different threads (in general). At the moment, <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> does not support the transparent tracing spans management (except for default use case) but provides the simple ways to do that (by letting to transfer spans from thread to thread). The client-side code stays unchanged.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Produces( { MediaType.APPLICATION_JSON } ) +<pre class="brush: java; gutter: false; theme: Default">@Produces( { MediaType.APPLICATION_JSON } ) @GET public void getBooks(@Suspended final AsyncResponse response, @Context final TracerContext tracer) throws Exception { tracer.continueSpan(new Traceable<Future<Void>>() { @@ -327,7 +327,7 @@ public void getBooks(@Suspended final As }); }</pre> </div></div><p>The actual invocation of the request by the client (with process name <strong><span class="label label-default service-filter-label service-tag-filtered">jaxrsclient/192.168.0.100</span></strong>) and consequent invocation of the service on the server side (process name<strong> <span class="label label-default service-filter-label">jaxrsserver/192.168.0.100</span></strong>) is going to generate the following sample traces:</p><p><span class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img class="confluence-embedded-image" height="250" src="using-apache-htrace.data/image2015-9-15%2021:26:5.png"></span></p><h2 id="UsingApacheHTrace-Example#7:ClientandServerwithasynchronousinvocation(client-side)">Example #7: Client and Server with asynchronous invocation (client-side)</h2><p>In this example server-side implementation of the JAX-RS service is going to be the default one:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeCont ent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Produces( { MediaType.APPLICATION_JSON } ) +<pre class="brush: java; gutter: false; theme: Default">@Produces( { MediaType.APPLICATION_JSON } ) @GET public Collection<Book> getBooks() { return Arrays.asList( @@ -335,14 +335,14 @@ public Collection<Book> getBooks() ); }</pre> </div></div><p>While the JAX-RS client implementation is going to perform the asynchronous invocation:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">final Future<Response> future = client +<pre class="brush: java; gutter: false; theme: Default">final Future<Response> future = client .target("http://localhost:8282/books") .request() .accept(MediaType.APPLICATION_JSON) .async() .get();</pre> </div></div><p>In this respect, there is no difference from the caller prospective however a bit more work is going under the hood to transfer the active tracing span from JAX-RS client request filter to client response filter as in general those are executed in different threads (similarly to server-side asynchronous JAX-RS resource invocation). The actual invocation of the request by the client (with process name <strong><span class="label label-default service-filter-label service-tag-filtered">jaxrsclient/192.168.0.100</span></strong>) and consequent invocation of the service on the server side (process name<strong> <span class="label label-default service-filter-label">jaxrsserver/192.168.0.100</span></strong>) is going to generate the following sample traces:</p><p><span class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img class="confluence-embedded-image" height="250" src="using-apache-htrace.data/image2015-9-16%2021:9:56.png"></span></p><h1 id="Using ApacheHTrace-DistributedTracingApacheHTraceandJAX-WSsupport">Distributed Tracing Apache HTrace and JAX-WS support</h1><p>Distributed tracing in the <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> is build primarily around JAX-RS 2.x implementation. However, JAX-WS is also supported but it requires to write some boiler-plate code and use <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> API directly (the JAX-WS integration is going to be enhanced in the nearest future). Essentially, from the server-side prospective the in/out interceptors, <strong>HTraceStartInterceptor</strong> and <strong>HTraceStopInterceptor </strong>respectively, should be configured as part of interceptor chains. The <strong>span</strong> receiver should be configured manually though, using <a shape="rect" class="external-link" href="http://htrace.incubator.apache.org/index.html">Apache HTrace</a> API, for example:</p><div class=" code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">final Map<String, String> properties = new HashMap<String, String>(); +<pre class="brush: java; gutter: false; theme: Default">final Map<String, String> properties = new HashMap<String, String>(); final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties); Trace.addReceiver(new StandardOutSpanReceiver(conf)); @@ -353,14 +353,14 @@ sf.getOutInterceptors().add(new HTraceSt ... sf.create();</pre> </div></div><div class="confluence-information-macro confluence-information-macro-information"><span class="aui-icon aui-icon-small aui-iconfont-info confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>Configuring right phases for interceptors is very important. The recommended phase for in-interceptor is <strong>PRE_INVOKE</strong> while for out-interceptor is <strong>PRE_MARSHAL</strong>. If wrong phases are being used, response or/and request headers could be ignored or not processed.</p></div></div><p>Similarly to the server-side, client-side needs own set of out/in interceptors, <strong>HTraceClientStartInterceptor</strong> and <strong>HTraceClientStopInterceptor</strong>. Please notice the difference from server-side: <strong>HTraceClientStartInterceptor</strong> becomes out-interceptor while <strong>HTraceClientStopInterceptor</strong> becomes in-interceptor. For example:</p><div class="code panel pdl" style="border-width: 1px;"><div cl ass="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); +<pre class="brush: java; gutter: false; theme: Default">JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); ... factory.getOutInterceptors().add(new HTraceClientStartInterceptor(sampler)); factory.getInInterceptors().add(new HTraceClientStopInterceptor()); ... factory.create();</pre> </div></div><h1 id="UsingApacheHTrace-PropagatingTraceDetailsToLogs">Propagating Trace Details To Logs</h1><p>In order to have better correlation between ongoing traces and logs, <a shape="rect" href="http://cxf.apache.org/">Apache CXF</a> since <strong>3.1.11</strong> / <strong>3.2.0</strong> releases distributes a helpful extension for <a shape="rect" class="external-link" href="https://logback.qos.ch/" rel="nofollow">Logback</a> users, <strong>LogbackSpanConverter</strong>. This converter can be used to complement log records with current trace details, such as tracer id and span id. For example, here is a simple <strong>logback.xml</strong> configuration file.</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;"><?xml version="1.0" encoding="UTF-8"?> +<pre class="brush: java; gutter: false; theme: Default"><?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="5 seconds"> <conversionRule conversionWord="trace" converterClass="org.apache.cxf.tracing.htrace.ext.LogbackSpanConverter" /> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> @@ -373,7 +373,7 @@ factory.create();</pre> </root> </configuration></pre> </div></div><p>In this case the tracing details will be propagated to each log record in following format: <strong><tracer_id>, span: <span id></strong>. For example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl"> -<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">[INFO] [-, -] 2017-03-11 14:40:13.603 org.eclipse.jetty.server.Server Started @2731ms +<pre class="brush: java; gutter: false; theme: Default">[INFO] [-, -] 2017-03-11 14:40:13.603 org.eclipse.jetty.server.Server Started @2731ms [INFO] [tracer-server/192.168.0.101, span: 6d3e0d975d4c883cce12aee1fd8f3e7e] 2017-03-11 14:40:24.013 com.example.rs.PeopleRestService Getting all employees [INFO] [tracer-server/192.168.0.101, span: 6d3e0d975d4c883c7592f4c2317dec22]