Add instrumentation for jetty 12 (#10575)

Co-authored-by: Jean Bisutti <jean.bisutti@gmail.com>
This commit is contained in:
Lauri Tulmin 2024-03-13 00:59:27 +02:00 committed by GitHub
parent 86c3263868
commit c8f2cc5a9b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 955 additions and 47 deletions

View File

@ -175,17 +175,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
@ -194,10 +203,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

View File

@ -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")

View File

@ -40,7 +40,7 @@ import org.eclipse.jetty.server.handler.AbstractHandler;
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();
@ -62,25 +62,17 @@ public class JettyHandlerTest extends AbstractHttpServerTest<Server> {
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

View File

@ -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)
}

View File

@ -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 {
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);
}
}

View File

@ -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;
class Jetty12HttpAttributesGetter implements HttpServerAttributesGetter<Request, Response> {
@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;
}
}

View File

@ -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");
}
}

View File

@ -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());
}
}

View File

@ -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> {
INSTANCE;
@Override
public void appendHeader(Response response, String name, String value) {
response.getHeaders().add(name, value);
}
}

View File

@ -0,0 +1,82 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;
import static io.opentelemetry.javaagent.instrumentation.jetty.v12_0.Jetty12Singletons.helper;
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.bootstrap.Java8BytecodeBridge;
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizerHolder;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
class Jetty12ServerInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.eclipse.jetty.server.Server");
}
@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
named("handle")
.and(takesArgument(0, named("org.eclipse.jetty.server.Request")))
.and(takesArgument(1, named("org.eclipse.jetty.server.Response")))
.and(takesArgument(2, named("org.eclipse.jetty.util.Callback")))
.and(isPublic()),
this.getClass().getName() + "$HandlerAdvice");
}
@SuppressWarnings("unused")
public static class HandlerAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void onEnter(
@Advice.This Object source,
@Advice.Argument(0) Request request,
@Advice.Argument(1) Response response,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
Context parentContext = Java8BytecodeBridge.currentContext();
if (!helper().shouldStart(parentContext, request)) {
return;
}
context = helper().start(parentContext, request, response);
scope = context.makeCurrent();
HttpServerResponseCustomizerHolder.getCustomizer()
.customize(context, response, Jetty12ResponseMutator.INSTANCE);
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void stopSpan(
@Advice.Argument(0) Request request,
@Advice.Argument(1) Response response,
@Advice.Thrown Throwable throwable,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
if (scope == null) {
return;
}
scope.close();
if (throwable != null) {
helper().end(context, request, response, throwable);
}
}
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor;
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute;
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor;
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
public final class Jetty12Singletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jetty-12.0";
private static final Instrumenter<Request, Response> INSTRUMENTER;
static {
Jetty12HttpAttributesGetter httpAttributesGetter = new Jetty12HttpAttributesGetter();
InstrumenterBuilder<Request, Response> builder =
Instrumenter.<Request, Response>builder(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.builder(httpAttributesGetter)
.setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders())
.setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders())
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.addContextCustomizer(
HttpServerRoute.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.addContextCustomizer(
(context, request, attributes) ->
new AppServerBridge.Builder()
.captureServletAttributes()
.recordException()
.init(context))
.addOperationMetrics(HttpServerMetrics.get());
if (CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) {
builder
.addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter))
.addOperationMetrics(HttpServerExperimentalMetrics.get());
}
INSTRUMENTER = builder.buildServerInstrumenter(Jetty12TextMapGetter.INSTANCE);
}
private static final Jetty12Helper HELPER = new Jetty12Helper(INSTRUMENTER);
public static Jetty12Helper helper() {
return HELPER;
}
private Jetty12Singletons() {}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;
import io.opentelemetry.context.propagation.TextMapGetter;
import org.eclipse.jetty.server.Request;
enum Jetty12TextMapGetter implements TextMapGetter<Request> {
INSTANCE;
@Override
public Iterable<String> keys(Request carrier) {
return carrier.getHeaders().getFieldNamesCollection();
}
@Override
public String get(Request carrier, String key) {
return carrier.getHeaders().get(key);
}
}

View File

@ -0,0 +1,137 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.jetty.v12_0;
import static io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions.DEFAULT_HTTP_ATTRIBUTES;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT;
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.collect.Sets;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest;
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions;
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint;
import io.opentelemetry.sdk.testing.assertj.SpanDataAssert;
import io.opentelemetry.semconv.SemanticAttributes;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Callback;
import org.junit.jupiter.api.extension.RegisterExtension;
class Jetty12HandlerTest extends AbstractHttpServerTest<Server> {
@RegisterExtension
static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forAgent();
private final TestHandler testHandler = new TestHandler();
@Override
protected Server setupServer() throws Exception {
Server server = new Server(port);
server.setHandler(testHandler);
server.start();
return server;
}
@Override
protected void stopServer(Server server) throws Exception {
server.stop();
}
@Override
protected void configure(HttpServerTestOptions options) {
options.setHttpAttributes(
unused ->
Sets.difference(
DEFAULT_HTTP_ATTRIBUTES, Collections.singleton(SemanticAttributes.HTTP_ROUTE)));
options.setExpectedException(new IllegalStateException(EXCEPTION.getBody()));
options.setHasResponseCustomizer(endpoint -> endpoint != EXCEPTION);
}
@Override
protected SpanDataAssert assertResponseSpan(
SpanDataAssert span, String method, ServerEndpoint endpoint) {
if (endpoint == REDIRECT) {
span.satisfies(spanData -> assertThat(spanData.getName()).endsWith(".sendRedirect"));
} else if (endpoint == ERROR) {
span.satisfies(spanData -> assertThat(spanData.getName()).endsWith(".sendError"));
}
span.hasKind(SpanKind.INTERNAL).hasAttributesSatisfying(Attributes::isEmpty);
return span;
}
private void handleRequest(Request request, Response response) {
ServerEndpoint endpoint = ServerEndpoint.forPath(request.getHttpURI().getPath());
controller(
endpoint,
() -> {
try {
response(request, response, endpoint);
} catch (IOException e) {
throw new RuntimeException(e);
}
return null;
});
}
private void response(Request request, Response response, ServerEndpoint endpoint)
throws IOException {
if (SUCCESS.equals(endpoint)) {
response.setStatus(endpoint.getStatus());
response.write(true, StandardCharsets.UTF_8.encode(endpoint.getBody()), Callback.NOOP);
} else if (QUERY_PARAM.equals(endpoint)) {
response.setStatus(endpoint.getStatus());
response.write(
true, StandardCharsets.UTF_8.encode(request.getHttpURI().getQuery()), Callback.NOOP);
} else if (REDIRECT.equals(endpoint)) {
response.setStatus(endpoint.getStatus());
response.getHeaders().add("Location", "http://localhost:" + port + endpoint.getBody());
} else if (ERROR.equals(endpoint)) {
response.setStatus(endpoint.getStatus());
response.write(true, StandardCharsets.UTF_8.encode(endpoint.getBody()), Callback.NOOP);
} else if (CAPTURE_HEADERS.equals(endpoint)) {
response.getHeaders().add("X-Test-Response", request.getHeaders().get("X-Test-Request"));
response.setStatus(endpoint.getStatus());
response.write(true, StandardCharsets.UTF_8.encode(endpoint.getBody()), Callback.NOOP);
} else if (EXCEPTION.equals(endpoint)) {
throw new IllegalStateException(endpoint.getBody());
} else if (INDEXED_CHILD.equals(endpoint)) {
INDEXED_CHILD.collectSpanAttributes(
name -> Request.extractQueryParameters(request).getValue(name));
response.setStatus(endpoint.getStatus());
response.write(true, StandardCharsets.UTF_8.encode(endpoint.getBody()), Callback.NOOP);
} else {
response.setStatus(NOT_FOUND.getStatus());
response.write(true, StandardCharsets.UTF_8.encode(NOT_FOUND.getBody()), Callback.NOOP);
}
}
private class TestHandler extends Handler.Abstract {
@Override
public boolean handle(Request baseRequest, Response response, Callback callback) {
handleRequest(baseRequest, response);
callback.succeeded();
return true;
}
}
}

View File

@ -23,6 +23,7 @@ dependencies {
testInstrumentation(project(":instrumentation:servlet:servlet-javax-common:javaagent"))
testInstrumentation(project(":instrumentation:jetty:jetty-11.0:javaagent"))
testInstrumentation(project(":instrumentation:jetty:jetty-12.0:javaagent"))
testLibrary("org.eclipse.jetty:jetty-servlet:8.0.0.v20110901")

View File

@ -40,7 +40,7 @@ import org.eclipse.jetty.server.handler.AbstractHandler;
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();
@ -62,25 +62,17 @@ public class JettyHandlerTest extends AbstractHttpServerTest<Server> {
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

View File

@ -17,7 +17,9 @@ dependencies {
compileOnly("jakarta.servlet:jakarta.servlet-api:5.0.0")
testImplementation(project(":instrumentation:servlet:servlet-common:bootstrap"))
testInstrumentation(project(":instrumentation:jetty:jetty-11.0:javaagent"))
testImplementation(project(":instrumentation:servlet:servlet-5.0:testing"))
testLibrary("org.eclipse.jetty:jetty-server:11.0.0")
testLibrary("org.eclipse.jetty:jetty-servlet:11.0.0")

View File

@ -3,6 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.javaagent.instrumentation.servlet.v5_0.RequestDispatcherServlet
import jakarta.servlet.Servlet
import jakarta.servlet.ServletException
import jakarta.servlet.http.HttpServletRequest
@ -10,6 +11,8 @@ import org.eclipse.jetty.server.Server
import org.eclipse.jetty.server.handler.ErrorHandler
import org.eclipse.jetty.servlet.ServletContextHandler
import spock.lang.IgnoreIf
import test.AbstractServlet5Test
import test.TestServlet5
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.AUTH_REQUIRED
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS
@ -120,6 +123,13 @@ class JettyServlet5TestAsync extends JettyServlet5Test {
boolean errorEndpointUsesSendError() {
false
}
@Override
String getMetricsInstrumentationName() {
// with async requests the span is started in one instrumentation (server instrumentation)
// but ended from another (servlet instrumentation)
"io.opentelemetry.servlet-5.0"
}
}
@IgnoreIf({ !jvm.java11Compatible })
@ -129,6 +139,13 @@ class JettyServlet5TestFakeAsync extends JettyServlet5Test {
Class<Servlet> servlet() {
TestServlet5.FakeAsync
}
@Override
String getMetricsInstrumentationName() {
// with async requests the span is started in one instrumentation (server instrumentation)
// but ended from another (servlet instrumentation)
"io.opentelemetry.servlet-5.0"
}
}
@IgnoreIf({ !jvm.java11Compatible })
@ -220,6 +237,13 @@ class JettyServlet5TestDispatchImmediate extends JettyDispatchTest {
addServlet(context, "/dispatch" + INDEXED_CHILD.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch/recursive", TestServlet5.DispatchRecursive)
}
@Override
String getMetricsInstrumentationName() {
// with async requests the span is started in one instrumentation (server instrumentation)
// but ended from another (servlet instrumentation)
"io.opentelemetry.servlet-5.0"
}
}
@IgnoreIf({ !jvm.java11Compatible })
@ -251,6 +275,13 @@ class JettyServlet5TestDispatchAsync extends JettyDispatchTest {
boolean errorEndpointUsesSendError() {
false
}
@Override
String getMetricsInstrumentationName() {
// with async requests the span is started in one instrumentation (server instrumentation)
// but ended from another (servlet instrumentation)
"io.opentelemetry.servlet-5.0"
}
}
abstract class JettyDispatchTest extends JettyServlet5Test {

View File

@ -13,6 +13,8 @@ import org.eclipse.jetty.server.Server
import org.eclipse.jetty.server.handler.ErrorHandler
import org.eclipse.jetty.servlet.ServletHandler
import spock.lang.IgnoreIf
import test.AbstractServlet5Test
import test.TestServlet5
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION

View File

@ -5,6 +5,7 @@
import io.opentelemetry.instrumentation.test.asserts.TraceAssert
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint
import io.opentelemetry.javaagent.instrumentation.servlet.v5_0.RequestDispatcherServlet
import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse
import jakarta.servlet.Servlet
import jakarta.servlet.ServletException
@ -20,6 +21,8 @@ import org.apache.tomcat.JarScanFilter
import org.apache.tomcat.JarScanType
import spock.lang.Shared
import spock.lang.Unroll
import test.AbstractServlet5Test
import test.TestServlet5
import java.nio.file.Files
import java.util.concurrent.TimeUnit

View File

@ -0,0 +1,24 @@
plugins {
id("otel.javaagent-testing")
}
dependencies {
library("org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.6")
testInstrumentation(project(":instrumentation:servlet:servlet-5.0:javaagent"))
testInstrumentation(project(":instrumentation:jetty:jetty-8.0:javaagent"))
testInstrumentation(project(":instrumentation:jetty:jetty-11.0:javaagent"))
testInstrumentation(project(":instrumentation:jetty:jetty-12.0:javaagent"))
testImplementation(project(":instrumentation:servlet:servlet-5.0:testing"))
}
otelJava {
minJavaVersionSupported.set(JavaVersion.VERSION_17)
}
tasks {
withType<Test>().configureEach {
jvmArgs("-Dotel.instrumentation.servlet.experimental.capture-request-parameters=test-parameter")
}
}

View File

@ -0,0 +1,241 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import io.opentelemetry.javaagent.instrumentation.servlet.v5_0.RequestDispatcherServlet
import jakarta.servlet.Servlet
import jakarta.servlet.ServletException
import org.eclipse.jetty.ee10.servlet.ServletContextHandler
import org.eclipse.jetty.server.Request
import org.eclipse.jetty.server.Response
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.util.Callback
import test.AbstractServlet5Test
import test.TestServlet5
import java.nio.charset.StandardCharsets
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.AUTH_REQUIRED
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_PARAMETERS
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT
import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS
abstract class Jetty12Servlet5Test extends AbstractServlet5Test<Object, Object> {
@Override
boolean testNotFound() {
false
}
@Override
Throwable expectedException() {
new ServletException(EXCEPTION.body)
}
@Override
Object startServer(int port) {
def jettyServer = new Server(port)
jettyServer.connectors.each {
it.setHost('localhost')
}
ServletContextHandler servletContext = new ServletContextHandler(contextPath)
servletContext.errorHandler = new Request.Handler() {
@Override
boolean handle(Request request, Response response, Callback callback) throws Exception {
String message = (String) request.getAttribute("org.eclipse.jetty.server.error_message")
if (message != null) {
response.write(true, StandardCharsets.UTF_8.encode(message), Callback.NOOP)
}
callback.succeeded()
return true
}
}
setupServlets(servletContext)
jettyServer.setHandler(servletContext)
jettyServer.start()
return jettyServer
}
@Override
void stopServer(Object serverObject) {
Server server = (Server) serverObject
server.stop()
server.destroy()
}
@Override
String getContextPath() {
return "/jetty-context"
}
@Override
void addServlet(Object handlerObject, String path, Class<Servlet> servlet) {
ServletContextHandler handler = (ServletContextHandler) handlerObject
handler.addServlet(servlet, path)
}
}
class JettyServlet5TestSync extends Jetty12Servlet5Test {
@Override
Class<Servlet> servlet() {
TestServlet5.Sync
}
}
class JettyServlet5TestAsync extends Jetty12Servlet5Test {
@Override
Class<Servlet> servlet() {
TestServlet5.Async
}
@Override
boolean errorEndpointUsesSendError() {
false
}
}
class JettyServlet5TestFakeAsync extends Jetty12Servlet5Test {
@Override
Class<Servlet> servlet() {
TestServlet5.FakeAsync
}
}
class JettyServlet5TestForward extends JettyDispatchTest {
@Override
Class<Servlet> servlet() {
TestServlet5.Sync // dispatch to sync servlet
}
@Override
protected void setupServlets(Object context) {
super.setupServlets(context)
addServlet(context, "/dispatch" + SUCCESS.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + HTML_PRINT_WRITER.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + HTML_SERVLET_OUTPUT_STREAM.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + QUERY_PARAM.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + REDIRECT.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + ERROR.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + EXCEPTION.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + AUTH_REQUIRED.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + CAPTURE_HEADERS.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + CAPTURE_PARAMETERS.path, RequestDispatcherServlet.Forward)
addServlet(context, "/dispatch" + INDEXED_CHILD.path, RequestDispatcherServlet.Forward)
}
}
class JettyServlet5TestInclude extends JettyDispatchTest {
@Override
Class<Servlet> servlet() {
TestServlet5.Sync // dispatch to sync servlet
}
@Override
boolean testRedirect() {
false
}
@Override
boolean testCapturedHttpHeaders() {
false
}
@Override
boolean testError() {
false
}
@Override
protected void setupServlets(Object context) {
super.setupServlets(context)
addServlet(context, "/dispatch" + SUCCESS.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + HTML_PRINT_WRITER.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + HTML_SERVLET_OUTPUT_STREAM.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + QUERY_PARAM.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + REDIRECT.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + ERROR.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + EXCEPTION.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + AUTH_REQUIRED.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + CAPTURE_HEADERS.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + CAPTURE_PARAMETERS.path, RequestDispatcherServlet.Include)
addServlet(context, "/dispatch" + INDEXED_CHILD.path, RequestDispatcherServlet.Include)
}
}
class JettyServlet5TestDispatchImmediate extends JettyDispatchTest {
@Override
Class<Servlet> servlet() {
TestServlet5.Sync
}
@Override
protected void setupServlets(Object context) {
super.setupServlets(context)
addServlet(context, "/dispatch" + HTML_PRINT_WRITER.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + HTML_SERVLET_OUTPUT_STREAM.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + SUCCESS.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + QUERY_PARAM.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + ERROR.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + EXCEPTION.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + REDIRECT.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + AUTH_REQUIRED.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + CAPTURE_HEADERS.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + CAPTURE_PARAMETERS.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch" + INDEXED_CHILD.path, TestServlet5.DispatchImmediate)
addServlet(context, "/dispatch/recursive", TestServlet5.DispatchRecursive)
}
}
class JettyServlet5TestDispatchAsync extends JettyDispatchTest {
@Override
Class<Servlet> servlet() {
TestServlet5.Async
}
@Override
protected void setupServlets(Object context) {
super.setupServlets(context)
addServlet(context, "/dispatch" + SUCCESS.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + HTML_PRINT_WRITER.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + HTML_SERVLET_OUTPUT_STREAM.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + QUERY_PARAM.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + ERROR.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + EXCEPTION.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + REDIRECT.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + AUTH_REQUIRED.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + CAPTURE_HEADERS.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + CAPTURE_PARAMETERS.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch" + INDEXED_CHILD.path, TestServlet5.DispatchAsync)
addServlet(context, "/dispatch/recursive", TestServlet5.DispatchRecursive)
}
@Override
boolean errorEndpointUsesSendError() {
false
}
}
abstract class JettyDispatchTest extends Jetty12Servlet5Test {
@Override
URI buildAddress() {
return new URI("http://localhost:$port$contextPath/dispatch/")
}
}

View File

@ -0,0 +1,10 @@
plugins {
id("otel.java-conventions")
}
dependencies {
api(project(":testing-common"))
api(project(":instrumentation:servlet:servlet-common:bootstrap"))
compileOnly("jakarta.servlet:jakarta.servlet-api:5.0.0")
}

View File

@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
package test
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.instrumentation.api.internal.HttpConstants
import io.opentelemetry.instrumentation.test.AgentTestTrait

View File

@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
package test
import io.opentelemetry.instrumentation.test.base.HttpServerTest
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint
import jakarta.servlet.RequestDispatcher

View File

@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.servlet.v5_0;
import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
@ -14,12 +16,11 @@ import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RequestDispatcherServlet {
/* There's something about the getRequestDispatcher call that breaks horribly when these classes
* are written in groovy.
*/
@WebServlet(asyncSupported = true)
public static class Forward extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
@ -32,6 +33,8 @@ public class RequestDispatcherServlet {
@WebServlet(asyncSupported = true)
public static class Include extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

View File

@ -14,7 +14,7 @@ public class ServletHelper<REQUEST, RESPONSE> extends BaseServletHelper<REQUEST,
ServletHelper.class.getName() + ".AsyncListener";
private static final String ASYNC_LISTENER_RESPONSE_ATTRIBUTE =
ServletHelper.class.getName() + ".AsyncListenerResponse";
private static final String ASYNC_EXCEPTION_ATTRIBUTE =
public static final String ASYNC_EXCEPTION_ATTRIBUTE =
ServletHelper.class.getName() + ".AsyncException";
public static final String CONTEXT_ATTRIBUTE = ServletHelper.class.getName() + ".Context";

View File

@ -321,6 +321,7 @@ include(":instrumentation:jedis:jedis-4.0:javaagent")
include(":instrumentation:jedis:jedis-common:javaagent")
include(":instrumentation:jetty:jetty-8.0:javaagent")
include(":instrumentation:jetty:jetty-11.0:javaagent")
include(":instrumentation:jetty:jetty-12.0:javaagent")
include(":instrumentation:jetty:jetty-common:javaagent")
include(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:javaagent")
include(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:library")
@ -502,6 +503,8 @@ include(":instrumentation:servlet:servlet-3.0:javaagent")
include(":instrumentation:servlet:servlet-3.0:javaagent-unit-tests")
include(":instrumentation:servlet:servlet-5.0:javaagent")
include(":instrumentation:servlet:servlet-5.0:javaagent-unit-tests")
include(":instrumentation:servlet:servlet-5.0:jetty12-testing")
include(":instrumentation:servlet:servlet-5.0:testing")
include(":instrumentation:spark-2.3:javaagent")
include(":instrumentation:spring:spring-batch-3.0:javaagent")
include(":instrumentation:spring:spring-boot-actuator-autoconfigure-2.0:javaagent")

View File

@ -57,7 +57,7 @@ abstract class AppServerTest extends SmokeTest {
@Override
protected String getTargetImage(String jdk, String serverVersion, boolean windows) {
String platformSuffix = windows ? "-windows" : ""
String extraTag = "20240209.7847080088"
String extraTag = "20240216.7928274208"
String fullSuffix = "${serverVersion}-jdk$jdk$platformSuffix-$extraTag"
return getTargetImagePrefix() + ":" + fullSuffix
}

View File

@ -98,3 +98,19 @@ class Jetty11Jdk21 extends JettySmokeTest {
@AppServer(version = "11.0.19", jdk = "21-openj9")
class Jetty11Jdk21Openj9 extends JettySmokeTest {
}
@AppServer(version = "12.0.6", jdk = "17")
class Jetty12Jdk17 extends JettySmokeTest {
}
@AppServer(version = "12.0.6", jdk = "17-openj9")
class Jetty12Jdk17Openj9 extends JettySmokeTest {
}
@AppServer(version = "12.0.6", jdk = "21")
class Jetty12Jdk21 extends JettySmokeTest {
}
@AppServer(version = "12.0.6", jdk = "21-openj9")
class Jetty12Jdk21Openj9 extends JettySmokeTest {
}