JAX-RS ApplicationPath annotation (#2824)
This commit is contained in:
parent
c4071c1c94
commit
a3c0b44b31
|
|
@ -0,0 +1,22 @@
|
|||
ext {
|
||||
skipPublish = true
|
||||
}
|
||||
apply from: "$rootDir/gradle/java.gradle"
|
||||
|
||||
// add repo for org.gradle:gradle-tooling-api which org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-gradle-depchain depends on
|
||||
repositories {
|
||||
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly "javax:javaee-api:7.0"
|
||||
|
||||
api project(':testing-common')
|
||||
implementation deps.opentelemetryApi
|
||||
|
||||
def arquillianVersion = '1.4.0.Final'
|
||||
implementation "org.jboss.arquillian.junit:arquillian-junit-container:${arquillianVersion}"
|
||||
implementation "org.jboss.arquillian.protocol:arquillian-protocol-servlet:${arquillianVersion}"
|
||||
implementation 'org.jboss.arquillian.spock:arquillian-spock-container:1.0.0.CR1'
|
||||
api "org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-gradle-depchain:3.1.3"
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import static io.opentelemetry.api.trace.SpanKind.SERVER
|
||||
|
||||
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
|
||||
import io.opentelemetry.instrumentation.test.utils.OkHttpUtils
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jboss.arquillian.container.test.api.Deployment
|
||||
import org.jboss.arquillian.container.test.api.RunAsClient
|
||||
import org.jboss.arquillian.spock.ArquillianSputnik
|
||||
import org.jboss.arquillian.test.api.ArquillianResource
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap
|
||||
import org.jboss.shrinkwrap.api.asset.EmptyAsset
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive
|
||||
import org.junit.runner.RunWith
|
||||
import spock.lang.Unroll
|
||||
import test.CdiRestResource
|
||||
import test.EjbRestResource
|
||||
import test.RestApplication
|
||||
|
||||
@RunWith(ArquillianSputnik)
|
||||
@RunAsClient
|
||||
abstract class ArquillianRestTest extends AgentInstrumentationSpecification {
|
||||
|
||||
static OkHttpClient client = OkHttpUtils.client()
|
||||
|
||||
@ArquillianResource
|
||||
static URI url
|
||||
|
||||
@Deployment
|
||||
static WebArchive createDeployment() {
|
||||
return ShrinkWrap.create(WebArchive)
|
||||
.addClass(RestApplication)
|
||||
.addClass(CdiRestResource)
|
||||
.addClass(EjbRestResource)
|
||||
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
|
||||
}
|
||||
|
||||
def getContextRoot() {
|
||||
return url.getPath()
|
||||
}
|
||||
|
||||
@Unroll
|
||||
def "test #path"() {
|
||||
when:
|
||||
Request request = new Request.Builder().url(HttpUrl.get(url.resolve(path))).build()
|
||||
Response response = client.newCall(request).execute()
|
||||
|
||||
then:
|
||||
response.withCloseable {
|
||||
assert response.code() == 200
|
||||
assert response.body().string() == "hello"
|
||||
true
|
||||
}
|
||||
|
||||
and:
|
||||
assertTraces(1) {
|
||||
trace(0, 2) {
|
||||
span(0) {
|
||||
name getContextRoot() + path
|
||||
kind SERVER
|
||||
hasNoParent()
|
||||
}
|
||||
span(1) {
|
||||
name className + ".hello"
|
||||
childOf span(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
where:
|
||||
path | className
|
||||
"rest-app/cdiHello" | "CdiRestResource"
|
||||
"rest-app/ejbHello" | "EjbRestResource"
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import java.util.Set;
|
|||
import javax.ws.rs.ApplicationPath;
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
@ApplicationPath("/")
|
||||
@ApplicationPath("/rest-app/")
|
||||
public class RestApplication extends Application {
|
||||
|
||||
@Override
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<arquillian xmlns="http://jboss.org/schema/arquillian"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://jboss.org/schema/arquillian
|
||||
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
|
||||
|
||||
<defaultProtocol type="Servlet 3.0" />
|
||||
|
||||
<container qualifier="wildfly-embedded" default="true">
|
||||
<configuration>
|
||||
<property name="jbossHome">build/server/wildfly-18.0.0.Final</property>
|
||||
<property name="modulePath">build/server/wildfly-18.0.0.Final/modules</property>
|
||||
</configuration>
|
||||
</container>
|
||||
</arquillian>
|
||||
|
|
@ -14,6 +14,7 @@ import io.opentelemetry.instrumentation.api.servlet.ServletContextPath;
|
|||
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
|
||||
import io.opentelemetry.instrumentation.api.tracer.ServerSpan;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.ClassHierarchyIterable;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.jaxrs.JaxrsContextPath;
|
||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
|
@ -66,6 +67,7 @@ public class JaxRsAnnotationsTracer extends BaseTracer {
|
|||
// empty when method and class don't have a jax-rs path annotation, this can happen when
|
||||
// creating an "abort" span, see RequestContextHelper.
|
||||
if (!pathBasedSpanName.isEmpty()) {
|
||||
pathBasedSpanName = JaxrsContextPath.prepend(context, pathBasedSpanName);
|
||||
pathBasedSpanName = ServletContextPath.prepend(context, pathBasedSpanName);
|
||||
}
|
||||
if (serverSpan == null) {
|
||||
|
|
|
|||
|
|
@ -7,11 +7,20 @@ muzzle {
|
|||
group = "org.apache.cxf"
|
||||
module = "cxf-rt-frontend-jaxrs"
|
||||
versions = "[3.2,)"
|
||||
extraDependency "javax.servlet:javax.servlet-api:3.1.0"
|
||||
}
|
||||
pass {
|
||||
group = "org.apache.tomee"
|
||||
module = "openejb-cxf-rs"
|
||||
// earlier versions of tomee use cxf older than 3.2
|
||||
versions = "(8,)"
|
||||
extraDependency "javax.servlet:javax.servlet-api:3.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0'
|
||||
compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
|
||||
library group: 'org.apache.cxf', name: 'cxf-rt-frontend-jaxrs', version: '3.2.0'
|
||||
|
||||
implementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent')
|
||||
|
|
@ -21,6 +30,7 @@ dependencies {
|
|||
|
||||
testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing')
|
||||
testImplementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.3'
|
||||
testImplementation group: 'org.eclipse.jetty', name: 'jetty-webapp', version: '9.4.6.v20170531'
|
||||
|
||||
testLibrary group: 'org.apache.cxf', name: 'cxf-rt-transports-http-jetty', version: '3.2.0'
|
||||
testLibrary group: 'org.apache.cxf', name: 'cxf-rt-ws-policy', version: '3.2.0'
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@AutoService(InstrumentationModule.class)
|
||||
|
|
@ -19,6 +20,9 @@ public class CxfInstrumentationModule extends InstrumentationModule {
|
|||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return Collections.singletonList(new CxfRequestContextInstrumentation());
|
||||
return asList(
|
||||
new CxfRequestContextInstrumentation(),
|
||||
new CxfServletControllerInstrumentation(),
|
||||
new CxfRsHttpListenerInstrumentation());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.jaxrs.JaxrsContextPath;
|
||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||
import java.util.Map;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
// TomEE specific instrumentation
|
||||
public class CxfRsHttpListenerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("org.apache.openejb.server.cxf.rs.CxfRsHttpListener");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
|
||||
return singletonMap(
|
||||
isMethod().and(named("doInvoke")),
|
||||
CxfRsHttpListenerInstrumentation.class.getName() + "$InvokeAdvice");
|
||||
}
|
||||
|
||||
public static class InvokeAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onEnter(
|
||||
@Advice.FieldValue("pattern") String pattern, @Advice.Local("otelScope") Scope scope) {
|
||||
Context context = JaxrsContextPath.init(Java8BytecodeBridge.currentContext(), pattern);
|
||||
if (context != null) {
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(@Advice.Local("otelScope") Scope scope) {
|
||||
if (scope != null) {
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.jaxrs.JaxrsContextPath;
|
||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class CxfServletControllerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("org.apache.cxf.transport.servlet.ServletController");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
|
||||
return Collections.singletonMap(
|
||||
isMethod()
|
||||
.and(isPublic())
|
||||
.and(named("invokeDestination"))
|
||||
.and(takesArgument(0, named("javax.servlet.http.HttpServletRequest"))),
|
||||
CxfServletControllerInstrumentation.class.getName() + "$InvokeAdvice");
|
||||
}
|
||||
|
||||
public static class InvokeAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onEnter(
|
||||
@Advice.Argument(0) HttpServletRequest httpServletRequest,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context context =
|
||||
JaxrsContextPath.init(
|
||||
Java8BytecodeBridge.currentContext(), httpServletRequest.getServletPath());
|
||||
if (context != null) {
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(@Advice.Local("otelScope") Scope scope) {
|
||||
if (scope != null) {
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import javax.ws.rs.core.Response
|
|||
import javax.ws.rs.ext.ExceptionMapper
|
||||
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean
|
||||
import org.apache.cxf.endpoint.Server
|
||||
import test.JaxRsTestApplication
|
||||
|
||||
class CxfHttpServerTest extends JaxRsHttpServerTest<Server> {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
class CxfJettyHttpServerTest extends JaxRsJettyHttpServerTest {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app version="3.0" metadata-complete="false"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>CXFNonSpringJaxrsServlet</servlet-name>
|
||||
<servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>javax.ws.rs.Application</param-name>
|
||||
<param-value>test.JaxRsApplicationPathTestApplication</param-value>
|
||||
</init-param>
|
||||
<async-supported>true</async-supported>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>CXFNonSpringJaxrsServlet</servlet-name>
|
||||
<url-pattern>/rest-app/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
||||
|
|
@ -7,12 +7,21 @@ muzzle {
|
|||
group = "org.glassfish.jersey.core"
|
||||
module = "jersey-server"
|
||||
versions = "[2.0,3.0.0)"
|
||||
extraDependency "javax.servlet:javax.servlet-api:3.1.0"
|
||||
}
|
||||
pass {
|
||||
group = "org.glassfish.jersey.containers"
|
||||
module = "jersey-container-servlet"
|
||||
versions = "[2.0,3.0.0)"
|
||||
extraDependency "javax.servlet:javax.servlet-api:3.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0'
|
||||
compileOnly group: 'org.glassfish.jersey.core', name: 'jersey-server', version: '2.0'
|
||||
compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
|
||||
library group: 'org.glassfish.jersey.core', name: 'jersey-server', version: '2.0'
|
||||
library group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet', version: '2.0'
|
||||
|
||||
implementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent')
|
||||
|
||||
|
|
@ -20,6 +29,7 @@ dependencies {
|
|||
testInstrumentation project(':instrumentation:servlet:servlet-javax-common:javaagent')
|
||||
|
||||
testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing')
|
||||
testImplementation group: 'org.eclipse.jetty', name: 'jetty-webapp', version: '8.0.0.v20110901'
|
||||
|
||||
// First version with DropwizardTestSupport:
|
||||
testLibrary group: 'io.dropwizard', name: 'dropwizard-testing', version: '0.8.0'
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@AutoService(InstrumentationModule.class)
|
||||
|
|
@ -19,6 +20,7 @@ public class JerseyInstrumentationModule extends InstrumentationModule {
|
|||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return Collections.singletonList(new JerseyRequestContextInstrumentation());
|
||||
return asList(
|
||||
new JerseyRequestContextInstrumentation(), new JerseyServletContainerInstrumentation());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.jaxrs.JaxrsContextPath;
|
||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class JerseyServletContainerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("org.glassfish.jersey.servlet.ServletContainer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
|
||||
return singletonMap(
|
||||
isMethod()
|
||||
.and(named("service"))
|
||||
.and(takesArgument(0, named("javax.servlet.http.HttpServletRequest")))
|
||||
.and(takesArgument(1, named("javax.servlet.http.HttpServletResponse"))),
|
||||
JerseyServletContainerInstrumentation.class.getName() + "$ServiceAdvice");
|
||||
}
|
||||
|
||||
public static class ServiceAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onEnter(
|
||||
@Advice.Argument(0) HttpServletRequest httpServletRequest,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context context =
|
||||
JaxrsContextPath.init(
|
||||
Java8BytecodeBridge.currentContext(), httpServletRequest.getServletPath());
|
||||
if (context != null) {
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(@Advice.Local("otelScope") Scope scope) {
|
||||
if (scope != null) {
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import org.eclipse.jetty.server.Server
|
|||
import org.eclipse.jetty.servlet.ServletContextHandler
|
||||
import org.glassfish.jersey.server.ResourceConfig
|
||||
import org.glassfish.jersey.servlet.ServletContainer
|
||||
import test.JaxRsTestApplication
|
||||
|
||||
class JerseyHttpServerTest extends JaxRsHttpServerTest<Server> {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
class JerseyJettyHttpServerTest extends JaxRsJettyHttpServerTest {
|
||||
|
||||
@Override
|
||||
boolean asyncCancelHasSendError() {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import javax.servlet.ServletContextEvent
|
||||
import javax.servlet.ServletContextListener
|
||||
import org.glassfish.jersey.servlet.init.JerseyServletContainerInitializer
|
||||
import test.JaxRsApplicationPathTestApplication
|
||||
|
||||
// ServletContainerInitializer isn't automatically called due to the way this test is set up
|
||||
// so we call it ourself
|
||||
class JerseyStartupListener implements ServletContextListener {
|
||||
@Override
|
||||
void contextInitialized(ServletContextEvent servletContextEvent) {
|
||||
new JerseyServletContainerInitializer().onStartup(Collections.singleton(JaxRsApplicationPathTestApplication),
|
||||
servletContextEvent.getServletContext())
|
||||
}
|
||||
|
||||
@Override
|
||||
void contextDestroyed(ServletContextEvent servletContextEvent) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app version="3.0" metadata-complete="false"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
|
||||
|
||||
<listener>
|
||||
<listener-class>JerseyStartupListener</listener-class>
|
||||
</listener>
|
||||
</web-app>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
ext {
|
||||
skipPublish = true
|
||||
}
|
||||
apply from: "$rootDir/gradle/instrumentation.gradle"
|
||||
|
||||
// add repo for org.gradle:gradle-tooling-api which org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-gradle-depchain
|
||||
// which is used by jaxrs-2.0-arquillian-testing depends on
|
||||
repositories {
|
||||
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-arquillian-testing')
|
||||
testImplementation "fish.payara.arquillian:arquillian-payara-server-embedded:2.4.1"
|
||||
testImplementation 'fish.payara.extras:payara-embedded-web:5.2021.2'
|
||||
|
||||
testInstrumentation project(':instrumentation:servlet:servlet-3.0:javaagent')
|
||||
testInstrumentation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent')
|
||||
testInstrumentation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-jersey-2.0:javaagent')
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
class PayaraRestTest extends ArquillianRestTest {
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<arquillian xmlns="http://jboss.org/schema/arquillian"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://jboss.org/schema/arquillian
|
||||
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
|
||||
|
||||
<defaultProtocol type="Servlet 3.0" />
|
||||
|
||||
<container qualifier="payara-embedded" default="true">
|
||||
<configuration>
|
||||
<!-- by default runs on port 8181 -->
|
||||
</configuration>
|
||||
</container>
|
||||
</arquillian>
|
||||
|
|
@ -30,11 +30,13 @@ dependencies {
|
|||
testInstrumentation project(':instrumentation:servlet:servlet-javax-common:javaagent')
|
||||
|
||||
testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing')
|
||||
testImplementation group: 'org.eclipse.jetty', name: 'jetty-webapp', version: '8.0.0.v20110901'
|
||||
|
||||
testLibrary(group: 'org.jboss.resteasy', name: 'resteasy-undertow', version: '3.0.4.Final') {
|
||||
exclude group: 'org.jboss.resteasy', module: 'resteasy-client'
|
||||
}
|
||||
testLibrary group: 'io.undertow', name: 'undertow-servlet', version: '1.0.0.Final'
|
||||
testLibrary group: 'org.jboss.resteasy', name: 'resteasy-servlet-initializer', version: '3.0.4.Final'
|
||||
|
||||
latestDepTestLibrary group: 'org.jboss.resteasy', name: 'resteasy-jaxrs', version: '3.+'
|
||||
latestDepTestLibrary(group: 'org.jboss.resteasy', name: 'resteasy-undertow', version: '3.+') {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@AutoService(InstrumentationModule.class)
|
||||
|
|
@ -19,6 +20,8 @@ public class Resteasy30InstrumentationModule extends InstrumentationModule {
|
|||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return Collections.singletonList(new Resteasy30RequestContextInstrumentation());
|
||||
return asList(
|
||||
new Resteasy30RequestContextInstrumentation(),
|
||||
new Resteasy30ServletContainerDispatcherInstrumentation());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.jaxrs.JaxrsContextPath;
|
||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class Resteasy30ServletContainerDispatcherInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
|
||||
return Collections.singletonMap(
|
||||
isMethod().and(named("service")),
|
||||
Resteasy30ServletContainerDispatcherInstrumentation.class.getName() + "$ServiceAdvice");
|
||||
}
|
||||
|
||||
public static class ServiceAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onEnter(
|
||||
@Advice.FieldValue("servletMappingPrefix") String servletMappingPrefix,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context context =
|
||||
JaxrsContextPath.init(Java8BytecodeBridge.currentContext(), servletMappingPrefix);
|
||||
if (context != null) {
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(@Advice.Local("otelScope") Scope scope) {
|
||||
if (scope != null) {
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import io.undertow.Undertow
|
||||
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer
|
||||
import test.JaxRsTestApplication
|
||||
|
||||
class ResteasyHttpServerTest extends JaxRsHttpServerTest<UndertowJaxrsServer> {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
class ResteasyJettyHttpServerTest extends JaxRsJettyHttpServerTest {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import javax.servlet.ServletContextEvent
|
||||
import javax.servlet.ServletContextListener
|
||||
import org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer
|
||||
import test.JaxRsApplicationPathTestApplication
|
||||
|
||||
// ServletContainerInitializer isn't automatically called due to the way this test is set up
|
||||
// so we call it ourself
|
||||
class ResteasyStartupListener implements ServletContextListener {
|
||||
@Override
|
||||
void contextInitialized(ServletContextEvent servletContextEvent) {
|
||||
new ResteasyServletInitializer().onStartup(Collections.singleton(JaxRsApplicationPathTestApplication),
|
||||
servletContextEvent.getServletContext())
|
||||
}
|
||||
|
||||
@Override
|
||||
void contextDestroyed(ServletContextEvent servletContextEvent) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app version="3.0" metadata-complete="false"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
|
||||
|
||||
<listener>
|
||||
<listener-class>ResteasyStartupListener</listener-class>
|
||||
</listener>
|
||||
</web-app>
|
||||
|
|
@ -30,10 +30,12 @@ dependencies {
|
|||
testInstrumentation project(':instrumentation:servlet:servlet-javax-common:javaagent')
|
||||
|
||||
testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing')
|
||||
testImplementation group: 'org.eclipse.jetty', name: 'jetty-webapp', version: '8.0.0.v20110901'
|
||||
|
||||
testLibrary(group: 'org.jboss.resteasy', name: 'resteasy-undertow', version: '3.1.0.Final') {
|
||||
exclude group: 'org.jboss.resteasy', module: 'resteasy-client'
|
||||
}
|
||||
testLibrary group: 'org.jboss.resteasy', name: 'resteasy-servlet-initializer', version: '3.1.0.Final'
|
||||
|
||||
// artifact name changed from 'resteasy-jaxrs' to 'resteasy-core' starting from version 4.0.0
|
||||
latestDepTestLibrary group: 'org.jboss.resteasy', name: 'resteasy-core', version: '+'
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.tooling.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@AutoService(InstrumentationModule.class)
|
||||
|
|
@ -19,6 +20,8 @@ public class Resteasy31InstrumentationModule extends InstrumentationModule {
|
|||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return Collections.singletonList(new Resteasy31RequestContextInstrumentation());
|
||||
return asList(
|
||||
new Resteasy31RequestContextInstrumentation(),
|
||||
new Resteasy31ServletContainerDispatcherInstrumentation());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.jaxrs.JaxrsContextPath;
|
||||
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class Resteasy31ServletContainerDispatcherInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
|
||||
return Collections.singletonMap(
|
||||
isMethod().and(named("service")),
|
||||
Resteasy31ServletContainerDispatcherInstrumentation.class.getName() + "$ServiceAdvice");
|
||||
}
|
||||
|
||||
public static class ServiceAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onEnter(
|
||||
@Advice.FieldValue("servletMappingPrefix") String servletMappingPrefix,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context context =
|
||||
JaxrsContextPath.init(Java8BytecodeBridge.currentContext(), servletMappingPrefix);
|
||||
if (context != null) {
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(@Advice.Local("otelScope") Scope scope) {
|
||||
if (scope != null) {
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import io.undertow.Undertow
|
||||
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer
|
||||
import test.JaxRsTestApplication
|
||||
|
||||
class ResteasyHttpServerTest extends JaxRsHttpServerTest<UndertowJaxrsServer> {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
class ResteasyJettyHttpServerTest extends JaxRsJettyHttpServerTest {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import javax.servlet.ServletContextEvent
|
||||
import javax.servlet.ServletContextListener
|
||||
import org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer
|
||||
import test.JaxRsApplicationPathTestApplication
|
||||
|
||||
// ServletContainerInitializer isn't automatically called due to the way this test is set up
|
||||
// so we call it ourself
|
||||
class ResteasyStartupListener implements ServletContextListener {
|
||||
@Override
|
||||
void contextInitialized(ServletContextEvent servletContextEvent) {
|
||||
new ResteasyServletInitializer().onStartup(Collections.singleton(JaxRsApplicationPathTestApplication),
|
||||
servletContextEvent.getServletContext())
|
||||
}
|
||||
|
||||
@Override
|
||||
void contextDestroyed(ServletContextEvent servletContextEvent) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app version="3.0" metadata-complete="false"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
|
||||
|
||||
<listener>
|
||||
<listener-class>ResteasyStartupListener</listener-class>
|
||||
</listener>
|
||||
</web-app>
|
||||
|
|
@ -13,4 +13,6 @@ dependencies {
|
|||
implementation project(':javaagent-api')
|
||||
implementation project(':instrumentation-api')
|
||||
implementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent')
|
||||
|
||||
compileOnly group: 'org.eclipse.jetty', name: 'jetty-webapp', version: '8.0.0.v20110901'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import okhttp3.HttpUrl
|
|||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import spock.lang.Unroll
|
||||
import test.JaxRsTestResource
|
||||
|
||||
abstract class JaxRsHttpServerTest<S> extends HttpServerTest<S> implements AgentTestTrait {
|
||||
@Unroll
|
||||
|
|
@ -225,7 +226,7 @@ abstract class JaxRsHttpServerTest<S> extends HttpServerTest<S> implements Agent
|
|||
}
|
||||
childOf((SpanData) parent)
|
||||
attributes {
|
||||
"${SemanticAttributes.CODE_NAMESPACE.key}" "JaxRsTestResource"
|
||||
"${SemanticAttributes.CODE_NAMESPACE.key}" "test.JaxRsTestResource"
|
||||
"${SemanticAttributes.CODE_FUNCTION.key}" methodName
|
||||
if (isCancelled) {
|
||||
"jaxrs.canceled" true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import static org.eclipse.jetty.util.resource.Resource.newResource
|
||||
|
||||
import org.eclipse.jetty.server.Server
|
||||
import org.eclipse.jetty.webapp.WebAppContext
|
||||
|
||||
class JaxRsJettyHttpServerTest extends JaxRsHttpServerTest<Server> {
|
||||
|
||||
@Override
|
||||
Server startServer(int port) {
|
||||
WebAppContext webAppContext = new WebAppContext()
|
||||
webAppContext.setContextPath("/")
|
||||
// set up test application
|
||||
webAppContext.setBaseResource(newResource("src/test/webapp"))
|
||||
|
||||
def jettyServer = new Server(port)
|
||||
jettyServer.connectors.each {
|
||||
it.setHost('localhost')
|
||||
}
|
||||
|
||||
jettyServer.setHandler(webAppContext)
|
||||
jettyServer.start()
|
||||
|
||||
return jettyServer
|
||||
}
|
||||
|
||||
@Override
|
||||
void stopServer(Server server) {
|
||||
server.stop()
|
||||
server.destroy()
|
||||
}
|
||||
|
||||
@Override
|
||||
String getContextPath() {
|
||||
"/rest-app"
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package test
|
||||
|
||||
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR
|
||||
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
|
||||
import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM
|
||||
|
|
@ -15,6 +17,7 @@ import io.opentelemetry.instrumentation.test.base.HttpServerTest
|
|||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.CompletionStage
|
||||
import java.util.concurrent.CyclicBarrier
|
||||
import javax.ws.rs.ApplicationPath
|
||||
import javax.ws.rs.GET
|
||||
import javax.ws.rs.Path
|
||||
import javax.ws.rs.PathParam
|
||||
|
|
@ -148,4 +151,8 @@ class JaxRsTestApplication extends Application {
|
|||
classes.add(JaxRsTestExceptionMapper)
|
||||
return classes
|
||||
}
|
||||
}
|
||||
|
||||
@ApplicationPath("/rest-app")
|
||||
class JaxRsApplicationPathTestApplication extends JaxRsTestApplication {
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
ext {
|
||||
skipPublish = true
|
||||
}
|
||||
apply from: "$rootDir/gradle/instrumentation.gradle"
|
||||
|
||||
// add repo for org.gradle:gradle-tooling-api which org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-gradle-depchain
|
||||
// which is used by jaxrs-2.0-arquillian-testing depends on
|
||||
repositories {
|
||||
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-arquillian-testing')
|
||||
testImplementation "org.apache.tomee:arquillian-tomee-embedded:8.0.6"
|
||||
testImplementation "org.apache.tomee:tomee-embedded:8.0.6"
|
||||
testImplementation "org.apache.tomee:tomee-jaxrs:8.0.6"
|
||||
|
||||
testInstrumentation project(':instrumentation:servlet:servlet-3.0:javaagent')
|
||||
testInstrumentation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent')
|
||||
testInstrumentation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-cxf-3.2:javaagent')
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import javax.enterprise.inject.Vetoed
|
||||
|
||||
// exclude this class from CDI as it causes NullPointerException when tomee is run with jdk8
|
||||
@Vetoed
|
||||
class TomeeRestTest extends ArquillianRestTest {
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<arquillian xmlns="http://jboss.org/schema/arquillian"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://jboss.org/schema/arquillian
|
||||
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
|
||||
|
||||
<defaultProtocol type="Servlet 3.0" />
|
||||
|
||||
<container qualifier="tomee-embedded" default="true">
|
||||
<configuration>
|
||||
<property name="httpPort">-1</property>
|
||||
<property name="stopPort">-1</property>
|
||||
</configuration>
|
||||
</container>
|
||||
</arquillian>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>
|
||||
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<root level="WARN">
|
||||
<appender-ref ref="console"/>
|
||||
</root>
|
||||
|
||||
<logger name="io.opentelemetry" level="debug"/>
|
||||
|
||||
</configuration>
|
||||
|
|
@ -3,6 +3,8 @@ ext {
|
|||
}
|
||||
apply from: "$rootDir/gradle/instrumentation.gradle"
|
||||
|
||||
// add repo for org.gradle:gradle-tooling-api which org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-gradle-depchain
|
||||
// which is used by jaxrs-2.0-arquillian-testing depends on
|
||||
repositories {
|
||||
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
|
||||
}
|
||||
|
|
@ -14,16 +16,12 @@ configurations {
|
|||
dependencies {
|
||||
testImplementation "javax:javaee-api:7.0"
|
||||
|
||||
def arquillianVersion = '1.4.0.Final'
|
||||
testImplementation "org.jboss.arquillian.junit:arquillian-junit-container:${arquillianVersion}"
|
||||
testImplementation "org.jboss.arquillian.protocol:arquillian-protocol-servlet:${arquillianVersion}"
|
||||
testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-arquillian-testing')
|
||||
testImplementation "org.wildfly.arquillian:wildfly-arquillian-container-embedded:2.2.0.Final"
|
||||
testImplementation 'org.jboss.arquillian.spock:arquillian-spock-container:1.0.0.CR1'
|
||||
testImplementation "org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-gradle-depchain:3.1.3"
|
||||
testImplementation "org.glassfish.jersey.core:jersey-client:2.8"
|
||||
|
||||
testInstrumentation project(':instrumentation:servlet:servlet-3.0:javaagent')
|
||||
testInstrumentation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent')
|
||||
testInstrumentation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-resteasy-3.0:javaagent')
|
||||
|
||||
// wildfly version used to run tests
|
||||
testServer "org.wildfly:wildfly-dist:18.0.0.Final@zip"
|
||||
|
|
|
|||
|
|
@ -3,75 +3,5 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import static io.opentelemetry.api.trace.SpanKind.SERVER
|
||||
|
||||
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
|
||||
import javax.ws.rs.client.Client
|
||||
import javax.ws.rs.client.WebTarget
|
||||
import org.glassfish.jersey.client.JerseyClientBuilder
|
||||
import org.jboss.arquillian.container.test.api.Deployment
|
||||
import org.jboss.arquillian.container.test.api.RunAsClient
|
||||
import org.jboss.arquillian.spock.ArquillianSputnik
|
||||
import org.jboss.arquillian.test.api.ArquillianResource
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap
|
||||
import org.jboss.shrinkwrap.api.asset.EmptyAsset
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive
|
||||
import org.junit.runner.RunWith
|
||||
import test.CdiRestResource
|
||||
import test.EjbRestResource
|
||||
import test.RestApplication
|
||||
|
||||
@RunWith(ArquillianSputnik)
|
||||
@RunAsClient
|
||||
class WildflyRestTest extends AgentInstrumentationSpecification {
|
||||
|
||||
@ArquillianResource
|
||||
static URI url
|
||||
|
||||
@Deployment
|
||||
static WebArchive createDeployment() {
|
||||
return ShrinkWrap.create(WebArchive)
|
||||
.addClass(RestApplication)
|
||||
.addClass(CdiRestResource)
|
||||
.addClass(EjbRestResource)
|
||||
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
|
||||
}
|
||||
|
||||
def getContextRoot() {
|
||||
return url.getPath()
|
||||
}
|
||||
|
||||
def "test #path"() {
|
||||
when:
|
||||
Client client = JerseyClientBuilder.newClient()
|
||||
WebTarget webTarget = client.target(url)
|
||||
|
||||
String result = webTarget.path(path)
|
||||
.request()
|
||||
.get()
|
||||
.readEntity(String)
|
||||
|
||||
then:
|
||||
result == "hello"
|
||||
|
||||
and:
|
||||
assertTraces(1) {
|
||||
trace(0, 2) {
|
||||
span(0) {
|
||||
name getContextRoot() + path
|
||||
kind SERVER
|
||||
hasNoParent()
|
||||
}
|
||||
span(1) {
|
||||
name className + ".hello"
|
||||
childOf span(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
where:
|
||||
path | className
|
||||
"cdiHello" | "CdiRestResource"
|
||||
"ejbHello" | "EjbRestResource"
|
||||
}
|
||||
class WildflyRestTest extends ArquillianRestTest {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.api.jaxrs;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.ContextKey;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Helper container for storing context path for jax-rs requests. Jax-rs context path is the path
|
||||
* where jax-rs servlet is mapped or the value of ApplicationPath annotation. Span name is built by
|
||||
* combining servlet context path from {@link
|
||||
* io.opentelemetry.instrumentation.api.servlet.ServletContextPath} jax-rs context path and the Path
|
||||
* annotation from called method or class.
|
||||
*/
|
||||
public final class JaxrsContextPath {
|
||||
private static final ContextKey<String> CONTEXT_KEY =
|
||||
ContextKey.named("opentelemetry-jaxrs-context-path-key");
|
||||
|
||||
private JaxrsContextPath() {}
|
||||
|
||||
public static @Nullable Context init(Context context, String path) {
|
||||
if (path == null || path.isEmpty() || "/".equals(path)) {
|
||||
return null;
|
||||
}
|
||||
// normalize path to have a leading slash and no trailing slash
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
if (path.endsWith("/")) {
|
||||
path = path.substring(0, path.length() - 1);
|
||||
}
|
||||
return context.with(CONTEXT_KEY, path);
|
||||
}
|
||||
|
||||
public static String prepend(Context context, String spanName) {
|
||||
String value = context.get(CONTEXT_KEY);
|
||||
// checking isEmpty just to avoid unnecessary string concat / allocation
|
||||
if (value != null && !value.isEmpty()) {
|
||||
return value + spanName;
|
||||
} else {
|
||||
return spanName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -190,6 +190,12 @@ public class GlobalIgnoresMatcher extends ElementMatcher.Junction.AbstractBase<T
|
|||
|| name.contains(".asm.")
|
||||
|| name.contains("$__sisu")
|
||||
|| name.contains("$$EnhancerByProxool$$")
|
||||
// glassfish ejb proxy
|
||||
// We skip instrumenting these because some instrumentations e.g. jax-rs instrument methods
|
||||
// that are annotated with @Path in an interface implemented by the class. We don't really
|
||||
// want to instrument these methods in generated classes as this would create spans that
|
||||
// have the generated class name in them instead of the actual class that handles the call.
|
||||
|| name.contains("__EJB31_Generated__")
|
||||
|| name.startsWith("org.springframework.core.$Proxy")) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,12 +127,15 @@ include ':instrumentation:http-url-connection:javaagent'
|
|||
include ':instrumentation:hystrix-1.4:javaagent'
|
||||
include ':instrumentation:java-httpclient:javaagent'
|
||||
include ':instrumentation:jaxrs:jaxrs-1.0:javaagent'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-arquillian-testing'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-cxf-3.2:javaagent'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-jersey-2.0:javaagent'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-payara-testing'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-resteasy-3.0:javaagent'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-resteasy-3.1:javaagent'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-tomee-testing'
|
||||
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-wildfly-testing'
|
||||
include ':instrumentation:jaxrs-client:jaxrs-client-1.1:javaagent'
|
||||
include ':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-common:javaagent'
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ abstract class HttpServerTest<SERVER> extends InstrumentationSpecification imple
|
|||
response.withCloseable {
|
||||
assert response.code() == REDIRECT.status
|
||||
assert response.header("location") == REDIRECT.body ||
|
||||
response.header("location") == "${address.resolve(REDIRECT.body)}"
|
||||
new URI(response.header("location")).normalize().toString() == "${address.resolve(REDIRECT.body)}"
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue