Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 50A9418A5F for ; Wed, 16 Sep 2015 01:47:19 +0000 (UTC) Received: (qmail 47423 invoked by uid 500); 16 Sep 2015 01:47:19 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 47350 invoked by uid 500); 16 Sep 2015 01:47:19 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 47336 invoked by uid 99); 16 Sep 2015 01:47:19 -0000 Received: from eris.apache.org (HELO hades.apache.org) (140.211.11.105) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Sep 2015 01:47:19 +0000 Received: from hades.apache.org (localhost [127.0.0.1]) by hades.apache.org (ASF Mail Server at hades.apache.org) with ESMTP id DAF81AC022D for ; Wed, 16 Sep 2015 01:47:18 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r965607 - in /websites/production/cxf/content: cache/docs.pageCache docs/using-apache-htrace.data/image2015-9-15-21:26:5.png docs/using-apache-htrace.html Date: Wed, 16 Sep 2015 01:47:18 -0000 To: commits@cxf.apache.org From: buildbot@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20150916014718.DAF81AC022D@hades.apache.org> Author: buildbot Date: Wed Sep 16 01:47:18 2015 New Revision: 965607 Log: Production update by buildbot for cxf Added: websites/production/cxf/content/docs/using-apache-htrace.data/image2015-9-15-21:26:5.png (with props) 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. Added: websites/production/cxf/content/docs/using-apache-htrace.data/image2015-9-15-21:26:5.png ============================================================================== Binary file - no diff available. Propchange: websites/production/cxf/content/docs/using-apache-htrace.data/image2015-9-15-21:26:5.png ------------------------------------------------------------------------------ svn:mime-type = image/png 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 Sep 16 01:47:18 2015 @@ -117,14 +117,14 @@ Apache CXF -- Using Apache HTrace

+/*]]>*/

Overview

Apache HTrace is a tracing framework intended for use with distributed systems written in java. Since version 3.1.3, Apache CXF fully supports integration with Apache HTrace, 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.

Distributed Tracing in Nutshell

Distributed tracing, first described by Google in Dapper, a Large-Scale Distributed Systems Tracing Infrastructure 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. Apache HTrace is inspired by Dapper, a Large-Scale Distributed Systems Tracing Infrastructure paper and essentially is a full-fledged distributed tracing framework.

Distributed tracing is additional instrumentation layer on top of new or existing applications. In terms of distributed tracing, span represents a basic unit of work. For example, executing database query is a span. Spans are identified by a unique 64-bit ID for the span and another 64-bit ID for the trace the span is a part of. Spans also have other data, such as descriptions, timelines, key-value annotations, the ID of the span that caused them (parent), and process ID’s (normally IP address and process name). Spans are started and stopped, and they keep track of their timing information. Once span is created, it should be stopped at some point in the future. In turn, trace 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 PUT request.

From implementation prospective, and in context of Java applications, spans are attached to their threads (in general, thread which created the span should close it). However it is possible to transfer spans from thread to thread in order to model a complex execution flows. It is also possible to have many spans 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.

Another two important concepts of in context of distributed tracing are span receivers and samplers. Essentially, all spans (including start/stop time, key/value annotations, timelines, ..) should be persisted (or collected) somewhere. Span receiver is a collector within a process that is the destination of spans when a trace is running (it could be a console, local file, data store, ...). Apache HTrace provides span receivers for Apache HBase, Apache Flume and Twitter Zipkin. From other side, samplers allow to control the frequency of the tracing (all the time, never, probability driven, ...). Using the sampler is the way to minimize tracing overhead (or just amount of traces) by limiting them to particular conditions.

Distributed Tracing in Apache CXF

Apache CXF 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 tec hnique 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.

The current integration of distributed tracing in Apache CXF supports Apache HTrace only in JAX-RS 2.x applications. From high-level prospective, it consists of three main parts:

  • TracerContext (injectable through @Context annotation)
  • HTraceProvider (server-side JAX-RS provider) and HTraceClientProvider (client-side JAX-RS provider)
  • HTraceFeature (server-side Apache CXF feature to simplify Apache HTrace configuration and integration)

Apache CXF 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 HTraceProvider and HTraceClientProvider, but are configurable. The default header names are declared in the TracerHeaders class:

  • X-Trace-Id: contains a current trace ID
  • X-Span-Id: contains a current span ID

By default, HTraceProvider will try pass the currently active span through HTTP headers on each service invocation. If there is no active span, the new span will be created and passed through HTTP headers on per-invocation basis. Essentially, just registering the HTraceProvider on the client and HTraceClientProvider on the server is enough to have tracing context to be properly passed everywhere. The only configuration part which is necessary are span receiver(s) and sampler.

It is also worth to mention the way Apache CXF attaches the description to spans. With regards to the client integration, the description becomes a full URL being invoked prefixed by HTTP method, for example: GET http://localhost:8282/books. On the server side integration, the description becomes a relation JAX-RS resource path prefixed by HTTP method, f.e.: GET books, POST book/123

Configuring Client

There are a couple of way the JAX-RS client could be configured, depending on the client implementation. Apache CXF provides its own WebClient which could be configured just like that (in future versions, there would be a simpler ways to do that using client specific features):

final Map<String, String> properties = new HashMap<String, String>();
 final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties);
@@ -253,7 +253,32 @@ public Collection<Book> getBooks(@
        
     return Arrays.asList(book1.get(), book2.get());
 }
-

The actual invocation of the request by the client (with process name jaxrsclient/192.168.0.100) and consequent invocation of the service on the server side (process name jaxrsserver/192.168.0.100) is going to generate the following sample traces:

Example #6: Client and Server with asynchronous JAX-RS service (server-side)

TODO

+

The actual invocation of the request by the client (with process name jaxrsclient/192.168.0.100) and consequent invocation of the service on the server side (process name jaxrsserver/192.168.0.100) is going to generate the following sample traces:

Example #6: Client and Server with asynchronous JAX-RS service (server-side)

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, Apache CXF 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.

+
@Produces( { MediaType.APPLICATION_JSON } )
+@GET
+public void getBooks(@Suspended final AsyncResponse response, @Context final TracerContext tracer) throws Exception {
+    tracer.continueSpan(new Traceable<Future<Void>>() {
+        public Future<Void> call(final TracerContext context) throws Exception {
+            return executor.submit(
+                tracer.wrap("Getting Book", new Traceable<Void>() {
+                    public Void call(final TracerContext context) throws Exception {
+                        // Simulating a processing delay of 50ms
+                        Thread.sleep(50);
+                            
+                        response.resume(
+                            Arrays.asList(
+                                new Book("Apache CXF Web Service Development", "Naveen Balani, Rajeev Hathi")
+                            )
+                        );
+                            
+                        return null;
+                    }
+                })
+            );
+        }
+    });
+}
+

The actual invocation of the request by the client (with process name jaxrsclient/192.168.0.100) and consequent invocation of the service on the server side (process name jaxrsserver/192.168.0.100) is going to generate the following sample traces:

Example #7: Client and Server with asynchronous invocation (client-side)

TODO

Future Work

TODO