Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add instrumentation for jetty 12 #10575

Merged
merged 6 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
39 changes: 24 additions & 15 deletions docs/supported-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,17 +174,26 @@ These are the supported libraries and frameworks:

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

| Application server | Version | JVM | OS |
| ------------------------------------------------------------------------------------- | --------------------------- | ----------------- | ------------------------------------- |
| [Jetty](https://www.eclipse.org/jetty/) | 9.4.x, 10.0.x, 11.0.x | OpenJDK 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
| [Payara](https://www.payara.fish/) | 5.0.x, 5.1.x | OpenJDK 8, 11 | [`ubuntu-latest`], [`windows-latest`] |
| [Tomcat](http://tomcat.apache.org/) | 7.0.x | OpenJDK 8 | [`ubuntu-latest`], [`windows-latest`] |
| [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`] |
| [TomEE](https://tomee.apache.org/) | 7.x, 8.x | OpenJDK 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
| [Open Liberty](https://openliberty.io/) | 21.x, 22.x, 23.x | OpenJDK 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
| [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 |
| [WildFly](https://www.wildfly.org/) | 13.x | OpenJDK 8 | [`ubuntu-latest`], [`windows-latest`] |
| [WildFly](https://www.wildfly.org/) | 17.x, 21.x, 25.x | OpenJDK 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
| Application server | Version | JVM | OS |
|---------------------------------------------------------------------------------------|------------------------------------------|------------------------------------------------|---------------------------------------|
| [Jetty](https://www.eclipse.org/jetty/) | 9.4.53 | OpenJDK 8, 11, 17, 21<br/>OpenJ9 8, 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
| [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`] |
| [Jetty](https://www.eclipse.org/jetty/) | 12.0.6 | OpenJDK 17, 21<br/>OpenJ9 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
| [Open Liberty](https://openliberty.io/) | 20.0.0.12 | OpenJDK 8, 11<br/>OpenJ9 8, 11 | [`ubuntu-latest`], [`windows-latest`] |
| [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`] |
| [Open Liberty](https://openliberty.io/) | 23.0.0.12 | OpenJDK 8, 11, 17, 20<br/>OpenJ9 8, 11, 17, 20 | [`ubuntu-latest`], [`windows-latest`] |
| [Payara](https://www.payara.fish/) | 5.2020.6, 5.2021.8 | OpenJDK 8, 11<br/>OpenJ9 8, 11 | [`ubuntu-latest`], [`windows-latest`] |
| [Payara](https://www.payara.fish/) | 6.2023.12 | OpenJDK 11, 17<br/>OpenJ9 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
| [Tomcat](http://tomcat.apache.org/) | 7.0.109 | OpenJDK 8<br/>OpenJ9 8 | [`ubuntu-latest`], [`windows-latest`] |
| [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`] |
| [Tomcat](http://tomcat.apache.org/) | 10.1.18 | OpenJDK 11, 17, 21<br/>OpenJ9 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
| [TomEE](https://tomee.apache.org/) | 7.0.9, 7.1.4 | OpenJDK 8<br/>OpenJ9 8 | [`ubuntu-latest`], [`windows-latest`] |
| [TomEE](https://tomee.apache.org/) | 8.0.16 | OpenJDK 8, 11, 17, 21<br/>OpenJ9 8, 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
| [TomEE](https://tomee.apache.org/) | 9.1.2 | OpenJDK 11, 17, 21<br/>OpenJ9 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
| [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 |
| [WildFly](https://www.wildfly.org/) | 13.0.0.Final | OpenJDK 8<br/>OpenJ9 8 | [`ubuntu-latest`], [`windows-latest`] |
| [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`] |
| [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`] |

[`ubuntu-latest`]: https://github.com/actions/runner-images#available-images
[`windows-latest`]: https://github.com/actions/runner-images#available-images
Expand All @@ -193,10 +202,10 @@ These are the application servers that the smoke tests are run against:

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

| JVM | Versions | OS |
| ----------------------------------------------------------------------------------------- | --------- | ------------------------------------- |
| [OpenJDK (Eclipse Temurin)](https://adoptium.net/) | 8, 11, 17 | [`ubuntu-latest`], [`windows-latest`] |
| [OpenJ9 (IBM Semeru Runtimes)](https://developer.ibm.com/languages/java/semeru-runtimes/) | 8, 11, 17 | [`ubuntu-latest`] |
| JVM | Versions | OS |
| ----------------------------------------------------------------------------------------- |---------------| ------------------------------------- |
| [OpenJDK (Eclipse Temurin)](https://adoptium.net/) | 8, 11, 17, 21 | [`ubuntu-latest`], [`windows-latest`] |
| [OpenJ9 (IBM Semeru Runtimes)](https://developer.ibm.com/languages/java/semeru-runtimes/) | 8, 11, 17 | [`ubuntu-latest`] |

## Disabled instrumentations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies {
bootstrap(project(":instrumentation:servlet:servlet-common:bootstrap"))

testInstrumentation(project(":instrumentation:jetty:jetty-8.0:javaagent"))
testInstrumentation(project(":instrumentation:jetty:jetty-12.0:javaagent"))

// jetty-servlet does not exist in jetty 12, so we don't need to explicitly pin it to 11.+
testLibrary("org.eclipse.jetty:jetty-servlet:11.0.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.junit.jupiter.api.extension.RegisterExtension;

public class JettyHandlerTest extends AbstractHttpServerTest<Server> {
class JettyHandlerTest extends AbstractHttpServerTest<Server> {

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

@Override
protected Server setupServer() {
protected Server setupServer() throws Exception {
Server server = new Server(port);
server.setHandler(testHandler);
server.addBean(errorHandler);
try {
server.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
server.start();
return server;
}

@Override
protected void stopServer(Server server) {
try {
server.stop();
} catch (Exception e) {
throw new RuntimeException(e);
}
protected void stopServer(Server server) throws Exception {
server.stop();
}

@Override
Expand Down
27 changes: 27 additions & 0 deletions instrumentation/jetty/jetty-12.0/javaagent/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
plugins {
id("otel.javaagent-instrumentation")
}

muzzle {
pass {
group.set("org.eclipse.jetty")
module.set("jetty-server")
versions.set("[12,)")
}
}

dependencies {
library("org.eclipse.jetty:jetty-server:12.0.0")

bootstrap(project(":instrumentation:servlet:servlet-common:bootstrap"))
implementation(project(":instrumentation:servlet:servlet-common:javaagent"))

testInstrumentation(project(":instrumentation:jetty:jetty-8.0:javaagent"))
testInstrumentation(project(":instrumentation:jetty:jetty-11.0:javaagent"))

testLibrary("org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.0")
}

otelJava {
minJavaVersionSupported.set(JavaVersion.VERSION_17)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;

import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge;
import io.opentelemetry.javaagent.instrumentation.servlet.ServletHelper;
import javax.annotation.Nullable;
import org.eclipse.jetty.server.HttpStream;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;

public class Jetty12Helper {
trask marked this conversation as resolved.
Show resolved Hide resolved
private final Instrumenter<Request, Response> instrumenter;

Jetty12Helper(Instrumenter<Request, Response> instrumenter) {
this.instrumenter = instrumenter;
}

public boolean shouldStart(Context parentContext, Request request) {
return instrumenter.shouldStart(parentContext, request);
}

public Context start(Context parentContext, Request request, Response response) {
Context context = instrumenter.start(parentContext, request);
request.addFailureListener(throwable -> end(context, request, response, throwable));
// detect request completion
// https://github.com/jetty/jetty.project/blob/52d94174e2c7a6e794c6377dcf9cd3ed0b9e1806/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/EventsHandler.java#L75
request.addHttpStreamWrapper(
stream ->
new HttpStream.Wrapper(stream) {
@Override
public void succeeded() {
end(context, request, response, null);
super.succeeded();
}

@Override
public void failed(Throwable throwable) {
end(context, request, response, throwable);
super.failed(throwable);
}
});

return context;
}

public void end(Context context, Request request, Response response, @Nullable Throwable error) {
if (error == null) {
error = AppServerBridge.getException(context);
}
if (error == null) {
error = (Throwable) request.getAttribute(ServletHelper.ASYNC_EXCEPTION_ATTRIBUTE);
}

instrumenter.end(context, request, response, error);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;

import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesGetter;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import javax.annotation.Nullable;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;

public class Jetty12HttpAttributesGetter implements HttpServerAttributesGetter<Request, Response> {
laurit marked this conversation as resolved.
Show resolved Hide resolved

@Override
public String getHttpRequestMethod(Request request) {
return request.getMethod();
}

@Override
public List<String> getHttpRequestHeader(Request request, String name) {
return request.getHeaders().getValuesList(name);
}

@Override
public Integer getHttpResponseStatusCode(
Request request, Response response, @Nullable Throwable error) {
if (!response.isCommitted() && error != null) {
return 500;
}
return response.getStatus();
}

@Override
public List<String> getHttpResponseHeader(Request request, Response response, String name) {
return response.getHeaders().getValuesList(name);
}

@Override
@Nullable
public String getUrlScheme(Request request) {
HttpURI uri = request.getHttpURI();
return uri == null ? null : uri.getScheme();
}

@Nullable
@Override
public String getUrlPath(Request request) {
HttpURI uri = request.getHttpURI();
return uri == null ? null : uri.getPath();
}

@Nullable
@Override
public String getUrlQuery(Request request) {
HttpURI uri = request.getHttpURI();
return uri == null ? null : uri.getQuery();
}

@Nullable
@Override
public String getNetworkProtocolName(Request request, @Nullable Response unused) {
String protocol = request.getConnectionMetaData().getProtocol();
if (protocol != null && protocol.startsWith("HTTP/")) {
return "http";
}
return null;
}

@Nullable
@Override
public String getNetworkProtocolVersion(Request request, @Nullable Response unused) {
String protocol = request.getConnectionMetaData().getProtocol();
if (protocol.startsWith("HTTP/")) {
return protocol.substring("HTTP/".length());
}
return null;
}

@Override
@Nullable
public InetSocketAddress getNetworkPeerInetSocketAddress(
Request request, @Nullable Response unused) {
SocketAddress address = request.getConnectionMetaData().getRemoteSocketAddress();
return address instanceof InetSocketAddress ? (InetSocketAddress) address : null;
}

@Nullable
@Override
public InetSocketAddress getNetworkLocalInetSocketAddress(
Request request, @Nullable Response unused) {
SocketAddress address = request.getConnectionMetaData().getLocalSocketAddress();
return address instanceof InetSocketAddress ? (InetSocketAddress) address : null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesBuilder;
import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesConfigurer;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;

@AutoService(IgnoredTypesConfigurer.class)
public class Jetty12IgnoredTypesConfigurer implements IgnoredTypesConfigurer {

@Override
public void configure(IgnoredTypesBuilder builder, ConfigProperties config) {
// handling pipelined request sends HttpConnection instance (implements Runnable) to executor
// while scope from the previous request is still active
builder.ignoreTaskClass("org.eclipse.jetty.server.internal.HttpConnection");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;

import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static java.util.Collections.singletonList;

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import java.util.List;
import net.bytebuddy.matcher.ElementMatcher;

@AutoService(InstrumentationModule.class)
public class Jetty12InstrumentationModule extends InstrumentationModule {

public Jetty12InstrumentationModule() {
super("jetty", "jetty-12.0");
}

@Override
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
return hasClassesNamed("org.eclipse.jetty.server.Request$Handler");
}

@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new Jetty12ServerInstrumentation());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;

import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseMutator;
import org.eclipse.jetty.server.Response;

public enum Jetty12ResponseMutator implements HttpServerResponseMutator<Response> {
laurit marked this conversation as resolved.
Show resolved Hide resolved
INSTANCE;

@Override
public void appendHeader(Response response, String name, String value) {
response.getHeaders().add(name, value);
}
}
Loading
Loading