Skip to content

Commit c8f2cc5

Browse files
lauritjeanbisutti
andauthored
Add instrumentation for jetty 12 (#10575)
Co-authored-by: Jean Bisutti <[email protected]>
1 parent 86c3263 commit c8f2cc5

File tree

29 files changed

+955
-47
lines changed

29 files changed

+955
-47
lines changed

docs/supported-libraries.md

+24-15
Original file line numberDiff line numberDiff line change
@@ -175,17 +175,26 @@ These are the supported libraries and frameworks:
175175

176176
These are the application servers that the smoke tests are run against:
177177

178-
| Application server | Version | JVM | OS |
179-
| ------------------------------------------------------------------------------------- | --------------------------- | ----------------- | ------------------------------------- |
180-
| [Jetty](https://www.eclipse.org/jetty/) | 9.4.x, 10.0.x, 11.0.x | OpenJDK 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
181-
| [Payara](https://www.payara.fish/) | 5.0.x, 5.1.x | OpenJDK 8, 11 | [`ubuntu-latest`], [`windows-latest`] |
182-
| [Tomcat](http://tomcat.apache.org/) | 7.0.x | OpenJDK 8 | [`ubuntu-latest`], [`windows-latest`] |
183-
| [Tomcat](http://tomcat.apache.org/) | 7.0.x, 8.5.x, 9.0.x, 10.0.x | OpenJDK 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
184-
| [TomEE](https://tomee.apache.org/) | 7.x, 8.x | OpenJDK 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
185-
| [Open Liberty](https://openliberty.io/) | 21.x, 22.x, 23.x | OpenJDK 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
186-
| [Websphere Traditional](https://www.ibm.com/uk-en/cloud/websphere-application-server) | 8.5.5.x, 9.0.x | IBM JDK 8 | Red Hat Enterprise Linux 8.4 |
187-
| [WildFly](https://www.wildfly.org/) | 13.x | OpenJDK 8 | [`ubuntu-latest`], [`windows-latest`] |
188-
| [WildFly](https://www.wildfly.org/) | 17.x, 21.x, 25.x | OpenJDK 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
178+
| Application server | Version | JVM | OS |
179+
|---------------------------------------------------------------------------------------|------------------------------------------|------------------------------------------------|---------------------------------------|
180+
| [Jetty](https://www.eclipse.org/jetty/) | 9.4.53 | OpenJDK 8, 11, 17, 21<br/>OpenJ9 8, 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
181+
| [Jetty](https://www.eclipse.org/jetty/) | 10.0.19, 11.0.19 | OpenJDK 11, 17, 21<br/>OpenJ9 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
182+
| [Jetty](https://www.eclipse.org/jetty/) | 12.0.6 | OpenJDK 17, 21<br/>OpenJ9 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
183+
| [Open Liberty](https://openliberty.io/) | 20.0.0.12 | OpenJDK 8, 11<br/>OpenJ9 8, 11 | [`ubuntu-latest`], [`windows-latest`] |
184+
| [Open Liberty](https://openliberty.io/) | 21.0.0.12, 22.0.0.12 | OpenJDK 8, 11, 17<br/>OpenJ9 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
185+
| [Open Liberty](https://openliberty.io/) | 23.0.0.12 | OpenJDK 8, 11, 17, 20<br/>OpenJ9 8, 11, 17, 20 | [`ubuntu-latest`], [`windows-latest`] |
186+
| [Payara](https://www.payara.fish/) | 5.2020.6, 5.2021.8 | OpenJDK 8, 11<br/>OpenJ9 8, 11 | [`ubuntu-latest`], [`windows-latest`] |
187+
| [Payara](https://www.payara.fish/) | 6.2023.12 | OpenJDK 11, 17<br/>OpenJ9 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
188+
| [Tomcat](http://tomcat.apache.org/) | 7.0.109 | OpenJDK 8<br/>OpenJ9 8 | [`ubuntu-latest`], [`windows-latest`] |
189+
| [Tomcat](http://tomcat.apache.org/) | 8.5.98, 9.0.85 | OpenJDK 8, 11, 17, 21<br/>OpenJ9 8, 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
190+
| [Tomcat](http://tomcat.apache.org/) | 10.1.18 | OpenJDK 11, 17, 21<br/>OpenJ9 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
191+
| [TomEE](https://tomee.apache.org/) | 7.0.9, 7.1.4 | OpenJDK 8<br/>OpenJ9 8 | [`ubuntu-latest`], [`windows-latest`] |
192+
| [TomEE](https://tomee.apache.org/) | 8.0.16 | OpenJDK 8, 11, 17, 21<br/>OpenJ9 8, 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
193+
| [TomEE](https://tomee.apache.org/) | 9.1.2 | OpenJDK 11, 17, 21<br/>OpenJ9 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
194+
| [Websphere Traditional](https://www.ibm.com/uk-en/cloud/websphere-application-server) | 8.5.5.22, 9.0.5.14 | IBM JDK 8 | Red Hat Enterprise Linux 8.4 |
195+
| [WildFly](https://www.wildfly.org/) | 13.0.0.Final | OpenJDK 8<br/>OpenJ9 8 | [`ubuntu-latest`], [`windows-latest`] |
196+
| [WildFly](https://www.wildfly.org/) | 17.0.1.Final, 21.0.0.Final | OpenJDK 8, 11, 17, 21<br/>OpenJ9 8, 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
197+
| [WildFly](https://www.wildfly.org/) | 28.0.1.Final, 29.0.1.Final, 30.0.1.Final | OpenJDK 11, 17, 21<br/>OpenJ9 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
189198

190199
[`ubuntu-latest`]: https://github.com/actions/runner-images#available-images
191200
[`windows-latest`]: https://github.com/actions/runner-images#available-images
@@ -194,10 +203,10 @@ These are the application servers that the smoke tests are run against:
194203

195204
These are the JVMs and operating systems that the integration tests are run against:
196205

197-
| JVM | Versions | OS |
198-
| ----------------------------------------------------------------------------------------- | --------- | ------------------------------------- |
199-
| [OpenJDK (Eclipse Temurin)](https://adoptium.net/) | 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
200-
| [OpenJ9 (IBM Semeru Runtimes)](https://developer.ibm.com/languages/java/semeru-runtimes/) | 8, 11, 17 | [`ubuntu-latest`] |
206+
| JVM | Versions | OS |
207+
| ----------------------------------------------------------------------------------------- |---------------| ------------------------------------- |
208+
| [OpenJDK (Eclipse Temurin)](https://adoptium.net/) | 8, 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
209+
| [OpenJ9 (IBM Semeru Runtimes)](https://developer.ibm.com/languages/java/semeru-runtimes/) | 8, 11, 17 | [`ubuntu-latest`] |
201210

202211
## Disabled instrumentations
203212

instrumentation/jetty/jetty-11.0/javaagent/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ dependencies {
1818
bootstrap(project(":instrumentation:servlet:servlet-common:bootstrap"))
1919

2020
testInstrumentation(project(":instrumentation:jetty:jetty-8.0:javaagent"))
21+
testInstrumentation(project(":instrumentation:jetty:jetty-12.0:javaagent"))
2122

2223
// jetty-servlet does not exist in jetty 12, so we don't need to explicitly pin it to 11.+
2324
testLibrary("org.eclipse.jetty:jetty-servlet:11.0.0")

instrumentation/jetty/jetty-11.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/v11_0/JettyHandlerTest.java

+5-13
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
import org.eclipse.jetty.server.handler.ErrorHandler;
4141
import org.junit.jupiter.api.extension.RegisterExtension;
4242

43-
public class JettyHandlerTest extends AbstractHttpServerTest<Server> {
43+
class JettyHandlerTest extends AbstractHttpServerTest<Server> {
4444

4545
@RegisterExtension
4646
static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent();
@@ -62,25 +62,17 @@ protected void handleErrorPage(
6262
private static final TestHandler testHandler = new TestHandler();
6363

6464
@Override
65-
protected Server setupServer() {
65+
protected Server setupServer() throws Exception {
6666
Server server = new Server(port);
6767
server.setHandler(testHandler);
6868
server.addBean(errorHandler);
69-
try {
70-
server.start();
71-
} catch (Exception e) {
72-
throw new RuntimeException(e);
73-
}
69+
server.start();
7470
return server;
7571
}
7672

7773
@Override
78-
protected void stopServer(Server server) {
79-
try {
80-
server.stop();
81-
} catch (Exception e) {
82-
throw new RuntimeException(e);
83-
}
74+
protected void stopServer(Server server) throws Exception {
75+
server.stop();
8476
}
8577

8678
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
plugins {
2+
id("otel.javaagent-instrumentation")
3+
}
4+
5+
muzzle {
6+
pass {
7+
group.set("org.eclipse.jetty")
8+
module.set("jetty-server")
9+
versions.set("[12,)")
10+
}
11+
}
12+
13+
dependencies {
14+
library("org.eclipse.jetty:jetty-server:12.0.0")
15+
16+
bootstrap(project(":instrumentation:servlet:servlet-common:bootstrap"))
17+
implementation(project(":instrumentation:servlet:servlet-common:javaagent"))
18+
19+
testInstrumentation(project(":instrumentation:jetty:jetty-8.0:javaagent"))
20+
testInstrumentation(project(":instrumentation:jetty:jetty-11.0:javaagent"))
21+
22+
testLibrary("org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.0")
23+
}
24+
25+
otelJava {
26+
minJavaVersionSupported.set(JavaVersion.VERSION_17)
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;
7+
8+
import io.opentelemetry.context.Context;
9+
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
10+
import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge;
11+
import io.opentelemetry.javaagent.instrumentation.servlet.ServletHelper;
12+
import javax.annotation.Nullable;
13+
import org.eclipse.jetty.server.HttpStream;
14+
import org.eclipse.jetty.server.Request;
15+
import org.eclipse.jetty.server.Response;
16+
17+
public class Jetty12Helper {
18+
private final Instrumenter<Request, Response> instrumenter;
19+
20+
Jetty12Helper(Instrumenter<Request, Response> instrumenter) {
21+
this.instrumenter = instrumenter;
22+
}
23+
24+
public boolean shouldStart(Context parentContext, Request request) {
25+
return instrumenter.shouldStart(parentContext, request);
26+
}
27+
28+
public Context start(Context parentContext, Request request, Response response) {
29+
Context context = instrumenter.start(parentContext, request);
30+
request.addFailureListener(throwable -> end(context, request, response, throwable));
31+
// detect request completion
32+
// https://github.com/jetty/jetty.project/blob/52d94174e2c7a6e794c6377dcf9cd3ed0b9e1806/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/EventsHandler.java#L75
33+
request.addHttpStreamWrapper(
34+
stream ->
35+
new HttpStream.Wrapper(stream) {
36+
@Override
37+
public void succeeded() {
38+
end(context, request, response, null);
39+
super.succeeded();
40+
}
41+
42+
@Override
43+
public void failed(Throwable throwable) {
44+
end(context, request, response, throwable);
45+
super.failed(throwable);
46+
}
47+
});
48+
49+
return context;
50+
}
51+
52+
public void end(Context context, Request request, Response response, @Nullable Throwable error) {
53+
if (error == null) {
54+
error = AppServerBridge.getException(context);
55+
}
56+
if (error == null) {
57+
error = (Throwable) request.getAttribute(ServletHelper.ASYNC_EXCEPTION_ATTRIBUTE);
58+
}
59+
60+
instrumenter.end(context, request, response, error);
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;
7+
8+
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesGetter;
9+
import java.net.InetSocketAddress;
10+
import java.net.SocketAddress;
11+
import java.util.List;
12+
import javax.annotation.Nullable;
13+
import org.eclipse.jetty.http.HttpURI;
14+
import org.eclipse.jetty.server.Request;
15+
import org.eclipse.jetty.server.Response;
16+
17+
class Jetty12HttpAttributesGetter implements HttpServerAttributesGetter<Request, Response> {
18+
19+
@Override
20+
public String getHttpRequestMethod(Request request) {
21+
return request.getMethod();
22+
}
23+
24+
@Override
25+
public List<String> getHttpRequestHeader(Request request, String name) {
26+
return request.getHeaders().getValuesList(name);
27+
}
28+
29+
@Override
30+
public Integer getHttpResponseStatusCode(
31+
Request request, Response response, @Nullable Throwable error) {
32+
if (!response.isCommitted() && error != null) {
33+
return 500;
34+
}
35+
return response.getStatus();
36+
}
37+
38+
@Override
39+
public List<String> getHttpResponseHeader(Request request, Response response, String name) {
40+
return response.getHeaders().getValuesList(name);
41+
}
42+
43+
@Override
44+
@Nullable
45+
public String getUrlScheme(Request request) {
46+
HttpURI uri = request.getHttpURI();
47+
return uri == null ? null : uri.getScheme();
48+
}
49+
50+
@Nullable
51+
@Override
52+
public String getUrlPath(Request request) {
53+
HttpURI uri = request.getHttpURI();
54+
return uri == null ? null : uri.getPath();
55+
}
56+
57+
@Nullable
58+
@Override
59+
public String getUrlQuery(Request request) {
60+
HttpURI uri = request.getHttpURI();
61+
return uri == null ? null : uri.getQuery();
62+
}
63+
64+
@Nullable
65+
@Override
66+
public String getNetworkProtocolName(Request request, @Nullable Response unused) {
67+
String protocol = request.getConnectionMetaData().getProtocol();
68+
if (protocol != null && protocol.startsWith("HTTP/")) {
69+
return "http";
70+
}
71+
return null;
72+
}
73+
74+
@Nullable
75+
@Override
76+
public String getNetworkProtocolVersion(Request request, @Nullable Response unused) {
77+
String protocol = request.getConnectionMetaData().getProtocol();
78+
if (protocol.startsWith("HTTP/")) {
79+
return protocol.substring("HTTP/".length());
80+
}
81+
return null;
82+
}
83+
84+
@Override
85+
@Nullable
86+
public InetSocketAddress getNetworkPeerInetSocketAddress(
87+
Request request, @Nullable Response unused) {
88+
SocketAddress address = request.getConnectionMetaData().getRemoteSocketAddress();
89+
return address instanceof InetSocketAddress ? (InetSocketAddress) address : null;
90+
}
91+
92+
@Nullable
93+
@Override
94+
public InetSocketAddress getNetworkLocalInetSocketAddress(
95+
Request request, @Nullable Response unused) {
96+
SocketAddress address = request.getConnectionMetaData().getLocalSocketAddress();
97+
return address instanceof InetSocketAddress ? (InetSocketAddress) address : null;
98+
}
99+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;
7+
8+
import com.google.auto.service.AutoService;
9+
import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesBuilder;
10+
import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesConfigurer;
11+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
12+
13+
@AutoService(IgnoredTypesConfigurer.class)
14+
public class Jetty12IgnoredTypesConfigurer implements IgnoredTypesConfigurer {
15+
16+
@Override
17+
public void configure(IgnoredTypesBuilder builder, ConfigProperties config) {
18+
// handling pipelined request sends HttpConnection instance (implements Runnable) to executor
19+
// while scope from the previous request is still active
20+
builder.ignoreTaskClass("org.eclipse.jetty.server.internal.HttpConnection");
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;
7+
8+
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
9+
import static java.util.Collections.singletonList;
10+
11+
import com.google.auto.service.AutoService;
12+
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
13+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
14+
import java.util.List;
15+
import net.bytebuddy.matcher.ElementMatcher;
16+
17+
@AutoService(InstrumentationModule.class)
18+
public class Jetty12InstrumentationModule extends InstrumentationModule {
19+
20+
public Jetty12InstrumentationModule() {
21+
super("jetty", "jetty-12.0");
22+
}
23+
24+
@Override
25+
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
26+
return hasClassesNamed("org.eclipse.jetty.server.Request$Handler");
27+
}
28+
29+
@Override
30+
public List<TypeInstrumentation> typeInstrumentations() {
31+
return singletonList(new Jetty12ServerInstrumentation());
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;
7+
8+
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseMutator;
9+
import org.eclipse.jetty.server.Response;
10+
11+
public enum Jetty12ResponseMutator implements HttpServerResponseMutator<Response> {
12+
INSTANCE;
13+
14+
@Override
15+
public void appendHeader(Response response, String name, String value) {
16+
response.getHeaders().add(name, value);
17+
}
18+
}

0 commit comments

Comments
 (0)