Skip to content

Commit

Permalink
Add instrumentation for jaxws metro 3.0+ (#9705)
Browse files Browse the repository at this point in the history
  • Loading branch information
philsttr authored Oct 27, 2023
1 parent 71ea355 commit dc975b7
Show file tree
Hide file tree
Showing 27 changed files with 569 additions and 81 deletions.
2 changes: 1 addition & 1 deletion docs/supported-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ These are the supported libraries and frameworks:
| [Eclipse Grizzly](https://javaee.github.io/grizzly/httpserverframework.html) | 2.3+ | N/A | [HTTP Server Spans], [HTTP Server Metrics] |
| [Eclipse Jersey](https://eclipse-ee4j.github.io/jersey/) | 2.0+ (not including 3.x yet) | N/A | Provides `http.route` [2], Controller Spans [3] |
| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2+ (not including 10+ yet) | [opentelemetry-jetty-httpclient-9.2](../instrumentation/jetty-httpclient/jetty-httpclient-9.2/library) | [HTTP Client Spans], [HTTP Client Metrics] |
| [Eclipse Metro](https://projects.eclipse.org/projects/ee4j.metro) | 2.2+ (not including 3.x yet) | N/A | Provides `http.route` [2], Controller Spans [3] |
| [Eclipse Metro](https://projects.eclipse.org/projects/ee4j.metro) | 2.2+ | N/A | Provides `http.route` [2], Controller Spans [3] |
| [Eclipse Mojarra](https://projects.eclipse.org/projects/ee4j.mojarra) | 1.2+ (not including 3.x yet) | N/A | Provides `http.route` [2], Controller Spans [3] |
| [Elasticsearch API Client](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html) | 7.16+ and 8.0+ | N/A | [Elasticsearch Client Spans] |
| [Elasticsearch REST Client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html) | 5.0+ | N/A | [Database Client Spans] |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ dependencies {
api("javax.xml.ws:jaxws-api:2.0")
api("javax.jws:javax.jws-api:1.1")

api("ch.qos.logback:logback-classic")
api("org.slf4j:log4j-over-slf4j")
api("org.slf4j:jcl-over-slf4j")
api("org.slf4j:jul-to-slf4j")
api("org.eclipse.jetty:jetty-webapp:9.4.35.v20201120")
api("org.springframework.ws:spring-ws-core:3.0.0.RELEASE")

Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,17 @@
plugins {
id("otel.javaagent-instrumentation")
}

muzzle {
pass {
group.set("com.sun.xml.ws")
module.set("jaxws-rt")
versions.set("[2.2.0.1,3)")
// version 2.3.4 depends on org.glassfish.gmbal:gmbal-api-only:4.0.3 which does not exist
skip("2.3.4")
assertInverse.set(true)
extraDependency("javax.servlet:javax.servlet-api:3.0.1")
}
id("otel.javaagent-testing")
}

dependencies {
bootstrap(project(":instrumentation:servlet:servlet-common:bootstrap"))

library("com.sun.xml.ws:jaxws-rt:2.2.0.1")
testLibrary("com.sun.xml.ws:jaxws-rt:2.2.0.1")
// early versions of streambuffer depend on latest release of org.jvnet.staxex:stax-ex
// which doesn't work with java 8
library("com.sun.xml.stream.buffer:streambuffer:1.4")

compileOnly("javax.servlet:javax.servlet-api:3.0.1")
testLibrary("com.sun.xml.stream.buffer:streambuffer:1.4")

testImplementation("javax.servlet:javax.servlet-api:3.0.1")
testImplementation(project(":instrumentation:jaxws:jaxws-2.0-common-testing"))

testInstrumentation(project(":instrumentation:jaxws:jaxws-metro-2.2:javaagent"))
testInstrumentation(project(":instrumentation:jaxws:jaxws-2.0:javaagent"))
testInstrumentation(project(":instrumentation:jaxws:jaxws-jws-api-1.1:javaagent"))

Expand Down

This file was deleted.

24 changes: 24 additions & 0 deletions instrumentation/jaxws/jaxws-3.0-common-testing/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
plugins {
id("org.unbroken-dome.xjc")
id("otel.java-conventions")
}

tasks {
named<Checkstyle>("checkstyleMain") {
// exclude generated web service classes
exclude("**/hello_web_service/**")
}
}

dependencies {
api("jakarta.xml.ws:jakarta.xml.ws-api:3.0.0")
api("jakarta.jws:jakarta.jws-api:3.0.0")

api("org.eclipse.jetty:jetty-webapp:11.0.17")
api("org.springframework.ws:spring-ws-core:4.0.0")

implementation(project(":testing-common"))

xjcTool("com.sun.xml.bind:jaxb-xjc:3.0.2")
xjcTool("com.sun.xml.bind:jaxb-impl:3.0.2")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.instrumentation.test.asserts.TraceAssert
import io.opentelemetry.instrumentation.test.base.HttpServerTestTrait
import io.opentelemetry.sdk.trace.data.SpanData
import io.opentelemetry.semconv.SemanticAttributes
import io.opentelemetry.test.hello_web_service.Hello2Request
import io.opentelemetry.test.hello_web_service.HelloRequest
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.util.resource.Resource
import org.eclipse.jetty.webapp.WebAppContext
import org.springframework.oxm.jaxb.Jaxb2Marshaller
import org.springframework.util.ClassUtils
import org.springframework.ws.client.core.WebServiceTemplate
import org.springframework.ws.soap.client.SoapFaultClientException
import spock.lang.Shared
import spock.lang.Unroll

import static io.opentelemetry.api.trace.SpanKind.INTERNAL
import static io.opentelemetry.api.trace.SpanKind.SERVER
import static io.opentelemetry.api.trace.StatusCode.ERROR

abstract class AbstractJaxWsTest extends AgentInstrumentationSpecification implements HttpServerTestTrait<Server> {

@Shared
private Jaxb2Marshaller marshaller = new Jaxb2Marshaller()

@Shared
protected WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marshaller)

def setupSpec() {
setupServer()

marshaller.setPackagesToScan(ClassUtils.getPackageName(HelloRequest))
marshaller.afterPropertiesSet()
}

def cleanupSpec() {
cleanupServer()
}

@Override
Server startServer(int port) {
WebAppContext webAppContext = new WebAppContext()
webAppContext.setContextPath(getContextPath())
// set up test application
webAppContext.setBaseResource(Resource.newSystemResource("test-app"))
webAppContext.getMetaData().addWebInfResource(Resource.newClassPathResource("/"))

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() {
return "/jetty-context"
}

String getServiceAddress(String serviceName) {
return address.resolve("ws/" + serviceName).toString()
}

def makeRequest(methodName, name) {
Object request = null
if ("hello" == methodName) {
request = new HelloRequest(name: name)
} else if ("hello2" == methodName) {
request = new Hello2Request(name: name)
} else {
throw new IllegalArgumentException(methodName)
}

return webServiceTemplate.marshalSendAndReceive(getServiceAddress("HelloService"), request)
}

@Unroll
def "test #methodName"() {
setup:
def response = makeRequest(methodName, "Test")

expect:
response.getMessage() == "Hello Test"

and:
def spanCount = 2
assertTraces(1) {
trace(0, spanCount) {
serverSpan(it, 0, serverSpanName(methodName))
handlerSpan(it, 1, methodName, span(0))
}
}

where:
methodName << ["hello", "hello2"]
}

@Unroll
def "test #methodName exception"() {
when:
makeRequest(methodName, "exception")

then:
def error = thrown(SoapFaultClientException)
error.getMessage() == "hello exception"

and:
def spanCount = 2
def expectedException = new Exception("hello exception")
assertTraces(1) {
trace(0, spanCount) {
serverSpan(it, 0, serverSpanName(methodName), expectedException)
handlerSpan(it, 1, methodName, span(0), expectedException)
}
}

where:
methodName << ["hello", "hello2"]
}

def serverSpanName(String operation) {
return getContextPath() + "/ws/HelloService/" + operation
}

static serverSpan(TraceAssert trace, int index, String operation, Throwable exception = null) {
trace.span(index) {
hasNoParent()
name operation
kind SERVER
if (exception != null) {
status ERROR
}
}
}

static handlerSpan(TraceAssert trace, int index, String operation, Object parentSpan = null, Throwable exception = null) {
trace.span(index) {
if (parentSpan == null) {
hasNoParent()
} else {
childOf((SpanData) parentSpan)
}
name "HelloService/" + operation
kind INTERNAL
if (exception) {
status ERROR
errorEvent(exception.class, exception.message)
}
}
}

static annotationHandlerSpan(TraceAssert trace, int index, String methodName, Object parentSpan = null, Throwable exception = null) {
trace.span(index) {
if (parentSpan == null) {
hasNoParent()
} else {
childOf((SpanData) parentSpan)
}
name "HelloServiceImpl." + methodName
kind INTERNAL
if (exception) {
status ERROR
errorEvent(exception.class, exception.message)
}
attributes {
"$SemanticAttributes.CODE_NAMESPACE" "hello.HelloServiceImpl"
"$SemanticAttributes.CODE_FUNCTION" methodName
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package hello

class BaseHelloService {

String hello2(String name) {
if ("exception" == name) {
throw new Exception("hello exception")
}
return "Hello " + name
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package hello

import jakarta.jws.WebParam
import jakarta.jws.WebResult
import jakarta.jws.WebService
import jakarta.xml.ws.RequestWrapper

@WebService(targetNamespace = "http://opentelemetry.io/test/hello-web-service")
interface HelloService {

@RequestWrapper(localName = "helloRequest")
@WebResult(name = "message")
String hello(@WebParam(name = "name") String name)

@RequestWrapper(localName = "hello2Request")
@WebResult(name = "message")
String hello2(@WebParam(name = "name") String name)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package hello

import jakarta.jws.WebService

@WebService(serviceName = "HelloService", endpointInterface = "hello.HelloService", targetNamespace = "http://opentelemetry.io/test/hello-web-service")
class HelloServiceImpl extends BaseHelloService implements HelloService {

String hello(String name) {
if ("exception" == name) {
throw new Exception("hello exception")
}
return "Hello " + name
}
}
Loading

0 comments on commit dc975b7

Please sign in to comment.