moving configuration to [config]
diff --git a/README.adoc b/README.adoc
new file mode 100644
index 0000000..e14611b
--- /dev/null
+++ b/README.adoc
@@ -0,0 +1,25 @@
+= Geronimo OpenTracing
+
+Geronimo OpenTracing provides an OpenTracing implementation and a Microprofile OpenTracing implementation at once.
+
+== Configuration
+
+NOTE: if you are using Microprofile Config it is used, otherwise it uses system properties.
+
+|===
+| Key | Description | Default
+|geronimo.opentracing.filter.active|Should OpenTracing be activated|true
+|geronimo.opentracing.filter.forcedTracing.urls|Urls for which the tracking should be activated automatically. The urls are actually the requets uri minus the context path.|-
+|geronimo.opentracing.filter.forcedTracing.matcherType|Type of matcher for the url, default is `prefix` which means a `startsWith` is used on the url but you can also use `regex` which compiles the url as a `Pattern`|prefix
+|geronimo.opentracing.filter.forcedTracing.skipDefaultTags|Should `HTTP_METHOD`, `HTTP_URL` not be added to tags|false
+|geronimo.opentracing.server.filter.request.skip.<endpoint class>_<endpoint method>|Should server instrumentation be ignored|false
+|geronimo.opentracing.server.filter.request.skip|Should server instrumentation be ignored (if previous is not set)|false
+|geronimo.opentracing.server.filter.request.skipDefaultTags|Should `HTTP_METHOD`, `HTTP_URL` not be added to tags|false
+|geronimo.opentracing.client.filter.request.skip|Should client instrumentation be ignored|false
+|geronimo.opentracing.client.filter.request.skipDefaultTags|Should `HTTP_METHOD`, `HTTP_URL` not be added to tags|false
+|geronimo.opentracing.client.filter.request.skipPeerTags|Should `PEER_HOSTNAME`, `PEER_PORT` not be added to tags|false
+|geronimo.opentracing.propagation.headers.spanId|Name of the header used to host the spanId value|`X-B3-SpanId`
+|geronimo.opentracing.propagation.headers.traceId|Name of the header used to host the traceId value|`X-B3-TraceId`
+|geronimo.opentracing.propagation.headers.baggagePrefix|Prefix of headers used to host the baggage values|`baggage-`
+|geronimo.opentracing.cdi.executorServices.wrappedNames|Name (as CDI names of the beans) of executor services which will get an interceptor propagating the current scope (span)|-
+|===
diff --git a/geronimo-opentracing-impl/pom.xml b/geronimo-opentracing-impl/pom.xml
index cfdba21..207dba6 100644
--- a/geronimo-opentracing-impl/pom.xml
+++ b/geronimo-opentracing-impl/pom.xml
@@ -36,6 +36,13 @@
<dependencies>
<dependency>
+ <groupId>org.eclipse.microprofile.config</groupId>
+ <artifactId>microprofile-config-api</artifactId>
+ <version>1.2</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
<groupId>org.apache.geronimo</groupId>
<artifactId>geronimo-microprofile-opentracing-spec</artifactId>
<version>${project.version}</version>
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/DefaultOpenTracingConfig.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/DefaultOpenTracingConfig.java
new file mode 100644
index 0000000..646c3a7
--- /dev/null
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/DefaultOpenTracingConfig.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.geronimo.microprofile.config;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.enterprise.inject.Vetoed;
+
+@Vetoed
+class DefaultOpenTracingConfig implements GeronimoOpenTracingConfig {
+ private final Map<String, String> configuration = new HashMap<>();
+
+ DefaultOpenTracingConfig() {
+ System.getProperties().stringPropertyNames()
+ .forEach(k -> configuration.put(k, System.getProperty(k)));
+ try (final InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("META-INF/geronimo/microprofile/opentracing.properties")) {
+ if (stream != null) {
+ final Properties properties = new Properties();
+ properties.load(stream);
+ properties.stringPropertyNames().forEach(k -> configuration.put(k, properties.getProperty(k)));
+ }
+ } catch (final IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public String read(final String value, final String def) {
+ return configuration.getOrDefault(value, def);
+ }
+}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/GeronimoOpenTracingConfig.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/GeronimoOpenTracingConfig.java
new file mode 100644
index 0000000..d9b3677
--- /dev/null
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/GeronimoOpenTracingConfig.java
@@ -0,0 +1,31 @@
+/*
+ * 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.geronimo.microprofile.config;
+
+@FunctionalInterface
+public interface GeronimoOpenTracingConfig {
+
+ String read(String value, String def);
+
+ static GeronimoOpenTracingConfig create() {
+ try {
+ return new PrefixedConfig(new OpenTracingConfigMpConfigImpl());
+ } catch (final NoClassDefFoundError | ExceptionInInitializerError cnfe) {
+ return new PrefixedConfig(new DefaultOpenTracingConfig());
+ }
+ }
+}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/OpenTracingConfigMpConfigImpl.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/OpenTracingConfigMpConfigImpl.java
new file mode 100644
index 0000000..7c54bd0
--- /dev/null
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/OpenTracingConfigMpConfigImpl.java
@@ -0,0 +1,36 @@
+/*
+ * 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.geronimo.microprofile.config;
+
+import javax.enterprise.inject.Vetoed;
+
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+
+@Vetoed
+class OpenTracingConfigMpConfigImpl implements GeronimoOpenTracingConfig {
+ private final Config config;
+
+ OpenTracingConfigMpConfigImpl() {
+ config = ConfigProvider.getConfig();
+ }
+
+ @Override
+ public String read(final String key, final String def) {
+ return config.getOptionalValue(key, String.class).orElse(def);
+ }
+}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/PrefixedConfig.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/PrefixedConfig.java
new file mode 100644
index 0000000..5575786
--- /dev/null
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/config/PrefixedConfig.java
@@ -0,0 +1,33 @@
+/*
+ * 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.geronimo.microprofile.config;
+
+import javax.enterprise.inject.Vetoed;
+
+@Vetoed
+class PrefixedConfig implements GeronimoOpenTracingConfig {
+ private final GeronimoOpenTracingConfig delegate;
+
+ PrefixedConfig(final GeronimoOpenTracingConfig geronimoOpenTracingConfig) {
+ this.delegate = geronimoOpenTracingConfig;
+ }
+
+ @Override
+ public String read(final String value, final String def) {
+ return delegate.read("geronimo.opentracing." + value, def);
+ }
+}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/GeronimoTracer.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/GeronimoTracer.java
index 791144e..ff9d47b 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/GeronimoTracer.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/GeronimoTracer.java
@@ -16,6 +16,7 @@
*/
package org.apache.geronimo.microprofile.opentracing.impl;
+import static java.util.Collections.list;
import static java.util.Optional.ofNullable;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
@@ -24,9 +25,11 @@
import java.util.Iterator;
import java.util.Map;
+import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Event;
import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MultivaluedMap;
import io.opentracing.Scope;
@@ -37,6 +40,8 @@
import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMap;
+import org.apache.geronimo.microprofile.config.GeronimoOpenTracingConfig;
+
@ApplicationScoped
public class GeronimoTracer implements Tracer {
@@ -49,6 +54,20 @@
@Inject
private Event<FinishedSpan> finishedSpanEvent;
+ @Inject
+ private GeronimoOpenTracingConfig config;
+
+ private String spanIdHeader;
+ private String traceIdHeader;
+ private String baggageHeaderPrefix;
+
+ @PostConstruct
+ private void init() {
+ spanIdHeader = config.read("propagation.headers.spanId", "X-B3-SpanId");
+ traceIdHeader = config.read("propagation.headers.traceId", "X-B3-TraceId");
+ baggageHeaderPrefix = config.read("propagation.headers.baggagePrefix", "baggage-");
+ }
+
@Override
public ScopeManager scopeManager() {
return scopeManager;
@@ -73,23 +92,33 @@
}
final TextMap textMap = TextMap.class.cast(carrier);
final SpanContextImpl context = SpanContextImpl.class.cast(spanContext);
- textMap.put("X-B3-TraceId", String.valueOf(context.getTraceId()));
- textMap.put("X-B3-SpanId", String.valueOf(context.getSpanId()));
- context.getBaggageItems().forEach((k, v) -> textMap.put("baggage-" + k, v));
+ textMap.put(traceIdHeader, String.valueOf(context.getTraceId()));
+ textMap.put(spanIdHeader, String.valueOf(context.getSpanId()));
+ context.getBaggageItems().forEach((k, v) -> textMap.put(baggageHeaderPrefix + k, v));
}
@Override
public <C> SpanContext extract(final Format<C> format, final C carrier) {
- if (HeaderTextMap.class.isInstance(carrier)) {
- final MultivaluedMap<String, ?> map = HeaderTextMap.class.cast(carrier).getMap();
- final String traceid = (String) map.getFirst("X-B3-TraceId");
- final String spanid = (String) map.getFirst("X-B3-SpanId");
+ if (JaxRsHeaderTextMap.class.isInstance(carrier)) {
+ final MultivaluedMap<String, ?> map = JaxRsHeaderTextMap.class.cast(carrier).getMap();
+ final String traceid = (String) map.getFirst(traceIdHeader);
+ final String spanid = (String) map.getFirst(spanIdHeader);
if (traceid != null && spanid != null) {
- return newContext(traceid, spanid, map.keySet().stream().filter(it -> it.startsWith("baggage-"))
+ return newContext(traceid, spanid, map.keySet().stream().filter(it -> it.startsWith(baggageHeaderPrefix))
.collect(toMap(identity(), k -> String.valueOf(map.getFirst(k)))));
}
return null;
}
+ if (ServletHeaderTextMap.class.isInstance(carrier)) {
+ final HttpServletRequest req = ServletHeaderTextMap.class.cast(carrier).getRequest();
+ final String traceid = req.getHeader(traceIdHeader);
+ final String spanid = req.getHeader(spanIdHeader);
+ if (traceid != null && spanid != null) {
+ return newContext(traceid, spanid, list(req.getHeaderNames()).stream().filter(it -> it.startsWith(baggageHeaderPrefix))
+ .collect(toMap(identity(), k -> String.valueOf(req.getHeader(k)))));
+ }
+ return null;
+ }
if (!TextMap.class.isInstance(carrier)) {
throw new IllegalArgumentException("Only TextMap are supported");
}
@@ -99,11 +128,11 @@
final Map<String, String> baggages = new HashMap<>();
while (textMap.hasNext()) {
final Map.Entry<String, String> next = textMap.next();
- if (next.getKey().startsWith("baggage-")) {
+ if (next.getKey().startsWith(baggageHeaderPrefix)) {
baggages.put(next.getKey(), next.getValue());
- } else if ("X-B3-SpanId".equals(next.getKey())) {
+ } else if (spanIdHeader.equals(next.getKey())) {
spanId = next.getValue();
- } else if ("X-B3-TracedId".equals(next.getKey())) {
+ } else if (traceIdHeader.equals(next.getKey())) {
traceId = next.getValue();
}
}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/HeaderTextMap.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/JaxRsHeaderTextMap.java
similarity index 94%
rename from geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/HeaderTextMap.java
rename to geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/JaxRsHeaderTextMap.java
index 82b1706..53d5944 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/HeaderTextMap.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/JaxRsHeaderTextMap.java
@@ -23,11 +23,11 @@
import io.opentracing.propagation.TextMap;
-public class HeaderTextMap<T> implements TextMap {
+public class JaxRsHeaderTextMap<T> implements TextMap {
private final MultivaluedMap<String, T> headers;
- public HeaderTextMap(final MultivaluedMap<String, T> headers) {
+ public JaxRsHeaderTextMap(final MultivaluedMap<String, T> headers) {
this.headers = headers;
}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/ScopeManagerImpl.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/ScopeManagerImpl.java
index af938a1..4ba677e 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/ScopeManagerImpl.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/ScopeManagerImpl.java
@@ -48,4 +48,8 @@
}
return scope;
}
+
+ public void clear() {
+ current.remove();
+ }
}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/HeaderTextMap.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/ServletHeaderTextMap.java
similarity index 69%
copy from geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/HeaderTextMap.java
copy to geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/ServletHeaderTextMap.java
index 82b1706..af135bc 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/HeaderTextMap.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/impl/ServletHeaderTextMap.java
@@ -16,38 +16,43 @@
*/
package org.apache.geronimo.microprofile.opentracing.impl;
+import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
-import javax.ws.rs.core.MultivaluedMap;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import io.opentracing.propagation.TextMap;
-public class HeaderTextMap<T> implements TextMap {
+public class ServletHeaderTextMap implements TextMap {
- private final MultivaluedMap<String, T> headers;
+ private final HttpServletRequest request;
- public HeaderTextMap(final MultivaluedMap<String, T> headers) {
- this.headers = headers;
+ private final HttpServletResponse response;
+
+ public ServletHeaderTextMap(final HttpServletRequest request, final HttpServletResponse response) {
+ this.request = request;
+ this.response = response;
}
- public MultivaluedMap<String, ?> getMap() {
- return headers;
+ public HttpServletRequest getRequest() {
+ return request;
}
@Override
public Iterator<Map.Entry<String, String>> iterator() {
- final Iterator<String> iterator = headers.keySet().iterator();
+ final Enumeration<String> iterator = request.getHeaderNames();
return new Iterator<Map.Entry<String, String>>() {
@Override
public boolean hasNext() {
- return iterator.hasNext();
+ return iterator.hasMoreElements();
}
@Override
public Map.Entry<String, String> next() {
- final String next = iterator.next();
+ final String next = iterator.nextElement();
return new Map.Entry<String, String>() {
@Override
@@ -57,7 +62,7 @@
@Override
public String getValue() {
- return String.valueOf(headers.getFirst(next));
+ return String.valueOf(request.getHeader(next));
}
@Override
@@ -71,6 +76,6 @@
@Override
public void put(final String key, final String value) {
- this.headers.putSingle(key, (T) value);
+ this.response.setHeader(key, value);
}
}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/OpenTracingExtension.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/OpenTracingExtension.java
index b57b669..a36f406 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/OpenTracingExtension.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/OpenTracingExtension.java
@@ -16,9 +16,23 @@
*/
package org.apache.geronimo.microprofile.opentracing.microprofile.cdi;
+import static java.util.Optional.ofNullable;
+import static java.util.stream.Collectors.toSet;
+
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.stream.Stream;
+
+import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Default;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.WithAnnotations;
@@ -26,22 +40,48 @@
import javax.ws.rs.HttpMethod;
import javax.ws.rs.Path;
+import org.apache.geronimo.microprofile.config.GeronimoOpenTracingConfig;
+import org.apache.geronimo.microprofile.opentracing.microprofile.thread.OpenTracingExecutorService;
import org.eclipse.microprofile.opentracing.Traced;
public class OpenTracingExtension implements Extension {
+
+ private GeronimoOpenTracingConfig config;
+
+ private Collection<String> instrumentedExecutorServices;
+
+ void onStart(@Observes final BeforeBeanDiscovery beforeBeanDiscovery) {
+ config = GeronimoOpenTracingConfig.create();
+ instrumentedExecutorServices = ofNullable(config.read("cdi.executorServices.wrappedNames", null))
+ .map(s -> Stream.of(s.split(",")).map(String::trim).filter(it -> !it.isEmpty()).collect(toSet())).orElse(null);
+ }
+
<T> void removeTracedFromJaxRsEndpoints(@Observes @WithAnnotations(Traced.class) final ProcessAnnotatedType<T> pat) {
if (isJaxRs(pat.getAnnotatedType())) { // we have filters with more accurate timing
final AnnotatedTypeConfigurator<T> configurator = pat.configureAnnotatedType();
configurator.remove(it -> it.annotationType() == Traced.class);
- configurator.methods().stream()
- .filter(m -> isJaxRs(m.getAnnotated()))
+ configurator.methods().stream().filter(m -> isJaxRs(m.getAnnotated()))
.forEach(m -> m.remove(it -> it.annotationType() == Traced.class));
}
}
+ <T> void instrumentExecutorServices(@Observes final ProcessAnnotatedType<T> pat) {
+ final Set<Type> typeClosure = pat.getAnnotatedType().getTypeClosure();
+ if (typeClosure.contains(ExecutorService.class) && !typeClosure.contains(OpenTracingExecutorService.class)) {
+ pat.configureAnnotatedType().add(TracedExecutorService.Literal.INSTANCE);
+ }
+ }
+
+ void addConfigAsBean(@Observes final AfterBeanDiscovery afterBeanDiscovery) {
+ afterBeanDiscovery.addBean().id(OpenTracingExtension.class.getName() + "#" + GeronimoOpenTracingConfig.class.getName())
+ .beanClass(GeronimoOpenTracingConfig.class).types(GeronimoOpenTracingConfig.class, Object.class)
+ .qualifiers(Default.Literal.INSTANCE, Any.Literal.INSTANCE).scope(ApplicationScoped.class)
+ .createWith(ctx -> config);
+ }
+
private <T> boolean isJaxRs(final AnnotatedType<T> annotatedType) {
- return annotatedType.getAnnotations().stream().anyMatch(it -> it.annotationType() == Path.class) ||
- annotatedType.getMethods().stream().anyMatch(this::isJaxRs);
+ return annotatedType.getAnnotations().stream().anyMatch(it -> it.annotationType() == Path.class)
+ || annotatedType.getMethods().stream().anyMatch(this::isJaxRs);
}
private <T> boolean isJaxRs(final AnnotatedMethod<? super T> m) {
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/TracedExecutorService.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/TracedExecutorService.java
new file mode 100644
index 0000000..61e511b
--- /dev/null
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/TracedExecutorService.java
@@ -0,0 +1,59 @@
+/*
+ * 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.geronimo.microprofile.opentracing.microprofile.cdi;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.interceptor.InterceptorBinding;
+
+@InterceptorBinding
+@Retention(RUNTIME)
+@Target({ TYPE, METHOD })
+public @interface TracedExecutorService {
+
+ class Literal implements TracedExecutorService {
+
+ public static final TracedExecutorService INSTANCE = new Literal();
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return TracedExecutorService.class;
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ return TracedExecutorService.class.isInstance(other) || (Annotation.class.isInstance(other)
+ && Annotation.class.cast(other).annotationType() == TracedExecutorService.class);
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "@" + TracedExecutorService.class.getName();
+ }
+ }
+}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/TracedExecutorServiceInterceptor.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/TracedExecutorServiceInterceptor.java
new file mode 100644
index 0000000..a7470f0
--- /dev/null
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/cdi/TracedExecutorServiceInterceptor.java
@@ -0,0 +1,40 @@
+/*
+ * 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.geronimo.microprofile.opentracing.microprofile.cdi;
+
+import io.opentracing.Tracer;
+
+import java.io.Serializable;
+
+import javax.annotation.Priority;
+import javax.inject.Inject;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+import org.apache.geronimo.microprofile.opentracing.microprofile.thread.ScopePropagatingCallable;
+
+@Interceptor
+@TracedExecutorService
+@Priority(Interceptor.Priority.LIBRARY_AFTER)
+public class TracedExecutorServiceInterceptor implements Serializable {
+ @Inject
+ private Tracer tracer;
+
+ public Object around(final InvocationContext context) throws Exception {
+ return new ScopePropagatingCallable<>(context::proceed, tracer).call();
+ }
+}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/GeronimoClientTracingRegistrarProvider.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/GeronimoClientTracingRegistrarProvider.java
index cefeb30..60bc46b 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/GeronimoClientTracingRegistrarProvider.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/GeronimoClientTracingRegistrarProvider.java
@@ -21,6 +21,7 @@
import javax.enterprise.inject.spi.CDI;
import javax.ws.rs.client.ClientBuilder;
+import org.apache.geronimo.microprofile.opentracing.microprofile.thread.OpenTracingExecutorService;
import org.eclipse.microprofile.opentracing.ClientTracingRegistrarProvider;
import io.opentracing.Tracer;
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/OpenTracingClientRequestFilter.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/OpenTracingClientRequestFilter.java
index 637ab74..f550774 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/OpenTracingClientRequestFilter.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/OpenTracingClientRequestFilter.java
@@ -21,12 +21,14 @@
import java.util.function.Consumer;
+import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
-import org.apache.geronimo.microprofile.opentracing.impl.HeaderTextMap;
+import org.apache.geronimo.microprofile.config.GeronimoOpenTracingConfig;
+import org.apache.geronimo.microprofile.opentracing.impl.JaxRsHeaderTextMap;
import io.opentracing.Scope;
import io.opentracing.Span;
@@ -41,10 +43,23 @@
@Inject
private Tracer tracer;
+ @Inject
+ private GeronimoOpenTracingConfig config;
+
+ private boolean skip;
+ private boolean skipDefaultTags;
+ private boolean skipPeerTags;
+
+ @PostConstruct
+ private void init() {
+ skip = Boolean.parseBoolean(config.read("client.filter.request.skip", "false"));
+ skipDefaultTags = Boolean.parseBoolean(config.read("client.filter.request.skipDefaultTags", "false"));
+ skipPeerTags = Boolean.parseBoolean(config.read("client.filter.request.skipPeerTags", "false"));
+ }
+
@Override
public void filter(final ClientRequestContext context) {
- if (context.getProperty(OpenTracingClientRequestFilter.class.getName()) != null || "true"
- .equalsIgnoreCase(String.valueOf(context.getProperty("org.apache.geronimo.microprofile.opentracing.skip")))) {
+ if (context.getProperty(OpenTracingClientRequestFilter.class.getName()) != null || skip) {
return;
}
@@ -57,8 +72,7 @@
final Scope scope = builder.startActive(true);
final Span span = scope.span();
- if (!"true".equalsIgnoreCase(
- String.valueOf(context.getProperty("org.apache.geronimo.microprofile.opentracing.client.skipDefaultSpanTags")))) {
+ if (!skipDefaultTags) {
Tags.HTTP_METHOD.set(span, context.getMethod());
Tags.HTTP_URL.set(span, context.getUri().toASCIIString());
}
@@ -71,7 +85,7 @@
ofNullable(context.getProperty("org.apache.geronimo.microprofile.opentracing.spanConsumer"))
.ifPresent(consumer -> Consumer.class.cast(consumer).accept(span));
- tracer.inject(span.context(), Format.Builtin.HTTP_HEADERS, new HeaderTextMap<>(context.getHeaders()));
+ tracer.inject(span.context(), Format.Builtin.HTTP_HEADERS, new JaxRsHeaderTextMap<>(context.getHeaders()));
context.setProperty(OpenTracingClientRequestFilter.class.getName(), scope);
}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/GeronimoOpenTracingFeature.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/GeronimoOpenTracingFeature.java
index 8032163..821f14e 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/GeronimoOpenTracingFeature.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/GeronimoOpenTracingFeature.java
@@ -30,6 +30,7 @@
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;
+import org.apache.geronimo.microprofile.config.GeronimoOpenTracingConfig;
import org.eclipse.microprofile.opentracing.Traced;
import io.opentracing.Tracer;
@@ -41,10 +42,15 @@
@Inject
private Tracer tracer;
+ @Inject
+ private GeronimoOpenTracingConfig config;
+
@Override
public void configure(final ResourceInfo resourceInfo, final FeatureContext context) {
if (tracer == null) { // configured instead of scanned
- tracer = CDI.current().select(Tracer.class).get();
+ CDI<Object> cdi = CDI.current();
+ tracer = cdi.select(Tracer.class).get();
+ config = cdi.select(GeronimoOpenTracingConfig.class).get();
}
final Optional<Traced> traced = ofNullable(ofNullable(resourceInfo.getResourceMethod().getAnnotation(Traced.class))
@@ -59,6 +65,9 @@
.map(a -> a.annotationType().getAnnotation(HttpMethod.class).value()).orElse("") + ':'
+ resourceInfo.getResourceClass().getName() + "." + resourceInfo.getResourceMethod().getName());
context.register(new OpenTracingServerResponseFilter())
- .register(new OpenTracingServerRequestFilter(operationName, tracer));
+ .register(new OpenTracingServerRequestFilter(
+ operationName, tracer,
+ Boolean.parseBoolean(config.read("server.filter.request.skip." + resourceInfo.getResourceClass().getName() + "_" + resourceInfo.getResourceMethod().getName(), config.read("server.filter.request.skip", "false"))),
+ Boolean.parseBoolean(config.read("server.filter.request.skipDefaultTags", "false"))));
}
}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/OpenTracingFilter.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/OpenTracingFilter.java
index 9d2307e..4fae300 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/OpenTracingFilter.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/OpenTracingFilter.java
@@ -1,24 +1,37 @@
package org.apache.geronimo.microprofile.opentracing.microprofile.server;
import static java.util.Optional.ofNullable;
+import static java.util.stream.Collectors.toList;
import java.io.IOException;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
import javax.inject.Inject;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.geronimo.microprofile.config.GeronimoOpenTracingConfig;
+import org.apache.geronimo.microprofile.opentracing.impl.ScopeManagerImpl;
+import org.apache.geronimo.microprofile.opentracing.impl.ServletHeaderTextMap;
+
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
+import io.opentracing.propagation.Format;
import io.opentracing.tag.Tags;
public class OpenTracingFilter implements Filter {
@@ -26,6 +39,39 @@
@Inject
private Tracer tracer;
+ @Inject
+ private GeronimoOpenTracingConfig config;
+
+ @Inject
+ private ScopeManagerImpl manager;
+
+ private Collection<Predicate<String>> forcedUrls;
+
+ private boolean skipDefaultTags;
+
+ @Override
+ public void init(final FilterConfig filterConfig) throws ServletException {
+ skipDefaultTags = Boolean.parseBoolean(config.read("filter.forcedTracing.skipDefaultTags", "false"));
+ forcedUrls = ofNullable(config.read("filter.forcedTracing.urls", null)).map(String::trim).filter(v -> !v.isEmpty())
+ .map(v -> {
+ final String matchingType = config.read("filter.forcedTracing.matcherType", "prefix");
+ final Function<String, Predicate<String>> matcherFactory;
+ switch (matchingType) {
+ case "regex":
+ matcherFactory = from -> {
+ final Pattern compiled = Pattern.compile(from);
+ return url -> compiled.matcher(url).matches();
+ };
+ break;
+ case "prefix":
+ default:
+ matcherFactory = from -> url -> url.startsWith(from);
+ }
+ return Stream.of(v.split(",")).map(String::trim).filter(it -> !it.isEmpty()).map(matcherFactory)
+ .collect(toList());
+ }).orElse(null);
+ }
+
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
@@ -33,26 +79,50 @@
chain.doFilter(request, response);
return;
}
- // todo: implicit start for matching urls
+ if (forcedUrls != null && !forcedUrls.isEmpty()) {
+ final HttpServletRequest req = HttpServletRequest.class.cast(request);
+ final String matching = req.getRequestURI().substring(req.getContextPath().length());
+ if (forcedUrls.stream().anyMatch(p -> p.test(matching))) {
+ final Tracer.SpanBuilder builder = tracer.buildSpan(buildServletOperationName(req));
+ builder.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER);
+ builder.withTag("component", "servlet");
+
+ ofNullable(ofNullable(tracer.activeSpan()).map(Span::context)
+ .orElseGet(() -> tracer.extract(Format.Builtin.HTTP_HEADERS,
+ new ServletHeaderTextMap(req, HttpServletResponse.class.cast(response)))))
+ .ifPresent(builder::asChildOf);
+
+ final Scope scope = builder.startActive(true);
+ final Span span = scope.span();
+
+ if (!skipDefaultTags) {
+ Tags.HTTP_METHOD.set(span, req.getMethod());
+ Tags.HTTP_URL.set(span, req.getRequestURL().toString());
+ }
+
+ request.setAttribute(OpenTracingFilter.class.getName(), scope);
+ }
+ }
try {
chain.doFilter(request, response);
} catch (final Exception ex) {
- ofNullable(request.getAttribute(OpenTracingFilter.class.getName())).map(Scope.class::cast).ifPresent(scope -> {
- final int status = HttpServletResponse.class.cast(response).getStatus();
- final Span span = scope.span();
- Tags.HTTP_STATUS.set(span, status == HttpServletResponse.SC_OK ? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : status);
- Tags.ERROR.set(span, true);
- span.log(new HashMap<String, Object>() {
+ getCurrentScope(request).ifPresent(scope -> {
+ final int status = HttpServletResponse.class.cast(response).getStatus();
+ final Span span = scope.span();
+ Tags.HTTP_STATUS.set(span,
+ status == HttpServletResponse.SC_OK ? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : status);
+ Tags.ERROR.set(span, true);
+ span.log(new HashMap<String, Object>() {
- {
- put("event", Tags.ERROR.getKey());
- put("event.object", ex);
- }
- });
- });
+ {
+ put("event", Tags.ERROR.getKey());
+ put("event.object", ex);
+ }
+ });
+ });
throw ex;
} finally {
- ofNullable(request.getAttribute(OpenTracingFilter.class.getName())).map(Scope.class::cast).ifPresent(scope -> {
+ getCurrentScope(request).ifPresent(scope -> {
if (request.isAsyncStarted()) {
request.getAsyncContext().addListener(new AsyncListener() {
@@ -76,10 +146,20 @@
// no-op
}
});
+ manager.clear();
} else {
scope.close();
}
});
}
}
+
+ private Optional<Scope> getCurrentScope(final ServletRequest request) {
+ return ofNullable(ofNullable(request.getAttribute(OpenTracingFilter.class.getName()))
+ .orElseGet(() -> tracer.scopeManager().active())).map(Scope.class::cast);
+ }
+
+ protected String buildServletOperationName(final HttpServletRequest req) {
+ return req.getMethod() + ":" + req.getRequestURL();
+ }
}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/OpenTracingServerRequestFilter.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/OpenTracingServerRequestFilter.java
index 7993db4..91aaed1 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/OpenTracingServerRequestFilter.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/OpenTracingServerRequestFilter.java
@@ -21,7 +21,7 @@
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
-import org.apache.geronimo.microprofile.opentracing.impl.HeaderTextMap;
+import org.apache.geronimo.microprofile.opentracing.impl.JaxRsHeaderTextMap;
import org.apache.geronimo.microprofile.opentracing.microprofile.client.OpenTracingClientRequestFilter;
import io.opentracing.Scope;
@@ -36,15 +36,21 @@
private final Tracer tracer;
- public OpenTracingServerRequestFilter(final String operationName, final Tracer tracer) {
+ private final boolean skip;
+
+ private final boolean skipDefaultTags;
+
+ public OpenTracingServerRequestFilter(final String operationName, final Tracer tracer,
+ final boolean skip, final boolean skipDefaultTags) {
this.operationName = operationName;
this.tracer = tracer;
+ this.skip = skip;
+ this.skipDefaultTags = skipDefaultTags;
}
@Override
public void filter(final ContainerRequestContext context) {
- if (context.getProperty(OpenTracingClientRequestFilter.class.getName()) != null || "true"
- .equalsIgnoreCase(String.valueOf(context.getProperty("org.apache.geronimo.microprofile.opentracing.skip")))) {
+ if (context.getProperty(OpenTracingClientRequestFilter.class.getName()) != null || skip) {
return;
}
@@ -53,14 +59,13 @@
builder.withTag("component", "jaxrs");
ofNullable(ofNullable(tracer.activeSpan()).map(Span::context)
- .orElseGet(() -> tracer.extract(Format.Builtin.HTTP_HEADERS, new HeaderTextMap<>(context.getHeaders()))))
+ .orElseGet(() -> tracer.extract(Format.Builtin.HTTP_HEADERS, new JaxRsHeaderTextMap<>(context.getHeaders()))))
.ifPresent(builder::asChildOf);
final Scope scope = builder.startActive(true);
final Span span = scope.span();
- if (!"true".equalsIgnoreCase(
- String.valueOf(context.getProperty("org.apache.geronimo.microprofile.opentracing.server.skipDefaultSpanTags")))) {
+ if (!skipDefaultTags) {
Tags.HTTP_METHOD.set(span, context.getMethod());
Tags.HTTP_URL.set(span, context.getUriInfo().getRequestUri().toASCIIString());
}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/ServletTracingSetup.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/ServletTracingSetup.java
index a0e01fd..72281fd 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/ServletTracingSetup.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/server/ServletTracingSetup.java
@@ -24,9 +24,15 @@
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
+import org.apache.geronimo.microprofile.config.GeronimoOpenTracingConfig;
+
public class ServletTracingSetup implements ServletContainerInitializer {
@Override
public void onStartup(final Set<Class<?>> c, final ServletContext ctx) {
+ final GeronimoOpenTracingConfig config = GeronimoOpenTracingConfig.create();
+ if (!"true".equalsIgnoreCase(config.read("filter.active", "true"))) {
+ return;
+ }
final FilterRegistration.Dynamic opentracing = ctx.addFilter("opentracing", OpenTracingFilter.class);
opentracing.setAsyncSupported(true);
opentracing.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/OpenTracingExecutorService.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/thread/OpenTracingExecutorService.java
similarity index 77%
rename from geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/OpenTracingExecutorService.java
rename to geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/thread/OpenTracingExecutorService.java
index 37e1059..9928fb2 100644
--- a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/client/OpenTracingExecutorService.java
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/thread/OpenTracingExecutorService.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.geronimo.microprofile.opentracing.microprofile.client;
+package org.apache.geronimo.microprofile.opentracing.microprofile.thread;
import static java.util.stream.Collectors.toList;
@@ -27,9 +27,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import io.opentracing.Span;
import io.opentracing.Tracer;
-import io.opentracing.tag.Tags;
public class OpenTracingExecutorService implements ExecutorService {
@@ -42,20 +40,6 @@
this.tracer = tracer;
}
- private Span before() {
- return tracer.activeSpan();
- }
-
- private void after(final Span span, final RuntimeException error) {
- if (span != null && error != null) {
- Tags.ERROR.set(span, true);
- if (error.getMessage() != null) {
- span.setTag("errorMessage", error.getMessage());
- span.setTag("errorType", error.getClass().getName());
- }
- }
- }
-
@Override
public void shutdown() {
delegate.shutdown();
@@ -124,32 +108,22 @@
}
private Runnable wrap(final Runnable task) {
+ final ScopePropagatingCallable<Void> decorator = new ScopePropagatingCallable<>(() -> {
+ task.run();
+ return null;
+ }, tracer);
return () -> {
- RuntimeException error = null;
- final Span span = before();
try {
- task.run();
- } catch (final RuntimeException re) {
- error = re;
- throw re;
- } finally {
- after(span, error);
+ decorator.call();
+ } catch (final RuntimeException | Error e) {
+ throw e;
+ } catch (final Exception e) { // unlikely since that's a Runnable
+ throw new IllegalStateException(e);
}
};
}
private <T> Callable<T> wrap(final Callable<T> task) {
- return () -> {
- RuntimeException error = null;
- final Span span = before();
- try {
- return task.call();
- } catch (final RuntimeException re) {
- error = re;
- throw re;
- } finally {
- after(span, error);
- }
- };
+ return new ScopePropagatingCallable<>(task, tracer);
}
}
diff --git a/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/thread/ScopePropagatingCallable.java b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/thread/ScopePropagatingCallable.java
new file mode 100644
index 0000000..bd56c7b
--- /dev/null
+++ b/geronimo-opentracing-impl/src/main/java/org/apache/geronimo/microprofile/opentracing/microprofile/thread/ScopePropagatingCallable.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.geronimo.microprofile.opentracing.microprofile.thread;
+
+import java.util.concurrent.Callable;
+
+import io.opentracing.Span;
+import io.opentracing.Tracer;
+import io.opentracing.tag.Tags;
+
+public class ScopePropagatingCallable<B> implements Callable<B> {
+
+ private final Callable<B> delegate;
+
+ private final Tracer tracer;
+
+ public ScopePropagatingCallable(final Callable<B> delegate, final Tracer tracer) {
+ this.delegate = delegate;
+ this.tracer = tracer;
+ }
+
+ private Span before() {
+ return tracer.activeSpan();
+ }
+
+ private void after(final Span span, final RuntimeException error) {
+ if (span != null && error != null) {
+ Tags.ERROR.set(span, true);
+ if (error.getMessage() != null) {
+ span.setTag("errorMessage", error.getMessage());
+ span.setTag("errorType", error.getClass().getName());
+ }
+ }
+ }
+
+ @Override
+ public B call() throws Exception {
+ RuntimeException error = null;
+ final Span span = before();
+ try {
+ return delegate.call();
+ } catch (final RuntimeException re) {
+ error = re;
+ throw re;
+ } finally {
+ after(span, error);
+ }
+ }
+}