Repository: cxf Updated Branches: refs/heads/master 3261d7ddf -> a7cc783a5
CXF-6360: Integration with Apache HTrace. Implemented asynchronous invocation support using HTrace's continueSpan Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/a7cc783a Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/a7cc783a Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/a7cc783a Branch: refs/heads/master Commit: a7cc783a5036e2900a22290738f6aa76d9fcf271 Parents: 3261d7d Author: reta <[email protected]> Authored: Sun Aug 30 17:58:05 2015 -0400 Committer: reta <[email protected]> Committed: Sun Aug 30 17:58:05 2015 -0400 ---------------------------------------------------------------------- .../java/demo/jaxrs/tracing/server/Catalog.java | 21 +++++----- .../demo/jaxrs/tracing/server/CatalogStore.java | 4 -- .../tracing/htrace/AbstractHTraceProvider.java | 9 ++++- .../cxf/tracing/htrace/HTraceTracerContext.java | 26 +++++++++++- .../htrace/jaxrs/HTraceContextProvider.java | 10 +++++ .../org/apache/cxf/tracing/TracerContext.java | 2 + .../cxf/systest/jaxrs/tracing/BookStore.java | 42 +++++++++++++++++--- .../jaxrs/tracing/htrace/HTraceTracingTest.java | 21 +++++++++- 8 files changed, 112 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/a7cc783a/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/Catalog.java ---------------------------------------------------------------------- diff --git a/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/Catalog.java b/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/Catalog.java index d761d1a..105c53e 100644 --- a/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/Catalog.java +++ b/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/Catalog.java @@ -22,7 +22,6 @@ package demo.jaxrs.tracing.server; import java.io.IOException; import java.util.UUID; -import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -48,9 +47,6 @@ import org.apache.cxf.tracing.Traceable; import org.apache.cxf.tracing.TracerContext; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hbase.trace.SpanReceiverHost; - -import demo.jaxrs.tracing.conf.TracingConfiguration; @Path("/catalog") public class Catalog { @@ -61,7 +57,6 @@ public class Catalog { final Configuration configuration = HBaseConfiguration.create(); configuration.set("hbase.zookeeper.quorum", "hbase"); configuration.set("hbase.zookeeper.property.clientPort", "2181"); - configuration.set(SpanReceiverHost.SPAN_RECEIVERS_CONF_KEY, TracingConfiguration.SPAN_RECEIVER.getName()); store = new CatalogStore(configuration, "catalog"); } @@ -99,11 +94,19 @@ public class Catalog { @GET @Produces(MediaType.APPLICATION_JSON) - public void getBooks(@Suspended final AsyncResponse response) throws IOException { - executor.submit(new Callable<Void>() { + public void getBooks(@Suspended final AsyncResponse response, + @Context final TracerContext tracing) throws Exception { + tracing.continueSpan(new Traceable<Void>() { @Override - public Void call() throws Exception { - response.resume(store.scan()); + public Void call(final TracerContext context) throws Exception { + executor.submit(tracing.wrap("Looking for books", new Traceable<Void>() { + @Override + public Void call(final TracerContext context) throws Exception { + response.resume(store.scan()); + return null; + } + })); + return null; } }); http://git-wip-us.apache.org/repos/asf/cxf/blob/a7cc783a/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/CatalogStore.java ---------------------------------------------------------------------- diff --git a/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/CatalogStore.java b/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/CatalogStore.java index 060cbbb..6a37e13 100644 --- a/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/CatalogStore.java +++ b/distribution/src/main/release/samples/jax_rs/tracing_htrace/src/main/java/demo/jaxrs/tracing/server/CatalogStore.java @@ -39,18 +39,14 @@ import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.Table; -import org.apache.hadoop.hbase.trace.SpanReceiverHost; import org.apache.hadoop.hbase.util.Bytes; public class CatalogStore { - @SuppressWarnings("unused") - private final SpanReceiverHost spanReceiverHost; private final Connection connection; private final String tableName; public CatalogStore(final Configuration configuration, final String tableName) throws IOException { this.connection = ConnectionFactory.createConnection(configuration); - this.spanReceiverHost = SpanReceiverHost.getInstance(configuration); this.tableName = tableName; } http://git-wip-us.apache.org/repos/asf/cxf/blob/a7cc783a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceProvider.java ---------------------------------------------------------------------- diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceProvider.java b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceProvider.java index 8f397a7..380d97b 100644 --- a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceProvider.java +++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceProvider.java @@ -28,6 +28,7 @@ import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.jaxrs.utils.JAXRSUtils; import org.apache.cxf.tracing.AbstractTracingProvider; import org.apache.htrace.Sampler; +import org.apache.htrace.Span; import org.apache.htrace.Trace; import org.apache.htrace.TraceInfo; import org.apache.htrace.TraceScope; @@ -69,12 +70,12 @@ public abstract class AbstractHTraceProvider extends AbstractTracingProvider { // If the service resource is using asynchronous processing mode, the trace // scope will be closed in another thread and as such should be detached. if (isAsyncResponse()) { - traceScope.detach(); + propagateContinuationSpan(traceScope.detach()); } return traceScope; } - + protected void stopTraceSpan(final Map<String, List<String>> requestHeaders, final Map<String, List<Object>> responseHeaders, final TraceScope span) { @@ -100,6 +101,10 @@ public abstract class AbstractHTraceProvider extends AbstractTracingProvider { } } + private void propagateContinuationSpan(final Span continuationSpan) { + JAXRSUtils.getCurrentMessage().put(Span.class, continuationSpan); + } + protected boolean isAsyncResponse() { return !JAXRSUtils.getCurrentMessage().getExchange().isSynchronous(); } http://git-wip-us.apache.org/repos/asf/cxf/blob/a7cc783a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceTracerContext.java ---------------------------------------------------------------------- diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceTracerContext.java b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceTracerContext.java index 2e92435..9b97741 100644 --- a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceTracerContext.java +++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceTracerContext.java @@ -24,15 +24,22 @@ import java.util.concurrent.Callable; import org.apache.cxf.tracing.Traceable; import org.apache.cxf.tracing.TracerContext; import org.apache.htrace.Sampler; +import org.apache.htrace.Span; import org.apache.htrace.Trace; import org.apache.htrace.TraceScope; import org.apache.htrace.wrappers.TraceCallable; public class HTraceTracerContext implements TracerContext { private final Sampler< ? > sampler; - + private final Span continuationSpan; + public HTraceTracerContext(final Sampler< ? > sampler) { + this(sampler, null); + } + + public HTraceTracerContext(final Sampler< ? > sampler, final Span continuationSpan) { this.sampler = sampler; + this.continuationSpan = continuationSpan; } @Override @@ -42,6 +49,23 @@ public class HTraceTracerContext implements TracerContext { } @Override + public <T> T continueSpan(final Traceable<T> traceable) throws Exception { + TraceScope continueSpan = null; + + if (!Trace.isTracing() && continuationSpan != null) { + continueSpan = Trace.continueSpan(continuationSpan); + } + + try { + return traceable.call(new HTraceTracerContext(sampler)); + } finally { + if (continueSpan != null) { + continueSpan.close(); + } + } + } + + @Override public <T> Callable<T> wrap(final String desription, final Traceable<T> traceable) { final Callable<T> callable = new Callable<T>() { @Override http://git-wip-us.apache.org/repos/asf/cxf/blob/a7cc783a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceContextProvider.java ---------------------------------------------------------------------- diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceContextProvider.java b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceContextProvider.java index 453f0d4..b2f122e 100644 --- a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceContextProvider.java +++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceContextProvider.java @@ -25,6 +25,7 @@ import org.apache.cxf.message.Message; import org.apache.cxf.tracing.TracerContext; import org.apache.cxf.tracing.htrace.HTraceTracerContext; import org.apache.htrace.Sampler; +import org.apache.htrace.Span; import org.apache.htrace.impl.NeverSampler; @Provider @@ -37,6 +38,15 @@ public class HTraceContextProvider implements ContextProvider< TracerContext > { @Override public TracerContext createContext(final Message message) { + // Check if there is a trace scope passed along with the message + final Span continuationSpan = message.get(Span.class); + + // If trace scope is already present, let us check if it is detached + // (asynchronous invocation) + if (continuationSpan != null) { + return new HTraceTracerContext(sampler, continuationSpan); + } + return new HTraceTracerContext(sampler); } } http://git-wip-us.apache.org/repos/asf/cxf/blob/a7cc783a/rt/management/src/main/java/org/apache/cxf/tracing/TracerContext.java ---------------------------------------------------------------------- diff --git a/rt/management/src/main/java/org/apache/cxf/tracing/TracerContext.java b/rt/management/src/main/java/org/apache/cxf/tracing/TracerContext.java index 9ab9f58..325527c 100644 --- a/rt/management/src/main/java/org/apache/cxf/tracing/TracerContext.java +++ b/rt/management/src/main/java/org/apache/cxf/tracing/TracerContext.java @@ -21,6 +21,8 @@ package org.apache.cxf.tracing; import java.util.concurrent.Callable; public interface TracerContext { + <T> T continueSpan(final Traceable<T> traceable) throws Exception; + <T> T startSpan(final String desription); <T> Callable<T> wrap(final String desription, final Traceable<T> traceable); http://git-wip-us.apache.org/repos/asf/cxf/blob/a7cc783a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/BookStore.java ---------------------------------------------------------------------- diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/BookStore.java b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/BookStore.java index 186b364..c88d4ba 100644 --- a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/BookStore.java +++ b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/BookStore.java @@ -21,6 +21,7 @@ package org.apache.cxf.systest.jaxrs.tracing; import java.util.Arrays; import java.util.Collection; import java.util.UUID; +import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -59,13 +60,44 @@ public class BookStore { @GET @Path("/books/async") @Produces(MediaType.APPLICATION_JSON) - public void getBooksAsync(@Suspended final AsyncResponse response) { + public void getBooksAsync(@Suspended final AsyncResponse response) throws Exception { + tracer.continueSpan(new Traceable<Void>() { + @Override + public Void call(final TracerContext context) throws Exception { + executor.submit( + tracer.wrap("Processing books", new Traceable<Void>() { + @Override + public Void call(final TracerContext context) throws Exception { + // Simulate some running job + Thread.sleep(200); + + response.resume( + Arrays.asList( + new Book("Apache CXF in Action", UUID.randomUUID().toString()), + new Book("Mastering Apache CXF", UUID.randomUUID().toString()) + ) + ); + + return null; + } + } + )); + + return null; + } + }); + } + + @GET + @Path("/books/async/notrace") + @Produces(MediaType.APPLICATION_JSON) + public void getBooksAsyncNoTrace(@Suspended final AsyncResponse response) throws Exception { executor.submit( - tracer.wrap("Processing books", new Traceable<Void>() { + new Callable<Void>() { @Override - public Void call(final TracerContext context) throws Exception { + public Void call() throws Exception { // Simulate some running job - Thread.sleep(100); + Thread.sleep(200); response.resume( Arrays.asList( @@ -76,7 +108,7 @@ public class BookStore { return null; } - }) + } ); } http://git-wip-us.apache.org/repos/asf/cxf/blob/a7cc783a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java ---------------------------------------------------------------------- diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java index 35938a4..75efad5 100644 --- a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java +++ b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/HTraceTracingTest.java @@ -168,8 +168,24 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase { .get(); assertEquals(Status.OK.getStatusCode(), r.getStatus()); - assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(1)); + assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2)); assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("bookstore/books/async")); + assertThat(TestSpanReceiver.getAllSpans().get(1).getDescription(), equalTo("Processing books")); + + assertThat((String)r.getHeaders().getFirst(TracerHeaders.DEFAULT_HEADER_TRACE_ID), equalTo("10")); + assertThat((String)r.getHeaders().getFirst(TracerHeaders.DEFAULT_HEADER_SPAN_ID), equalTo("20")); + } + + @Test + public void testThatOuterSpanIsCreatedUsingAsyncInvocation() { + final Response r = createWebClient("/bookstore/books/async/notrace") + .header(TracerHeaders.DEFAULT_HEADER_TRACE_ID, 10L) + .header(TracerHeaders.DEFAULT_HEADER_SPAN_ID, 20L) + .get(); + assertEquals(Status.OK.getStatusCode(), r.getStatus()); + + assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(1)); + assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("bookstore/books/async/notrace")); assertThat((String)r.getHeaders().getFirst(TracerHeaders.DEFAULT_HEADER_TRACE_ID), equalTo("10")); assertThat((String)r.getHeaders().getFirst(TracerHeaders.DEFAULT_HEADER_SPAN_ID), equalTo("20")); @@ -180,8 +196,9 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase { final Response r = createWebClient("/bookstore/books/async").get(); assertEquals(Status.OK.getStatusCode(), r.getStatus()); - assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(1)); + assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2)); assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("bookstore/books/async")); + assertThat(TestSpanReceiver.getAllSpans().get(1).getDescription(), equalTo("Processing books")); } protected WebClient createWebClient(final String url, final Object ... providers) {
