Add agent instrumentation for Ratpack 1.7+ (#12572)
This commit is contained in:
parent
11773aa889
commit
8a3f1eb03d
|
@ -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<AttributeKey<?>> computeHttpAttributes(URI uri) {
|
||||
Set<AttributeKey<?>> attributes = new HashSet<>(super.computeHttpAttributes(uri));
|
||||
// underlying netty instrumentation does not provide these
|
||||
attributes.remove(SERVER_ADDRESS);
|
||||
attributes.remove(SERVER_PORT);
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<AttributeKey<?>> computeHttpAttributes(URI uri) {
|
||||
Set<AttributeKey<?>> attributes = new HashSet<>(super.computeHttpAttributes(uri));
|
||||
// underlying netty instrumentation does not provide these
|
||||
attributes.remove(SERVER_ADDRESS);
|
||||
attributes.remove(SERVER_PORT);
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<AttributeKey<?>> computeHttpAttributes(URI uri) {
|
||||
Set<AttributeKey<?>> attributes = new HashSet<>(super.computeHttpAttributes(uri));
|
||||
// underlying netty instrumentation does not provide these
|
||||
attributes.remove(SERVER_ADDRESS);
|
||||
attributes.remove(SERVER_PORT);
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 @@ import ratpack.test.exec.ExecHarness;
|
|||
|
||||
public abstract class AbstractRatpackHttpClientTest extends AbstractHttpClientTest<Void> {
|
||||
|
||||
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 abstract class AbstractRatpackHttpClientTest extends AbstractHttpClientTe
|
|||
@Override
|
||||
public int sendRequest(Void request, String method, URI uri, Map<String, String> 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 abstract class AbstractRatpackHttpClientTest extends AbstractHttpClientTe
|
|||
Map<String, String> 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 @@ public abstract class AbstractRatpackHttpClientTest extends AbstractHttpClientTe
|
|||
.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 @@ public abstract class AbstractRatpackHttpClientTest extends AbstractHttpClientTe
|
|||
case "https://192.0.2.1/": // non routable address
|
||||
return Collections.emptySet();
|
||||
default:
|
||||
return HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES;
|
||||
HashSet<AttributeKey<?>> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Test>().configureEach {
|
||||
systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean)
|
||||
jvmArgs("-Dotel.instrumentation.common.experimental.controller-telemetry.enabled=true")
|
||||
}
|
||||
}
|
|
@ -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<TypeDescription> 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<? extends ExecInitializer> enter(
|
||||
@Advice.Argument(0) ImmutableList<? extends ExecInitializer> initializers) {
|
||||
return ImmutableList.<ExecInitializer>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<? extends ExecInterceptor> enter(
|
||||
@Advice.Argument(0) ImmutableList<? extends ExecInterceptor> interceptors) {
|
||||
return ImmutableList.<ExecInterceptor>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<? extends ExecInitializer> initializers,
|
||||
@Advice.FieldValue("interceptors") ImmutableList<? extends ExecInterceptor> interceptors) {
|
||||
return new Object[] {
|
||||
ImmutableList.of(OpenTelemetryExecInitializer.INSTANCE),
|
||||
ImmutableList.of(OpenTelemetryExecInterceptor.INSTANCE)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<T> implements Downstream<T> {
|
||||
|
||||
private final Downstream<T> delegate;
|
||||
private final Context parentContext;
|
||||
|
||||
private DownstreamWrapper(Downstream<T> 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 <T> Downstream<T> wrapIfNeeded(Downstream<T> 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);
|
||||
}
|
||||
}
|
|
@ -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<TypeDescription> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<ClassLoader> classLoaderMatcher() {
|
||||
// Only activate when running ratpack 1.7 or later
|
||||
return hasClassesNamed("ratpack.exec.util.retry.Delay");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return asList(
|
||||
new DefaultExecControllerInstrumentation(),
|
||||
new HttpClientInstrumentation(),
|
||||
new RequestActionSupportInstrumentation());
|
||||
}
|
||||
}
|
|
@ -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() {}
|
||||
}
|
|
@ -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<TypeDescription> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -7,6 +7,10 @@ package io.opentelemetry.instrumentation.ratpack.v1_7;
|
|||
|
||||
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;
|
||||
|
|
|
@ -13,6 +13,8 @@ import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
|||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
|
@ -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.ExecInterceptor;
|
|||
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 {
|
|
@ -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 @@ import ratpack.handling.Context;
|
|||
// 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();
|
|
@ -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<RequestSpec, HttpResponse> instrumenter;
|
||||
|
||||
OpenTelemetryHttpClient(Instrumenter<RequestSpec, HttpResponse> instrumenter) {
|
||||
public OpenTelemetryHttpClient(Instrumenter<RequestSpec, HttpResponse> instrumenter) {
|
||||
this.instrumenter = instrumenter;
|
||||
}
|
||||
|
||||
|
@ -44,18 +47,30 @@ final class OpenTelemetryHttpClient {
|
|||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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();
|
|
@ -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.handling.Handler;
|
|||
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<Request, Response> instrumenter;
|
||||
|
||||
OpenTelemetryServerHandler(Instrumenter<Request, Response> instrumenter) {
|
||||
public OpenTelemetryServerHandler(Instrumenter<Request, Response> instrumenter) {
|
||||
this.instrumenter = instrumenter;
|
||||
}
|
||||
|
|
@ -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<RequestSpec, HttpResponse> create(
|
||||
String instrumentationName, OpenTelemetry openTelemetry) {
|
||||
|
||||
return DefaultHttpClientInstrumenterBuilder.create(
|
||||
instrumentationName,
|
||||
openTelemetry,
|
||||
RatpackHttpClientAttributesGetter.INSTANCE,
|
||||
RequestHeaderSetter.INSTANCE);
|
||||
}
|
||||
}
|
|
@ -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<Request> {
|
||||
INSTANCE;
|
||||
|
|
@ -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.Request;
|
|||
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<Request, Response> {
|
||||
INSTANCE;
|
||||
|
|
@ -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 javax.annotation.Nullable;
|
|||
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<RequestSpec, HttpResponse> {
|
||||
INSTANCE;
|
|
@ -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<Request, Response> create(
|
||||
String instrumentationName, OpenTelemetry openTelemetry) {
|
||||
|
||||
return DefaultHttpServerInstrumenterBuilder.create(
|
||||
instrumentationName,
|
||||
openTelemetry,
|
||||
RatpackHttpAttributesGetter.INSTANCE,
|
||||
RatpackGetter.INSTANCE);
|
||||
}
|
||||
}
|
|
@ -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<RequestSpec> {
|
||||
INSTANCE;
|
||||
|
|
@ -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
|
||||
|
|
|
@ -11,6 +11,8 @@ import com.google.common.collect.ImmutableList;
|
|||
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 @@ abstract class AbstractRatpackHttpClientTest extends AbstractHttpClientTest<Void
|
|||
}
|
||||
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<AttributeKey<?>> getHttpAttributes(URI uri) {
|
||||
protected Set<AttributeKey<?>> computeHttpAttributes(URI uri) {
|
||||
Set<AttributeKey<?>> attributes = new HashSet<>(HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES);
|
||||
attributes.remove(NETWORK_PROTOCOL_VERSION);
|
||||
return attributes;
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue