From 30ebf4482bb33be2f4d214a80cf39852098c7118 Mon Sep 17 00:00:00 2001 From: anosek Date: Mon, 23 Aug 2021 09:20:23 +0200 Subject: [PATCH 1/8] 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 59baa53cde98..dc6ba7cc2ed6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -278,6 +278,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") From 3bbbf832000d28ead8cda66ac8eb769757ba69a5 Mon Sep 17 00:00:00 2001 From: anosek Date: Thu, 2 Sep 2021 12:56:59 +0200 Subject: [PATCH 2/8] migrate to instrumenter API, move TracingFilter to library, rename module, other review refinements --- .../javaagent/build.gradle.kts | 8 +- .../v1_1/RestletInstrumentationModule.java | 2 +- .../restlet/v1_1/RouteInstrumentation.java | 8 +- .../restlet/v1_1/ServerInstrumentation.java | 27 +++-- .../src/test/groovy/RestletServerTest.groovy | 0 .../library/build.gradle.kts | 2 +- .../restlet/v1_1/HeadersAdapter.java | 0 .../restlet/v1_1/RestletHeadersGetter.java} | 4 +- .../v1_1/RestletHttpAttributesExtractor.java | 99 +++++++++++++++++++ .../v1_1/RestletNetAttributesExtractor.java | 34 +++++++ .../restlet/v1_1/RestletSingletons.java | 57 +++++++++++ .../restlet/v1_1/TracingFilter.java | 67 +++++++++++++ .../src/test/groovy/RestletServerTest.groovy | 24 +++++ .../testing/build.gradle.kts | 0 .../v1_1/AbstractRestletServerTest.groovy | 34 ++++++- .../restlet/v1_1/RestletHttpServerTracer.java | 78 --------------- .../src/test/groovy/RestletServerTest.groovy | 81 --------------- settings.gradle.kts | 6 +- 18 files changed, 340 insertions(+), 191 deletions(-) rename instrumentation/restlet/{restlet-core-1.1 => restlet-1.1}/javaagent/build.gradle.kts (56%) rename instrumentation/restlet/{restlet-core-1.1 => restlet-1.1}/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java (93%) rename instrumentation/restlet/{restlet-core-1.1 => restlet-1.1}/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java (85%) rename instrumentation/restlet/{restlet-core-1.1 => restlet-1.1}/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java (78%) rename instrumentation/restlet/{restlet-core-1.1 => restlet-1.1}/javaagent/src/test/groovy/RestletServerTest.groovy (100%) rename instrumentation/restlet/{restlet-core-1.1 => restlet-1.1}/library/build.gradle.kts (76%) rename instrumentation/restlet/{restlet-core-1.1 => restlet-1.1}/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java (100%) rename instrumentation/restlet/{restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletExtractAdapter.java => restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHeadersGetter.java} (76%) create mode 100644 instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpAttributesExtractor.java create mode 100644 instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletNetAttributesExtractor.java create mode 100644 instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletSingletons.java create mode 100644 instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/TracingFilter.java create mode 100644 instrumentation/restlet/restlet-1.1/library/src/test/groovy/RestletServerTest.groovy rename instrumentation/restlet/{restlet-core-1.1 => restlet-1.1}/testing/build.gradle.kts (100%) rename instrumentation/restlet/{restlet-core-1.1 => restlet-1.1}/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy (81%) delete mode 100644 instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpServerTracer.java delete mode 100644 instrumentation/restlet/restlet-core-1.1/library/src/test/groovy/RestletServerTest.groovy diff --git a/instrumentation/restlet/restlet-core-1.1/javaagent/build.gradle.kts b/instrumentation/restlet/restlet-1.1/javaagent/build.gradle.kts similarity index 56% rename from instrumentation/restlet/restlet-core-1.1/javaagent/build.gradle.kts rename to instrumentation/restlet/restlet-1.1/javaagent/build.gradle.kts index 97928ec22f37..8ec25f487870 100644 --- a/instrumentation/restlet/restlet-core-1.1/javaagent/build.gradle.kts +++ b/instrumentation/restlet/restlet-1.1/javaagent/build.gradle.kts @@ -6,7 +6,7 @@ muzzle { pass { group.set("org.restlet") module.set("org.restlet") - versions.set("[1.0.0, 1.2.0)") + versions.set("[1.0.0, 1.2-M1)") } } @@ -17,10 +17,10 @@ repositories { } dependencies { - api(project(":instrumentation:restlet:restlet-core-1.1:library")) + api(project(":instrumentation:restlet:restlet-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")) + implementation(project(":instrumentation:restlet:restlet-1.1:library")) + testImplementation(project(":instrumentation:restlet:restlet-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-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java similarity index 93% rename from instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java rename to instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java index d08e57b341d6..a346d76d93d1 100644 --- a/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java +++ b/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java @@ -15,7 +15,7 @@ public class RestletInstrumentationModule extends InstrumentationModule { public RestletInstrumentationModule() { - super("restlet-core", "restlet-core-1.1"); + super("restlet", "restlet-1.1"); } @Override 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-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java similarity index 85% rename from instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java rename to instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java index 62d620f51565..393e5aad1821 100644 --- a/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java +++ b/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java @@ -5,12 +5,14 @@ package io.opentelemetry.javaagent.instrumentation.restlet.v1_1; -import static io.opentelemetry.instrumentation.restlet.v1_1.RestletHttpServerTracer.tracer; +import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; 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.context.Context; +import io.opentelemetry.instrumentation.api.tracer.ServerSpan; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; @@ -45,7 +47,9 @@ public static void getRouteInfo(@Advice.This Route route, @Advice.Argument(0) Re return; } - Span serverSpan = tracer().getServerSpan(request); + Context context = currentContext(); + + Span serverSpan = ServerSpan.fromContextOrNull(context); if (serverSpan == null) { return; 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-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java similarity index 78% rename from instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java rename to instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java index b835c07348c8..425a1dd7c855 100644 --- a/instrumentation/restlet/restlet-core-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java +++ b/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java @@ -5,7 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.restlet.v1_1; -import static io.opentelemetry.instrumentation.restlet.v1_1.RestletHttpServerTracer.tracer; +import static io.opentelemetry.instrumentation.restlet.v1_1.RestletSingletons.instrumenter; +import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; @@ -43,17 +44,17 @@ public static class ServerHandleAdvice { public static void beginRequest( @Advice.Argument(0) Request request, @Advice.Argument(1) Response response, + @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - Context serverContext = tracer().getServerContext(request); + Context parentContext = currentContext(); - if (serverContext != null) { + if (!instrumenter().shouldStart(parentContext, request)) { return; } - serverContext = - tracer().startSpan(request, request, request, request.getResourceRef().getPath()); - scope = serverContext.makeCurrent(); + context = instrumenter().start(parentContext, request); + scope = context.makeCurrent(); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) @@ -61,34 +62,28 @@ public static void finishRequest( @Advice.Argument(0) Request request, @Advice.Argument(1) Response response, @Advice.Thrown Throwable exception, + @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - Context serverContext = tracer().getServerContext(request); - if (scope == null) { return; } scope.close(); - if (serverContext == null) { + if (context == null) { return; } if (exception != null) { - tracer().endExceptionally(serverContext, exception, response); + instrumenter().end(context, request, response, exception); 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); + instrumenter().end(context, request, response, statusThrowable); } } } diff --git a/instrumentation/restlet/restlet-core-1.1/javaagent/src/test/groovy/RestletServerTest.groovy b/instrumentation/restlet/restlet-1.1/javaagent/src/test/groovy/RestletServerTest.groovy similarity index 100% rename from instrumentation/restlet/restlet-core-1.1/javaagent/src/test/groovy/RestletServerTest.groovy rename to instrumentation/restlet/restlet-1.1/javaagent/src/test/groovy/RestletServerTest.groovy diff --git a/instrumentation/restlet/restlet-core-1.1/library/build.gradle.kts b/instrumentation/restlet/restlet-1.1/library/build.gradle.kts similarity index 76% rename from instrumentation/restlet/restlet-core-1.1/library/build.gradle.kts rename to instrumentation/restlet/restlet-1.1/library/build.gradle.kts index f14d8e82ba4a..7a6ba61f4994 100644 --- a/instrumentation/restlet/restlet-core-1.1/library/build.gradle.kts +++ b/instrumentation/restlet/restlet-1.1/library/build.gradle.kts @@ -13,5 +13,5 @@ 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")) + testImplementation(project(":instrumentation:restlet:restlet-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-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java similarity index 100% rename from instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java rename to instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java 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-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHeadersGetter.java similarity index 76% rename from instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletExtractAdapter.java rename to instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHeadersGetter.java index 764e318ba714..3557fe04c845 100644 --- a/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletExtractAdapter.java +++ b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHeadersGetter.java @@ -8,9 +8,9 @@ import io.opentelemetry.context.propagation.TextMapGetter; import org.restlet.data.Request; -final class RestletExtractAdapter implements TextMapGetter { +final class RestletHeadersGetter implements TextMapGetter { - static final RestletExtractAdapter GETTER = new RestletExtractAdapter(); + static final RestletHeadersGetter GETTER = new RestletHeadersGetter(); @Override public Iterable keys(Request carrier) { diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpAttributesExtractor.java b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpAttributesExtractor.java new file mode 100644 index 000000000000..a861e3d1a019 --- /dev/null +++ b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpAttributesExtractor.java @@ -0,0 +1,99 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_1; + +import io.opentelemetry.instrumentation.api.instrumenter.http.HttpAttributesExtractor; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.restlet.data.Reference; +import org.restlet.data.Request; +import org.restlet.data.Response; + +final class RestletHttpAttributesExtractor extends HttpAttributesExtractor { + @Override + protected @Nullable String method(Request request) { + return request.getMethod().toString(); + } + + @Override + protected @Nullable String url(Request request) { + return request.getOriginalRef().toString(); + } + + @Override + protected @Nullable String target(Request request) { + Reference ref = request.getOriginalRef(); + String path = ref.getPath(); + return ref.hasQuery() ? path + "?" + ref.getQuery() : path; + } + + @Override + protected @Nullable String host(Request request) { + return null; + } + + @Override + protected @Nullable String route(Request request) { + return null; + } + + @Override + protected @Nullable String scheme(Request request) { + return request.getOriginalRef().getScheme(); + } + + @Override + protected @Nullable String userAgent(Request request) { + return request.getClientInfo().getAgent(); + } + + @Override + protected @Nullable Long requestContentLength(Request request, @Nullable Response response) { + return null; + } + + @Override + protected @Nullable Long requestContentLengthUncompressed( + Request request, @Nullable Response response) { + return null; + } + + @Override + protected @Nullable String flavor(Request request, @Nullable Response response) { + String version = (String) request.getAttributes().get("org.restlet.http.version"); + switch (version) { + case "HTTP/1.0": + return SemanticAttributes.HttpFlavorValues.HTTP_1_0; + case "HTTP/1.1": + return SemanticAttributes.HttpFlavorValues.HTTP_1_1; + case "HTTP/2.0": + return SemanticAttributes.HttpFlavorValues.HTTP_2_0; + default: + // fall through + } + return null; + } + + @Override + protected @Nullable String serverName(Request request, @Nullable Response response) { + return null; + } + + @Override + protected @Nullable Integer statusCode(Request request, Response response) { + return response.getStatus().getCode(); + } + + @Override + protected @Nullable Long responseContentLength(Request request, Response response) { + return null; + } + + @Override + protected @Nullable Long responseContentLengthUncompressed(Request request, Response response) { + return null; + } +} diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletNetAttributesExtractor.java b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletNetAttributesExtractor.java new file mode 100644 index 000000000000..38f9506876a5 --- /dev/null +++ b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletNetAttributesExtractor.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_1; + +import io.opentelemetry.instrumentation.api.instrumenter.net.NetAttributesExtractor; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.restlet.data.Request; +import org.restlet.data.Response; + +final class RestletNetAttributesExtractor extends NetAttributesExtractor { + @Override + public String transport(Request request) { + return SemanticAttributes.NetTransportValues.IP_TCP; + } + + @Override + public @Nullable String peerName(Request request, @Nullable Response response) { + return request.getHostRef().getUserInfo(); + } + + @Override + public @Nullable Integer peerPort(Request request, @Nullable Response response) { + return request.getClientInfo().getPort(); + } + + @Override + public @Nullable String peerIp(Request request, @Nullable Response response) { + return request.getClientInfo().getAddress(); + } +} diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletSingletons.java b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletSingletons.java new file mode 100644 index 000000000000..6042c0b6ea5c --- /dev/null +++ b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletSingletons.java @@ -0,0 +1,57 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_1; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.http.HttpAttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.net.NetAttributesExtractor; +import org.restlet.data.Request; +import org.restlet.data.Response; + +public final class RestletSingletons { + + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.restlet-1.1"; + + private static final Instrumenter INSTRUMENTER; + + static { + HttpAttributesExtractor httpAttributesExtractor = + new RestletHttpAttributesExtractor(); + SpanNameExtractor spanNameExtractor = + HttpSpanNameExtractor.create(httpAttributesExtractor); + SpanStatusExtractor spanStatusExtractor = + HttpSpanStatusExtractor.create(httpAttributesExtractor); + NetAttributesExtractor netAttributesExtractor = + new RestletNetAttributesExtractor(); + + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + + INSTRUMENTER = + Instrumenter.newBuilder( + openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) + .setSpanStatusExtractor(spanStatusExtractor) + .addAttributesExtractor(httpAttributesExtractor) + .addAttributesExtractor(netAttributesExtractor) + .newServerInstrumenter(RestletHeadersGetter.GETTER); + } + + public static Instrumenter instrumenter() { + return INSTRUMENTER; + } + + public static TextMapGetter getter() { + return RestletHeadersGetter.GETTER; + } + + private RestletSingletons() {} +} diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/TracingFilter.java b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/TracingFilter.java new file mode 100644 index 000000000000..036856f55c85 --- /dev/null +++ b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/TracingFilter.java @@ -0,0 +1,67 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_1; + +import static io.opentelemetry.instrumentation.restlet.v1_1.RestletSingletons.instrumenter; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.tracer.ServerSpan; +import org.restlet.Filter; +import org.restlet.data.Request; +import org.restlet.data.Response; + +public final class TracingFilter extends Filter { + + private static final ThreadLocal otelScope = new ThreadLocal<>(); + private static final ThreadLocal otelContext = new ThreadLocal<>(); + private final String path; + + public TracingFilter(String path) { + this.path = path; + } + + @Override + protected int beforeHandle(Request request, Response response) { + + Context parentContext = Context.current(); + + if (!instrumenter().shouldStart(parentContext, request)) { + return CONTINUE; + } + + otelContext.set(instrumenter().start(parentContext, request)); + + Span span = ServerSpan.fromContextOrNull(otelContext.get()); + + if (span != null) { + span.updateName(path); + otelScope.set(otelContext.get().makeCurrent()); + } + + return CONTINUE; + } + + @Override + protected void afterHandle(Request request, Response response) { + + if (otelScope.get() == null) { + return; + } + + otelScope.get().close(); + + if (otelContext.get() == null) { + return; + } + + // Restlet suppresses exceptions and sets the throwable in status + Throwable statusThrowable = response.getStatus().getThrowable(); + + instrumenter().end(otelContext.get(), request, response, statusThrowable); + } +} diff --git a/instrumentation/restlet/restlet-1.1/library/src/test/groovy/RestletServerTest.groovy b/instrumentation/restlet/restlet-1.1/library/src/test/groovy/RestletServerTest.groovy new file mode 100644 index 000000000000..f17cfeae6b12 --- /dev/null +++ b/instrumentation/restlet/restlet-1.1/library/src/test/groovy/RestletServerTest.groovy @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.restlet.v1_1.AbstractRestletServerTest +import io.opentelemetry.instrumentation.restlet.v1_1.TracingFilter +import io.opentelemetry.instrumentation.test.LibraryTestTrait +import org.restlet.Restlet + +class RestletServerTest extends AbstractRestletServerTest implements LibraryTestTrait { + + @Override + Restlet wrapRestlet(Restlet restlet, String path){ + def filter = new TracingFilter(path) + filter.setNext(restlet) + return filter + } + + @Override + boolean testException() { + false //Filter's 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-1.1/testing/build.gradle.kts similarity index 100% rename from instrumentation/restlet/restlet-core-1.1/testing/build.gradle.kts rename to instrumentation/restlet/restlet-1.1/testing/build.gradle.kts 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-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy similarity index 81% rename from instrumentation/restlet/restlet-core-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy rename to instrumentation/restlet/restlet-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy index 74332b3a0a39..f5a196a6d9fe 100644 --- a/instrumentation/restlet/restlet-core-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy +++ b/instrumentation/restlet/restlet-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy @@ -5,12 +5,15 @@ package io.opentelemetry.instrumentation.restlet.v1_1 +import io.opentelemetry.api.common.AttributeKey import io.opentelemetry.instrumentation.test.base.HttpServerTest +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes import org.restlet.Component import org.restlet.Context import org.restlet.Redirector import org.restlet.Restlet import org.restlet.Server +import org.restlet.VirtualHost import org.restlet.data.MediaType import org.restlet.data.Protocol import org.restlet.data.Request @@ -19,6 +22,7 @@ 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.INDEXED_CHILD 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 @@ -27,8 +31,8 @@ import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEn abstract class AbstractRestletServerTest extends HttpServerTest { - def component - def host + Component component + VirtualHost host @Override Server startServer(int port) { @@ -100,7 +104,7 @@ abstract class AbstractRestletServerTest extends HttpServerTest { } }) - attachAndWrap(NOT_FOUND.path,new Restlet() { + attachAndWrap(NOT_FOUND.path, new Restlet() { @Override void handle(Request request, Response response){ controller(NOT_FOUND){ @@ -120,6 +124,25 @@ abstract class AbstractRestletServerTest extends HttpServerTest { } }) + attachAndWrap(INDEXED_CHILD.path, new Restlet() { + @Override + void handle(Request request, Response response) { + controller(INDEXED_CHILD) { + INDEXED_CHILD.collectSpanAttributes {request.getOriginalRef().getQueryAsForm().getFirst(it).getValue() } + response.setStatus(Status.valueOf(INDEXED_CHILD.status)) + } + } + }) + + } + + @Override + List> extraAttributes() { + [ + SemanticAttributes.HTTP_TARGET, + SemanticAttributes.HTTP_SCHEME, + SemanticAttributes.NET_TRANSPORT, + ] } @Override @@ -127,6 +150,11 @@ abstract class AbstractRestletServerTest extends HttpServerTest { true } + @Override + boolean testConcurrency() { + true + } + @Override String expectedServerSpanName(ServerEndpoint endpoint) { switch (endpoint) { 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 deleted file mode 100644 index f0428de8a76f..000000000000 --- a/instrumentation/restlet/restlet-core-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpServerTracer.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 deleted file mode 100644 index ba706ea4e92f..000000000000 --- a/instrumentation/restlet/restlet-core-1.1/library/src/test/groovy/RestletServerTest.groovy +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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/settings.gradle.kts b/settings.gradle.kts index dc6ba7cc2ed6..7e592d86c969 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -278,9 +278,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:restlet:restlet-1.1:javaagent") +include(":instrumentation:restlet:restlet-1.1:library") +include(":instrumentation:restlet:restlet-1.1:testing") include(":instrumentation:rmi:bootstrap") include(":instrumentation:rmi:javaagent") include(":instrumentation:rocketmq-client-4.8:javaagent") From 3e095a5e51d2877b27bd1ad23c860fdee2de7e46 Mon Sep 17 00:00:00 2001 From: anosek Date: Mon, 6 Sep 2021 11:02:22 +0200 Subject: [PATCH 3/8] change name to 1.0 and rebase --- .../javaagent/build.gradle.kts | 6 +++--- .../restlet/v1_0}/RestletInstrumentationModule.java | 4 ++-- .../restlet/v1_0}/RouteInstrumentation.java | 2 +- .../restlet/v1_0}/ServerInstrumentation.java | 4 ++-- .../restlet/v1_0}/RestletServerTest.groovy | 8 +++++++- .../library/build.gradle.kts | 2 +- .../instrumentation/restlet/v1_0}/HeadersAdapter.java | 2 +- .../restlet/v1_0}/RestletHeadersGetter.java | 2 +- .../restlet/v1_0}/RestletHttpAttributesExtractor.java | 2 +- .../restlet/v1_0}/RestletNetAttributesExtractor.java | 2 +- .../restlet/v1_0}/RestletSingletons.java | 4 ++-- .../instrumentation/restlet/v1_0}/TracingFilter.java | 4 ++-- .../restlet/v1_0}/RestletServerTest.groovy | 10 ++++++++-- .../testing/build.gradle.kts | 0 .../restlet/v1_0}/AbstractRestletServerTest.groovy | 2 +- settings.gradle.kts | 6 +++--- 16 files changed, 36 insertions(+), 24 deletions(-) rename instrumentation/restlet/{restlet-1.1 => restlet-1.0}/javaagent/build.gradle.kts (76%) rename instrumentation/restlet/{restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1 => restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0}/RestletInstrumentationModule.java (86%) rename instrumentation/restlet/{restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1 => restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0}/RouteInstrumentation.java (96%) rename instrumentation/restlet/{restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1 => restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0}/ServerInstrumentation.java (95%) rename instrumentation/restlet/{restlet-1.1/javaagent/src/test/groovy => restlet-1.0/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/restlet/v1_0}/RestletServerTest.groovy (63%) rename instrumentation/restlet/{restlet-1.1 => restlet-1.0}/library/build.gradle.kts (95%) rename instrumentation/restlet/{restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1 => restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0}/HeadersAdapter.java (91%) rename instrumentation/restlet/{restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1 => restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0}/RestletHeadersGetter.java (91%) rename instrumentation/restlet/{restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1 => restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0}/RestletHttpAttributesExtractor.java (97%) rename instrumentation/restlet/{restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1 => restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0}/RestletNetAttributesExtractor.java (94%) rename instrumentation/restlet/{restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1 => restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0}/RestletSingletons.java (96%) rename instrumentation/restlet/{restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1 => restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0}/TracingFilter.java (93%) rename instrumentation/restlet/{restlet-1.1/library/src/test/groovy => restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0}/RestletServerTest.groovy (68%) rename instrumentation/restlet/{restlet-1.1 => restlet-1.0}/testing/build.gradle.kts (100%) rename instrumentation/restlet/{restlet-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1 => restlet-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_0}/AbstractRestletServerTest.groovy (98%) diff --git a/instrumentation/restlet/restlet-1.1/javaagent/build.gradle.kts b/instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts similarity index 76% rename from instrumentation/restlet/restlet-1.1/javaagent/build.gradle.kts rename to instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts index 8ec25f487870..b05a26ab8191 100644 --- a/instrumentation/restlet/restlet-1.1/javaagent/build.gradle.kts +++ b/instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts @@ -17,10 +17,10 @@ repositories { } dependencies { - api(project(":instrumentation:restlet:restlet-1.1:library")) + api(project(":instrumentation:restlet:restlet-1.0:library")) library("org.restlet:org.restlet:1.1.5") library("com.noelios.restlet:com.noelios.restlet:1.1.5") - implementation(project(":instrumentation:restlet:restlet-1.1:library")) - testImplementation(project(":instrumentation:restlet:restlet-1.1:testing")) + implementation(project(":instrumentation:restlet:restlet-1.0:library")) + testImplementation(project(":instrumentation:restlet:restlet-1.0:testing")) } diff --git a/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletInstrumentationModule.java similarity index 86% rename from instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java rename to instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletInstrumentationModule.java index a346d76d93d1..af81c0990294 100644 --- a/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletInstrumentationModule.java +++ b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletInstrumentationModule.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.restlet.v1_1; +package io.opentelemetry.javaagent.instrumentation.restlet.v1_0; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; @@ -15,7 +15,7 @@ public class RestletInstrumentationModule extends InstrumentationModule { public RestletInstrumentationModule() { - super("restlet", "restlet-1.1"); + super("restlet", "restlet-1.0"); } @Override diff --git a/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java similarity index 96% rename from instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java rename to instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java index 393e5aad1821..2ebabef73111 100644 --- a/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RouteInstrumentation.java +++ b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.restlet.v1_1; +package io.opentelemetry.javaagent.instrumentation.restlet.v1_0; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; import static net.bytebuddy.matcher.ElementMatchers.isMethod; diff --git a/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/ServerInstrumentation.java similarity index 95% rename from instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java rename to instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/ServerInstrumentation.java index 425a1dd7c855..126fec37fd1b 100644 --- a/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/ServerInstrumentation.java +++ b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/ServerInstrumentation.java @@ -3,9 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.restlet.v1_1; +package io.opentelemetry.javaagent.instrumentation.restlet.v1_0; -import static io.opentelemetry.instrumentation.restlet.v1_1.RestletSingletons.instrumenter; +import static io.opentelemetry.instrumentation.restlet.v1_0.RestletSingletons.instrumenter; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; diff --git a/instrumentation/restlet/restlet-1.1/javaagent/src/test/groovy/RestletServerTest.groovy b/instrumentation/restlet/restlet-1.0/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletServerTest.groovy similarity index 63% rename from instrumentation/restlet/restlet-1.1/javaagent/src/test/groovy/RestletServerTest.groovy rename to instrumentation/restlet/restlet-1.0/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletServerTest.groovy index 2a08ceef9b3d..eeb7e2ba0089 100644 --- a/instrumentation/restlet/restlet-1.1/javaagent/src/test/groovy/RestletServerTest.groovy +++ b/instrumentation/restlet/restlet-1.0/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletServerTest.groovy @@ -3,7 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -import io.opentelemetry.instrumentation.restlet.v1_1.AbstractRestletServerTest +package io.opentelemetry.javaagent.instrumentation.restlet.v1_0 +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.restlet.v1_0.AbstractRestletServerTest import io.opentelemetry.instrumentation.test.AgentTestTrait import org.restlet.Restlet diff --git a/instrumentation/restlet/restlet-1.1/library/build.gradle.kts b/instrumentation/restlet/restlet-1.0/library/build.gradle.kts similarity index 95% rename from instrumentation/restlet/restlet-1.1/library/build.gradle.kts rename to instrumentation/restlet/restlet-1.0/library/build.gradle.kts index 7a6ba61f4994..b2b45ced5cb7 100644 --- a/instrumentation/restlet/restlet-1.1/library/build.gradle.kts +++ b/instrumentation/restlet/restlet-1.0/library/build.gradle.kts @@ -13,5 +13,5 @@ dependencies { library("org.restlet:org.restlet:1.1.5") library("com.noelios.restlet:com.noelios.restlet:1.1.5") - testImplementation(project(":instrumentation:restlet:restlet-1.1:testing")) + testImplementation(project(":instrumentation:restlet:restlet-1.0:testing")) } diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/HeadersAdapter.java similarity index 91% rename from instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java rename to instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/HeadersAdapter.java index 1b1d11694cc9..0f6ef8ee610b 100644 --- a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/HeadersAdapter.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/HeadersAdapter.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.restlet.v1_1; +package io.opentelemetry.instrumentation.restlet.v1_0; import java.util.Locale; import org.restlet.data.Form; diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHeadersGetter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java similarity index 91% rename from instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHeadersGetter.java rename to instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java index 3557fe04c845..8666c77f95ae 100644 --- a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHeadersGetter.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.restlet.v1_1; +package io.opentelemetry.instrumentation.restlet.v1_0; import io.opentelemetry.context.propagation.TextMapGetter; import org.restlet.data.Request; diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpAttributesExtractor.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHttpAttributesExtractor.java similarity index 97% rename from instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpAttributesExtractor.java rename to instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHttpAttributesExtractor.java index a861e3d1a019..e90895c665dc 100644 --- a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletHttpAttributesExtractor.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHttpAttributesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.restlet.v1_1; +package io.opentelemetry.instrumentation.restlet.v1_0; import io.opentelemetry.instrumentation.api.instrumenter.http.HttpAttributesExtractor; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletNetAttributesExtractor.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletNetAttributesExtractor.java similarity index 94% rename from instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletNetAttributesExtractor.java rename to instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletNetAttributesExtractor.java index 38f9506876a5..e67d5a6b2ecf 100644 --- a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletNetAttributesExtractor.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletNetAttributesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.restlet.v1_1; +package io.opentelemetry.instrumentation.restlet.v1_0; import io.opentelemetry.instrumentation.api.instrumenter.net.NetAttributesExtractor; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletSingletons.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletSingletons.java similarity index 96% rename from instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletSingletons.java rename to instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletSingletons.java index 6042c0b6ea5c..f65b2b199078 100644 --- a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/RestletSingletons.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletSingletons.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.restlet.v1_1; +package io.opentelemetry.instrumentation.restlet.v1_0; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; @@ -20,7 +20,7 @@ public final class RestletSingletons { - private static final String INSTRUMENTATION_NAME = "io.opentelemetry.restlet-1.1"; + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.restlet-1.0"; private static final Instrumenter INSTRUMENTER; diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/TracingFilter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java similarity index 93% rename from instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/TracingFilter.java rename to instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java index 036856f55c85..94c355172c1a 100644 --- a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/TracingFilter.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java @@ -3,9 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.restlet.v1_1; +package io.opentelemetry.instrumentation.restlet.v1_0; -import static io.opentelemetry.instrumentation.restlet.v1_1.RestletSingletons.instrumenter; +import static io.opentelemetry.instrumentation.restlet.v1_0.RestletSingletons.instrumenter; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; diff --git a/instrumentation/restlet/restlet-1.1/library/src/test/groovy/RestletServerTest.groovy b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy similarity index 68% rename from instrumentation/restlet/restlet-1.1/library/src/test/groovy/RestletServerTest.groovy rename to instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy index f17cfeae6b12..5a31068691cd 100644 --- a/instrumentation/restlet/restlet-1.1/library/src/test/groovy/RestletServerTest.groovy +++ b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy @@ -3,8 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import io.opentelemetry.instrumentation.restlet.v1_1.AbstractRestletServerTest -import io.opentelemetry.instrumentation.restlet.v1_1.TracingFilter +package io.opententelemetry.instrumentation.restlet.v1_0 +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.restlet.v1_0.AbstractRestletServerTest +import io.opentelemetry.instrumentation.restlet.v1_0.TracingFilter import io.opentelemetry.instrumentation.test.LibraryTestTrait import org.restlet.Restlet diff --git a/instrumentation/restlet/restlet-1.1/testing/build.gradle.kts b/instrumentation/restlet/restlet-1.0/testing/build.gradle.kts similarity index 100% rename from instrumentation/restlet/restlet-1.1/testing/build.gradle.kts rename to instrumentation/restlet/restlet-1.0/testing/build.gradle.kts diff --git a/instrumentation/restlet/restlet-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy b/instrumentation/restlet/restlet-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_0/AbstractRestletServerTest.groovy similarity index 98% rename from instrumentation/restlet/restlet-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy rename to instrumentation/restlet/restlet-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_0/AbstractRestletServerTest.groovy index f5a196a6d9fe..438cefabdfae 100644 --- a/instrumentation/restlet/restlet-1.1/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_1/AbstractRestletServerTest.groovy +++ b/instrumentation/restlet/restlet-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/restlet/v1_0/AbstractRestletServerTest.groovy @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.restlet.v1_1 +package io.opentelemetry.instrumentation.restlet.v1_0 import io.opentelemetry.api.common.AttributeKey import io.opentelemetry.instrumentation.test.base.HttpServerTest diff --git a/settings.gradle.kts b/settings.gradle.kts index 7e592d86c969..8ed856adbbfb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -278,9 +278,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-1.1:javaagent") -include(":instrumentation:restlet:restlet-1.1:library") -include(":instrumentation:restlet:restlet-1.1:testing") +include(":instrumentation:restlet:restlet-1.0:javaagent") +include(":instrumentation:restlet:restlet-1.0:library") +include(":instrumentation:restlet:restlet-1.0:testing") include(":instrumentation:rmi:bootstrap") include(":instrumentation:rmi:javaagent") include(":instrumentation:rocketmq-client-4.8:javaagent") From 12cc9366ad58fe334dc401852341e4f34be56554 Mon Sep 17 00:00:00 2001 From: anosek Date: Wed, 8 Sep 2021 10:25:00 +0200 Subject: [PATCH 4/8] review, add ServerSpanNaming, create RestletTracing --- .../restlet-1.0/javaagent/build.gradle.kts | 2 + .../restlet/v1_0/RestletSingletons.java | 24 ++++++++++ .../restlet/v1_0/RouteInstrumentation.java | 20 +++------ .../restlet/v1_0/ServerInstrumentation.java | 6 +-- .../restlet-1.0/library/build.gradle.kts | 3 ++ .../restlet/v1_0/ContextAndScope.java | 26 +++++++++++ .../v1_0/RestletHttpAttributesExtractor.java | 6 +-- .../v1_0/RestletNetAttributesExtractor.java | 4 +- .../restlet/v1_0/RestletServerSpanNaming.java | 23 ++++++++++ .../restlet/v1_0/RestletTracing.java | 36 +++++++++++++++ ...letons.java => RestletTracingBuilder.java} | 38 +++++++++------- .../restlet/v1_0/TracingFilter.java | 44 +++++++++---------- .../restlet/v1_0/RestletServerTest.groovy | 9 +++- 13 files changed, 174 insertions(+), 67 deletions(-) create mode 100644 instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletSingletons.java create mode 100644 instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/ContextAndScope.java create mode 100644 instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletServerSpanNaming.java create mode 100644 instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracing.java rename instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/{RestletSingletons.java => RestletTracingBuilder.java} (68%) diff --git a/instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts b/instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts index b05a26ab8191..7a0122a031cd 100644 --- a/instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts +++ b/instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts @@ -7,6 +7,7 @@ muzzle { group.set("org.restlet") module.set("org.restlet") versions.set("[1.0.0, 1.2-M1)") + assertInverse.set(true) } } @@ -21,6 +22,7 @@ dependencies { library("org.restlet:org.restlet:1.1.5") library("com.noelios.restlet:com.noelios.restlet:1.1.5") + implementation(project(":instrumentation:restlet:restlet-1.0:library")) testImplementation(project(":instrumentation:restlet:restlet-1.0:testing")) } diff --git a/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletSingletons.java b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletSingletons.java new file mode 100644 index 000000000000..c1f5c8bbfd43 --- /dev/null +++ b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletSingletons.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.restlet.v1_0; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.restlet.v1_0.RestletTracing; +import org.restlet.data.Request; +import org.restlet.data.Response; + +public final class RestletSingletons { + + private static final Instrumenter INSTRUMENTER = + RestletTracing.create(GlobalOpenTelemetry.get()).getServerInstrumenter(); + + public static Instrumenter instrumenter() { + return INSTRUMENTER; + } + + private RestletSingletons() {} +} diff --git a/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java index 2ebabef73111..986105ddeca5 100644 --- a/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java +++ b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java @@ -5,14 +5,14 @@ package io.opentelemetry.javaagent.instrumentation.restlet.v1_0; +import static io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming.Source.CONTROLLER; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; 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.context.Context; -import io.opentelemetry.instrumentation.api.tracer.ServerSpan; +import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming; +import io.opentelemetry.instrumentation.restlet.v1_0.RestletServerSpanNaming; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; @@ -43,19 +43,9 @@ 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; - } - Context context = currentContext(); - - Span serverSpan = ServerSpan.fromContextOrNull(context); - - if (serverSpan == null) { - return; - } - - serverSpan.updateName(pattern); + ServerSpanNaming.updateServerSpanName( + currentContext(), CONTROLLER, RestletServerSpanNaming.SERVER_SPAN_NAME, pattern); } } } diff --git a/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/ServerInstrumentation.java b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/ServerInstrumentation.java index 126fec37fd1b..32fdc3e7179b 100644 --- a/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/ServerInstrumentation.java +++ b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/ServerInstrumentation.java @@ -5,8 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.restlet.v1_0; -import static io.opentelemetry.instrumentation.restlet.v1_0.RestletSingletons.instrumenter; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; +import static io.opentelemetry.javaagent.instrumentation.restlet.v1_0.RestletSingletons.instrumenter; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; @@ -71,10 +71,6 @@ public static void finishRequest( scope.close(); - if (context == null) { - return; - } - if (exception != null) { instrumenter().end(context, request, response, exception); return; diff --git a/instrumentation/restlet/restlet-1.0/library/build.gradle.kts b/instrumentation/restlet/restlet-1.0/library/build.gradle.kts index b2b45ced5cb7..569dbcfedf0d 100644 --- a/instrumentation/restlet/restlet-1.0/library/build.gradle.kts +++ b/instrumentation/restlet/restlet-1.0/library/build.gradle.kts @@ -10,6 +10,9 @@ repositories { dependencies { + compileOnly("com.google.auto.value:auto-value-annotations") + annotationProcessor("com.google.auto.value:auto-value") + library("org.restlet:org.restlet:1.1.5") library("com.noelios.restlet:com.noelios.restlet:1.1.5") diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/ContextAndScope.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/ContextAndScope.java new file mode 100644 index 000000000000..5e2b71da1f53 --- /dev/null +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/ContextAndScope.java @@ -0,0 +1,26 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_0; + +import com.google.auto.value.AutoValue; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; + +@AutoValue +abstract class ContextAndScope { + + static ContextAndScope create(Context context, Scope scope) { + return new AutoValue_ContextAndScope(context, scope); + } + + abstract Context getContext(); + + abstract Scope getScope(); + + void close() { + getScope().close(); + } +} diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHttpAttributesExtractor.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHttpAttributesExtractor.java index e90895c665dc..ad800158c161 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHttpAttributesExtractor.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHttpAttributesExtractor.java @@ -14,12 +14,12 @@ final class RestletHttpAttributesExtractor extends HttpAttributesExtractor { @Override - protected @Nullable String method(Request request) { + protected String method(Request request) { return request.getMethod().toString(); } @Override - protected @Nullable String url(Request request) { + protected String url(Request request) { return request.getOriginalRef().toString(); } @@ -83,7 +83,7 @@ final class RestletHttpAttributesExtractor extends HttpAttributesExtractor SERVER_SPAN_NAME = + (context, pattern) -> { + if (pattern == null || pattern.equals("")) { + return null; + } + + return ServletContextPath.prepend(context, pattern); + }; + + private RestletServerSpanNaming() {} +} diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracing.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracing.java new file mode 100644 index 000000000000..840b604f874f --- /dev/null +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracing.java @@ -0,0 +1,36 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.restlet.v1_0; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import org.restlet.data.Request; +import org.restlet.data.Response; + +public final class RestletTracing { + + public static RestletTracing create(OpenTelemetry openTelemetry) { + return newBuilder(openTelemetry).build(); + } + + public static RestletTracingBuilder newBuilder(OpenTelemetry openTelemetry) { + return new RestletTracingBuilder(openTelemetry); + } + + private final Instrumenter serverInstrumenter; + + RestletTracing(Instrumenter serverInstrumenter) { + this.serverInstrumenter = serverInstrumenter; + } + + public TracingFilter newFilter(String path) { + return new TracingFilter(serverInstrumenter, path); + } + + public Instrumenter getServerInstrumenter() { + return serverInstrumenter; + } +} diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletSingletons.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracingBuilder.java similarity index 68% rename from instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletSingletons.java rename to instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracingBuilder.java index f65b2b199078..07fb4c6778c9 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletSingletons.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracingBuilder.java @@ -5,9 +5,8 @@ package io.opentelemetry.instrumentation.restlet.v1_0; -import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor; @@ -15,16 +14,30 @@ import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor; import io.opentelemetry.instrumentation.api.instrumenter.net.NetAttributesExtractor; +import java.util.ArrayList; +import java.util.List; import org.restlet.data.Request; import org.restlet.data.Response; -public final class RestletSingletons { +public final class RestletTracingBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.restlet-1.0"; - private static final Instrumenter INSTRUMENTER; + private final OpenTelemetry openTelemetry; + private final List> additionalExtractors = + new ArrayList<>(); - static { + RestletTracingBuilder(OpenTelemetry openTelemetry) { + this.openTelemetry = openTelemetry; + } + + public RestletTracingBuilder addAttributesExtractor( + AttributesExtractor attributesExtractor) { + additionalExtractors.add(attributesExtractor); + return this; + } + + public RestletTracing build() { HttpAttributesExtractor httpAttributesExtractor = new RestletHttpAttributesExtractor(); SpanNameExtractor spanNameExtractor = @@ -34,24 +47,15 @@ public final class RestletSingletons { NetAttributesExtractor netAttributesExtractor = new RestletNetAttributesExtractor(); - OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); - - INSTRUMENTER = + Instrumenter instrumenter = Instrumenter.newBuilder( openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) .setSpanStatusExtractor(spanStatusExtractor) .addAttributesExtractor(httpAttributesExtractor) .addAttributesExtractor(netAttributesExtractor) + .addAttributesExtractors(additionalExtractors) .newServerInstrumenter(RestletHeadersGetter.GETTER); - } - - public static Instrumenter instrumenter() { - return INSTRUMENTER; - } - public static TextMapGetter getter() { - return RestletHeadersGetter.GETTER; + return new RestletTracing(instrumenter); } - - private RestletSingletons() {} } diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java index 94c355172c1a..9fe52c0f739c 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java @@ -5,23 +5,24 @@ package io.opentelemetry.instrumentation.restlet.v1_0; -import static io.opentelemetry.instrumentation.restlet.v1_0.RestletSingletons.instrumenter; +import static io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming.Source.CONTROLLER; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.tracer.ServerSpan; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming; import org.restlet.Filter; import org.restlet.data.Request; import org.restlet.data.Response; public final class TracingFilter extends Filter { - private static final ThreadLocal otelScope = new ThreadLocal<>(); - private static final ThreadLocal otelContext = new ThreadLocal<>(); + private static final ThreadLocal otelContextAndScope = new ThreadLocal<>(); + private final Instrumenter instrumenter; private final String path; - public TracingFilter(String path) { + public TracingFilter(Instrumenter instrumenter, String path) { + this.instrumenter = instrumenter; this.path = path; } @@ -30,18 +31,17 @@ protected int beforeHandle(Request request, Response response) { Context parentContext = Context.current(); - if (!instrumenter().shouldStart(parentContext, request)) { - return CONTINUE; + if (instrumenter.shouldStart(parentContext, request)) { + Context context = instrumenter.start(parentContext, request); + Scope scope = context.makeCurrent(); + otelContextAndScope.set(ContextAndScope.create(context, scope)); } - otelContext.set(instrumenter().start(parentContext, request)); - - Span span = ServerSpan.fromContextOrNull(otelContext.get()); - - if (span != null) { - span.updateName(path); - otelScope.set(otelContext.get().makeCurrent()); - } + ServerSpanNaming.updateServerSpanName( + otelContextAndScope.get().getContext(), + CONTROLLER, + RestletServerSpanNaming.SERVER_SPAN_NAME, + path); return CONTINUE; } @@ -49,19 +49,17 @@ protected int beforeHandle(Request request, Response response) { @Override protected void afterHandle(Request request, Response response) { - if (otelScope.get() == null) { - return; - } - - otelScope.get().close(); + ContextAndScope contextAndScope = otelContextAndScope.get(); - if (otelContext.get() == null) { + if (contextAndScope.getScope() == null) { return; } + contextAndScope.getScope().close(); + // Restlet suppresses exceptions and sets the throwable in status Throwable statusThrowable = response.getStatus().getThrowable(); - instrumenter().end(otelContext.get(), request, response, statusThrowable); + instrumenter.end(contextAndScope.getContext(), request, response, statusThrowable); } } diff --git a/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy index 5a31068691cd..82e7302d3c9c 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy +++ b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy @@ -4,13 +4,17 @@ */ package io.opententelemetry.instrumentation.restlet.v1_0 + +import io.opentelemetry.api.GlobalOpenTelemetry +import io.opentelemetry.api.OpenTelemetry + /* * Copyright The OpenTelemetry Authors * SPDX-License-Identifier: Apache-2.0 */ import io.opentelemetry.instrumentation.restlet.v1_0.AbstractRestletServerTest -import io.opentelemetry.instrumentation.restlet.v1_0.TracingFilter +import io.opentelemetry.instrumentation.restlet.v1_0.RestletTracing import io.opentelemetry.instrumentation.test.LibraryTestTrait import org.restlet.Restlet @@ -18,7 +22,8 @@ class RestletServerTest extends AbstractRestletServerTest implements LibraryTest @Override Restlet wrapRestlet(Restlet restlet, String path){ - def filter = new TracingFilter(path) + RestletTracing tracing = RestletTracing.create(openTelemetry) + def filter = tracing.newFilter(path) filter.setNext(restlet) return filter } From 4830b4363cf574260d60472f66aa0fc4a6af946b Mon Sep 17 00:00:00 2001 From: anosek Date: Wed, 8 Sep 2021 10:47:01 +0200 Subject: [PATCH 5/8] codenarc fix --- .../instrumentation/restlet/v1_0/RestletServerTest.groovy | 3 --- 1 file changed, 3 deletions(-) diff --git a/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy index 82e7302d3c9c..b1dad087146e 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy +++ b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy @@ -5,9 +5,6 @@ package io.opententelemetry.instrumentation.restlet.v1_0 -import io.opentelemetry.api.GlobalOpenTelemetry -import io.opentelemetry.api.OpenTelemetry - /* * Copyright The OpenTelemetry Authors * SPDX-License-Identifier: Apache-2.0 From 66fe65788f2e12bc8aaf07892c8574c50d0d1758 Mon Sep 17 00:00:00 2001 From: anosek Date: Wed, 8 Sep 2021 13:42:21 +0200 Subject: [PATCH 6/8] review --- .../restlet/v1_0/RouteInstrumentation.java | 2 +- .../restlet/v1_0/RestletHeadersGetter.java | 2 -- .../restlet/v1_0/RestletTracing.java | 13 ++++++++++++- .../restlet/v1_0/RestletTracingBuilder.java | 10 +++++++++- .../restlet/v1_0/TracingFilter.java | 15 ++++++++------- .../{ => internal}/RestletServerSpanNaming.java | 4 ++-- 6 files changed, 32 insertions(+), 14 deletions(-) rename instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/{ => internal}/RestletServerSpanNaming.java (83%) diff --git a/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java index 986105ddeca5..63a5cbeaf898 100644 --- a/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java +++ b/instrumentation/restlet/restlet-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RouteInstrumentation.java @@ -12,7 +12,7 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming; -import io.opentelemetry.instrumentation.restlet.v1_0.RestletServerSpanNaming; +import io.opentelemetry.instrumentation.restlet.v1_0.internal.RestletServerSpanNaming; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java index 8666c77f95ae..62e477bd68f8 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java @@ -10,8 +10,6 @@ final class RestletHeadersGetter implements TextMapGetter { - static final RestletHeadersGetter GETTER = new RestletHeadersGetter(); - @Override public Iterable keys(Request carrier) { return HeadersAdapter.getHeaders(carrier).getNames(); diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracing.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracing.java index 840b604f874f..cd1fdd14f050 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracing.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracing.java @@ -7,15 +7,21 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import org.restlet.Filter; import org.restlet.data.Request; import org.restlet.data.Response; +/** Entrypoint for tracing Restlet servers. */ public final class RestletTracing { + /** Returns a new {@link RestletTracing} configured with the given {@link OpenTelemetry}. */ public static RestletTracing create(OpenTelemetry openTelemetry) { return newBuilder(openTelemetry).build(); } + /** + * Returns a new {@link RestletTracingBuilder} configured with the given {@link OpenTelemetry}. + */ public static RestletTracingBuilder newBuilder(OpenTelemetry openTelemetry) { return new RestletTracingBuilder(openTelemetry); } @@ -26,10 +32,15 @@ public static RestletTracingBuilder newBuilder(OpenTelemetry openTelemetry) { this.serverInstrumenter = serverInstrumenter; } - public TracingFilter newFilter(String path) { + /** + * Returns a new {@link Filter} which can be used to wrap {@link org.restlet.Restlet} + * implementations. + */ + public Filter newFilter(String path) { return new TracingFilter(serverInstrumenter, path); } + /** Returns a server {@link Instrumenter}. */ public Instrumenter getServerInstrumenter() { return serverInstrumenter; } diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracingBuilder.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracingBuilder.java index 07fb4c6778c9..330e7b961666 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracingBuilder.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletTracingBuilder.java @@ -19,6 +19,7 @@ import org.restlet.data.Request; import org.restlet.data.Response; +/** A builder of {@link RestletTracing}. */ public final class RestletTracingBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.restlet-1.0"; @@ -31,12 +32,19 @@ public final class RestletTracingBuilder { this.openTelemetry = openTelemetry; } + /** + * Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented + * items. + */ public RestletTracingBuilder addAttributesExtractor( AttributesExtractor attributesExtractor) { additionalExtractors.add(attributesExtractor); return this; } + /** + * Returns a new {@link RestletTracing} with the settings of this {@link RestletTracingBuilder}. + */ public RestletTracing build() { HttpAttributesExtractor httpAttributesExtractor = new RestletHttpAttributesExtractor(); @@ -54,7 +62,7 @@ public RestletTracing build() { .addAttributesExtractor(httpAttributesExtractor) .addAttributesExtractor(netAttributesExtractor) .addAttributesExtractors(additionalExtractors) - .newServerInstrumenter(RestletHeadersGetter.GETTER); + .newServerInstrumenter(new RestletHeadersGetter()); return new RestletTracing(instrumenter); } diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java index 9fe52c0f739c..1275edc0083d 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java @@ -11,11 +11,12 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.servlet.ServerSpanNaming; +import io.opentelemetry.instrumentation.restlet.v1_0.internal.RestletServerSpanNaming; import org.restlet.Filter; import org.restlet.data.Request; import org.restlet.data.Response; -public final class TracingFilter extends Filter { +final class TracingFilter extends Filter { private static final ThreadLocal otelContextAndScope = new ThreadLocal<>(); private final Instrumenter instrumenter; @@ -30,18 +31,16 @@ public TracingFilter(Instrumenter instrumenter, String path) protected int beforeHandle(Request request, Response response) { Context parentContext = Context.current(); + Context context = parentContext; if (instrumenter.shouldStart(parentContext, request)) { - Context context = instrumenter.start(parentContext, request); + context = instrumenter.start(parentContext, request); Scope scope = context.makeCurrent(); otelContextAndScope.set(ContextAndScope.create(context, scope)); } ServerSpanNaming.updateServerSpanName( - otelContextAndScope.get().getContext(), - CONTROLLER, - RestletServerSpanNaming.SERVER_SPAN_NAME, - path); + context, CONTROLLER, RestletServerSpanNaming.SERVER_SPAN_NAME, path); return CONTINUE; } @@ -51,10 +50,12 @@ protected void afterHandle(Request request, Response response) { ContextAndScope contextAndScope = otelContextAndScope.get(); - if (contextAndScope.getScope() == null) { + if (contextAndScope == null) { return; } + otelContextAndScope.remove(); + contextAndScope.getScope().close(); // Restlet suppresses exceptions and sets the throwable in status diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletServerSpanNaming.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/internal/RestletServerSpanNaming.java similarity index 83% rename from instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletServerSpanNaming.java rename to instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/internal/RestletServerSpanNaming.java index 2fcb5af6eef5..8db5ed94710b 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletServerSpanNaming.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/internal/RestletServerSpanNaming.java @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.restlet.v1_0; +package io.opentelemetry.instrumentation.restlet.v1_0.internal; import io.opentelemetry.instrumentation.api.servlet.ServerSpanNameSupplier; import io.opentelemetry.instrumentation.api.servlet.ServletContextPath; -public class RestletServerSpanNaming { +public final class RestletServerSpanNaming { public static final ServerSpanNameSupplier SERVER_SPAN_NAME = (context, pattern) -> { From dd9481b8db1896e1d1864f6b07072a0580257438 Mon Sep 17 00:00:00 2001 From: anosek Date: Mon, 13 Sep 2021 13:11:29 +0200 Subject: [PATCH 7/8] fix TracingFilter behaviour on exception, inline HeadersAdapter's methods --- .../restlet/v1_0/RestletServerTest.groovy | 4 --- .../restlet/v1_0/HeadersAdapter.java | 26 ------------------- .../restlet/v1_0/RestletHeadersGetter.java | 17 ++++++++++-- .../restlet/v1_0/TracingFilter.java | 16 +++++++++++- .../restlet/v1_0/RestletServerTest.groovy | 9 ------- 5 files changed, 30 insertions(+), 42 deletions(-) delete mode 100644 instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/HeadersAdapter.java diff --git a/instrumentation/restlet/restlet-1.0/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletServerTest.groovy b/instrumentation/restlet/restlet-1.0/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletServerTest.groovy index eeb7e2ba0089..5a811b6ccdc9 100644 --- a/instrumentation/restlet/restlet-1.0/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletServerTest.groovy +++ b/instrumentation/restlet/restlet-1.0/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/restlet/v1_0/RestletServerTest.groovy @@ -4,10 +4,6 @@ */ package io.opentelemetry.javaagent.instrumentation.restlet.v1_0 -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ import io.opentelemetry.instrumentation.restlet.v1_0.AbstractRestletServerTest import io.opentelemetry.instrumentation.test.AgentTestTrait diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/HeadersAdapter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/HeadersAdapter.java deleted file mode 100644 index 0f6ef8ee610b..000000000000 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/HeadersAdapter.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.restlet.v1_0; - -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-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java index 62e477bd68f8..2df5e3d7503d 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/RestletHeadersGetter.java @@ -6,17 +6,30 @@ package io.opentelemetry.instrumentation.restlet.v1_0; import io.opentelemetry.context.propagation.TextMapGetter; +import java.util.Locale; +import org.restlet.data.Form; import org.restlet.data.Request; final class RestletHeadersGetter implements TextMapGetter { @Override public Iterable keys(Request carrier) { - return HeadersAdapter.getHeaders(carrier).getNames(); + return getHeaders(carrier).getNames(); } @Override public String get(Request carrier, String key) { - return HeadersAdapter.getValue(carrier, key); + + Form headers = getHeaders(carrier); + + String value = headers.getFirstValue(key); + if (value != null) { + return value; + } + return headers.getFirstValue(key.toLowerCase(Locale.ROOT)); + } + + private static Form getHeaders(Request carrier) { + return (Form) carrier.getAttributes().get("org.restlet.http.headers"); } } diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java index 1275edc0083d..f34c104afb24 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java @@ -15,6 +15,7 @@ import org.restlet.Filter; import org.restlet.data.Request; import org.restlet.data.Response; +import org.restlet.data.Status; final class TracingFilter extends Filter { @@ -27,6 +28,16 @@ public TracingFilter(Instrumenter instrumenter, String path) this.path = path; } + @Override + public int doHandle(Request request, Response response) { + try { + super.doHandle(request, response); + } catch (Throwable t) { + response.setStatus(new Status(Status.SERVER_ERROR_INTERNAL, t)); + } + return CONTINUE; + } + @Override protected int beforeHandle(Request request, Response response) { @@ -59,7 +70,10 @@ protected void afterHandle(Request request, Response response) { contextAndScope.getScope().close(); // Restlet suppresses exceptions and sets the throwable in status - Throwable statusThrowable = response.getStatus().getThrowable(); + Throwable statusThrowable = null; + if (response.getStatus() != null && response.getStatus().isError()) { + statusThrowable = response.getStatus().getThrowable(); + } instrumenter.end(contextAndScope.getContext(), request, response, statusThrowable); } diff --git a/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy index b1dad087146e..cca7a5af9ba1 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy +++ b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy @@ -5,11 +5,6 @@ package io.opententelemetry.instrumentation.restlet.v1_0 -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - import io.opentelemetry.instrumentation.restlet.v1_0.AbstractRestletServerTest import io.opentelemetry.instrumentation.restlet.v1_0.RestletTracing import io.opentelemetry.instrumentation.test.LibraryTestTrait @@ -25,8 +20,4 @@ class RestletServerTest extends AbstractRestletServerTest implements LibraryTest return filter } - @Override - boolean testException() { - false //Filter's afterHandle does not execute if exception was thrown in the next restlet - } } From 23bbf0d2d91c5538087e79f1f21a0b609737fb51 Mon Sep 17 00:00:00 2001 From: anosek Date: Mon, 13 Sep 2021 15:20:46 +0200 Subject: [PATCH 8/8] move instrumentation to doHandle, add StatusFilter in library test --- .../restlet/v1_0/ContextAndScope.java | 26 ----------- .../restlet/v1_0/TracingFilter.java | 44 +++++++------------ .../restlet/v1_0/RestletServerTest.groovy | 13 ++++-- 3 files changed, 25 insertions(+), 58 deletions(-) delete mode 100644 instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/ContextAndScope.java diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/ContextAndScope.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/ContextAndScope.java deleted file mode 100644 index 5e2b71da1f53..000000000000 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/ContextAndScope.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.restlet.v1_0; - -import com.google.auto.value.AutoValue; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; - -@AutoValue -abstract class ContextAndScope { - - static ContextAndScope create(Context context, Scope scope) { - return new AutoValue_ContextAndScope(context, scope); - } - - abstract Context getContext(); - - abstract Scope getScope(); - - void close() { - getScope().close(); - } -} diff --git a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java index f34c104afb24..72865eaa7600 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java +++ b/instrumentation/restlet/restlet-1.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_0/TracingFilter.java @@ -15,11 +15,9 @@ import org.restlet.Filter; import org.restlet.data.Request; import org.restlet.data.Response; -import org.restlet.data.Status; final class TracingFilter extends Filter { - private static final ThreadLocal otelContextAndScope = new ThreadLocal<>(); private final Instrumenter instrumenter; private final String path; @@ -30,51 +28,39 @@ public TracingFilter(Instrumenter instrumenter, String path) @Override public int doHandle(Request request, Response response) { - try { - super.doHandle(request, response); - } catch (Throwable t) { - response.setStatus(new Status(Status.SERVER_ERROR_INTERNAL, t)); - } - return CONTINUE; - } - - @Override - protected int beforeHandle(Request request, Response response) { Context parentContext = Context.current(); Context context = parentContext; + Scope scope = null; + if (instrumenter.shouldStart(parentContext, request)) { context = instrumenter.start(parentContext, request); - Scope scope = context.makeCurrent(); - otelContextAndScope.set(ContextAndScope.create(context, scope)); + scope = context.makeCurrent(); } ServerSpanNaming.updateServerSpanName( context, CONTROLLER, RestletServerSpanNaming.SERVER_SPAN_NAME, path); - return CONTINUE; - } - - @Override - protected void afterHandle(Request request, Response response) { - - ContextAndScope contextAndScope = otelContextAndScope.get(); - - if (contextAndScope == null) { - return; + Throwable statusThrowable = null; + try { + super.doHandle(request, response); + } catch (Throwable t) { + statusThrowable = t; } - otelContextAndScope.remove(); + if (scope == null) { + return CONTINUE; + } - contextAndScope.getScope().close(); + scope.close(); - // Restlet suppresses exceptions and sets the throwable in status - Throwable statusThrowable = null; if (response.getStatus() != null && response.getStatus().isError()) { statusThrowable = response.getStatus().getThrowable(); } - instrumenter.end(contextAndScope.getContext(), request, response, statusThrowable); + instrumenter.end(context, request, response, statusThrowable); + + return CONTINUE; } } diff --git a/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy index cca7a5af9ba1..18efd7bfbd7d 100644 --- a/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy +++ b/instrumentation/restlet/restlet-1.0/library/src/test/groovy/io/opententelemetry/instrumentation/restlet/v1_0/RestletServerTest.groovy @@ -5,6 +5,7 @@ package io.opententelemetry.instrumentation.restlet.v1_0 +import com.noelios.restlet.StatusFilter import io.opentelemetry.instrumentation.restlet.v1_0.AbstractRestletServerTest import io.opentelemetry.instrumentation.restlet.v1_0.RestletTracing import io.opentelemetry.instrumentation.test.LibraryTestTrait @@ -14,10 +15,16 @@ class RestletServerTest extends AbstractRestletServerTest implements LibraryTest @Override Restlet wrapRestlet(Restlet restlet, String path){ + RestletTracing tracing = RestletTracing.create(openTelemetry) - def filter = tracing.newFilter(path) - filter.setNext(restlet) - return filter + + def tracingFilter = tracing.newFilter(path) + def statusFilter = new StatusFilter(component.getContext(), false, null, null) + + tracingFilter.setNext(statusFilter) + statusFilter.setNext(restlet) + + return tracingFilter } }