diff --git a/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackForkedHttpClientTest.java b/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackForkedHttpClientTest.java index bb5e2be158d7..ed453607a20d 100644 --- a/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackForkedHttpClientTest.java +++ b/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackForkedHttpClientTest.java @@ -5,29 +5,13 @@ package io.opentelemetry.javaagent.instrumentation.ratpack; -import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; -import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT; - -import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.instrumentation.ratpack.client.AbstractRatpackForkedHttpClientTest; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; -import java.net.URI; -import java.util.HashSet; -import java.util.Set; import org.junit.jupiter.api.extension.RegisterExtension; class RatpackForkedHttpClientTest extends AbstractRatpackForkedHttpClientTest { @RegisterExtension static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); - - @Override - protected Set> computeHttpAttributes(URI uri) { - Set> attributes = new HashSet<>(super.computeHttpAttributes(uri)); - // underlying netty instrumentation does not provide these - attributes.remove(SERVER_ADDRESS); - attributes.remove(SERVER_PORT); - return attributes; - } } diff --git a/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackHttpClientTest.java b/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackHttpClientTest.java index 972b2f6676fe..13b941a21879 100644 --- a/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackHttpClientTest.java +++ b/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackHttpClientTest.java @@ -5,29 +5,13 @@ package io.opentelemetry.javaagent.instrumentation.ratpack; -import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; -import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT; - -import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.instrumentation.ratpack.client.AbstractRatpackHttpClientTest; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; -import java.net.URI; -import java.util.HashSet; -import java.util.Set; import org.junit.jupiter.api.extension.RegisterExtension; class RatpackHttpClientTest extends AbstractRatpackHttpClientTest { @RegisterExtension static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); - - @Override - protected Set> computeHttpAttributes(URI uri) { - Set> attributes = new HashSet<>(super.computeHttpAttributes(uri)); - // underlying netty instrumentation does not provide these - attributes.remove(SERVER_ADDRESS); - attributes.remove(SERVER_PORT); - return attributes; - } } diff --git a/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackPooledHttpClientTest.java b/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackPooledHttpClientTest.java index 6a5c668b7037..1b5863d5b0b1 100644 --- a/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackPooledHttpClientTest.java +++ b/instrumentation/ratpack/ratpack-1.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackPooledHttpClientTest.java @@ -5,29 +5,13 @@ package io.opentelemetry.javaagent.instrumentation.ratpack; -import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; -import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT; - -import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.instrumentation.ratpack.client.AbstractRatpackPooledHttpClientTest; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; -import java.net.URI; -import java.util.HashSet; -import java.util.Set; import org.junit.jupiter.api.extension.RegisterExtension; class RatpackPooledHttpClientTest extends AbstractRatpackPooledHttpClientTest { @RegisterExtension static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); - - @Override - protected Set> computeHttpAttributes(URI uri) { - Set> attributes = new HashSet<>(super.computeHttpAttributes(uri)); - // underlying netty instrumentation does not provide these - attributes.remove(SERVER_ADDRESS); - attributes.remove(SERVER_PORT); - return attributes; - } } diff --git a/instrumentation/ratpack/ratpack-1.4/testing/src/main/java/io/opentelemetry/instrumentation/ratpack/client/AbstractRatpackHttpClientTest.java b/instrumentation/ratpack/ratpack-1.4/testing/src/main/java/io/opentelemetry/instrumentation/ratpack/client/AbstractRatpackHttpClientTest.java index bb6a43e8aa84..3e3ed9a1f6f1 100644 --- a/instrumentation/ratpack/ratpack-1.4/testing/src/main/java/io/opentelemetry/instrumentation/ratpack/client/AbstractRatpackHttpClientTest.java +++ b/instrumentation/ratpack/ratpack-1.4/testing/src/main/java/io/opentelemetry/instrumentation/ratpack/client/AbstractRatpackHttpClientTest.java @@ -5,15 +5,20 @@ package io.opentelemetry.instrumentation.ratpack.client; +import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; +import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT; + import io.netty.channel.ConnectTimeoutException; import io.netty.handler.timeout.ReadTimeoutException; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; +import io.opentelemetry.semconv.NetworkAttributes; import java.net.URI; import java.time.Duration; import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.Set; import org.junit.jupiter.api.AfterAll; @@ -29,13 +34,13 @@ public abstract class AbstractRatpackHttpClientTest extends AbstractHttpClientTest { - private final ExecHarness exec = ExecHarness.harness(); + protected final ExecHarness exec = ExecHarness.harness(); - private HttpClient client; - private HttpClient singleConnectionClient; + protected HttpClient client; + protected HttpClient singleConnectionClient; @BeforeAll - void setUpClient() throws Exception { + protected void setUpClient() throws Exception { exec.run( unused -> { client = buildHttpClient(); @@ -66,7 +71,7 @@ public Void buildRequest(String method, URI uri, Map headers) { @Override public int sendRequest(Void request, String method, URI uri, Map headers) throws Exception { - return exec.yield(unused -> internalSendRequest(client, method, uri, headers)) + return exec.yield(execution -> internalSendRequest(client, method, uri, headers)) .getValueOrThrow(); } @@ -78,13 +83,17 @@ public final void sendRequestWithCallback( Map headers, HttpClientResult httpClientResult) throws Exception { - exec.execute( - Operation.of( - () -> - internalSendRequest(client, method, uri, headers) - .result( - result -> - httpClientResult.complete(result::getValue, result.getThrowable())))); + exec.yield( + (e) -> + Operation.of( + () -> + internalSendRequest(client, method, uri, headers) + .result( + result -> + httpClientResult.complete( + result::getValue, result.getThrowable()))) + .promise()) + .getValueOrThrow(); } // overridden in RatpackForkedHttpClientTest @@ -118,32 +127,13 @@ protected void configure(HttpClientTestOptions.Builder optionsBuilder) { .getValueOrThrow(); }); - optionsBuilder.setExpectedClientSpanNameMapper( - (uri, method) -> { - switch (uri.toString()) { - case "http://localhost:61/": // unopened port - case "https://192.0.2.1/": // non routable address - return "CONNECT"; - default: - return HttpClientTestOptions.DEFAULT_EXPECTED_CLIENT_SPAN_NAME_MAPPER.apply( - uri, method); - } - }); + if (useNettyClientAttributes()) { + optionsBuilder.setExpectedClientSpanNameMapper( + AbstractRatpackHttpClientTest::nettyExpectedClientSpanNameMapper); + } optionsBuilder.setClientSpanErrorMapper( - (uri, exception) -> { - if (uri.toString().equals("https://192.0.2.1/")) { - return new ConnectTimeoutException( - "connection timed out" - + (Boolean.getBoolean("testLatestDeps") ? " after 2000 ms" : "") - + ": /192.0.2.1:443"); - } else if (OS.WINDOWS.isCurrentOs() && uri.toString().equals("http://localhost:61/")) { - return new ConnectTimeoutException("connection timed out: localhost/127.0.0.1:61"); - } else if (uri.getPath().equals("/read-timeout")) { - return ReadTimeoutException.INSTANCE; - } - return exception; - }); + AbstractRatpackHttpClientTest::nettyClientSpanErrorMapper); optionsBuilder.setHttpAttributes(this::computeHttpAttributes); @@ -160,7 +150,45 @@ protected Set> computeHttpAttributes(URI uri) { case "https://192.0.2.1/": // non routable address return Collections.emptySet(); default: - return HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES; + HashSet> attributes = + new HashSet<>(HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES); + if (useNettyClientAttributes()) { + // underlying netty instrumentation does not provide these + attributes.remove(SERVER_ADDRESS); + attributes.remove(SERVER_PORT); + } else { + // ratpack client instrumentation does not provide this + attributes.remove(NetworkAttributes.NETWORK_PROTOCOL_VERSION); + } + return attributes; + } + } + + protected boolean useNettyClientAttributes() { + return true; + } + + private static Throwable nettyClientSpanErrorMapper(URI uri, Throwable exception) { + if (uri.toString().equals("https://192.0.2.1/")) { + return new ConnectTimeoutException( + "connection timed out" + + (Boolean.getBoolean("testLatestDeps") ? " after 2000 ms" : "") + + ": /192.0.2.1:443"); + } else if (OS.WINDOWS.isCurrentOs() && uri.toString().equals("http://localhost:61/")) { + return new ConnectTimeoutException("connection timed out: localhost/127.0.0.1:61"); + } else if (uri.getPath().equals("/read-timeout")) { + return ReadTimeoutException.INSTANCE; + } + return exception; + } + + private static String nettyExpectedClientSpanNameMapper(URI uri, String method) { + switch (uri.toString()) { + case "http://localhost:61/": // unopened port + case "https://192.0.2.1/": // non routable address + return "CONNECT"; + default: + return HttpClientTestOptions.DEFAULT_EXPECTED_CLIENT_SPAN_NAME_MAPPER.apply(uri, method); } } } diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/build.gradle.kts b/instrumentation/ratpack/ratpack-1.7/javaagent/build.gradle.kts new file mode 100644 index 000000000000..eaebce6016a6 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/build.gradle.kts @@ -0,0 +1,33 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +muzzle { + pass { + group.set("io.ratpack") + module.set("ratpack-core") + versions.set("[1.7.0,)") + } + fail { + group.set("io.ratpack") + module.set("ratpack-core") + versions.set("[1.0,1.7)") + } +} + +dependencies { + library("io.ratpack:ratpack-core:1.7.0") + + implementation(project(":instrumentation:netty:netty-4.1:library")) + implementation(project(":instrumentation:ratpack:ratpack-1.7:library")) + + testImplementation(project(":instrumentation:ratpack:ratpack-1.4:testing")) + testInstrumentation(project(":instrumentation:ratpack:ratpack-1.4:javaagent")) +} + +tasks { + withType().configureEach { + systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) + jvmArgs("-Dotel.instrumentation.common.experimental.controller-telemetry.enabled=true") + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/DefaultExecControllerInstrumentation.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/DefaultExecControllerInstrumentation.java new file mode 100644 index 000000000000..27ebfc0bcefb --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/DefaultExecControllerInstrumentation.java @@ -0,0 +1,93 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import static net.bytebuddy.matcher.ElementMatchers.isConstructor; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import com.google.common.collect.ImmutableList; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryExecInitializer; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryExecInterceptor; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.asm.Advice.AssignReturned.ToArguments.ToArgument; +import net.bytebuddy.asm.Advice.AssignReturned.ToFields.ToField; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import ratpack.exec.ExecInitializer; +import ratpack.exec.ExecInterceptor; + +public class DefaultExecControllerInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("ratpack.exec.internal.DefaultExecController"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("setInitializers") + .and(takesArgument(0, named("com.google.common.collect.ImmutableList"))), + DefaultExecControllerInstrumentation.class.getName() + "$SetInitializersAdvice"); + + transformer.applyAdviceToMethod( + named("setInterceptors") + .and(takesArgument(0, named("com.google.common.collect.ImmutableList"))), + DefaultExecControllerInstrumentation.class.getName() + "$SetInterceptorsAdvice"); + + transformer.applyAdviceToMethod( + isConstructor(), + DefaultExecControllerInstrumentation.class.getName() + "$ConstructorAdvice"); + } + + @SuppressWarnings("unused") + public static class SetInitializersAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + @Advice.AssignReturned.ToArguments(@ToArgument(0)) + public static ImmutableList enter( + @Advice.Argument(0) ImmutableList initializers) { + return ImmutableList.builder() + .addAll(initializers) + .add(OpenTelemetryExecInitializer.INSTANCE) + .build(); + } + } + + @SuppressWarnings("unused") + public static class SetInterceptorsAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + @Advice.AssignReturned.ToArguments(@ToArgument(0)) + public static ImmutableList enter( + @Advice.Argument(0) ImmutableList interceptors) { + return ImmutableList.builder() + .addAll(interceptors) + .add(OpenTelemetryExecInterceptor.INSTANCE) + .build(); + } + } + + @SuppressWarnings("unused") + public static class ConstructorAdvice { + + @SuppressWarnings("UnusedVariable") + @Advice.OnMethodExit(suppress = Throwable.class) + @Advice.AssignReturned.ToFields({ + @ToField(value = "initializers", index = 0), + @ToField(value = "interceptors", index = 1) + }) + public static Object[] exit( + @Advice.FieldValue("initializers") ImmutableList initializers, + @Advice.FieldValue("interceptors") ImmutableList interceptors) { + return new Object[] { + ImmutableList.of(OpenTelemetryExecInitializer.INSTANCE), + ImmutableList.of(OpenTelemetryExecInterceptor.INSTANCE) + }; + } + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/DownstreamWrapper.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/DownstreamWrapper.java new file mode 100644 index 000000000000..e4540162d4e6 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/DownstreamWrapper.java @@ -0,0 +1,55 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import ratpack.exec.Downstream; + +public final class DownstreamWrapper implements Downstream { + + private final Downstream delegate; + private final Context parentContext; + + private DownstreamWrapper(Downstream delegate, Context parentContext) { + assert parentContext != null; + this.delegate = delegate; + this.parentContext = parentContext; + } + + @Override + public void success(T value) { + try (Scope ignored = parentContext.makeCurrent()) { + delegate.success(value); + } + } + + @Override + public void error(Throwable throwable) { + try (Scope ignored = parentContext.makeCurrent()) { + delegate.error(throwable); + } + } + + @Override + public void complete() { + try (Scope ignored = parentContext.makeCurrent()) { + delegate.complete(); + } + } + + public static Downstream wrapIfNeeded(Downstream delegate) { + if (delegate instanceof DownstreamWrapper) { + return delegate; + } + Context context = Context.current(); + if (context == Context.root()) { + // Skip wrapping, there is no need to propagate root context. + return delegate; + } + return new DownstreamWrapper<>(delegate, context); + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/HttpClientInstrumentation.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/HttpClientInstrumentation.java new file mode 100644 index 000000000000..866b9c41e4de --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/HttpClientInstrumentation.java @@ -0,0 +1,46 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.isStatic; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +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 ratpack.http.client.HttpClient; + +public class HttpClientInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("ratpack.http.client.HttpClient"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + isMethod() + .and(isStatic()) + .and(named("of")) + .and(takesArgument(0, named("ratpack.func.Action"))), + HttpClientInstrumentation.class.getName() + "$OfAdvice"); + } + + @SuppressWarnings("unused") + public static class OfAdvice { + + @Advice.OnMethodExit(suppress = Throwable.class) + @Advice.AssignReturned.ToReturned + public static HttpClient injectTracing(@Advice.Return HttpClient httpClient) throws Exception { + return RatpackSingletons.httpClient().instrument(httpClient); + } + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackInstrumentationModule.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackInstrumentationModule.java new file mode 100644 index 000000000000..992e9583c652 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackInstrumentationModule.java @@ -0,0 +1,44 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; +import static java.util.Arrays.asList; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; +import java.util.List; +import net.bytebuddy.matcher.ElementMatcher; + +@AutoService(InstrumentationModule.class) +public class RatpackInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { + public RatpackInstrumentationModule() { + super("ratpack", "ratpack-1.7"); + } + + @Override + public String getModuleGroup() { + // relies on netty + return "netty"; + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + // Only activate when running ratpack 1.7 or later + return hasClassesNamed("ratpack.exec.util.retry.Delay"); + } + + @Override + public List typeInstrumentations() { + return asList( + new DefaultExecControllerInstrumentation(), + new HttpClientInstrumentation(), + new RequestActionSupportInstrumentation()); + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackSingletons.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackSingletons.java new file mode 100644 index 000000000000..8c0adac4ba75 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackSingletons.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import io.netty.channel.Channel; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.ContextHolder; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryHttpClient; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.RatpackClientInstrumenterBuilderFactory; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import ratpack.exec.Execution; + +public final class RatpackSingletons { + + static { + HTTP_CLIENT = + new OpenTelemetryHttpClient( + RatpackClientInstrumenterBuilderFactory.create( + "io.opentelemetry.ratpack-1.7", GlobalOpenTelemetry.get()) + .configure(AgentCommonConfig.get()) + .build()); + } + + private static final OpenTelemetryHttpClient HTTP_CLIENT; + + public static OpenTelemetryHttpClient httpClient() { + return HTTP_CLIENT; + } + + public static void propagateContextToChannel(Execution execution, Channel channel) { + Context parentContext = + execution + .maybeGet(ContextHolder.class) + .map(ContextHolder::context) + .orElse(Context.current()); + channel.attr(AttributeKeys.CLIENT_PARENT_CONTEXT).set(parentContext); + } + + private RatpackSingletons() {} +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RequestActionSupportInstrumentation.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RequestActionSupportInstrumentation.java new file mode 100644 index 000000000000..10be05690e86 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RequestActionSupportInstrumentation.java @@ -0,0 +1,95 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.isPrivate; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import io.netty.channel.Channel; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.ContextHolder; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.asm.Advice.AssignReturned.ToArguments.ToArgument; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import ratpack.exec.Downstream; +import ratpack.exec.Execution; + +public class RequestActionSupportInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return extendsClass(named("ratpack.http.client.internal.RequestActionSupport")); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + isMethod() + .and(isPrivate()) + .and(named("send")) + .and(takesArgument(0, named("ratpack.exec.Downstream"))) + .and(takesArgument(1, named("io.netty.channel.Channel"))), + RequestActionSupportInstrumentation.class.getName() + "$SendAdvice"); + transformer.applyAdviceToMethod( + isMethod().and(named("connect")).and(takesArgument(0, named("ratpack.exec.Downstream"))), + RequestActionSupportInstrumentation.class.getName() + "$ConnectDownstreamAdvice"); + transformer.applyAdviceToMethod( + isMethod().and(named("connect")).and(takesArgument(0, named("ratpack.exec.Downstream"))), + RequestActionSupportInstrumentation.class.getName() + "$ContextAdvice"); + } + + @SuppressWarnings("unused") + public static class SendAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void injectChannelAttribute( + @Advice.FieldValue("execution") Execution execution, @Advice.Argument(1) Channel channel) { + RatpackSingletons.propagateContextToChannel(execution, channel); + } + } + + @SuppressWarnings("unused") + public static class ConnectDownstreamAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + @Advice.AssignReturned.ToArguments(@ToArgument(0)) + public static Object wrapDownstream(@Advice.Argument(0) Downstream downstream) { + // Propagate the current context to downstream + // since that is the subsequent code chained to the http client call + return DownstreamWrapper.wrapIfNeeded(downstream); + } + } + + @SuppressWarnings("unused") + public static class ContextAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static Scope injectChannelAttribute( + @Advice.FieldValue("execution") Execution execution) { + + // Capture the CLIENT span and make it current before calling Netty layer + return execution + .maybeGet(ContextHolder.class) + .map(ContextHolder::context) + .map(Context::makeCurrent) + .orElse(null); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void exit(@Advice.Enter Scope scope) { + if (scope != null) { + scope.close(); + } + } + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackAsyncHttpServerTest.groovy b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackAsyncHttpServerTest.groovy new file mode 100644 index 000000000000..dc1cc42df27f --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackAsyncHttpServerTest.groovy @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package server + +import io.opentelemetry.instrumentation.ratpack.server.AbstractRatpackAsyncHttpServerTest +import io.opentelemetry.instrumentation.test.AgentTestTrait +import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint +import ratpack.server.RatpackServerSpec + +class RatpackAsyncHttpServerTest extends AbstractRatpackAsyncHttpServerTest implements AgentTestTrait { + @Override + void configure(RatpackServerSpec serverSpec) { + } + + @Override + boolean hasResponseCustomizer(ServerEndpoint endpoint) { + true + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackForkedHttpServerTest.groovy b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackForkedHttpServerTest.groovy new file mode 100644 index 000000000000..87dc2848b1ff --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackForkedHttpServerTest.groovy @@ -0,0 +1,27 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package server + +import io.opentelemetry.instrumentation.ratpack.server.AbstractRatpackForkedHttpServerTest +import io.opentelemetry.instrumentation.test.AgentTestTrait +import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint +import ratpack.server.RatpackServerSpec + +class RatpackForkedHttpServerTest extends AbstractRatpackForkedHttpServerTest implements AgentTestTrait { + @Override + void configure(RatpackServerSpec serverSpec) { + } + + @Override + boolean hasResponseCustomizer(ServerEndpoint endpoint) { + true + } + + @Override + boolean testHttpPipelining() { + false + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackHttpServerTest.groovy b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackHttpServerTest.groovy new file mode 100644 index 000000000000..3fd085dde585 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackHttpServerTest.groovy @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package server + +import io.opentelemetry.instrumentation.ratpack.server.AbstractRatpackHttpServerTest +import io.opentelemetry.instrumentation.test.AgentTestTrait +import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint +import ratpack.server.RatpackServerSpec + +class RatpackHttpServerTest extends AbstractRatpackHttpServerTest implements AgentTestTrait { + @Override + void configure(RatpackServerSpec serverSpec) { + } + + @Override + boolean hasResponseCustomizer(ServerEndpoint endpoint) { + true + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackRoutesTest.groovy b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackRoutesTest.groovy new file mode 100644 index 000000000000..e52bd4f93c1e --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/groovy/server/RatpackRoutesTest.groovy @@ -0,0 +1,21 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package server + +import io.opentelemetry.instrumentation.ratpack.server.AbstractRatpackRoutesTest +import io.opentelemetry.instrumentation.test.AgentTestTrait +import ratpack.server.RatpackServerSpec + +class RatpackRoutesTest extends AbstractRatpackRoutesTest implements AgentTestTrait { + @Override + void configure(RatpackServerSpec serverSpec) { + } + + @Override + boolean hasHandlerSpan() { + return true + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackForkedHttpClientTest.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackForkedHttpClientTest.java new file mode 100644 index 000000000000..509d08576c80 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackForkedHttpClientTest.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import io.opentelemetry.instrumentation.ratpack.client.AbstractRatpackForkedHttpClientTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; +import org.junit.jupiter.api.extension.RegisterExtension; + +class RatpackForkedHttpClientTest extends AbstractRatpackForkedHttpClientTest { + + @RegisterExtension + static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); + + @Override + protected boolean useNettyClientAttributes() { + return false; + } + + @Override + protected void configure(HttpClientTestOptions.Builder optionsBuilder) { + super.configure(optionsBuilder); + optionsBuilder.setClientSpanErrorMapper(RatpackTestUtils::ratpackClientSpanErrorMapper); + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackHttpClientTest.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackHttpClientTest.java new file mode 100644 index 000000000000..53e6e22734d5 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackHttpClientTest.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import io.opentelemetry.instrumentation.ratpack.client.AbstractRatpackHttpClientTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; +import org.junit.jupiter.api.extension.RegisterExtension; + +class RatpackHttpClientTest extends AbstractRatpackHttpClientTest { + + @RegisterExtension + static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); + + @Override + protected boolean useNettyClientAttributes() { + return false; + } + + @Override + protected void configure(HttpClientTestOptions.Builder optionsBuilder) { + super.configure(optionsBuilder); + optionsBuilder.setClientSpanErrorMapper(RatpackTestUtils::ratpackClientSpanErrorMapper); + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackPooledHttpClientTest.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackPooledHttpClientTest.java new file mode 100644 index 000000000000..396b4db4da64 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackPooledHttpClientTest.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import io.opentelemetry.instrumentation.ratpack.client.AbstractRatpackPooledHttpClientTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; +import org.junit.jupiter.api.extension.RegisterExtension; + +class RatpackPooledHttpClientTest extends AbstractRatpackPooledHttpClientTest { + + @RegisterExtension + static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); + + @Override + protected boolean useNettyClientAttributes() { + return false; + } + + @Override + protected void configure(HttpClientTestOptions.Builder optionsBuilder) { + super.configure(optionsBuilder); + optionsBuilder.setClientSpanErrorMapper(RatpackTestUtils::ratpackClientSpanErrorMapper); + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackTestUtils.java b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackTestUtils.java new file mode 100644 index 000000000000..4c4a9418f507 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/ratpack/v1_7/RatpackTestUtils.java @@ -0,0 +1,27 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.ratpack.v1_7; + +import io.netty.channel.ConnectTimeoutException; +import java.net.URI; +import org.junit.jupiter.api.condition.OS; +import ratpack.http.client.HttpClientReadTimeoutException; + +public final class RatpackTestUtils { + + private RatpackTestUtils() {} + + public static Throwable ratpackClientSpanErrorMapper(URI uri, Throwable exception) { + if (uri.toString().equals("https://192.0.2.1/") + || (OS.WINDOWS.isCurrentOs() && uri.toString().equals("http://localhost:61/"))) { + return new ConnectTimeoutException("Connect timeout (PT2S) connecting to " + uri); + } else if (uri.getPath().equals("/read-timeout")) { + return new HttpClientReadTimeoutException( + "Read timeout (PT2S) waiting on HTTP server at " + uri); + } + return exception; + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackTelemetry.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackTelemetry.java index f8468d491908..95ea733c4fe7 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackTelemetry.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackTelemetry.java @@ -7,6 +7,10 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryExecInitializer; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryExecInterceptor; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryHttpClient; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryServerHandler; import ratpack.exec.ExecInitializer; import ratpack.exec.ExecInterceptor; import ratpack.handling.HandlerDecorator; diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackTelemetryBuilder.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackTelemetryBuilder.java index a7e56610913a..1192a8d8d936 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackTelemetryBuilder.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackTelemetryBuilder.java @@ -13,6 +13,8 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.RatpackClientInstrumenterBuilderFactory; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.RatpackServerInstrumenterBuilderFactory; import java.util.List; import java.util.Set; import java.util.function.Function; @@ -31,17 +33,9 @@ public final class RatpackTelemetryBuilder { RatpackTelemetryBuilder(OpenTelemetry openTelemetry) { clientBuilder = - DefaultHttpClientInstrumenterBuilder.create( - INSTRUMENTATION_NAME, - openTelemetry, - RatpackHttpClientAttributesGetter.INSTANCE, - RequestHeaderSetter.INSTANCE); + RatpackClientInstrumenterBuilderFactory.create(INSTRUMENTATION_NAME, openTelemetry); serverBuilder = - DefaultHttpServerInstrumenterBuilder.create( - INSTRUMENTATION_NAME, - openTelemetry, - RatpackHttpAttributesGetter.INSTANCE, - RatpackGetter.INSTANCE); + RatpackServerInstrumenterBuilderFactory.create(INSTRUMENTATION_NAME, openTelemetry); } /** diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryExecInitializer.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryExecInitializer.java similarity index 68% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryExecInitializer.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryExecInitializer.java index 5788db8c5655..b192859d8221 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryExecInitializer.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryExecInitializer.java @@ -3,13 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; -import io.opentelemetry.instrumentation.ratpack.v1_7.internal.ContextHolder; import ratpack.exec.ExecInitializer; import ratpack.exec.Execution; -final class OpenTelemetryExecInitializer implements ExecInitializer { +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class OpenTelemetryExecInitializer implements ExecInitializer { public static final ExecInitializer INSTANCE = new OpenTelemetryExecInitializer(); @Override diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryExecInterceptor.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryExecInterceptor.java similarity index 85% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryExecInterceptor.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryExecInterceptor.java index f78c0671fe74..b75c801c17fa 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryExecInterceptor.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryExecInterceptor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; @@ -11,9 +11,13 @@ import ratpack.exec.Execution; import ratpack.func.Block; -final class OpenTelemetryExecInterceptor implements ExecInterceptor { +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class OpenTelemetryExecInterceptor implements ExecInterceptor { - static final ExecInterceptor INSTANCE = new OpenTelemetryExecInterceptor(); + public static final ExecInterceptor INSTANCE = new OpenTelemetryExecInterceptor(); @Override public void intercept(Execution execution, ExecType type, Block continuation) throws Exception { diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryFallbackErrorHandler.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryFallbackErrorHandler.java similarity index 94% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryFallbackErrorHandler.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryFallbackErrorHandler.java index f3f2db80c352..4c909be89f8f 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryFallbackErrorHandler.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryFallbackErrorHandler.java @@ -20,7 +20,7 @@ * limitations under the License. */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; import static java.util.logging.Level.WARNING; @@ -32,6 +32,10 @@ // Copied from // https://github.com/ratpack/ratpack/blob/master/ratpack-core/src/main/java/ratpack/core/error/internal/DefaultProductionErrorHandler.java // since it is internal and has had breaking changes. +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ final class OpenTelemetryFallbackErrorHandler implements ClientErrorHandler, ServerErrorHandler { static final OpenTelemetryFallbackErrorHandler INSTANCE = new OpenTelemetryFallbackErrorHandler(); diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryHttpClient.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryHttpClient.java similarity index 58% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryHttpClient.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryHttpClient.java index aea5fc96faf6..c657d98bdb9c 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryHttpClient.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryHttpClient.java @@ -3,23 +3,26 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.ratpack.v1_7.internal.ContextHolder; import io.opentelemetry.semconv.HttpAttributes; import ratpack.exec.Execution; import ratpack.http.client.HttpClient; import ratpack.http.client.HttpResponse; import ratpack.http.client.RequestSpec; -final class OpenTelemetryHttpClient { +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class OpenTelemetryHttpClient { private final Instrumenter instrumenter; - OpenTelemetryHttpClient(Instrumenter instrumenter) { + public OpenTelemetryHttpClient(Instrumenter instrumenter) { this.instrumenter = instrumenter; } @@ -44,18 +47,30 @@ public HttpClient instrument(HttpClient httpClient) throws Exception { httpClientSpec.responseIntercept( httpResponse -> { Execution execution = Execution.current(); - ContextHolder contextHolder = execution.get(ContextHolder.class); - execution.remove(ContextHolder.class); - instrumenter.end( - contextHolder.context(), contextHolder.requestSpec(), httpResponse, null); + execution + .maybeGet(ContextHolder.class) + .ifPresent( + contextHolder -> { + execution.remove(ContextHolder.class); + instrumenter.end( + contextHolder.context(), + contextHolder.requestSpec(), + httpResponse, + null); + }); }); httpClientSpec.errorIntercept( ex -> { Execution execution = Execution.current(); - ContextHolder contextHolder = execution.get(ContextHolder.class); - execution.remove(ContextHolder.class); - instrumenter.end(contextHolder.context(), contextHolder.requestSpec(), null, ex); + execution + .maybeGet(ContextHolder.class) + .ifPresent( + contextHolder -> { + execution.remove(ContextHolder.class); + instrumenter.end( + contextHolder.context(), contextHolder.requestSpec(), null, ex); + }); }); }); } diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryServerErrorHandler.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryServerErrorHandler.java similarity index 83% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryServerErrorHandler.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryServerErrorHandler.java index bc84c476203b..26316c3fe839 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryServerErrorHandler.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryServerErrorHandler.java @@ -3,11 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; import ratpack.error.ServerErrorHandler; import ratpack.handling.Context; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ final class OpenTelemetryServerErrorHandler implements ServerErrorHandler { static final ServerErrorHandler INSTANCE = new OpenTelemetryServerErrorHandler(); diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryServerHandler.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryServerHandler.java similarity index 91% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryServerHandler.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryServerHandler.java index 7dedf77ef9ab..2d5f23782066 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/OpenTelemetryServerHandler.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/OpenTelemetryServerHandler.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; import static io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource.CONTROLLER; @@ -16,11 +16,15 @@ import ratpack.http.Request; import ratpack.http.Response; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ public final class OpenTelemetryServerHandler implements Handler { private final Instrumenter instrumenter; - OpenTelemetryServerHandler(Instrumenter instrumenter) { + public OpenTelemetryServerHandler(Instrumenter instrumenter) { this.instrumenter = instrumenter; } diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackClientInstrumenterBuilderFactory.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackClientInstrumenterBuilderFactory.java new file mode 100644 index 000000000000..c5a0999dea35 --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackClientInstrumenterBuilderFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import ratpack.http.client.HttpResponse; +import ratpack.http.client.RequestSpec; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class RatpackClientInstrumenterBuilderFactory { + private RatpackClientInstrumenterBuilderFactory() {} + + public static DefaultHttpClientInstrumenterBuilder create( + String instrumentationName, OpenTelemetry openTelemetry) { + + return DefaultHttpClientInstrumenterBuilder.create( + instrumentationName, + openTelemetry, + RatpackHttpClientAttributesGetter.INSTANCE, + RequestHeaderSetter.INSTANCE); + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackGetter.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackGetter.java similarity index 75% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackGetter.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackGetter.java index e9326b12acfc..b50e28244418 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackGetter.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackGetter.java @@ -3,12 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; import io.opentelemetry.context.propagation.TextMapGetter; import javax.annotation.Nullable; import ratpack.http.Request; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ enum RatpackGetter implements TextMapGetter { INSTANCE; diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackHttpAttributesGetter.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackHttpAttributesGetter.java similarity index 92% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackHttpAttributesGetter.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackHttpAttributesGetter.java index 95a3d4f888c5..fcf38f576e9f 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackHttpAttributesGetter.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackHttpAttributesGetter.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesGetter; import java.util.List; @@ -13,6 +13,10 @@ import ratpack.http.Response; import ratpack.server.PublicAddress; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ enum RatpackHttpAttributesGetter implements HttpServerAttributesGetter { INSTANCE; diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackHttpClientAttributesGetter.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackHttpClientAttributesGetter.java similarity index 88% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackHttpClientAttributesGetter.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackHttpClientAttributesGetter.java index 6aa8f0227fa5..fbf8059096c5 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RatpackHttpClientAttributesGetter.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackHttpClientAttributesGetter.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; import java.util.List; @@ -11,6 +11,10 @@ import ratpack.http.client.HttpResponse; import ratpack.http.client.RequestSpec; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ enum RatpackHttpClientAttributesGetter implements HttpClientAttributesGetter { INSTANCE; diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackServerInstrumenterBuilderFactory.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackServerInstrumenterBuilderFactory.java new file mode 100644 index 000000000000..c0539634ab8f --- /dev/null +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackServerInstrumenterBuilderFactory.java @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; +import ratpack.http.Request; +import ratpack.http.Response; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class RatpackServerInstrumenterBuilderFactory { + + private RatpackServerInstrumenterBuilderFactory() {} + + public static DefaultHttpServerInstrumenterBuilder create( + String instrumentationName, OpenTelemetry openTelemetry) { + + return DefaultHttpServerInstrumenterBuilder.create( + instrumentationName, + openTelemetry, + RatpackHttpAttributesGetter.INSTANCE, + RatpackGetter.INSTANCE); + } +} diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RequestHeaderSetter.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RequestHeaderSetter.java similarity index 71% rename from instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RequestHeaderSetter.java rename to instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RequestHeaderSetter.java index d6da0e36d752..f847e7e8271e 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/RequestHeaderSetter.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RequestHeaderSetter.java @@ -3,12 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.ratpack.v1_7; +package io.opentelemetry.instrumentation.ratpack.v1_7.internal; import io.opentelemetry.context.propagation.TextMapSetter; import ratpack.api.Nullable; import ratpack.http.client.RequestSpec; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ enum RequestHeaderSetter implements TextMapSetter { INSTANCE; diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/test/groovy/io/opentelemetry/instrumentation/ratpack/v1_7/server/RatpackServerApplicationTest.groovy b/instrumentation/ratpack/ratpack-1.7/library/src/test/groovy/io/opentelemetry/instrumentation/ratpack/v1_7/server/RatpackServerApplicationTest.groovy index ced2052acce7..3e0ed088f401 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/test/groovy/io/opentelemetry/instrumentation/ratpack/v1_7/server/RatpackServerApplicationTest.groovy +++ b/instrumentation/ratpack/ratpack-1.7/library/src/test/groovy/io/opentelemetry/instrumentation/ratpack/v1_7/server/RatpackServerApplicationTest.groovy @@ -10,7 +10,7 @@ import com.google.inject.Provides import groovy.transform.CompileStatic import io.opentelemetry.api.OpenTelemetry import io.opentelemetry.api.trace.SpanKind -import io.opentelemetry.instrumentation.ratpack.v1_7.OpenTelemetryServerHandler +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryServerHandler import io.opentelemetry.instrumentation.ratpack.v1_7.RatpackFunctionalTest import io.opentelemetry.instrumentation.ratpack.v1_7.RatpackTelemetry import io.opentelemetry.sdk.OpenTelemetrySdk diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/test/java/io/opentelemetry/instrumentation/ratpack/v1_7/AbstractRatpackHttpClientTest.java b/instrumentation/ratpack/ratpack-1.7/library/src/test/java/io/opentelemetry/instrumentation/ratpack/v1_7/AbstractRatpackHttpClientTest.java index d13cbcc65932..2704b1ad6ba5 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/test/java/io/opentelemetry/instrumentation/ratpack/v1_7/AbstractRatpackHttpClientTest.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/test/java/io/opentelemetry/instrumentation/ratpack/v1_7/AbstractRatpackHttpClientTest.java @@ -11,6 +11,8 @@ import io.netty.channel.ConnectTimeoutException; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryExecInitializer; +import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryExecInterceptor; import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; @@ -148,16 +150,16 @@ protected void configure(HttpClientTestOptions.Builder optionsBuilder) { } return exception; }); + optionsBuilder.setHttpAttributes(this::computeHttpAttributes); optionsBuilder.disableTestRedirects(); + // these tests will pass, but they don't really test anything since REQUEST is Void optionsBuilder.disableTestReusedRequest(); - optionsBuilder.setHttpAttributes(this::getHttpAttributes); - optionsBuilder.spanEndsAfterBody(); } - protected Set> getHttpAttributes(URI uri) { + protected Set> computeHttpAttributes(URI uri) { Set> attributes = new HashSet<>(HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES); attributes.remove(NETWORK_PROTOCOL_VERSION); return attributes; diff --git a/settings.gradle.kts b/settings.gradle.kts index 68cd7bff023f..418f2a101515 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -507,6 +507,7 @@ include(":instrumentation:r2dbc-1.0:testing") include(":instrumentation:rabbitmq-2.7:javaagent") include(":instrumentation:ratpack:ratpack-1.4:javaagent") include(":instrumentation:ratpack:ratpack-1.4:testing") +include(":instrumentation:ratpack:ratpack-1.7:javaagent") include(":instrumentation:ratpack:ratpack-1.7:library") include(":instrumentation:reactor:reactor-3.1:javaagent") include(":instrumentation:reactor:reactor-3.1:library")