From 89e648513ccf6660606db3dc580e1d3a5f16754b Mon Sep 17 00:00:00 2001 From: anosek Date: Mon, 23 Aug 2021 09:20:23 +0200 Subject: [PATCH] server instrumentation with first tests --- .../javaagent/build.gradle.kts | 26 ++++ .../v1_1/RestletInstrumentationModule.java | 25 +++ .../restlet/v1_1/RouteInstrumentation.java | 57 +++++++ .../restlet/v1_1/ServerInstrumentation.java | 94 ++++++++++++ .../src/test/groovy/RestletServerTest.groovy | 17 +++ .../restlet-core-1.1/library/build.gradle.kts | 17 +++ .../restlet/v1_1/HeadersAdapter.java | 26 ++++ .../restlet/v1_1/RestletExtractAdapter.java | 24 +++ .../restlet/v1_1/RestletHttpServerTracer.java | 78 ++++++++++ .../src/test/groovy/RestletServerTest.groovy | 81 ++++++++++ .../restlet-core-1.1/testing/build.gradle.kts | 20 +++ .../v1_1/AbstractRestletServerTest.groovy | 144 ++++++++++++++++++ settings.gradle.kts | 3 + 13 files changed, 612 insertions(+) create mode 100644 instrumentation/restlet/restlet-core-1.1/javaagent/build.gradle.kts create mode 100644 instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java create mode 100644 instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java create mode 100644 instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java create mode 100644 instrumentation/restlet/restlet-core-1.1/javaagent/src/test/groovy/RestletServerTest.groovy create mode 100644 instrumentation/restlet/restlet-core-1.1/library/build.gradle.kts create mode 100644 instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java create mode 100644 instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletExtractAdapter.java create mode 100644 instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpServerTracer.java create mode 100644 instrumentation/restlet/restlet-core-1.1/library/src/test/groovy/RestletServerTest.groovy create mode 100644 instrumentation/restlet/restlet-core-1.1/testing/build.gradle.kts create mode 100644 instrumentation/restlet/restlet-core-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy diff --git a/instrumentation/restlet/restlet-core-1.1/javaagent/build.gradle.kts b/instrumentation/restlet/restlet-core-1.1/javaagent/build.gradle.kts new file mode 100644 index 000000000000..97928ec22f37 --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/javaagent/build.gradle.kts @@ -0,0 +1,26 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +muzzle { + pass { + group.set("org.restlet") + module.set("org.restlet") + versions.set("[1.0.0, 1.2.0)") + } +} + +repositories { + mavenCentral() + maven("https://maven.restlet.talend.com/") + mavenLocal() +} + +dependencies { + api(project(":instrumentation:restlet:restlet-core-1.1:library")) + + library("org.restlet:org.restlet:1.1.5") + library("com.noelios.restlet:com.noelios.restlet:1.1.5") + implementation(project(":instrumentation:restlet:restlet-core-1.1:library")) + testImplementation(project(":instrumentation:restlet:restlet-core-1.1:testing")) +} diff --git a/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java b/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java new file mode 100644 index 000000000000..d08e57b341d6 --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.restlet.v1_1; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import java.util.Arrays; +import java.util.List; + +@AutoService(InstrumentationModule.class) +public class RestletInstrumentationModule extends InstrumentationModule { + + public RestletInstrumentationModule() { + super("restlet-core", "restlet-core-1.1"); + } + + @Override + public List typeInstrumentations() { + return Arrays.asList(new ServerInstrumentation(), new RouteInstrumentation()); + } +} diff --git a/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java b/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java new file mode 100644 index 000000000000..62d620f51565 --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java @@ -0,0 +1,57 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.restlet.v1_1; + +import static io.opentelemetry.instrumentation.restlet.v1_1.RestletHttpServerTracer.tracer; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import io.opentelemetry.api.trace.Span; +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.restlet.Route; +import org.restlet.data.Request; + +public class RouteInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("org.restlet.Route"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + isMethod() + .and(named("beforeHandle")) + .and(takesArgument(0, named("org.restlet.data.Request"))) + .and(takesArgument(1, named("org.restlet.data.Response"))), + this.getClass().getName() + "$RouteBeforeHandleAdvice"); + } + + @SuppressWarnings("unused") + public static class RouteBeforeHandleAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void getRouteInfo(@Advice.This Route route, @Advice.Argument(0) Request request) { + String pattern = route.getTemplate().getPattern(); + if (pattern == null || pattern.equals("")) { + return; + } + + Span serverSpan = tracer().getServerSpan(request); + + if (serverSpan == null) { + return; + } + + serverSpan.updateName(pattern); + } + } +} diff --git a/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java b/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java new file mode 100644 index 000000000000..b835c07348c8 --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java @@ -0,0 +1,94 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.restlet.v1_1; + +import static io.opentelemetry.instrumentation.restlet.v1_1.RestletHttpServerTracer.tracer; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +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.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.restlet.data.Request; +import org.restlet.data.Response; + +public class ServerInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("org.restlet.Server"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + isMethod() + .and(named("handle")) + .and(takesArgument(0, named("org.restlet.data.Request"))) + .and(takesArgument(1, named("org.restlet.data.Response"))), + this.getClass().getName() + "$ServerHandleAdvice"); + } + + @SuppressWarnings("unused") + public static class ServerHandleAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void beginRequest( + @Advice.Argument(0) Request request, + @Advice.Argument(1) Response response, + @Advice.Local("otelScope") Scope scope) { + + Context serverContext = tracer().getServerContext(request); + + if (serverContext != null) { + return; + } + + serverContext = + tracer().startSpan(request, request, request, request.getResourceRef().getPath()); + scope = serverContext.makeCurrent(); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void finishRequest( + @Advice.Argument(0) Request request, + @Advice.Argument(1) Response response, + @Advice.Thrown Throwable exception, + @Advice.Local("otelScope") Scope scope) { + + Context serverContext = tracer().getServerContext(request); + + if (scope == null) { + return; + } + + scope.close(); + + if (serverContext == null) { + return; + } + + if (exception != null) { + tracer().endExceptionally(serverContext, exception, response); + return; + } + + // Restlet suppresses exceptions and sets the throwable in status + Throwable statusThrowable = response.getStatus().getThrowable(); + + if (statusThrowable != null) { + tracer().endExceptionally(serverContext, statusThrowable, response); + return; + } + + tracer().end(serverContext, response); + } + } +} diff --git a/instrumentation/restlet/restlet-core-1.1/javaagent/src/test/groovy/RestletServerTest.groovy b/instrumentation/restlet/restlet-core-1.1/javaagent/src/test/groovy/RestletServerTest.groovy new file mode 100644 index 000000000000..2a08ceef9b3d --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/javaagent/src/test/groovy/RestletServerTest.groovy @@ -0,0 +1,17 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.restlet.v1_1.AbstractRestletServerTest +import io.opentelemetry.instrumentation.test.AgentTestTrait +import org.restlet.Restlet + +class RestletServerTest extends AbstractRestletServerTest implements AgentTestTrait { + + @Override + Restlet wrapRestlet(Restlet restlet, String path){ + return restlet + } + +} diff --git a/instrumentation/restlet/restlet-core-1.1/library/build.gradle.kts b/instrumentation/restlet/restlet-core-1.1/library/build.gradle.kts new file mode 100644 index 000000000000..f14d8e82ba4a --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/library/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id("otel.library-instrumentation") +} + +repositories { + mavenCentral() + maven("https://maven.restlet.talend.com/") + mavenLocal() +} + +dependencies { + + library("org.restlet:org.restlet:1.1.5") + library("com.noelios.restlet:com.noelios.restlet:1.1.5") + + testImplementation(project(":instrumentation:restlet:restlet-core-1.1:testing")) +} diff --git a/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java b/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java new file mode 100644 index 000000000000..1b1d11694cc9 --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java @@ -0,0 +1,26 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_1; + +import java.util.Locale; +import org.restlet.data.Form; +import org.restlet.data.Request; + +final class HeadersAdapter { + + static Form getHeaders(Request request) { + return (Form) request.getAttributes().get("org.restlet.http.headers"); + } + + static String getValue(Request request, String name) { + Form headers = getHeaders(request); + String value = headers.getFirstValue(name); + if (value != null) { + return value; + } + return headers.getFirstValue(name.toLowerCase(Locale.ROOT)); + } +} diff --git a/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletExtractAdapter.java b/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletExtractAdapter.java new file mode 100644 index 000000000000..764e318ba714 --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletExtractAdapter.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_1; + +import io.opentelemetry.context.propagation.TextMapGetter; +import org.restlet.data.Request; + +final class RestletExtractAdapter implements TextMapGetter { + + static final RestletExtractAdapter GETTER = new RestletExtractAdapter(); + + @Override + public Iterable keys(Request carrier) { + return HeadersAdapter.getHeaders(carrier).getNames(); + } + + @Override + public String get(Request carrier, String key) { + return HeadersAdapter.getValue(carrier, key); + } +} diff --git a/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpServerTracer.java b/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpServerTracer.java new file mode 100644 index 000000000000..f0428de8a76f --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpServerTracer.java @@ -0,0 +1,78 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_1; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.restlet.data.Request; +import org.restlet.data.Response; + +public class RestletHttpServerTracer extends HttpServerTracer { + + private static final RestletHttpServerTracer TRACER = new RestletHttpServerTracer(); + + public static RestletHttpServerTracer tracer() { + return TRACER; + } + + @Override + protected String getInstrumentationName() { + return "io.opentelemetry.restlet-core-1.1"; + } + + @Override + public @Nullable Context getServerContext(Request request) { + Object context = request.getAttributes().get(CONTEXT_ATTRIBUTE); + return context instanceof Context ? (Context) context : null; + } + + @Override + protected @Nullable Integer peerPort(Request request) { + return request.getClientInfo().getPort(); + } + + @Override + protected @Nullable String peerHostIp(Request request) { + return request.getClientInfo().getAddress(); + } + + @Override + protected String flavor(Request connection, Request request) { + return (String) request.getAttributes().get("org.restlet.http.version"); + } + + @Override + protected TextMapGetter getGetter() { + return RestletExtractAdapter.GETTER; + } + + @Override + protected String url(Request request) { + return request.getOriginalRef().toString(); + } + + @Override + protected String method(Request request) { + return request.getMethod().getName(); + } + + @Override + protected @Nullable String requestHeader(Request request, String name) { + return HeadersAdapter.getValue(request, name); + } + + @Override + protected int responseStatus(Response response) { + return response.getStatus().getCode(); + } + + @Override + protected void attachServerContext(Context context, Request request) { + request.getAttributes().put(CONTEXT_ATTRIBUTE, context); + } +} diff --git a/instrumentation/restlet/restlet-core-1.1/library/src/test/groovy/RestletServerTest.groovy b/instrumentation/restlet/restlet-core-1.1/library/src/test/groovy/RestletServerTest.groovy new file mode 100644 index 000000000000..ba706ea4e92f --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/library/src/test/groovy/RestletServerTest.groovy @@ -0,0 +1,81 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import static io.opentelemetry.instrumentation.restlet.v1_1.RestletHttpServerTracer.tracer + +import io.opentelemetry.context.Context +import io.opentelemetry.context.Scope +import io.opentelemetry.instrumentation.restlet.v1_1.AbstractRestletServerTest +import io.opentelemetry.instrumentation.test.LibraryTestTrait +import org.restlet.Filter +import org.restlet.Restlet +import org.restlet.data.Request +import org.restlet.data.Response + +class RestletServerTest extends AbstractRestletServerTest implements LibraryTestTrait { + + @Override + Restlet wrapRestlet(Restlet restlet, String path){ + def filter = new TracingFilter(path) + filter.setNext(restlet) + return filter + } + + static class TracingFilter extends Filter { + + private Scope scope + private String path + + TracingFilter(String path){ + this.path = path + } + + @Override + protected int beforeHandle(Request request, Response response) { + + Context serverContext = tracer().getServerContext(request) + + if(serverContext != null){ + return CONTINUE + } + + serverContext = tracer().startSpan(request, request, request, path) + scope = serverContext.makeCurrent() + + return CONTINUE + } + + @Override + protected void afterHandle(Request request, Response response) { + + Context serverContext = tracer().getServerContext(request) + + if(scope == null){ + return + } + + scope.close() + + if(serverContext == null) { + return + } + + Throwable statusThrowable = response.getStatus().getThrowable() + + if(statusThrowable != null) { + tracer().endExceptionally(serverContext, statusThrowable, response) + return + } + + tracer().end(serverContext, response) + } + + } + + @Override + boolean testException() { + false //afterHandle does not execute if exception was thrown in the next restlet + } +} diff --git a/instrumentation/restlet/restlet-core-1.1/testing/build.gradle.kts b/instrumentation/restlet/restlet-core-1.1/testing/build.gradle.kts new file mode 100644 index 000000000000..06d1f438a1a5 --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/testing/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + id("otel.java-conventions") +} + +repositories { + mavenCentral() + maven("https://maven.restlet.talend.com/") + mavenLocal() +} + +dependencies { + api(project(":testing-common")) + + implementation("org.restlet:org.restlet:1.1.5") + implementation("com.noelios.restlet:com.noelios.restlet:1.1.5") + + implementation("org.codehaus.groovy:groovy-all") + implementation("io.opentelemetry:opentelemetry-api") + implementation("org.spockframework:spock-core") +} diff --git a/instrumentation/restlet/restlet-core-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy b/instrumentation/restlet/restlet-core-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy new file mode 100644 index 000000000000..74332b3a0a39 --- /dev/null +++ b/instrumentation/restlet/restlet-core-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy @@ -0,0 +1,144 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_1 + +import io.opentelemetry.instrumentation.test.base.HttpServerTest +import org.restlet.Component +import org.restlet.Context +import org.restlet.Redirector +import org.restlet.Restlet +import org.restlet.Server +import org.restlet.data.MediaType +import org.restlet.data.Protocol +import org.restlet.data.Request +import org.restlet.data.Response +import org.restlet.data.Status + +import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR +import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION +import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND +import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM +import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM +import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT +import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS + +abstract class AbstractRestletServerTest extends HttpServerTest { + + def component + def host + + @Override + Server startServer(int port) { + + component = new Component() + def server = component.getServers().add(Protocol.HTTP, port) + + host = component.getDefaultHost() + attachRestlets() + component.start() + + return server + } + + @Override + void stopServer(Server server) { + component.stop() + } + + def attachAndWrap(path, restlet){ + host.attach(path, wrapRestlet(restlet, path)) + } + + def attachRestlets(){ + attachAndWrap(SUCCESS.path, new Restlet() { + @Override + void handle(Request request, Response response) { + controller(SUCCESS) { + response.setEntity(SUCCESS.body, MediaType.TEXT_PLAIN) + response.setStatus(Status.valueOf(SUCCESS.status), SUCCESS.body) + } + } + }) + + attachAndWrap(REDIRECT.path, new Redirector(Context.getCurrent(), REDIRECT.body, Redirector.MODE_CLIENT_FOUND) { + @Override + void handle(Request request, Response response){ + super.handle(request, response) + controller(REDIRECT){ + } //TODO: check why handle fails inside controller + } + }) + + attachAndWrap(ERROR.path, new Restlet(){ + @Override + void handle(Request request, Response response){ + controller(ERROR){ + response.setStatus(Status.valueOf(ERROR.getStatus()), ERROR.getBody()) + } + } + }) + + attachAndWrap(EXCEPTION.path, new Restlet(){ + @Override + void handle(Request request, Response response){ + controller(EXCEPTION){ + throw new Exception(EXCEPTION.getBody()) + } + } + }) + + attachAndWrap(QUERY_PARAM.path, new Restlet() { + @Override + void handle(Request request, Response response){ + controller(QUERY_PARAM){ + response.setEntity(QUERY_PARAM.getBody(), MediaType.TEXT_PLAIN) + response.setStatus(Status.valueOf(QUERY_PARAM.getStatus()), QUERY_PARAM.getBody()) + } + } + }) + + attachAndWrap(NOT_FOUND.path,new Restlet() { + @Override + void handle(Request request, Response response){ + controller(NOT_FOUND){ + response.setEntity(NOT_FOUND.getBody(), MediaType.TEXT_PLAIN) + response.setStatus(Status.valueOf(NOT_FOUND.getStatus()), NOT_FOUND.getBody()) + } + } + }) + + attachAndWrap("/path/{id}/param", new Restlet(){ + @Override + void handle(Request request, Response response) { + controller(PATH_PARAM) { + response.setEntity(PATH_PARAM.getBody(), MediaType.TEXT_PLAIN) + response.setStatus(Status.valueOf(PATH_PARAM.getStatus()), PATH_PARAM.getBody()) + } + } + }) + + } + + @Override + boolean testPathParam() { + true + } + + @Override + String expectedServerSpanName(ServerEndpoint endpoint) { + switch (endpoint) { + case PATH_PARAM: + return getContextPath() + "/path/{id}/param" + case NOT_FOUND: + return getContextPath() + "/notFound" + default: + return endpoint.resolvePath(address).path + } + } + + abstract Restlet wrapRestlet(Restlet restlet, String path) + +} diff --git a/settings.gradle.kts b/settings.gradle.kts index ffe19e060fd0..2a8885d86572 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -272,6 +272,9 @@ include(":instrumentation:reactor-netty:reactor-netty-0.9:javaagent") include(":instrumentation:reactor-netty:reactor-netty-1.0:javaagent") include(":instrumentation:rediscala-1.8:javaagent") include(":instrumentation:redisson-3.0:javaagent") +include(":instrumentation:restlet:restlet-core-1.1:javaagent") +include(":instrumentation:restlet:restlet-core-1.1:library") +include(":instrumentation:restlet:restlet-core-1.1:testing") include(":instrumentation:rmi:bootstrap") include(":instrumentation:rmi:javaagent") include(":instrumentation:rocketmq-client-4.8:javaagent")