Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@
* Introduces a new configuration option `disable_metrics` which disables the collection of metrics via a wildcard expression.
* Support for HttpUrlConnection
* Adds `subtype` and `action` to spans. This replaces former typing mechanism where type, subtype and action were all set through
the type in an hierarchical dotted-syntax. In order to support existing API usages, dotted types are parsed into subtype and action,
however `Span.createSpan` and `Span.setType` are deprecated starting this version. Instead, type-less spans can be created using the new
`Span.startSpan` API and typed spans can be created using the new `Span.startSpan(String type, String subtype, String action)` API
* Add support for JBoss EAP
* Improving startup times
the type in an hierarchical dotted-syntax. In order to support existing API usages, dotted types are parsed into subtype and action,
however `Span.createSpan` and `Span.setType` are deprecated starting this version. Instead, type-less spans can be created using the new
`Span.startSpan` API and typed spans can be created using the new `Span.startSpan(String type, String subtype, String action)` API
* Support for JBoss EAP 6.4, 7.0, 7.1 and 7.2
* Improved startup times
* Support for SOAP (JAX-WS).
SOAP client create spans and propagate context.
Transactions are created for `@WebService` classes and `@WebMethod` methods.

## Bug Fixes
* Fixes a failure in BitBucket when agent deployed ([#349](https://github.com/elastic/apm-agent-java/issues/349))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;

Expand Down Expand Up @@ -103,6 +102,6 @@ public ElementMatcher<? super MethodDescription> getMethodMatcher() {

@Override
public Collection<String> getInstrumentationGroupNames() {
return Arrays.asList("jax-rs", "jax-rs-annotations");
return Collections.singletonList("jax-rs");
}
}
24 changes: 24 additions & 0 deletions apm-agent-plugins/apm-jaxws-plugin/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>apm-agent-plugins</artifactId>
<groupId>co.elastic.apm</groupId>
<version>1.3.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>apm-jaxws-plugin</artifactId>

<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>test</scope>
</dependency>
</dependencies>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*-
* #%L
* Elastic APM Java agent
* %%
* Copyright (C) 2018 - 2019 Elastic and contributors
* %%
* Licensed 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.
* #L%
*/
package co.elastic.apm.agent.jaxws;

import co.elastic.apm.agent.bci.ElasticApmInstrumentation;
import co.elastic.apm.agent.bci.bytebuddy.SimpleMethodSignatureOffsetMappingFactory.SimpleMethodSignature;
import co.elastic.apm.agent.impl.ElasticApmTracer;
import co.elastic.apm.agent.impl.stacktrace.StacktraceConfiguration;
import co.elastic.apm.agent.impl.transaction.Transaction;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;

import java.util.Collection;
import java.util.Collections;

import static co.elastic.apm.agent.bci.bytebuddy.CustomElementMatchers.classLoaderCanLoadClass;
import static co.elastic.apm.agent.bci.bytebuddy.CustomElementMatchers.isInAnyPackage;
import static co.elastic.apm.agent.bci.bytebuddy.CustomElementMatchers.overridesOrImplementsMethodThat;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.isBootstrapClassLoader;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;

public class JaxWsTransactionNameInstrumentation extends ElasticApmInstrumentation {

private Collection<String> applicationPackages = Collections.emptyList();

@Advice.OnMethodEnter(suppress = Throwable.class)
private static void setTransactionName(@SimpleMethodSignature String signature) {
if (tracer != null) {
final Transaction transaction = tracer.currentTransaction();
if (transaction != null && transaction.getName().length() == 0) {
transaction.withName(signature);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SOAP clients calls will not be captured?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not about capturing SOAP calls, it's just about naming SOAP transactions

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant- would this instrumentation be executed for SOAP client invocations, thus changing the wrong transaction names, or the annotation in the type matching eliminates that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's actually a good question. I think it works because the stub created for the WS request does not contain the annotations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test I suggested would verify that

}
}
}

@Override
public void init(ElasticApmTracer tracer) {
applicationPackages = tracer.getConfig(StacktraceConfiguration.class).getApplicationPackages();
}

@Override
public ElementMatcher<? super NamedElement> getTypeMatcherPreFilter() {
// setting application_packages makes this matcher more performant but is not required
// could lead to false negative matches when importing a 3rd party library whose JAX-WS resources are exposed
return isInAnyPackage(applicationPackages, ElementMatchers.<NamedElement>any());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this false negative interesting? I assume mostly it would be application code, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this would only be an edge case. I expect that mostly, the JAX-WS resources are inside of the application. If they're not, then they can just add the 3rd party packages as well.

}

@Override
public ElementMatcher<? super TypeDescription> getTypeMatcher() {
// the implementations have to be annotated as well
// quote from javadoc:
// "Marks a Java class as implementing a Web Service, or a Java interface as defining a Web Service interface."
return isAnnotatedWith(named("javax.jws.WebService")).and(not(isInterface()));
}

@Override
public ElementMatcher.Junction<ClassLoader> getClassLoaderMatcher() {
return not(isBootstrapClassLoader())
.and(classLoaderCanLoadClass("javax.jws.WebService"));
}

@Override
public ElementMatcher<? super MethodDescription> getMethodMatcher() {
return overridesOrImplementsMethodThat(
isAnnotatedWith(
named("javax.jws.WebMethod")))
.onSuperClassesThat(isInAnyPackage(applicationPackages, ElementMatchers.<NamedElement>any()));
}

@Override
public Collection<String> getInstrumentationGroupNames() {
return Collections.singletonList("jax-ws");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*-
* #%L
* Elastic APM Java agent
* %%
* Copyright (C) 2018 - 2019 Elastic and contributors
* %%
* Licensed 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.
* #L%
*/
@NonnullApi
package co.elastic.apm.agent.jaxws;

import co.elastic.apm.agent.annotation.NonnullApi;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
co.elastic.apm.agent.jaxws.JaxWsTransactionNameInstrumentation
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*-
* #%L
* Elastic APM Java agent
* %%
* Copyright (C) 2018 - 2019 Elastic and contributors
* %%
* Licensed 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.
* #L%
*/
package co.elastic.apm.agent.jaxws;

import co.elastic.apm.agent.AbstractInstrumentationTest;
import co.elastic.apm.agent.impl.Scope;
import co.elastic.apm.agent.impl.transaction.Transaction;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

import static org.assertj.core.api.Assertions.assertThat;

class JaxWsTransactionNameInstrumentationTest extends AbstractInstrumentationTest {

private HelloWorldService helloWorldService;

@BeforeEach
void setUp() {
helloWorldService = new HelloWorldServiceImpl();
}

@Test
void testTransactionName() {
final Transaction transaction = tracer.startTransaction();
try (Scope scope = transaction.activateInScope()) {
helloWorldService.sayHello();
} finally {
transaction.end();
}
assertThat(transaction.getName().toString()).isEqualTo("HelloWorldServiceImpl#sayHello");
}

@SOAPBinding(style = SOAPBinding.Style.RPC)
@WebService(targetNamespace = "elastic")
public interface HelloWorldService {
@WebMethod
String sayHello();
}

@WebService(serviceName = "HelloWorldService", portName = "HelloWorld", name = "HelloWorld",
endpointInterface = "co.elastic.apm.agent.jaxws.JaxWsTransactionNameInstrumentationTest.HelloWorldService",
targetNamespace = "elastic")
public static class HelloWorldServiceImpl implements HelloWorldService {
@Override
public String sayHello() {
return "Hello World";
}
}

}
1 change: 1 addition & 0 deletions apm-agent-plugins/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<module>apm-okhttp-plugin</module>
<module>apm-java-concurrent-plugin</module>
<module>apm-urlconnection-plugin</module>
<module>apm-jaxws-plugin</module>
</modules>

<properties>
Expand Down
28 changes: 25 additions & 3 deletions docs/supported-technologies.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,30 @@ the agent does not capture transactions.
[[supported-web-frameworks]]
=== Web Frameworks
|===
|Framework |Supported versions | Description
|Framework |Supported versions | Description | Since

|Servlet API
|3+
|A transaction will be created for all incoming HTTP requests to your Servlet API-based application.
See also <<supported-app-servers>>
|1.0.0

|Spring Web MVC
|4.x, 5.x
|If you are using Spring MVC (for example with Spring Boot),
the transactions are named based on your controllers (`ControllerClass#controllerMethod`).
|1.0.0

|JavaServer Faces
|2.2.x, 2.3.x
|If you are using JSF, transactions are named based on the requested Facelets and spans are captured for visibility into execution and
rendering
|1.0.0

|Spring Boot
|1.5+, 2.x
|Supports embedded Tomcat, Jetty and Undertow
|1.0.0

|JAX-RS
|2.x
Expand All @@ -75,6 +79,18 @@ rendering
This comes at the cost of increased startup times, however.

Note: JAX-RS is only supported when running on a supported <<supported-app-servers, Application Server/Servlet Container>>.
|1.0.0

|JAX-WS
|
|The transactions are named based on your `@javax.jws.WebService` annotated classes and `@javax.jws.WebMethod` annotated method names (`WebServiceClass#webMethod`).
Note that only the packages configured in <<config-application-packages>> are scanned for JAX-WS resources.
If you don't set this option,
all classes are scanned.
This comes at the cost of increased startup times, however.

Note: JAX-WS is only supported when running on a supported <<supported-app-servers, Application Server/Servlet Container>> and when using the HTTP binding.
|1.4.0

|===

Expand Down Expand Up @@ -168,6 +184,12 @@ The spans are named after the schema `<method> <host>`, for example `GET elastic
|
| 1.4.0

|JAX-WS client
|
|JAX-WS clients created via link:https://docs.oracle.com/javaee/7/api/javax/xml/ws/Service.html[`javax.xml.ws.Service`]
inherently support context propagation as they are using `HttpUrlConnection` underneath.
|1.4.0

|===


Expand All @@ -193,10 +215,10 @@ This section lists all supported asynchronous frameworks.
[float]
[[supported-technologies-caveats]]
=== Caveats
* Tracing of asynchronous invocations (for example `java.util.concurrent.ExecutorService`) is currently not supported.
* Certain OSGi containers need the following configuration setting in case you see exceptions like
`java.lang.NoClassDefFoundError: co/elastic/apm/jdbc/StatementInstrumentation`:
`org.osgi.framework.bootdelegation=co.elastic.apm.agent.*`
* Other JVM languages, like Scala, Kotlin and Groovy have not been tested yet.
* The agent does currently not support running on JVMs with an enabled `SecurityManager`.
You may see exceptions like this: `java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "getProtectionDomain")`
You may see exceptions like this: `java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "getProtectionDomain")`.
Try to grant `java.security.AllPermission` to the agent.
5 changes: 5 additions & 0 deletions elastic-apm-agent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@
<artifactId>apm-jaxrs-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>apm-jaxws-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>apm-jdbc-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>simple-webapp-integration-test</artifactId>
<artifactId>application-server-integration-tests</artifactId>

<name>${project.groupId}:${project.artifactId}</name>

Expand Down
Loading