You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2017/09/07 11:48:25 UTC

[2/2] cxf git commit: CXF-7439: Support OpenTracing Tracer API

CXF-7439: Support OpenTracing Tracer API


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/4080fbaf
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/4080fbaf
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/4080fbaf

Branch: refs/heads/master
Commit: 4080fbafc25f6a4ea30c72abf2ba3b6cedf7e604
Parents: e47f445
Author: reta <dr...@gmail.com>
Authored: Mon Sep 4 19:29:56 2017 -0400
Committer: reta <dr...@gmail.com>
Committed: Thu Sep 7 07:19:31 2017 -0400

----------------------------------------------------------------------
 .../jax_rs/tracing_opentracing/README.txt       |  30 ++
 .../samples/jax_rs/tracing_opentracing/pom.xml  | 135 +++++++
 .../java/demo/jaxrs/tracing/Slf4jLogSender.java |  46 +++
 .../java/demo/jaxrs/tracing/client/Client.java  |  55 +++
 .../java/demo/jaxrs/tracing/server/Catalog.java | 135 +++++++
 .../tracing/server/CatalogApplication.java      |  45 +++
 .../demo/jaxrs/tracing/server/CatalogStore.java |  71 ++++
 .../java/demo/jaxrs/tracing/server/Server.java  |  64 ++++
 distribution/src/main/release/samples/pom.xml   |   1 +
 integration/pom.xml                             |   1 +
 .../tracing/brave/AbstractBraveInterceptor.java |  34 +-
 integration/tracing/tracing-opentracing/pom.xml |  90 +++++
 .../AbstractOpenTracingClientInterceptor.java   |  63 ++++
 .../AbstractOpenTracingClientProvider.java      |  94 +++++
 .../AbstractOpenTracingInterceptor.java         |  68 ++++
 .../AbstractOpenTracingProvider.java            | 122 ++++++
 .../opentracing/OpenTracingClientFeature.java   |  47 +++
 .../OpenTracingClientStartInterceptor.java      |  51 +++
 .../OpenTracingClientStopInterceptor.java       |  49 +++
 .../tracing/opentracing/OpenTracingContext.java | 107 ++++++
 .../tracing/opentracing/OpenTracingFeature.java |  55 +++
 .../OpenTracingStartInterceptor.java            |  49 +++
 .../opentracing/OpenTracingStopInterceptor.java |  65 ++++
 .../cxf/tracing/opentracing/TraceScope.java     |  50 +++
 .../internal/TextMapInjectAdapter.java          |  45 +++
 .../jaxrs/OpenTracingClientProvider.java        |  60 +++
 .../jaxrs/OpenTracingContextProvider.java       |  50 +++
 .../opentracing/jaxrs/OpenTracingFeature.java   |  46 +++
 .../opentracing/jaxrs/OpenTracingProvider.java  |  77 ++++
 parent/pom.xml                                  |  17 +
 .../cxf/tracing/AbstractTracingProvider.java    |  44 +++
 systests/tracing/pom.xml                        |  20 +
 .../apache/cxf/systest/TestSpanReceiver.java    |  60 ---
 .../apache/cxf/systest/TestSpanReporter.java    |  42 ---
 .../cxf/systest/brave/TestSpanReporter.java     |  42 +++
 .../cxf/systest/htrace/TestSpanReceiver.java    |  60 +++
 .../apache/cxf/systest/jaeger/TestSender.java   |  54 +++
 .../jaxrs/tracing/brave/BraveTracingTest.java   |   2 +-
 .../jaxrs/tracing/htrace/HTraceTracingTest.java |   2 +-
 .../jaxrs/tracing/opentracing/HasSpan.java      |  71 ++++
 .../tracing/opentracing/IsLogContaining.java    |  47 +++
 .../tracing/opentracing/IsTagContaining.java    |  33 ++
 .../opentracing/OpenTracingTracingTest.java     | 376 +++++++++++++++++++
 .../systest/jaxws/tracing/brave/BookStore.java  |   2 +-
 .../jaxws/tracing/brave/BraveTracingTest.java   |   2 +-
 .../jaxws/tracing/htrace/HTraceTracingTest.java |   2 +-
 .../jaxws/tracing/opentracing/BookStore.java    |  57 +++
 .../opentracing/OpenTracingTracingTest.java     | 254 +++++++++++++
 48 files changed, 2854 insertions(+), 138 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/distribution/src/main/release/samples/jax_rs/tracing_opentracing/README.txt
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/tracing_opentracing/README.txt b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/README.txt
new file mode 100644
index 0000000..d8f5ba8
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/README.txt
@@ -0,0 +1,30 @@
+JAX-RS Brave/OpenZipkin Tracing Demo 
+=================
+
+The demo shows a basic usage of OpenTracing API + Jaeger distributed tracer 
+with REST based Web Services using  JAX-RS 2.0 (JSR-339). The REST server provides the 
+following services at URL http://localhost:9000/catalog: 
+
+ - GET to http://localhost:9000/catalog 
+ - POST to http://localhost:9000/catalog 
+ - GET to http://localhost:9000/catalog/<id> 
+ - DELETE to URL http://localhost:9000/catalog/<id> 
+
+Building and running the demo using Maven
+---------------------------------------
+
+From the base directory of this sample (i.e., where this README file is
+located), the Maven pom.xml file can be used to build and run the demo. 
+
+
+Using either UNIX or Windows:
+
+  mvn install
+  mvn -Pserver  (from one command line window)
+  mvn -Pclient  (from a second command line window)
+    
+
+To remove the target dir, run mvn clean".
+
+
+

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/distribution/src/main/release/samples/jax_rs/tracing_opentracing/pom.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/tracing_opentracing/pom.xml b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/pom.xml
new file mode 100644
index 0000000..e1821450
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/pom.xml
@@ -0,0 +1,135 @@
+<?xml version="1.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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>jax_rs_tracing_opentracing</artifactId>
+    <name>JAX-RS Demo Using Distributed Tracing with OpenTracing API and Jaeger</name>
+    <description>JAX-RS Demo Using Distributed Tracing with OpenTracing API and Jaeger</description>
+    <parent>
+        <groupId>org.apache.cxf.samples</groupId>
+        <artifactId>cxf-samples</artifactId>
+        <version>3.2.1-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
+    </parent>
+    <properties>
+        <cxf.version>${project.version}</cxf.version>
+    </properties>
+    <profiles>
+        <profile>
+            <id>server</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>demo.jaxrs.tracing.server.Server</mainClass>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>client</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>demo.jaxrs.tracing.client.Client</mainClass>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http</artifactId>
+            <version>3.2.0-SNAPSHOT</version>
+        </dependency>
+        <!-- This dependency is needed if you're using the Jetty container -->
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-jetty</artifactId>
+            <version>3.2.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>3.2.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-client</artifactId>
+            <version>3.2.0-SNAPSHOT</version>
+        </dependency>    
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-integration-tracing-opentracing</artifactId>
+            <version>3.2.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-extension-providers</artifactId>
+            <version>3.2.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.json</groupId>
+            <artifactId>javax.json-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish</groupId>
+            <artifactId>javax.json</artifactId>
+        </dependency>                    
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-webapp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.uber.jaeger</groupId>
+            <artifactId>jaeger-core</artifactId>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/Slf4jLogSender.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/Slf4jLogSender.java b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/Slf4jLogSender.java
new file mode 100644
index 0000000..1fd3486
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/Slf4jLogSender.java
@@ -0,0 +1,46 @@
+/**
+ * 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 demo.jaxrs.tracing;
+
+import com.uber.jaeger.Span;
+import com.uber.jaeger.exceptions.SenderException;
+import com.uber.jaeger.senders.Sender;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Slf4jLogSender implements Sender {
+    private static final Logger LOG = LoggerFactory.getLogger(Slf4jLogSender.class);
+    @Override
+    public int append(Span span) throws SenderException {
+        LOG.info("{}", span);
+        return 0;
+    }
+
+    @Override
+    public int flush() throws SenderException {
+        return 0;
+    }
+
+    @Override
+    public int close() throws SenderException {
+        return 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/client/Client.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/client/Client.java b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/client/Client.java
new file mode 100644
index 0000000..b34ec2c
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/client/Client.java
@@ -0,0 +1,55 @@
+/**
+ * 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 demo.jaxrs.tracing.client;
+
+import java.util.Arrays;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import com.uber.jaeger.Configuration;
+import com.uber.jaeger.samplers.ConstSampler;
+
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.tracing.opentracing.jaxrs.OpenTracingClientProvider;
+
+import demo.jaxrs.tracing.Slf4jLogSender;
+import io.opentracing.Tracer;
+
+public final class Client {
+    private Client() {
+    }
+
+    public static void main(final String[] args) throws Exception {
+        final Tracer tracer = new Configuration("tracer-client", 
+                new Configuration.SamplerConfiguration(ConstSampler.TYPE, 1),
+                new Configuration.ReporterConfiguration(new Slf4jLogSender())
+            ).getTracer();
+        final OpenTracingClientProvider provider = new OpenTracingClientProvider(tracer);
+
+        final Response response = WebClient
+            .create("http://localhost:9000/catalog", Arrays.asList(provider))
+            .accept(MediaType.APPLICATION_JSON)
+            .get();
+
+        System.out.println(response.readEntity(String.class));
+        response.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/Catalog.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/Catalog.java b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/Catalog.java
new file mode 100644
index 0000000..141effc
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/Catalog.java
@@ -0,0 +1,135 @@
+/**
+ * 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 demo.jaxrs.tracing.server;
+
+
+import java.io.IOException;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.cxf.tracing.Traceable;
+import org.apache.cxf.tracing.TracerContext;
+
+@Path("/catalog")
+public class Catalog {
+    private final ExecutorService executor = Executors.newFixedThreadPool(2);
+    private final CatalogStore store;
+
+    public Catalog() {
+        store = new CatalogStore();
+    }
+
+    @POST
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response addBook(@Context final UriInfo uriInfo, @Context final TracerContext tracing,
+            @FormParam("title") final String title)  {
+        try {
+            final String id = UUID.randomUUID().toString();
+
+            executor.submit(
+                tracing.wrap("Inserting New Book",
+                    new Traceable<Void>() {
+                        public Void call(final TracerContext context) throws Exception {
+                            store.put(id, title);
+                            return null;
+                        }
+                    }
+                )
+            ).get(10, TimeUnit.SECONDS);
+
+            return Response
+                .created(uriInfo.getRequestUriBuilder().path(id).build())
+                .build();
+        } catch (final Exception ex) {
+            return Response
+                .serverError()
+                .entity(Json
+                     .createObjectBuilder()
+                     .add("error", ex.getMessage())
+                     .build())
+                .build();
+        }
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public void getBooks(@Suspended final AsyncResponse response,
+            @Context final TracerContext tracing) throws Exception {
+        tracing.continueSpan(new Traceable<Void>() {
+            @Override
+            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;
+            }
+        });
+    }
+
+    @GET
+    @Path("/{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public JsonObject getBook(@PathParam("id") final String id) throws IOException {
+        final JsonObject book = store.get(id);
+
+        if (book == null) {
+            throw new NotFoundException("Book with does not exists: " + id);
+        }
+
+        return book;
+    }
+
+    @DELETE
+    @Path("/{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response delete(@PathParam("id") final String id) throws IOException {
+        if (!store.remove(id)) {
+            throw new NotFoundException("Book with does not exists: " + id);
+        }
+
+        return Response.ok().build();
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/CatalogApplication.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/CatalogApplication.java b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/CatalogApplication.java
new file mode 100644
index 0000000..9c19a79
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/CatalogApplication.java
@@ -0,0 +1,45 @@
+/**
+ * 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 demo.jaxrs.tracing.server;
+
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+import org.apache.cxf.jaxrs.provider.jsrjsonp.JsrJsonpProvider;
+import org.apache.cxf.tracing.opentracing.OpenTracingFeature;
+
+@ApplicationPath("/")
+public class CatalogApplication extends Application {
+    @Override
+    public Set<Object> getSingletons() {
+        return new HashSet<>(
+            Arrays.asList(
+                new Catalog(),
+                new OpenTracingFeature(),
+                new JsrJsonpProvider()
+            )
+        );
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/CatalogStore.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/CatalogStore.java b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/CatalogStore.java
new file mode 100644
index 0000000..9d6b8c7
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/CatalogStore.java
@@ -0,0 +1,71 @@
+/**
+ * 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 demo.jaxrs.tracing.server;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+
+public class CatalogStore {
+    private final Map<String, String> books = new ConcurrentHashMap<>();
+
+    public CatalogStore() {
+    }
+
+    public boolean remove(final String key) throws IOException {
+        return books.remove(key) != null;
+    }
+
+    public JsonObject get(final String key) throws IOException {
+        final String title = books.get(key);
+
+        if (title != null) {
+            return Json.createObjectBuilder()
+                .add("id", key)
+                .add("title", title)
+                .build();
+        }
+
+        return null;
+    }
+
+    public void put(final String key, final String title) throws IOException {
+        books.put(key, title);
+    }
+
+    public JsonArray scan() throws IOException {
+        final JsonArrayBuilder builder = Json.createArrayBuilder();
+
+        for (Map.Entry<String, String> entry: books.entrySet()) {
+            builder.add(Json.createObjectBuilder()
+                .add("id", entry.getKey())
+                .add("title", entry.getValue())
+            );
+        }
+
+        return builder.build();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/Server.java
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/Server.java b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/Server.java
new file mode 100644
index 0000000..402637e
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/tracing_opentracing/src/main/java/demo/jaxrs/tracing/server/Server.java
@@ -0,0 +1,64 @@
+/**
+ * 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 demo.jaxrs.tracing.server;
+
+import com.uber.jaeger.Configuration;
+import com.uber.jaeger.samplers.ConstSampler;
+
+import org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+import io.opentracing.Tracer;
+import io.opentracing.util.GlobalTracer;
+
+public class Server {
+    protected Server() throws Exception {
+        org.eclipse.jetty.server.Server server = new org.eclipse.jetty.server.Server(9000);
+
+        // Register and map the dispatcher servlet
+        final ServletHolder servletHolder = new ServletHolder(new CXFNonSpringJaxrsServlet());
+        final ServletContextHandler context = new ServletContextHandler();
+        context.setContextPath("/");
+        context.addServlet(servletHolder, "/*");
+
+        servletHolder.setInitParameter("javax.ws.rs.Application",
+            CatalogApplication.class.getName());
+
+        final Tracer tracer = new Configuration("tracer-server", 
+                new Configuration.SamplerConfiguration(ConstSampler.TYPE, 1),
+                new Configuration.ReporterConfiguration()
+            ).getTracer();
+        GlobalTracer.register(tracer);
+        
+        server.setHandler(context);
+        server.start();
+        server.join();
+    }
+
+    public static void main(String args[]) throws Exception {
+        new Server();
+        System.out.println("Server ready...");
+
+        Thread.sleep(5 * 6000 * 1000);
+        System.out.println("Server exiting");
+        System.exit(0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/distribution/src/main/release/samples/pom.xml
----------------------------------------------------------------------
diff --git a/distribution/src/main/release/samples/pom.xml b/distribution/src/main/release/samples/pom.xml
index a9fa9ad..e9014fa 100644
--- a/distribution/src/main/release/samples/pom.xml
+++ b/distribution/src/main/release/samples/pom.xml
@@ -125,6 +125,7 @@
         <module>jax_rs/tracing_brave</module>
         <module>jax_rs/tracing_brave_osgi</module>
         <module>jaxws_tracing_brave_osgi</module>
+        <module>jax_rs/tracing_opentracing</module>
     </modules>
     <dependencyManagement>
         <dependencies>

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/pom.xml
----------------------------------------------------------------------
diff --git a/integration/pom.xml b/integration/pom.xml
index f26b0e1..43ae799 100644
--- a/integration/pom.xml
+++ b/integration/pom.xml
@@ -34,6 +34,7 @@
         <module>cdi</module>
         <module>tracing/tracing-htrace</module>
         <module>tracing/tracing-brave</module>
+        <module>tracing/tracing-opentracing</module>
         <module>spring-boot</module>
     </modules>
 </project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java
index 91d54ed..8a07bdb 100644
--- a/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java
+++ b/integration/tracing/tracing-brave/src/main/java/org/apache/cxf/tracing/brave/AbstractBraveInterceptor.java
@@ -19,7 +19,6 @@
 package org.apache.cxf.tracing.brave;
 
 import java.net.URI;
-import java.net.URISyntaxException;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -32,6 +31,7 @@ import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.phase.PhaseInterceptor;
+import org.apache.cxf.tracing.AbstractTracingProvider;
 
 import brave.http.HttpTracing;
 
@@ -52,37 +52,9 @@ public abstract class AbstractBraveInterceptor extends AbstractBraveProvider imp
             Object value = message.get(key);
             return (value instanceof String) ? value.toString() : null;
         }
-
-        private String getUriSt() {
-            String uri = safeGet(Message.REQUEST_URL);
-            if (uri == null) {
-                String address = safeGet(Message.ENDPOINT_ADDRESS);
-                uri = safeGet(Message.REQUEST_URI);
-                if (uri != null && uri.startsWith("/")) {
-                    if (address != null && !address.startsWith(uri)) {
-                        if (address.endsWith("/") && address.length() > 1) {
-                            address = address.substring(0, address.length());
-                        }
-                        uri = address + uri;
-                    }
-                } else {
-                    uri = address;
-                }
-            }
-            String query = safeGet(Message.QUERY_STRING);
-            if (query != null) {
-                return uri + "?" + query;
-            }
-            return uri;
-        }
-
+      
         URI getUri() {
-            try {
-                String uriSt = getUriSt();
-                return uriSt != null ? new URI(uriSt) : new URI("");
-            } catch (URISyntaxException e) {
-                throw new RuntimeException(e.getMessage(), e);
-            }
+            return AbstractTracingProvider.getUri(message);
         }
 
         Message getEffectiveMessage() {

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/pom.xml
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/pom.xml b/integration/tracing/tracing-opentracing/pom.xml
new file mode 100644
index 0000000..2629d32
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/pom.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>cxf-integration-tracing-opentracing</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache CXF Distributed Tracing using OpenTracing</name>
+    <description>Apache CXF Distributed using OpenTracing</description>
+    <url>http://cxf.apache.org</url>
+    <parent>
+        <groupId>org.apache.cxf</groupId>
+        <artifactId>cxf-parent</artifactId>
+        <version>3.2.1-SNAPSHOT</version>
+        <relativePath>../../../parent/pom.xml</relativePath>
+    </parent>
+    
+    <properties>
+        <cxf.osgi.export>
+            org.apache.cxf.tracing,
+            org.apache.cxf.tracing.opentracing,
+            org.apache.cxf.tracing.opentracing.jaxrs
+        </cxf.osgi.export>
+    </properties>
+    
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${project.version}</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxws</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-management</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.opentracing</groupId>
+            <artifactId>opentracing-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.opentracing</groupId>
+            <artifactId>opentracing-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-jetty</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingClientInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingClientInterceptor.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingClientInterceptor.java
new file mode 100644
index 0000000..e758b3e
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingClientInterceptor.java
@@ -0,0 +1,63 @@
+/**
+ * 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.opentracing;
+
+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 io.opentracing.Tracer;
+
+public abstract class AbstractOpenTracingClientInterceptor extends AbstractOpenTracingClientProvider
+        implements PhaseInterceptor<Message> {
+
+    private String phase;
+
+    protected AbstractOpenTracingClientInterceptor(final String phase, final Tracer tracer) {
+        super(tracer);
+        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/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingClientProvider.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingClientProvider.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingClientProvider.java
new file mode 100644
index 0000000..8a1bdd7
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingClientProvider.java
@@ -0,0 +1,94 @@
+/**
+ * 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.opentracing;
+
+import java.net.URI;
+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.cxf.tracing.opentracing.internal.TextMapInjectAdapter;
+
+import io.opentracing.ActiveSpan;
+import io.opentracing.ActiveSpan.Continuation;
+import io.opentracing.Tracer;
+import io.opentracing.propagation.Format.Builtin;
+
+public abstract class AbstractOpenTracingClientProvider extends AbstractTracingProvider {
+    protected static final Logger LOG = LogUtils.getL7dLogger(AbstractOpenTracingClientProvider.class);
+    protected static final String TRACE_SPAN = "org.apache.cxf.tracing.client.opentracing.span";
+
+    private final Tracer tracer;
+
+    public AbstractOpenTracingClientProvider(final Tracer tracer) {
+        this.tracer = tracer;
+    }
+
+    protected TraceScopeHolder<TraceScope> startTraceSpan(final Map<String, List<String>> requestHeaders,
+            URI uri, String method) {
+
+        ActiveSpan span = tracer.activeSpan();
+        boolean managed = false;
+        if (span == null) {
+            span = tracer.buildSpan(buildSpanDescription(uri.toString(), method)).startActive();
+            managed = true;
+        }
+        
+        tracer.inject(span.context(), Builtin.HTTP_HEADERS, new TextMapInjectAdapter(requestHeaders));
+
+        // 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.
+        Continuation continuation = null;
+        if (isAsyncInvocation() && managed) {
+            continuation = span.capture();
+            span.deactivate();
+        }
+
+        return new TraceScopeHolder<TraceScope>(new TraceScope(span, continuation, managed), 
+            continuation != null /* detached */);
+    }
+
+    private boolean isAsyncInvocation() {
+        return !JAXRSUtils.getCurrentMessage().getExchange().isSynchronous();
+    }
+
+    protected void stopTraceSpan(final TraceScopeHolder<TraceScope> holder, final int responseStatus) {
+        if (holder == null) {
+            return;
+        }
+
+        final TraceScope scope = holder.getScope();
+        if (scope != null) {
+            ActiveSpan span = scope.getSpan();
+            
+            // If the client invocation was asynchronous , the trace span has been created
+            // in another thread and should be re-attached to the current one.
+            if (holder.isDetached()) {
+                span = scope.getContinuation().activate();
+            }
+
+            if (scope.isManaged()) {
+                span.close();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingInterceptor.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingInterceptor.java
new file mode 100644
index 0000000..d954e23
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingInterceptor.java
@@ -0,0 +1,68 @@
+/**
+ * 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.opentracing;
+
+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 io.opentracing.Tracer;
+
+public abstract class AbstractOpenTracingInterceptor extends AbstractOpenTracingProvider 
+        implements PhaseInterceptor<Message> {
+
+    private final String phase;
+
+    protected AbstractOpenTracingInterceptor(String phase, Tracer tracer) {
+        super(tracer);
+        this.phase = phase;
+    }
+
+    @Override
+    public Set<String> getAfter() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Set<String> getBefore() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public String getId() {
+        return getClass().getName();
+    }
+
+    @Override
+    public String getPhase() {
+        return phase;
+    }
+
+    @Override
+    public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() {
+        return null;
+    }
+
+    @Override
+    public void handleFault(Message message) {
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingProvider.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingProvider.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingProvider.java
new file mode 100644
index 0000000..2c41c38
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/AbstractOpenTracingProvider.java
@@ -0,0 +1,122 @@
+/**
+ * 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.opentracing;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.tracing.AbstractTracingProvider;
+
+import io.opentracing.ActiveSpan;
+import io.opentracing.ActiveSpan.Continuation;
+import io.opentracing.SpanContext;
+import io.opentracing.Tracer;
+import io.opentracing.propagation.Format.Builtin;
+import io.opentracing.propagation.TextMapExtractAdapter;
+
+public abstract class AbstractOpenTracingProvider extends AbstractTracingProvider {
+    protected static final Logger LOG = LogUtils.getL7dLogger(AbstractOpenTracingProvider.class);
+    protected static final String TRACE_SPAN = "org.apache.cxf.tracing.opentracing.span";
+
+    protected final Tracer tracer;
+    
+    protected AbstractOpenTracingProvider(final Tracer tracer) {
+        this.tracer = tracer;
+    }
+
+    protected TraceScopeHolder<TraceScope> startTraceSpan(final Map<String, List<String>> requestHeaders,
+            URI uri, String method) {
+
+        SpanContext parent = tracer.extract(Builtin.HTTP_HEADERS, 
+            new TextMapExtractAdapter(
+                requestHeaders
+                    .entrySet()
+                    .stream()
+                    .collect(Collectors.toMap(Map.Entry::getKey, this::getFirstValueOrEmpty))
+            ));
+        
+        ActiveSpan scope = null;
+        if (parent == null) {
+            scope = tracer.buildSpan(buildSpanDescription(uri.getPath(), method)).startActive();
+        } else {
+            scope = tracer.buildSpan(buildSpanDescription(uri.getPath(), method)).asChildOf(parent).startActive();
+        }
+        
+        // If the service resource is using asynchronous processing mode, the trace
+        // scope will be closed in another thread and as such should be detached.
+        Continuation continuation = null;
+        if (isAsyncResponse()) {
+           // Do not modify the current context span
+            continuation = scope.capture();
+            propagateContinuationSpan(continuation);
+            scope.deactivate();
+        } 
+
+        return new TraceScopeHolder<TraceScope>(new TraceScope(scope, continuation), 
+            continuation != null);
+    }
+
+    protected void stopTraceSpan(final Map<String, List<String>> requestHeaders,
+                                 final Map<String, List<Object>> responseHeaders,
+                                 final int responseStatus,
+                                 final TraceScopeHolder<TraceScope> holder) {
+
+        if (holder == null) {
+            return;
+        }
+
+        final TraceScope scope = holder.getScope();
+        if (scope != null) {
+            ActiveSpan span = scope.getSpan();
+
+            // If the service resource is using asynchronous processing mode, the trace
+            // scope has been created in another thread and should be re-attached to the current
+            // one.
+            if (holder.isDetached()) {
+                span = scope.getContinuation().activate();
+            }
+
+            span.close();
+        }
+    }
+
+    protected boolean isAsyncResponse() {
+        return !PhaseInterceptorChain.getCurrentMessage().getExchange().isSynchronous();
+    }
+
+    private void propagateContinuationSpan(final Continuation continuationScope) {
+        PhaseInterceptorChain.getCurrentMessage().put(Continuation.class, continuationScope);
+    }
+
+    private String getFirstValueOrEmpty(Map.Entry<String, List<String>> entry) {
+        final List<String> values = entry.getValue();
+
+        if (values == null || values.isEmpty()) {
+            return "";
+        }
+        
+        final String value = values.get(0);
+        return (value != null) ? value : "";
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientFeature.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientFeature.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientFeature.java
new file mode 100644
index 0000000..d5ab3cf
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientFeature.java
@@ -0,0 +1,47 @@
+/**
+ * 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.opentracing;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.annotations.Provider;
+import org.apache.cxf.annotations.Provider.Scope;
+import org.apache.cxf.annotations.Provider.Type;
+import org.apache.cxf.common.injection.NoJSR250Annotations;
+import org.apache.cxf.feature.AbstractFeature;
+import org.apache.cxf.interceptor.InterceptorProvider;
+
+import io.opentracing.Tracer;
+
+@NoJSR250Annotations
+@Provider(value = Type.Feature, scope = Scope.Client)
+public class OpenTracingClientFeature extends AbstractFeature {
+    private OpenTracingClientStartInterceptor out;
+    private OpenTracingClientStopInterceptor in;
+    
+    public OpenTracingClientFeature(Tracer tracer) {
+        out = new OpenTracingClientStartInterceptor(tracer);
+        in = new OpenTracingClientStopInterceptor(tracer);
+    }
+
+    @Override
+    protected void initializeProvider(InterceptorProvider provider, Bus bus) {
+        provider.getInInterceptors().add(in);
+        provider.getOutInterceptors().add(out);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientStartInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientStartInterceptor.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientStartInterceptor.java
new file mode 100644
index 0000000..011fef6
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientStartInterceptor.java
@@ -0,0 +1,51 @@
+/**
+ * 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.opentracing;
+
+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 io.opentracing.Tracer;
+
+public class OpenTracingClientStartInterceptor extends AbstractOpenTracingClientInterceptor {
+    public OpenTracingClientStartInterceptor(final Tracer tracer) {
+        this(Phase.PRE_STREAM, tracer);
+    }
+
+    public OpenTracingClientStartInterceptor(final String phase, final Tracer tracer) {
+        super(phase, tracer);
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        final Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
+        final TraceScopeHolder<TraceScope> holder = super.startTraceSpan(headers,
+            getUri(message), (String)message.get(Message.HTTP_REQUEST_METHOD));
+
+        if (holder != null) {
+            message.getExchange().put(TRACE_SPAN, holder);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientStopInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientStopInterceptor.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientStopInterceptor.java
new file mode 100644
index 0000000..0c28185
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingClientStopInterceptor.java
@@ -0,0 +1,49 @@
+/**
+ * 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.opentracing;
+
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.Phase;
+
+import io.opentracing.Tracer;
+
+public class OpenTracingClientStopInterceptor extends AbstractOpenTracingClientInterceptor {
+    public OpenTracingClientStopInterceptor(final Tracer tracer) {
+        this(Phase.RECEIVE, tracer);
+    }
+
+    public OpenTracingClientStopInterceptor(final String phase, final Tracer tracer) {
+        super(phase, tracer);
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        @SuppressWarnings("unchecked")
+        final TraceScopeHolder<TraceScope> holder =
+            (TraceScopeHolder<TraceScope>)message.getExchange().get(TRACE_SPAN);
+
+        Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE);
+        if (responseCode == null) {
+            responseCode = 200;
+        }
+
+        super.stopTraceSpan(holder, responseCode);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingContext.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingContext.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingContext.java
new file mode 100644
index 0000000..772d685
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingContext.java
@@ -0,0 +1,107 @@
+/**
+ * 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.opentracing;
+
+import java.util.concurrent.Callable;
+
+import org.apache.cxf.tracing.Traceable;
+import org.apache.cxf.tracing.TracerContext;
+
+import io.opentracing.ActiveSpan;
+import io.opentracing.ActiveSpan.Continuation;
+import io.opentracing.Tracer;
+
+public class OpenTracingContext implements TracerContext {
+    private final Tracer tracer;
+    private final Continuation continuation;
+
+    public OpenTracingContext(final Tracer tracer) {
+        this(tracer, null);
+    }
+
+    public OpenTracingContext(final Tracer tracer, final Continuation continuation) {
+        this.tracer = tracer;
+        this.continuation = continuation;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ActiveSpan startSpan(final String description) {
+        return newOrChildSpan(description, null);
+    }
+
+    @Override
+    public <T> T continueSpan(final Traceable<T> traceable) throws Exception {
+        ActiveSpan scope = null;
+        
+        if (tracer.activeSpan() == null && continuation != null) {
+            scope = continuation.activate();
+        }
+
+        try {
+            return traceable.call(new OpenTracingContext(tracer));
+        } finally {
+            if (continuation != null && scope != null) {
+                scope.deactivate();
+            }
+        }
+    }
+
+    @Override
+    public <T> Callable<T> wrap(final String description, final Traceable<T> traceable) {
+        final Callable<T> callable = new Callable<T>() {
+            @Override
+            public T call() throws Exception {
+                return traceable.call(new OpenTracingContext(tracer));
+            }
+        };
+
+        // Carry over parent from the current thread
+        final ActiveSpan parent = tracer.activeSpan();
+        return () -> {
+            try (ActiveSpan span = newOrChildSpan(description, parent)) {
+                return callable.call();
+            }
+        };
+    }
+
+    @Override
+    public void annotate(String key, String value) {
+        final ActiveSpan current = tracer.activeSpan();
+        if (current != null) {
+            current.setTag(key, value);
+        }
+    }
+
+    @Override
+    public void timeline(String message) {
+        final ActiveSpan current = tracer.activeSpan();
+        if (current != null) {
+            current.log(message);
+        }
+    }
+    
+    private ActiveSpan newOrChildSpan(final String description, final ActiveSpan parent) {
+        if (parent == null) {
+            return tracer.buildSpan(description).startActive();
+        } else {
+            return tracer.buildSpan(description).asChildOf(parent).startActive();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingFeature.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingFeature.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingFeature.java
new file mode 100644
index 0000000..5ed3223
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingFeature.java
@@ -0,0 +1,55 @@
+/**
+ * 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.opentracing;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.annotations.Provider;
+import org.apache.cxf.annotations.Provider.Scope;
+import org.apache.cxf.annotations.Provider.Type;
+import org.apache.cxf.common.injection.NoJSR250Annotations;
+import org.apache.cxf.feature.AbstractFeature;
+import org.apache.cxf.interceptor.InterceptorProvider;
+
+import io.opentracing.Tracer;
+import io.opentracing.util.GlobalTracer;
+
+@NoJSR250Annotations
+@Provider(value = Type.Feature, scope = Scope.Server)
+public class OpenTracingFeature extends AbstractFeature {
+    private OpenTracingStartInterceptor in;
+    private OpenTracingStopInterceptor out;
+
+    public OpenTracingFeature() {
+        this(GlobalTracer.get());
+    }
+    
+    public OpenTracingFeature(final Tracer tracer) {
+        in = new OpenTracingStartInterceptor(tracer);
+        out = new OpenTracingStopInterceptor(tracer);
+    }
+
+    @Override
+    protected void initializeProvider(InterceptorProvider provider, Bus bus) {
+        provider.getInInterceptors().add(in);
+        provider.getInFaultInterceptors().add(in);
+
+        provider.getOutInterceptors().add(out);
+        provider.getOutFaultInterceptors().add(out);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingStartInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingStartInterceptor.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingStartInterceptor.java
new file mode 100644
index 0000000..736c228
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingStartInterceptor.java
@@ -0,0 +1,49 @@
+/**
+ * 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.opentracing;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.common.injection.NoJSR250Annotations;
+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 io.opentracing.Tracer;
+
+@NoJSR250Annotations
+public class OpenTracingStartInterceptor extends AbstractOpenTracingInterceptor {
+    public OpenTracingStartInterceptor(Tracer tracer) {
+        super(Phase.PRE_INVOKE, tracer);
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        final Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
+
+        final TraceScopeHolder<TraceScope> holder = super.startTraceSpan(headers,
+            getUri(message), (String)message.get(Message.HTTP_REQUEST_METHOD));
+
+        if (holder != null) {
+            message.getExchange().put(TRACE_SPAN, holder);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingStopInterceptor.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingStopInterceptor.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingStopInterceptor.java
new file mode 100644
index 0000000..9ecc0c4
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/OpenTracingStopInterceptor.java
@@ -0,0 +1,65 @@
+/**
+ * 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.opentracing;
+
+import java.util.HashMap;
+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.message.MessageUtils;
+import org.apache.cxf.phase.Phase;
+
+import io.opentracing.Tracer;
+
+public class OpenTracingStopInterceptor extends AbstractOpenTracingInterceptor {
+    public OpenTracingStopInterceptor(final Tracer tracer) {
+        super(Phase.PRE_MARSHAL, tracer);
+    }
+
+    @Override
+    public void handleMessage(Message message) throws Fault {
+        Map<String, List<Object>> responseHeaders = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
+
+        if (responseHeaders == null) {
+            responseHeaders = new HashMap<>();
+            message.put(Message.PROTOCOL_HEADERS, responseHeaders);
+        }
+
+        boolean isRequestor = MessageUtils.isRequestor(message);
+        Message requestMessage = isRequestor ? message.getExchange().getOutMessage()
+            : message.getExchange().getInMessage();
+        Map<String, List<String>> requestHeaders =
+            CastUtils.cast((Map<?, ?>)requestMessage.get(Message.PROTOCOL_HEADERS));
+
+        @SuppressWarnings("unchecked")
+        final TraceScopeHolder<TraceScope> holder =
+            (TraceScopeHolder<TraceScope>)message.getExchange().get(TRACE_SPAN);
+        
+        Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE);
+        if (responseCode == null) {
+            responseCode = 200;
+        }
+
+        super.stopTraceSpan(requestHeaders, responseHeaders, responseCode, holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/TraceScope.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/TraceScope.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/TraceScope.java
new file mode 100644
index 0000000..3f04515
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/TraceScope.java
@@ -0,0 +1,50 @@
+/**
+ * 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.opentracing;
+
+import io.opentracing.ActiveSpan;
+import io.opentracing.ActiveSpan.Continuation;
+
+public class TraceScope {
+    private final ActiveSpan span;
+    private final Continuation continuation;
+    private final boolean managed;
+    
+    TraceScope(final ActiveSpan span, final Continuation continuation) {
+        this(span, continuation, true);
+    }
+    
+    TraceScope(final ActiveSpan span, final Continuation continuation, final boolean managed) {
+        this.span = span;
+        this.continuation = continuation;
+        this.managed = managed;
+    }
+    
+    public ActiveSpan getSpan() {
+        return span;
+    }
+    
+    public Continuation getContinuation() {
+        return continuation;
+    }
+    
+    public boolean isManaged() {
+        return managed;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/internal/TextMapInjectAdapter.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/internal/TextMapInjectAdapter.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/internal/TextMapInjectAdapter.java
new file mode 100644
index 0000000..5d0e06f
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/internal/TextMapInjectAdapter.java
@@ -0,0 +1,45 @@
+/**
+ * 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.opentracing.internal;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import io.opentracing.propagation.TextMap;
+
+public class TextMapInjectAdapter implements TextMap {
+    private final Map<String, List<String>> headers;
+    
+    public TextMapInjectAdapter(final Map<String, List<String>> headers) {
+        this.headers = headers;
+    }
+    
+    @Override
+    public void put(String key, String value) {
+        headers.put(key, Collections.singletonList(value)); 
+    }
+    
+    @Override
+    public Iterator<Entry<String, String>> iterator() {
+        throw new UnsupportedOperationException("TextMapInjectAdapter should only be used with Tracer.inject()");
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingClientProvider.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingClientProvider.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingClientProvider.java
new file mode 100644
index 0000000..6bc4862
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingClientProvider.java
@@ -0,0 +1,60 @@
+/**
+ * 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.opentracing.jaxrs;
+
+import java.io.IOException;
+
+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.ext.Provider;
+
+import org.apache.cxf.tracing.opentracing.AbstractOpenTracingClientProvider;
+import org.apache.cxf.tracing.opentracing.TraceScope;
+
+import io.opentracing.Tracer;
+
+@Provider
+public class OpenTracingClientProvider extends AbstractOpenTracingClientProvider
+        implements ClientRequestFilter, ClientResponseFilter {
+
+    public OpenTracingClientProvider(final Tracer tracer) {
+        super(tracer);
+    }
+
+    @Override
+    public void filter(final ClientRequestContext requestContext) throws IOException {
+        final TraceScopeHolder<TraceScope> holder = super.startTraceSpan(requestContext.getStringHeaders(),
+            requestContext.getUri(), requestContext.getMethod());
+
+        if (holder != null) {
+            requestContext.setProperty(TRACE_SPAN, holder);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void filter(final ClientRequestContext requestContext,
+            final ClientResponseContext responseContext) throws IOException {
+        final TraceScopeHolder<TraceScope> holder =
+            (TraceScopeHolder<TraceScope>)requestContext.getProperty(TRACE_SPAN);
+        super.stopTraceSpan(holder, responseContext.getStatus());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingContextProvider.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingContextProvider.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingContextProvider.java
new file mode 100644
index 0000000..22bfd9d
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingContextProvider.java
@@ -0,0 +1,50 @@
+/**
+ * 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.opentracing.jaxrs;
+
+import org.apache.cxf.jaxrs.ext.ContextProvider;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.tracing.TracerContext;
+import org.apache.cxf.tracing.opentracing.OpenTracingContext;
+
+import io.opentracing.ActiveSpan.Continuation;
+import io.opentracing.Tracer;
+
+public class OpenTracingContextProvider implements ContextProvider< TracerContext > {
+    private final Tracer tracer;
+
+    public OpenTracingContextProvider(final Tracer tracer) {
+        this.tracer = tracer;
+    }
+
+    @Override
+    public TracerContext createContext(final Message message) {
+        // Check if there is a server span passed along with the message
+        final Continuation continuation = message.get(Continuation.class);
+
+        // If server span is already present, let us check if it is detached
+        // (asynchronous invocation)
+        if (continuation != null) {
+            return new OpenTracingContext(tracer, continuation);
+        }
+
+        return new OpenTracingContext(tracer);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingFeature.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingFeature.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingFeature.java
new file mode 100644
index 0000000..c1c824f
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingFeature.java
@@ -0,0 +1,46 @@
+/**
+ * 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.opentracing.jaxrs;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+import javax.ws.rs.ext.Provider;
+
+import io.opentracing.Tracer;
+import io.opentracing.util.GlobalTracer;
+
+@Provider
+public class OpenTracingFeature implements Feature {
+    private final Tracer tracer;
+
+    public OpenTracingFeature() {
+        this(GlobalTracer.get());
+    }
+
+    public OpenTracingFeature(final Tracer tracer) {
+        this.tracer = tracer;
+    }
+
+    @Override
+    public boolean configure(FeatureContext context) {
+        context.register(new OpenTracingProvider(tracer));
+        context.register(new OpenTracingContextProvider(tracer));
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4080fbaf/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingProvider.java
----------------------------------------------------------------------
diff --git a/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingProvider.java b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingProvider.java
new file mode 100644
index 0000000..5144447
--- /dev/null
+++ b/integration/tracing/tracing-opentracing/src/main/java/org/apache/cxf/tracing/opentracing/jaxrs/OpenTracingProvider.java
@@ -0,0 +1,77 @@
+/**
+ * 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.opentracing.jaxrs;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.cxf.tracing.opentracing.AbstractOpenTracingProvider;
+import org.apache.cxf.tracing.opentracing.TraceScope;
+
+import io.opentracing.Tracer;
+
+@Provider
+public class OpenTracingProvider extends AbstractOpenTracingProvider
+    implements ContainerRequestFilter, ContainerResponseFilter {
+    @Context
+    private ResourceInfo resourceInfo;
+
+    public OpenTracingProvider(final Tracer tracer) {
+        super(tracer);
+    }
+
+    @Override
+    public void filter(final ContainerRequestContext requestContext) throws IOException {
+        final TraceScopeHolder<TraceScope> holder = super.startTraceSpan(requestContext.getHeaders(),
+            requestContext.getUriInfo().getRequestUri(), requestContext.getMethod());
+
+        if (holder != null) {
+            requestContext.setProperty(TRACE_SPAN, holder);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void filter(final ContainerRequestContext requestContext,
+            final ContainerResponseContext responseContext) throws IOException {
+        super.stopTraceSpan(requestContext.getHeaders(), responseContext.getHeaders(),
+            responseContext.getStatus(), (TraceScopeHolder<TraceScope>)requestContext.getProperty(TRACE_SPAN));
+    }
+
+    @Override
+    protected boolean isAsyncResponse() {
+        for (final Annotation[] annotations: resourceInfo.getResourceMethod().getParameterAnnotations()) {
+            for (final Annotation annotation: annotations) {
+                if (annotation.annotationType().equals(Suspended.class)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}