Repository: cxf Updated Branches: refs/heads/master 008c8835a -> 8a82bbfb5
CXF-6360: Integration with Apache HTrace. Added JAX-WS client-side interceptors and more test cases for HTrace tracing. Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/8a82bbfb Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/8a82bbfb Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/8a82bbfb Branch: refs/heads/master Commit: 8a82bbfb59141801864e74ebe92f499f117ba6ef Parents: 008c883 Author: reta <[email protected]> Authored: Thu Sep 24 21:41:33 2015 -0400 Committer: reta <[email protected]> Committed: Thu Sep 24 21:41:33 2015 -0400 ---------------------------------------------------------------------- .../htrace/AbstractHTraceClientInterceptor.java | 62 ++++++++++++++ .../htrace/AbstractHTraceClientProvider.java | 87 +++++++++++++++++++ .../htrace/HTraceClientStartInterceptor.java | 48 +++++++++++ .../htrace/HTraceClientStopInterceptor.java | 41 +++++++++ .../htrace/jaxrs/HTraceClientProvider.java | 61 ++------------ .../apache/cxf/systest/TestSpanReceiver.java | 66 +++++++++++++++ .../jaxrs/tracing/htrace/HTraceTracingTest.java | 52 ++++++++++++ .../jaxrs/tracing/htrace/TestSpanReceiver.java | 66 --------------- .../jaxws/tracing/htrace/HTraceTracingTest.java | 89 ++++++++++++++++++-- 9 files changed, 448 insertions(+), 124 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientInterceptor.java ---------------------------------------------------------------------- diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientInterceptor.java b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientInterceptor.java new file mode 100644 index 0000000..4cdbc9c --- /dev/null +++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientInterceptor.java @@ -0,0 +1,62 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.tracing.htrace; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import org.apache.cxf.message.Message; +import org.apache.cxf.phase.PhaseInterceptor; +import org.apache.htrace.Sampler; + +public abstract class AbstractHTraceClientInterceptor extends AbstractHTraceClientProvider + implements PhaseInterceptor<Message> { + + private String phase; + + protected AbstractHTraceClientInterceptor(final String phase, final Sampler< ? > sampler) { + super(sampler); + this.phase = phase; + } + + public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() { + return null; + } + + public Set<String> getAfter() { + return Collections.emptySet(); + } + + public Set<String> getBefore() { + return Collections.emptySet(); + } + + public String getId() { + return getClass().getName(); + } + + public String getPhase() { + return phase; + } + + public void handleFault(Message message) { + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientProvider.java ---------------------------------------------------------------------- diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientProvider.java b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientProvider.java new file mode 100644 index 0000000..d1cbcb0 --- /dev/null +++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/AbstractHTraceClientProvider.java @@ -0,0 +1,87 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.tracing.htrace; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.apache.cxf.common.logging.LogUtils; +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.TraceScope; + +public abstract class AbstractHTraceClientProvider extends AbstractTracingProvider { + protected static final Logger LOG = LogUtils.getL7dLogger(AbstractHTraceClientProvider.class); + protected static final String TRACE_SPAN = "org.apache.cxf.tracing.htrace.span"; + + private final Sampler< ? > sampler; + + public AbstractHTraceClientProvider(final Sampler< ? > sampler) { + this.sampler = sampler; + } + + protected TraceScope startTraceSpan(final Map<String, List<String>> requestHeaders, String path, String method) { + Span span = Trace.currentSpan(); + TraceScope scope = null; + + if (span == null) { + scope = Trace.startSpan(buildSpanDescription(path, method), sampler); + span = scope.getSpan(); + } + + if (span != null) { + final String traceIdHeader = getTraceIdHeader(); + final String spanIdHeader = getSpanIdHeader(); + + // Transfer tracing headers into the response headers + requestHeaders.put(traceIdHeader, Collections.singletonList(Long.toString(span.getTraceId()))); + requestHeaders.put(spanIdHeader, Collections.singletonList(Long.toString(span.getSpanId()))); + } + + // In case of asynchronous client invocation, the span should be detached as JAX-RS + // client request / response filters are going to be executed in different threads. + if (isAsyncInvocation() && scope != null) { + scope.detach(); + } + + return scope; + } + + private boolean isAsyncInvocation() { + return !JAXRSUtils.getCurrentMessage().getExchange().isSynchronous(); + } + + protected void stopTraceSpan(final TraceScope scope) { + if (scope != null) { + // If the client invocation was asynchronous , the trace scope has been created + // in another thread and should be re-attached to the current one. + if (scope.isDetached()) { + final TraceScope continueSpan = Trace.continueSpan(scope.getSpan()); + continueSpan.close(); + } else { + scope.close(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStartInterceptor.java ---------------------------------------------------------------------- diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStartInterceptor.java b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStartInterceptor.java new file mode 100644 index 0000000..72005eb --- /dev/null +++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStartInterceptor.java @@ -0,0 +1,48 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.tracing.htrace; + +import java.util.List; +import java.util.Map; + +import org.apache.cxf.helpers.CastUtils; +import org.apache.cxf.interceptor.Fault; +import org.apache.cxf.message.Message; +import org.apache.cxf.phase.Phase; +import org.apache.htrace.Sampler; +import org.apache.htrace.TraceScope; + +public class HTraceClientStartInterceptor extends AbstractHTraceClientInterceptor { + public HTraceClientStartInterceptor(final Sampler< ? > sampler) { + this(Phase.PRE_STREAM, sampler); + } + + public HTraceClientStartInterceptor(final String phase, final Sampler< ? > sampler) { + super(phase, sampler); + } + + @Override + public void handleMessage(Message message) throws Fault { + Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS)); + TraceScope scope = super.startTraceSpan(headers, (String)message.get(Message.REQUEST_URI), + (String)message.get(Message.HTTP_REQUEST_METHOD)); + message.getExchange().put(TRACE_SPAN, scope); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStopInterceptor.java ---------------------------------------------------------------------- diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStopInterceptor.java b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStopInterceptor.java new file mode 100644 index 0000000..d52fb07 --- /dev/null +++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/HTraceClientStopInterceptor.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.tracing.htrace; + +import org.apache.cxf.interceptor.Fault; +import org.apache.cxf.message.Message; +import org.apache.cxf.phase.Phase; +import org.apache.htrace.TraceScope; + +public class HTraceClientStopInterceptor extends AbstractHTraceClientInterceptor { + public HTraceClientStopInterceptor() { + this(Phase.RECEIVE); + } + + public HTraceClientStopInterceptor(final String phase) { + super(phase, null); + } + + @Override + public void handleMessage(Message message) throws Fault { + final TraceScope span = (TraceScope)message.getExchange().get(TRACE_SPAN); + super.stopTraceSpan(span); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java ---------------------------------------------------------------------- diff --git a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java index cfd5ca7..7a5f2c1 100644 --- a/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java +++ b/integration/tracing/tracing-htrace/src/main/java/org/apache/cxf/tracing/htrace/jaxrs/HTraceClientProvider.java @@ -24,83 +24,40 @@ import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.ClientResponseContext; import javax.ws.rs.client.ClientResponseFilter; -import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.Provider; -import org.apache.cxf.jaxrs.utils.JAXRSUtils; -import org.apache.cxf.tracing.AbstractTracingProvider; +import org.apache.cxf.tracing.htrace.AbstractHTraceClientProvider; import org.apache.htrace.Sampler; -import org.apache.htrace.Span; -import org.apache.htrace.Trace; import org.apache.htrace.TraceScope; import org.apache.htrace.impl.NeverSampler; @Provider -public class HTraceClientProvider extends AbstractTracingProvider +public class HTraceClientProvider extends AbstractHTraceClientProvider implements ClientRequestFilter, ClientResponseFilter { private static final String TRACE_SPAN = "org.apache.cxf.tracing.client.htrace.span"; - private final Sampler< ? > sampler; - public HTraceClientProvider() { this(NeverSampler.INSTANCE); } public HTraceClientProvider(final Sampler< ? > sampler) { - this.sampler = sampler; + super(sampler); } @Override public void filter(final ClientRequestContext requestContext) throws IOException { - Span span = Trace.currentSpan(); - TraceScope scope = null; - - if (span == null) { - scope = Trace.startSpan(buildSpanDescription(requestContext.getUri().toString(), - requestContext.getMethod()), sampler); - span = scope.getSpan(); - - if (span != null) { - requestContext.setProperty(TRACE_SPAN, scope); - } - } - - if (span != null) { - final MultivaluedMap<String, Object> requestHeaders = requestContext.getHeaders(); - - final String traceIdHeader = getTraceIdHeader(); - final String spanIdHeader = getSpanIdHeader(); - - // Transfer tracing headers into the response headers - requestHeaders.putSingle(traceIdHeader, Long.toString(span.getTraceId())); - requestHeaders.putSingle(spanIdHeader, Long.toString(span.getSpanId())); - } - - // In case of asynchronous client invocation, the span should be detached as JAX-RS - // client request / response filters are going to be executed in different threads. - if (isAsyncInvocation() && scope != null) { - scope.detach(); + final TraceScope scope = super.startTraceSpan(requestContext.getStringHeaders(), + requestContext.getUri().toString(), requestContext.getMethod()); + + if (scope != null) { + requestContext.setProperty(TRACE_SPAN, scope); } } @Override public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) throws IOException { - final TraceScope scope = (TraceScope)requestContext.getProperty(TRACE_SPAN); - if (scope != null) { - // If the client invocation was asynchronous , the trace scope has been created - // in another thread and should be re-attached to the current one. - if (scope.isDetached()) { - final TraceScope continueSpan = Trace.continueSpan(scope.getSpan()); - continueSpan.close(); - } else { - scope.close(); - } - } - } - - private boolean isAsyncInvocation() { - return !JAXRSUtils.getCurrentMessage().getExchange().isSynchronous(); + super.stopTraceSpan(scope); } } http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/systests/tracing/src/test/java/org/apache/cxf/systest/TestSpanReceiver.java ---------------------------------------------------------------------- diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/TestSpanReceiver.java b/systests/tracing/src/test/java/org/apache/cxf/systest/TestSpanReceiver.java new file mode 100644 index 0000000..e5f6c97 --- /dev/null +++ b/systests/tracing/src/test/java/org/apache/cxf/systest/TestSpanReceiver.java @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.systest; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.htrace.HTraceConfiguration; +import org.apache.htrace.Span; +import org.apache.htrace.SpanReceiver; +import org.apache.htrace.Trace; + +/** + * Test HTrace Span receiver + */ +public class TestSpanReceiver implements SpanReceiver { + private static List<Span> spans = new ArrayList<Span>(); + private static TestSpanReceiver instance; + + public TestSpanReceiver(final HTraceConfiguration conf) { + if (instance != null) { + Trace.removeReceiver(instance); + } + instance = this; + } + + public Collection<Span> getSpans() { + return spans; + } + + @Override + public void close() throws IOException { + } + + @Override + public void receiveSpan(Span span) { + spans.add(span); + } + + public static void clear() { + spans.clear(); + } + + public static List<Span> getAllSpans() { + return spans; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/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 11b7442..74704ba 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 @@ -18,6 +18,7 @@ */ package org.apache.cxf.systest.jaxrs.tracing.htrace; +import java.net.MalformedURLException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -34,6 +35,7 @@ import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.client.WebClient; import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; import org.apache.cxf.jaxrs.model.AbstractResourceInfo; +import org.apache.cxf.systest.TestSpanReceiver; import org.apache.cxf.systest.jaxrs.tracing.BookStore; import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase; import org.apache.cxf.testutil.common.AbstractBusTestServerBase; @@ -41,6 +43,8 @@ import org.apache.cxf.tracing.TracerHeaders; import org.apache.cxf.tracing.htrace.jaxrs.HTraceClientProvider; import org.apache.cxf.tracing.htrace.jaxrs.HTraceFeature; import org.apache.htrace.HTraceConfiguration; +import org.apache.htrace.Trace; +import org.apache.htrace.TraceScope; import org.apache.htrace.impl.AlwaysSampler; import org.junit.Before; import org.junit.BeforeClass; @@ -222,6 +226,54 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase { assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_SPAN_ID)); } + @Test + public void testThatProvidedSpanIsNotClosedWhenActive() throws MalformedURLException { + final Map<String, String> properties = new HashMap<String, String>(); + final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties); + final AlwaysSampler sampler = new AlwaysSampler(conf); + + try (final TraceScope scope = Trace.startSpan("test span", sampler)) { + final Response r = createWebClient("/bookstore/books", htraceClientProvider).get(); + assertEquals(Status.OK.getStatusCode(), r.getStatus()); + + assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2)); + assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("Get Books")); + assertThat(TestSpanReceiver.getAllSpans().get(0).getParents().length, equalTo(1)); + assertThat(TestSpanReceiver.getAllSpans().get(1).getDescription(), equalTo("GET bookstore/books")); + + assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_TRACE_ID)); + assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_SPAN_ID)); + } + + assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(3)); + assertThat(TestSpanReceiver.getAllSpans().get(2).getDescription(), equalTo("test span")); + } + + @Test + public void testThatProvidedSpanIsNotDetachedWhenActiveUsingAsyncClient() throws Exception { + final Map<String, String> properties = new HashMap<String, String>(); + final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties); + final AlwaysSampler sampler = new AlwaysSampler(conf); + + final WebClient client = createWebClient("/bookstore/books", htraceClientProvider); + try (final TraceScope scope = Trace.startSpan("test span", sampler)) { + final Future<Response> f = client.async().get(); + + final Response r = f.get(1, TimeUnit.SECONDS); + assertEquals(Status.OK.getStatusCode(), r.getStatus()); + assertThat(scope.isDetached(), equalTo(false)); + + assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2)); + assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("Get Books")); + assertThat(TestSpanReceiver.getAllSpans().get(1).getDescription(), equalTo("GET bookstore/books")); + + assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_TRACE_ID)); + assertTrue(r.getHeaders().containsKey(TracerHeaders.DEFAULT_HEADER_SPAN_ID)); + } + + assertThat(TestSpanReceiver.getAllSpans().get(2).getDescription(), equalTo("test span")); + } + protected WebClient createWebClient(final String url, final Object ... providers) { return WebClient .create("http://localhost:" + PORT + url, Arrays.asList(providers)) http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/TestSpanReceiver.java ---------------------------------------------------------------------- diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/TestSpanReceiver.java b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/TestSpanReceiver.java deleted file mode 100644 index 6567422..0000000 --- a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxrs/tracing/htrace/TestSpanReceiver.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cxf.systest.jaxrs.tracing.htrace; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.apache.htrace.HTraceConfiguration; -import org.apache.htrace.Span; -import org.apache.htrace.SpanReceiver; -import org.apache.htrace.Trace; - -/** - * Test HTrace Span receiver - */ -public class TestSpanReceiver implements SpanReceiver { - private static List<Span> spans = new ArrayList<Span>(); - private static TestSpanReceiver instance; - - public TestSpanReceiver(final HTraceConfiguration conf) { - if (instance != null) { - Trace.removeReceiver(instance); - } - instance = this; - } - - public Collection<Span> getSpans() { - return spans; - } - - @Override - public void close() throws IOException { - } - - @Override - public void receiveSpan(Span span) { - spans.add(span); - } - - public static void clear() { - spans.clear(); - } - - public static List<Span> getAllSpans() { - return spans; - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/8a82bbfb/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java ---------------------------------------------------------------------- diff --git a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java index 684a4b4..66810c1 100644 --- a/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java +++ b/systests/tracing/src/test/java/org/apache/cxf/systest/jaxws/tracing/htrace/HTraceTracingTest.java @@ -33,16 +33,19 @@ import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.apache.cxf.jaxws.JaxWsServerFactoryBean; import org.apache.cxf.message.Message; import org.apache.cxf.phase.Phase; -import org.apache.cxf.systest.jaxrs.tracing.htrace.TestSpanReceiver; +import org.apache.cxf.systest.TestSpanReceiver; import org.apache.cxf.systest.jaxws.tracing.BookStore; import org.apache.cxf.systest.jaxws.tracing.BookStoreService; import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase; import org.apache.cxf.testutil.common.AbstractBusTestServerBase; import org.apache.cxf.tracing.TracerHeaders; +import org.apache.cxf.tracing.htrace.HTraceClientStartInterceptor; +import org.apache.cxf.tracing.htrace.HTraceClientStopInterceptor; import org.apache.cxf.tracing.htrace.HTraceStartInterceptor; import org.apache.cxf.tracing.htrace.HTraceStopInterceptor; import org.apache.htrace.HTraceConfiguration; import org.apache.htrace.Trace; +import org.apache.htrace.TraceScope; import org.apache.htrace.impl.AlwaysSampler; import org.junit.Before; import org.junit.BeforeClass; @@ -51,6 +54,7 @@ import org.junit.Test; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.nullValue; public class HTraceTracingTest extends AbstractBusClientServerTestBase { @@ -72,6 +76,10 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase { } } + private interface Configurator { + void configure(final JaxWsProxyFactoryBean factory); + } + @BeforeClass public static void startServers() throws Exception { //keep out of process due to stack traces testing failures @@ -100,13 +108,11 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase { @Test public void testThatNewInnerSpanIsCreated() throws MalformedURLException { - final BookStoreService service = createJaxWsService(); - final Client proxy = ClientProxy.getClient(service); - final Map<String, List<String>> headers = new HashMap<String, List<String>>(); headers.put(TracerHeaders.DEFAULT_HEADER_TRACE_ID, Arrays.asList("10")); headers.put(TracerHeaders.DEFAULT_HEADER_SPAN_ID, Arrays.asList("20")); - proxy.getRequestContext().put(Message.PROTOCOL_HEADERS, headers); + + final BookStoreService service = createJaxWsService(headers); assertThat(service.getBooks().size(), equalTo(2)); assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2)); @@ -118,22 +124,93 @@ public class HTraceTracingTest extends AbstractBusClientServerTestBase { assertThat(response.get(TracerHeaders.DEFAULT_HEADER_SPAN_ID), hasItems("20")); } + @Test + public void testThatNewChildSpanIsCreatedWhenParentIsProvided() throws MalformedURLException { + final Map<String, String> properties = new HashMap<String, String>(); + final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties); + + final BookStoreService service = createJaxWsService(new Configurator() { + @Override + public void configure(final JaxWsProxyFactoryBean factory) { + factory.getOutInterceptors().add(new HTraceClientStartInterceptor(new AlwaysSampler(conf))); + factory.getInInterceptors().add(new HTraceClientStopInterceptor()); + } + }); + assertThat(service.getBooks().size(), equalTo(2)); + + assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(3)); + assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("Get Books")); + assertThat(TestSpanReceiver.getAllSpans().get(0).getParents().length, equalTo(1)); + + final Map<String, List<String>> response = getResponseHeaders(service); + assertThat(response.get(TracerHeaders.DEFAULT_HEADER_TRACE_ID), not(nullValue())); + assertThat(response.get(TracerHeaders.DEFAULT_HEADER_SPAN_ID), not(nullValue())); + } + + @Test + public void testThatProvidedSpanIsNotClosedWhenActive() throws MalformedURLException { + final Map<String, String> properties = new HashMap<String, String>(); + final HTraceConfiguration conf = HTraceConfiguration.fromMap(properties); + + final AlwaysSampler sampler = new AlwaysSampler(conf); + final BookStoreService service = createJaxWsService(new Configurator() { + @Override + public void configure(final JaxWsProxyFactoryBean factory) { + + factory.getOutInterceptors().add(new HTraceClientStartInterceptor(sampler)); + factory.getInInterceptors().add(new HTraceClientStopInterceptor()); + } + }); + + try (final TraceScope scope = Trace.startSpan("test span", sampler)) { + assertThat(service.getBooks().size(), equalTo(2)); + assertThat(Trace.isTracing(), equalTo(true)); + + assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(2)); + assertThat(TestSpanReceiver.getAllSpans().get(0).getDescription(), equalTo("Get Books")); + assertThat(TestSpanReceiver.getAllSpans().get(0).getParents().length, equalTo(1)); + assertThat(TestSpanReceiver.getAllSpans().get(1).getDescription(), equalTo("POST /BookStore")); + } + + assertThat(TestSpanReceiver.getAllSpans().size(), equalTo(3)); + assertThat(TestSpanReceiver.getAllSpans().get(2).getDescription(), equalTo("test span")); + + final Map<String, List<String>> response = getResponseHeaders(service); + assertThat(response.get(TracerHeaders.DEFAULT_HEADER_TRACE_ID), not(nullValue())); + assertThat(response.get(TracerHeaders.DEFAULT_HEADER_SPAN_ID), not(nullValue())); + } + + private BookStoreService createJaxWsService() throws MalformedURLException { return createJaxWsService(new HashMap<String, List<String>>()); } private BookStoreService createJaxWsService(final Map<String, List<String>> headers) throws MalformedURLException { + return createJaxWsService(headers, null); + } + + private BookStoreService createJaxWsService(final Configurator configurator) throws MalformedURLException { + return createJaxWsService(new HashMap<String, List<String>>(), configurator); + } + + private BookStoreService createJaxWsService(final Map<String, List<String>> headers, + final Configurator configurator) throws MalformedURLException { + JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.getOutInterceptors().add(new LoggingOutInterceptor()); factory.getInInterceptors().add(new LoggingInInterceptor()); factory.setServiceClass(BookStoreService.class); factory.setAddress("http://localhost:" + PORT + "/BookStore"); + if (configurator != null) { + configurator.configure(factory); + } + final BookStoreService service = (BookStoreService) factory.create(); final Client proxy = ClientProxy.getClient(service); proxy.getRequestContext().put(Message.PROTOCOL_HEADERS, headers); - return (BookStoreService) factory.create(); + return service; } private Map<String, List<String>> getResponseHeaders(final BookStoreService service) {
